This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: PATCH: Provide runtime intialization of _STL_mutex_lock class (revised)


I have updated the patch to hopefully address your concerns and Loren's.

> 1) why are you adding this to libsupc++? it should be added to 
> src/Makefile.am
> 
> 2) there is already a src/globals.cc -- why can't you use that?

1) Global code moved to src/globals.cc.

> 3) In general, the naming seems a bit off. stl_globals, yet the patch is 
> for threads and mutexes.... also we're trying to go away from _STL bits and 
> towad _GLIBCPP_ bits in names. 

2) Global names changed.

3) _GTHREAD_MUTEX_INIT selected in preference to _GTHREAD_MUTEX_INIT_FUNCTION.

4) Added an additional call to __gthread_once after the global lock has been
   obtained to try to further ensure that the initialization of _M_lock works
   correctly on multiprocessor systems.

There is one minor issue.  A warning occurs in the compilation of stl-inst.cc
because only a partial inilization of the _STL_mutex_lock struct is done.
This could be fixed if the gthr.h thread idiom were augmented to provide
a default mutex initializer for the __gthread_mutex_t type for use when
__GTHREAD_MUTEX_INIT_FUNCTION is defined.

I have tested this under i686 linux and hpux 10.20.  Under linux, I have
checked both the __GTHREAD_MUTEX_INIT and __GTHREAD_MUTEX_INIT_FUNCTION.
I don't see any regressions.  The only v3 errors that I see are 

FAIL: 21_strings/insert.cc execution test
FAIL: 27_io/ios_members.cc execution test

for unix/-static.

How about it?

Dave
-- 
J. David Anglin                                  dave.anglin@nrc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6605)

2001-06-12  John David Anglin  <dave@hiauly1.hia.nrc.ca>

	* src/globals.cc: Define globals _GLIBCPP_mutex_init (),
	_GLIBCPP_mutex_address_init (), _GLIBCPP_once, _GLIBCPP_mutex
	and _GLIBCPP_mutex_address.
	* include/bits/stl_threads.h (_STL_mutex_lock): Use above to provide
	once-only runtime initialization of _M_lock mutex when
	__GTHREAD_MUTEX_INIT_FUNCTION is defined.

--- src/globals.cc.orig	Wed Jun  6 14:13:01 2001
+++ src/globals.cc	Mon Jun 11 16:53:03 2001
@@ -25,6 +25,8 @@
 // invalidate any other reasons why the executable file might be covered by
 // the GNU General Public License.
 
+#include "bits/c++config.h"
+#include "bits/gthr.h"
 #include <fstream>
 #include <istream>
 #include <ostream>
@@ -73,4 +74,31 @@
   fake_wfilebuf buf_wcin;
   fake_wfilebuf buf_wcerr;
 #endif
+
+// Globals for once-only runtime initialization of mutex objects.  This
+// allows static initialization of these objects on systems that need a
+// function call to initialize a mutex.  For example, see stl_threads.h.
+#if __GTHREADS
+#ifdef __GTHREAD_MUTEX_INIT
+// This path is not needed since static initialization of mutexs works
+// on this platform.
+#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION)
+__gthread_once_t _GLIBCPP_once = __GTHREAD_ONCE_INIT;
+__gthread_mutex_t _GLIBCPP_mutex;
+__gthread_mutex_t *_GLIBCPP_mutex_address;
+
+// Once-only initializer function for _GLIBCPP_mutex.  
+void
+_GLIBCPP_mutex_init ()
+{
+  __GTHREAD_MUTEX_INIT_FUNCTION (&_GLIBCPP_mutex);
+}
+// Once-only initializer function for _GLIBCPP_mutex_address.  
+void
+_GLIBCPP_mutex_address_init ()
+{
+  __GTHREAD_MUTEX_INIT_FUNCTION (_GLIBCPP_mutex_address);
+}
+#endif
+#endif
 }
--- include/bits/stl_threads.h.orig	Fri Jun  8 18:44:50 2001
+++ include/bits/stl_threads.h	Mon Jun 11 17:42:03 2001
@@ -296,21 +296,62 @@
 template <int __inst>
 unsigned _STL_mutex_spin<__inst>::__last = 0;
 
+// GCC extension begin
+#if defined(__STL_GTHREADS)
+#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)
+extern __gthread_mutex_t _GLIBCPP_mutex;
+extern __gthread_mutex_t *_GLIBCPP_mutex_address;
+extern __gthread_once_t _GLIBCPP_once;
+extern void _GLIBCPP_mutex_init (void);
+extern void _GLIBCPP_mutex_address_init (void);
+#endif
+#endif
+// GCC extension end
+
 struct _STL_mutex_lock
 {
 // GCC extension begin
 #if defined(__STL_GTHREADS)
+  // The class must be statically initialized with __STL_MUTEX_INITIALIZER.
+#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)
+  int _M_init_flag;
+  __gthread_once_t _M_once;
+#endif
   __gthread_mutex_t _M_lock;
-  void _M_initialize()
-  {
+  void _M_initialize() {
 #ifdef __GTHREAD_MUTEX_INIT
-  // There should be no code in this path given the usage rules above.
+    // There should be no code in this path given the usage rules above.
 #elif defined(__GTHREAD_MUTEX_INIT_FUNCTION)
-    __GTHREAD_MUTEX_INIT_FUNCTION (&_M_lock);
+    if (_M_init_flag) return;
+    if (__gthread_once (&_GLIBCPP_once, _GLIBCPP_mutex_init) != 0
+        && __gthread_active_p ())
+      abort ();
+    __gthread_mutex_lock (&_GLIBCPP_mutex);
+    if (!_M_init_flag) {
+	// Even though we have a global lock, we use __gthread_once to be
+	// absolutely certain the _M_lock mutex is only initialized once on
+	// multiprocessor systems.
+	_GLIBCPP_mutex_address = &_M_lock;
+	if (__gthread_once (&_M_once, _GLIBCPP_mutex_address_init) != 0
+	    && __gthread_active_p ())
+	  abort ();
+	_M_init_flag = 1;
+    }
+    __gthread_mutex_unlock (&_GLIBCPP_mutex);
 #endif
   }
-  void _M_acquire_lock() { __gthread_mutex_lock(&_M_lock); }
-  void _M_release_lock() { __gthread_mutex_unlock(&_M_lock); }
+  void _M_acquire_lock() {
+#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)
+    if (!_M_init_flag) _M_initialize();
+#endif
+    __gthread_mutex_lock(&_M_lock);
+  }
+  void _M_release_lock() {
+#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)
+    if (!_M_init_flag) _M_initialize();
+#endif
+    __gthread_mutex_unlock(&_M_lock);
+  }
 #else
 // GCC extension end
 #if defined(__STL_SGI_THREADS) || defined(__STL_WIN32THREADS)
@@ -415,8 +456,8 @@
 #if defined(__STL_GTHREADS)
 #ifdef __GTHREAD_MUTEX_INIT
 #define __STL_MUTEX_INITIALIZER = { __GTHREAD_MUTEX_INIT }
-#else
-#define __STL_MUTEX_INITIALIZER
+#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION)
+#define __STL_MUTEX_INITIALIZER = { 0, __GTHREAD_ONCE_INIT }
 #endif
 #else
 // GCC extension end


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]