Lockless uidinfo.

Maciej Sobczak prog at msobczak.com
Sat Aug 18 13:29:07 PDT 2007

Pawel Jakub Dawidek wrote:

> thread1 (uifind)		thread2 (uifree)
> ----------------		----------------
> 				refcount_release(&uip->ui_ref))
> 				/* ui_ref == 0 */
> mtx_lock(&uihashtbl_mtx);
> refcount_acquire(&uip->ui_ref);
> /* ui_ref == 1 */
> mtx_unlock(&uihashtbl_mtx);
> 				mtx_lock(&uihashtbl_mtx);
> 				if (uip->ui_ref > 0) {
> 					mtx_unlock(&uihashtbl_mtx);
> 					return;
> 				}
> Now, you suggest that ui_ref in 'if (uip->ui_ref > 0)' may still have
> cached 0? I don't think it is possible, first refcount_acquire() uses
> read memory bariers (but we may still need ui_ref to volatile for this
> to make any difference) and second, think of ui_ref as a field protected
> by uihashtbl_mtx mutex in this very case.
> Is my thinking correct?

Yes, but I believe you are too conservative even with the above explanation.

Unlocking (thread1) and subsequent locking (thread2) of the same mutex 
guarantees memory visibility between threads, at least if the mutex 
provides the fundamental release-acquire consistency. In this case, the 
memory barrier is part of this process itself and you don't need to do 
anything else to guarantee the visibility of ui_ref == 1 in thread2.

The only thing to worry about is caching of values in CPU registers 
(note that this issue is separate from visibility), but these should be 
prevented by the compiler at the point of mtx_lock. There are basically 
two ways to guarantee it: either the compiler is too stupid/conservative 
to cache the value across mtx_lock if it's a function call, or it is 
smart enough to know (or just see) that there is a membar inside. In any 
case no register-level caching will take place.

There should be no need to make anything volatile.

Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/

More information about the freebsd-arch mailing list