PATCH: Provide runtime intialization of _STL_mutex_lock class (revised)

John David Anglin dave@hiauly1.hia.nrc.ca
Tue Jun 12 17:47:00 GMT 2001


> I am happy with everything except adding a __gthread_once_t to a
> struct that might be an automatic (note that _STL_mutex_lock is used
> in _STL_auto_lock which is clearly intended for that use):

Unfortunately, the __gthread_once_t type in the struct can't be static
since as I understand it that makes it have "global" linkage.  There
would be only one __gthread_once_t for all the _STL_mutex_lock structures
and this clearly will not work.

With the current arrangement, the __gthread_once_t type lasts as long as
the lock mutex itself.  If _STL_mutex_lock is automatic and a thread
tries to use the lock or initialize the lock after the thread which
created it returns, then this is clearly a recipe for disaster.  Thus,
great care must be taken if the _STL_mutex_lock struct is to be automatic.
Essentially, the thread that created the automatic can't return until
all threads that use the struct complete.

I suspect the _STL_auto_lock code is broken.  I don't see how the
_STL_mutex_lock struct gets initialized but my knowledge of c++ is
rather limited.  If you look at what is done in stl_alloc.h, you
see that _S_node_allocator_lock is `static _STL_mutex_lock' and we
have explicit initialization using __STL_MUTEX_INITIALIZER:

#ifdef __STL_THREADS
    template <bool __threads, int __inst>
    _STL_mutex_lock
    __default_alloc_template<__threads, __inst>::_S_node_allocator_lock
	__STL_MUTEX_INITIALIZER;
#endif

The code in stl_alloc.h looks like a proper implementation to me.

> In pthread_once(3) on FreeBSD, I see this:
> 
>      The behavior of pthread_once() is undefined if once_control has automatic
>      storage duration or is not initialized by PTHREAD_ONCE_INIT.
> 
> _Programming with POSIX threads_ by David R. Butenhof has a similar
> warning on pg 132 regarding the fact that pthread_once_t must be
> statically initialized (in the C sense).

I think the main point of this warning is to ensure that the storage
lasts for the duration of threads that might use it.  Basically,
pthread_once creates a lock, checks the once control block, calls
the init routine if needed, updates the control block, and clears
the lock.  The control block can be anywhere as long as it is not
destroyed prematurely.

The first implementation doesn't have this problem although there is
possibility that cache issues could cause _M_lock to get initialized
twice in a multiprocessor implementation.  My impression is that we are
off in a bit of new territory here.  Until this is pounded by some real
thread intensive code, it's hard to know whether we have got it right
or not.  Remember, the systems that define __GTHREAD_MUTEX_INIT_FUNCTION
haven't had this kind of thread support before as far as I am aware of.

What's your call?

Dave
-- 
J. David Anglin                                  dave.anglin@nrc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6605)



More information about the Libstdc++ mailing list