This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PATCH: Provide runtime intialization of _STL_mutex_lock class (revised)
- To: bkoz at redhat dot com (Benjamin Kosnik)
- Subject: Re: PATCH: Provide runtime intialization of _STL_mutex_lock class (revised)
- From: "John David Anglin" <dave at hiauly1 dot hia dot nrc dot ca>
- Date: Tue, 12 Jun 2001 15:14:38 -0400 (EDT)
- Cc: rittle at labs dot mot dot com, gcc-patches at gcc dot gnu dot org, libstdc++ at gcc dot gnu dot org
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