This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
PATCH: Provide runtime intialization of _STL_mutex_lock class
- To: rittle at labs dot mot dot com
- Subject: PATCH: Provide runtime intialization of _STL_mutex_lock class
- From: "John David Anglin" <dave at hiauly1 dot hia dot nrc dot ca>
- Date: Sat, 9 Jun 2001 23:54:05 -0400 (EDT)
- Cc: gcc-patches at gcc dot gnu dot org, libstdc++ at gcc dot gnu dot org
Lorne,
I have tweaked the patch to initialize the _STL_mutex_lock class mutex
at runtime. There is now a single global mutex to ensure that the class
mutex is only initialized once. I would greatly appreciate your comments
and suggestions on improving the patch.
The advantage of having this patch installed is that _STL_mutex_lock
objects can be intialized with the _STL_MUTEX_INITIALIZER on systems
that require a function call for mutex initialization (eg., hpux 10.20).
As a result, they can be treated with exactly the same methodology as
they would on systems where the mutex can be initialized using an
aggregate initializer. _M_initialize no longer needs to called to
initialize the object. The STL allocator should now work correctly
for systems that define __GTHREAD_MUTEX_INIT_FUNCTION.
There is a separate patch to gthr-dce.h which is needed to define
__GTHREAD_MUTEX_INIT_FUNCTION and correct various other minor problems.
I will send it in a separate email.
I have tested this patch under hpux 10.20 with DCE threads and done
a v3 check with -static, -threads, -fPIC and "" with no regressions
of FAILs attributable to the patch. I also tried an abreviated test
using the STL memory leak program that you have posted. If anyone is
interested, I have a patch for gthr-posix.h that allows testing using
the __GTHREAD_MUTEX_INIT_FUNCTION mode on systems with posix threads.
This was tested on the 3.0 branch.
Dave
--
J. David Anglin dave.anglin@nrc.ca
National Research Council of Canada (613) 990-0752 (FAX: 952-6605)
2001-06-09 John David Anglin <dave@hiauly1.hia.nrc.ca>
* libsupc++/Makefile.am (sources): Add stl_globals.cc.
* libsupc++/stl_globals.cc: New file.
* include/bits/stl_threads.h (_STL_mutex_lock): Provide once-only
runtime initialization of _M_lock when __GTHREAD_MUTEX_INIT_FUNCTION
is defined.
--- libsupc++/Makefile.am.orig Wed Jun 6 14:12:55 2001
+++ libsupc++/Makefile.am Sat Jun 9 01:06:06 2001
@@ -90,6 +90,7 @@
new_opv.cc \
new_opvnt.cc \
pure.cc \
+ stl_globals.cc \
tinfo.cc \
tinfo2.cc \
vec.cc
--- /dev/null Sat Jun 9 12:59:51 2001
+++ libsupc++/stl_globals.cc Sat Jun 9 12:16:21 2001
@@ -0,0 +1,52 @@
+// -*- C++ -*- Global lock initialization for stl
+// Copyright (C) 2001 Free Software Foundation, Inc.
+//
+// This file is part of GNU CC.
+//
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING. If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// 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"
+
+using namespace std;
+
+// Globals for once-only runtime initialization of STL_mutex_lock objects.
+// This allows static initialization of these objects even on systems that
+// need a function call to initialize a mutex.
+#if __GTHREADS
+__gthread_once_t _STL_mutex_lock_init_once = __GTHREAD_ONCE_INIT;
+#ifdef __GTHREAD_MUTEX_INIT
+__gthread_mutex_t _STL_mutex_lock_init_mutex = __GTHREAD_MUTEX_INIT;
+#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION)
+__gthread_mutex_t _STL_mutex_lock_init_mutex = { 0 };
+
+void
+_STL_mutex_lock_init ()
+{
+ __GTHREAD_MUTEX_INIT_FUNCTION (&_STL_mutex_lock_init_mutex);
+}
+#endif
+#endif
--- include/bits/stl_threads.h.orig Fri Jun 8 18:44:50 2001
+++ include/bits/stl_threads.h Sat Jun 9 01:13:13 2001
@@ -296,21 +296,50 @@
template <int __inst>
unsigned _STL_mutex_spin<__inst>::__last = 0;
+// GCC extension begin
+#if defined(__STL_GTHREADS) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)
+extern __gthread_mutex_t _STL_mutex_lock_init_mutex;
+extern __gthread_once_t _STL_mutex_lock_init_once;
+extern void _STL_mutex_lock_init ();
+#endif
+// GCC extension end
+
struct _STL_mutex_lock
{
// GCC extension begin
#if defined(__STL_GTHREADS)
+#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
+ int _M_init_flag;
+#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.
#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION)
- __GTHREAD_MUTEX_INIT_FUNCTION (&_M_lock);
+ if (!_M_init_flag) return;
+ if (__gthread_once (&_STL_mutex_lock_init_once, _STL_mutex_lock_init) != 0
+ && __gthread_active_p ())
+ abort ();
+ __gthread_mutex_lock (&_STL_mutex_lock_init_mutex);
+ if (_M_init_flag) {
+ __GTHREAD_MUTEX_INIT_FUNCTION (&_M_lock);
+ _M_init_flag = 0;
+ }
+ __gthread_mutex_unlock (&_STL_mutex_lock_init_mutex);
+#endif
+ }
+ void _M_acquire_lock() {
+#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
+ if (_M_init_flag) _M_initialize();
#endif
+ __gthread_mutex_lock(&_M_lock);
+ }
+ void _M_release_lock() {
+#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
+ if (_M_init_flag) _M_initialize();
+#endif
+ __gthread_mutex_unlock(&_M_lock);
}
- void _M_acquire_lock() { __gthread_mutex_lock(&_M_lock); }
- void _M_release_lock() { __gthread_mutex_unlock(&_M_lock); }
#else
// GCC extension end
#if defined(__STL_SGI_THREADS) || defined(__STL_WIN32THREADS)
@@ -415,8 +444,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 = { 1 }
#endif
#else
// GCC extension end