http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52839

--- Comment #12 from Alan Modra <amodra at gmail dot com> 2012-04-04 22:27:43 
UTC ---
glibc/ntpl/pthread_once.c:

static int once_lock = LLL_LOCK_INITIALIZER;

int
__pthread_once (once_control, init_routine)
     pthread_once_t *once_control;
     void (*init_routine) (void);
{
  /* XXX Depending on whether the LOCK_IN_ONCE_T is defined use a
     global lock variable or one which is part of the pthread_once_t
     object.  */
  if (*once_control == PTHREAD_ONCE_INIT)
    {
      lll_lock (once_lock, LLL_PRIVATE);

      /* XXX This implementation is not complete.  It doesn't take
     cancelation and fork into account.  */
      if (*once_control == PTHREAD_ONCE_INIT)
    {
      init_routine ();

      *once_control = !PTHREAD_ONCE_INIT;
    }

      lll_unlock (once_lock, LLL_PRIVATE);
    }

  return 0;
}
strong_alias (__pthread_once, pthread_once)

This is quite broken for weakly ordered memory model.  Notice how a thread that
sees *once_control != PTHREAD_ONCE_INIT has no barriers at all.  That means the
read of *once_control has no ordering with respect to what happened on the
thread that ran init_routine.

Reply via email to