Multiple locks and missing wakeup.

Konstantin Belousov kostikbel at gmail.com
Tue Apr 8 08:52:03 UTC 2014


On Tue, Apr 08, 2014 at 08:34:30AM +0200, Edward Tomasz Napiera?a wrote:
> Let's say I have a kernel thread processing elements from a queue,
> sleeping until there is work to do; something like this:
> 
> mtx_lock(&mtx1);
> for (;;) {
> 	while (!LIST_EMPTY(&list1)) {
> 		elt = LIST_FIRST(&list1);
> 		do_stuff(elt);
> 		LIST_REMOVE(&list1, elt);
> 	}
> 	sleep(&list1, &mtx1);
> }
> mtx_unlock(&mtx1);
> 
> Now, is there some way to make it work with two lists, protected
> by different mutexes?  The mutex part is crucial here; the whole
> point of this is to reduce lock contention on one of the lists.  The
> following code would result in a missing wakeup:
> 
> mtx_lock(&mtx1);
> for (;;) {
> 	while (!LIST_EMPTY(&list1)) {
> 		elt = LIST_FIRST(&list1);
> 		do_stuff(elt);
> 		LIST_REMOVE(&list1, elt);
> 	}
mtx_unlock(&mtx1);, right ?
> 
> 	mtx_lock(&mtx2);
> 	while (!LIST_EMPTY(&list2)) {
> 		elt = LIST_FIRST(&list2);
> 		do_other_stuff(elt);
> 		LIST_REMOVE(&list2, elt);
> 	}
> 	mtx_unlock(&mtx2);
> 
> 	sleep(&list1, &mtx1);
> }
> mtx_unlock(&mtx1);

You should clarify your intent.  Do you need to sleep waiting for the work
items to appear for list2 ?  What wakeup do you miss in the pseudo-code
you posted ?

If you do need the notification for the list2, use &list1 as the wakeup
channel for it.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 834 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20140408/9a8235ad/attachment.sig>


More information about the freebsd-hackers mailing list