This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Fwd: local equivalent for pthread_once() in glibc?
- From: Adhemerval Zanella <adhemerval dot zanella at linaro dot org>
- To: libc-alpha at sourceware dot org
- Date: Tue, 25 Apr 2017 19:55:15 -0300
- Subject: Re: Fwd: local equivalent for pthread_once() in glibc?
- Authentication-results: sourceware.org; auth=none
- References: <9EBFE06E-AF1D-48E9-85AB-B74C048438B1@oracle.com> <F050C948-50BF-4305-84AC-9003F97D9F59@oracle.com>
On 25/04/2017 18:19, Chris Aoki wrote:
> One of my colleagues suggested that I forward the question
> below to the libc-alpha alias which would increase my chances
> of reaching a glibc malloc expert. Actually my main question
> (in the original message, below) is a general one, since situations
> calling for pthread_once() can presumably occur in other contexts.
>
> Chris Aoki
>
> p.s. The secondary question, which is specific to glibc malloc, is
> whether ptmalloc_init() can be called concurrently by multiple threads.
It shouldn't, that's why it has the '__malloc_initialized' variable to control
its initialization. Although, current code without any atomic do not guarantee
very strong semantics (I think it should use something similar to pthread_once
which is indeed __libc_once, see below).
>
>> Begin forwarded message:
>>
>> From: Chris Aoki <christopher.aoki@oracle.com>
>> Subject: local equivalent for pthread_once() in glibc?
>> Date: April 25, 2017 at 10:50:41 AM PDT
>> To: libc-help@sourceware.org
>> Cc: Chris Aoki <christopher.aoki@oracle.com>
>>
>> I have a question about glibc internals.
>>
>> Is there a private glibc function equivalent to pthread_once()?
>>
>> I have a structure that is frequently accessed after initialization
>> so putting a lock around initialization and a check for initialization
>> would add considerable overhead. Normally one would use pthread_once()
>> in this situation, but my colleagues tell me that adding a reference to an
>> external function is prohibited within libc.so. I see a macro __libc_once()
>> but it does not appear to synchronize:
>>
>> /* Define once control variable. */
>> #define __libc_once_define(CLASS, NAME) CLASS int NAME = 0
>>
>> /* Call handler iff the first call. */
>> #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
>> do { \
>> if ((ONCE_CONTROL) == 0) { \
>> INIT_FUNCTION (); \
>> (ONCE_CONTROL) = 1; \
>> } \
>> } while (0)
>>
>> Any clues appreciated. Thanks
>>
>> Chris Aoki
>
This is the default implementation which won't be used on nptl target (basically
all current supported). It will use the sysdeps/nptl/libc-lockP.h in fact:
250 /* Call handler iff the first call. */
251 #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
252 do { \
253 if (PTFAVAIL (__pthread_once)) \
254 __libc_ptf_call_always (__pthread_once, (&(ONCE_CONTROL), \
255 INIT_FUNCTION)); \
256 else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \
257 INIT_FUNCTION (); \
258 (ONCE_CONTROL) |= 2; \
259 } \
260 } while (0)
Which will call pthread_once for multithread programs (since PTFAVAIL will
returns true).