Add memory barriers to pthread_once.
The implementation was using a double-checked locking approach that could break on SMP. In addition to the barriers I also switched to a volatile pointer. I don't think this will matter unless gcc can conclude that _normal_lock can't affect *once_control, but I figured it was better to be safe. (It seems to have no impact whatsoever on the generated code.) Bug 3022795. Change-Id: Ib91da25d57ff5bee4288526e39d457153ef6aacd
This commit is contained in:
parent
8939c1e1cc
commit
b1c9cc2f2d
@ -1886,12 +1886,16 @@ int pthread_getcpuclockid(pthread_t tid, clockid_t *clockid)
|
|||||||
int pthread_once( pthread_once_t* once_control, void (*init_routine)(void) )
|
int pthread_once( pthread_once_t* once_control, void (*init_routine)(void) )
|
||||||
{
|
{
|
||||||
static pthread_mutex_t once_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
|
static pthread_mutex_t once_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
|
||||||
|
volatile pthread_once_t* ocptr = once_control;
|
||||||
|
|
||||||
if (*once_control == PTHREAD_ONCE_INIT) {
|
pthread_once_t tmp = *ocptr;
|
||||||
|
ANDROID_MEMBAR_FULL();
|
||||||
|
if (tmp == PTHREAD_ONCE_INIT) {
|
||||||
pthread_mutex_lock( &once_lock );
|
pthread_mutex_lock( &once_lock );
|
||||||
if (*once_control == PTHREAD_ONCE_INIT) {
|
if (*ocptr == PTHREAD_ONCE_INIT) {
|
||||||
(*init_routine)();
|
(*init_routine)();
|
||||||
*once_control = ~PTHREAD_ONCE_INIT;
|
ANDROID_MEMBAR_FULL();
|
||||||
|
*ocptr = ~PTHREAD_ONCE_INIT;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock( &once_lock );
|
pthread_mutex_unlock( &once_lock );
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user