This is the mail archive of the glibc-linux@ricardo.ecn.wfu.edu mailing list for the glibc project.


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

Re: pthread_once() problem?


>>>>> "Kaz" == Kaz Kylheku <kaz@ashi.footprints.net> writes:

Kaz> On Tue, 2 Nov 1999, Joerg Faschingbauer wrote:

>> Hi,
>> 
>> last week I posted a note to comp.programming.threads. I quote the
>> note below. It entailed an interesting thread (well, a news-thread
>> :-), IMO.

Kaz> It's too bad I don't read that these days. Finding a news server
Kaz> has gotten problematic. ;)

>> I believe the LinuxThreads pthread_once() implementation has a similar
>> problem. I.e., the test without holding the lock, in the first line of
>> the body. The memory init_routine() wrote (whatever that is) is the
>> equivalent of the Singleton instance in the quoted note.

Kaz> This problem has been discussed in comp.programming.threads in the past.  The
Kaz> concensus is that it's basically safe on mainstream architectures.

Kaz> You don't have to worry about it because it is buried in the implementation of
Kaz> a system library, which is by definition platform specific. If it ever doesn't
Kaz> work on a particular target, the library maintainers will have to patch
Kaz> in a code variant to support that platform and you can happily continue to
Kaz> use pthread_once.

I didn't expect the maintainers to be supernatural.

>> Opinions?
>> 
>> int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void))
>> {
>> /* Test without locking first for speed */
>> if (*once_control == DONE) return 0;

Kaz> Note that if access to the *once control is not atomic, this technique still works.
Kaz> The *once_control variable is only ever written to once and starts with the
Kaz> value zero. Until the write completes, it's not possible for it to have 
Kaz> any other value, and once it has a value other than zero, the init routine
Kaz> has been called.  If the value is inspected  after the init routine is done,
Kaz> but before *once_control is written to, then it will come up with the value
Kaz> zero, and the lock will be acquired. 

Kaz> What about multiprocessor platforms which reorder reads and writes, and hence
Kaz> require memory barriers? The risk in such an environment would be that the
Kaz> shared data initialized by the init_routine() is not yet stable when the
Kaz> *once_control variable indicates DONE. However, note that there is a
Kaz> pthread_mutex_lock() operation between the call to init_routine() and
Kaz> the assignment to *once_control. This pthread_mutex_lock() would introduce
Kaz> the requisite memory barrier, ensuring that the initialized data is stable
Kaz> before the *once_control modification appears on any other processor.

Ok. Got it. Should have looked in more detail.

Thanks for pointing this out,
Joerg

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