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]

PATCH: Provide runtime intialization of _STL_mutex_lock class


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


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