Robust mutexes implementation

Konstantin Belousov kostikbel at gmail.com
Thu May 5 18:58:17 UTC 2016


On Thu, May 05, 2016 at 06:20:35PM +0100, Martin Simmons wrote:
> There is a potential bug in enqueue_mutex when it tests m1 == NULL and m1 !=
> NULL.  These tests only work because m_lock is the first slot in struct
> pthread_mutex and hence 0 in curthread->robust_list is converted to NULL
> (rather than a negative value).
Yes.  In fact I wrote the __containerof stuff only later, initial
version of the patch did relied on the fact that m_lock is at the
beginning of pthread_mutex.

I rewrote the code in enqueue, and there is one more similar check in
dequeue_mutex().

Updated patch is at https://kib.kiev.ua/kib/pshared/robust.2.patch .
It also fixed the lack of userland split for non-robust pp/robust pp queues.

> 
> Also, is it safe to assume memory ordering between the assignments of
> m->m_lock.m_rb_lnk and curthread->robust_list?  Maybe it is OK because the
> kernel will never read curthread->robust_list until after the CPU executing
> enqueue_mutex has passed a memory barrier?

Inter-CPU ordering (I suppose you mean this, because you mention
barriers) only matter when we consider multi-threaded interaction.
In case of dequeue_mutex, paired to corresponding enqueue_mutex(),
the calls occur in the same thread, and the thread is always
self-consistent.

WRT possible reordering, we in fact only care that enqueue writes do
not become visible before lock is obtained, and dequeue must finish
for external observers before lock is released.  This is ensured by
the umutex lock semantic, which has neccessary acquire barrier on
lock and release barrier on unlock.


More information about the freebsd-threads mailing list