[OpenAFS-devel] pthreads, darwin, microsoft: untwisting the knot

Kyle Moffett mrmacman_g4@mac.com
Thu, 26 May 2005 23:31:51 -0400


On May 26, 2005, at 23:04:05, Marcus Watts wrote:
> The fix: modify pthread_mutex_t to have a new field, "IsInitialized".
> [ It might be wise to include padding to some round boundary as  
> well to
> make library versioning a bit simplier. ]  Declare  
> PTHREAD_MUTEX_INITIALIZER
> to put a 0 into this field.  Modify
>     pthread_mutex_init
>     pthread_mutex_trylock
>     pthread_mutex_lock
>     pthread_mutex_unlock
>     pthread_mutex_destroy
> to check this.  Generally speaking, if it's not set, acquire a private
> mutex, and if it's still not set, call InitializeCriticalSection for
> the mutex.

Hmm, depending on the CPU's instruction reordering and data  
dependency handling,
this could actually be kinda racy.  Some compilers might (legitimately)
optimize the code to something like this (Except in real assembly :-D):

/* Check if it's initialized */
     load   r8, IsInitialized
     test   r8
     bnz    AlreadyInitialized

/* Lock a global mutex */
     load   r0, GlobalLockPtr
     call   mutex_lock

/* Recheck, except in a racy fashion */
     test   r8
     bnz    AlreadyInitializedUnlock

/* Initialize */
     load   r0, NewLockPtr
     call   mutex_init

/* Mark as initialized */
     store  #1, [r0]4

/* Unlock */
AlreadyInitializedUnlock:
     load   r0, GlobalLockPtr
     call   mutex_unlock

/* Lock the real mutex */
AlreadyInitialized:
     load   r0, NewLockPtr
     call   mutex_lock

Basically, I think the general rule of thumb is that you should not  
check any
variable (non-atomic OR atomic), in a non-atomic way (IE: outside the  
lock
that protects it).  The mutex operations provide data ordering  
guarantees,
such that read and write operations will not be moved across the  
barrier, but
they do not necessarily provide cache-flush guarantees for all data,  
because
that would be a severe performance penalty (They naturally provide  
them for
the lock itself, but that's a different concept entirely).


Cheers,
Kyle Moffett

-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCM/CS/IT/U d- s++: a18 C++++>$ UB/L/X/*++++(+)>$ P+++(++++)>$
L++++(+++) E W++(+) N+++(++) o? K? w--- O? M++ V? PS+() PE+(-) Y+
PGP+++ t+(+++) 5 X R? tv-(--) b++++(++) DI+ D+ G e->++++$ h!*()>++$  
r  !y?(-)
------END GEEK CODE BLOCK------