globals.cc: Define globals _GLIBCPP_mutex_init ()...
authorJohn David Anglin <dave@hiauly1.hia.nrc.ca>
Thu, 14 Jun 2001 06:06:48 +0000 (06:06 +0000)
committerLoren J. Rittle <ljrittle@gcc.gnu.org>
Thu, 14 Jun 2001 06:06:48 +0000 (06:06 +0000)
* 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.
(__STL_MUTEX_INITIALIZER): Provide initializer for _STL_mutex_lock
for __GTHREAD_MUTEX_INIT_FUNCTION case.

From-SVN: r43360

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/stl_threads.h
libstdc++-v3/src/globals.cc

index 63eeb61..2cf5c70 100644 (file)
@@ -1,3 +1,16 @@
+2001-06-13  John David Anglin  <dave@hiauly1.hia.nrc.ca>
+
+       (Approved by Mark and Benjamin.  Applied by Loren.)
+
+       * 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.
+       (__STL_MUTEX_INITIALIZER): Provide initializer for _STL_mutex_lock
+       for __GTHREAD_MUTEX_INIT_FUNCTION case.
+
 2001-06-13  Gabriel Dos Reis  <gdr@merlin.codesourcery.com>
 
        * testsuite/26_numerics/slice_array_assignment.cc (main): New test.
index 21f4722..cdbf205 100644 (file)
@@ -296,21 +296,62 @@ unsigned _STL_mutex_spin<__inst>::__max = _STL_mutex_spin<__inst>::__low_max;
 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)
+  volatile 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,13 @@ struct _STL_mutex_lock
 #if defined(__STL_GTHREADS)
 #ifdef __GTHREAD_MUTEX_INIT
 #define __STL_MUTEX_INITIALIZER = { __GTHREAD_MUTEX_INIT }
+#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION)
+#ifdef __GTHREAD_MUTEX_INIT_DEFAULT
+#define __STL_MUTEX_INITIALIZER \
+  = { 0, __GTHREAD_ONCE_INIT, __GTHREAD_MUTEX_INIT_DEFAULT }
 #else
-#define __STL_MUTEX_INITIALIZER
+#define __STL_MUTEX_INITIALIZER = { 0, __GTHREAD_ONCE_INIT }
+#endif
 #endif
 #else
 // GCC extension end
index 11930b0..d70cc29 100644 (file)
@@ -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 +75,31 @@ namespace std
   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
 }