From 91bfd02daeabbe18216560b47d54919c98bcce36 Mon Sep 17 00:00:00 2001 From: John David Anglin Date: Thu, 14 Jun 2001 06:06:48 +0000 Subject: [PATCH] globals.cc: Define globals _GLIBCPP_mutex_init ()... * 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 | 13 ++++++ libstdc++-v3/include/bits/stl_threads.h | 60 ++++++++++++++++++++++--- libstdc++-v3/src/globals.cc | 29 ++++++++++++ 3 files changed, 95 insertions(+), 7 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 63eeb61109e..2cf5c7015b4 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2001-06-13 John David Anglin + + (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 * testsuite/26_numerics/slice_array_assignment.cc (main): New test. diff --git a/libstdc++-v3/include/bits/stl_threads.h b/libstdc++-v3/include/bits/stl_threads.h index 21f47225320..cdbf205df37 100644 --- a/libstdc++-v3/include/bits/stl_threads.h +++ b/libstdc++-v3/include/bits/stl_threads.h @@ -296,21 +296,62 @@ unsigned _STL_mutex_spin<__inst>::__max = _STL_mutex_spin<__inst>::__low_max; template 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 diff --git a/libstdc++-v3/src/globals.cc b/libstdc++-v3/src/globals.cc index 11930b00834..d70cc295407 100644 --- a/libstdc++-v3/src/globals.cc +++ b/libstdc++-v3/src/globals.cc @@ -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 #include #include @@ -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 } -- 2.30.2