This is the mail archive of the
libc-help@sourceware.org
mailing list for the glibc project.
Re: pthread_once on ARM SMP
- From: "Carlos O'Donell" <carlos at systemhalted dot org>
- To: Jan Klötzke <jan at kloetzke dot net>
- Cc: "libc-help at sourceware dot org" <libc-help at sourceware dot org>
- Date: Mon, 14 Oct 2013 21:31:09 -0400
- Subject: Re: pthread_once on ARM SMP
- Authentication-results: sourceware.org; auth=none
- References: <201310112059 dot 01618 dot jan at kloetzke dot net>
On Fri, Oct 11, 2013 at 2:59 PM, Jan Klötzke <jan@kloetzke.net> wrote:
> Hi,
>
> While debugging something else I stumbled across the pthread_once
> implementation of glibc. Looking at it I have the feeling that it is actually
> not 100% safe on SMP. Quoting the relevant fast path code from
> ports/sysdeps/unix/sysv/linux/arm/nptl/pthread_once.c:
>
> int
> __pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
> {
> for (;;)
> {
> int oldval;
> int newval;
> [...]
> do
> {
> newval = __fork_generation | 1;
> oldval = *once_control;
> if (oldval & 2)
> break;
> } while (atomic_compare_and_exchange_val_acq (once_control, newval,
> oldval) != oldval);
>
> /* Check if the initializer has already been done. */
> if ((oldval & 2) != 0)
> return 0;
> [...]
> }
> [...]
> init_routine ();
> pthread_cleanup_pop (0);
> *once_control = __fork_generation | 2;
> [...]
> }
>
> In the fast path ((oldval & 2) != 0) I don't actually see a memory barrier
> which would prevent the processor from reordering reads. In particular the CPU
> might reorder reads that should happen after the once_control check.
Why does it need one?
Where would the reads rorder to which would be wrong?
The atomic operation should be a sufficient barrier.
Remember that ARM does not have a weakly ordered memory
model like Power, where it really is important to get all the
barriers in the right places.
See the Power implementation for a "always correct" implementation.
Either way Torvald Riegel is rewriting all of the pthread_once implementations
and unifying them:
https://sourceware.org/ml/libc-alpha/2013-10/msg00257.html
https://sourceware.org/ml/libc-alpha/2013-10/msg00416.html
https://sourceware.org/ml/libc-alpha/2013-10/msg00415.html
> Likewise, shouldn't the assignment of once_control at the end involve some
> kind of barrier too? Otherwise the once_control assignment might be observable
> on another CPU before the side effects of init_routine(), right? Do I overlook
> something fundamentally here?
No, it's just that on a non-weakly-ordered system it doesn't really matter much.
We're going to fix this though and it will help ARM.
Cheers,
Carlos.