Multiple locks and missing wakeup.
Edward Tomasz Napierała
trasz at FreeBSD.org
Tue Apr 8 16:38:24 UTC 2014
Wiadomość napisana przez Konstantin Belousov w dniu 8 kwi 2014, o godz. 10:51:
> 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 ?
Yes. Well, there is no exit condition in that loop, but anyway.
>> 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 ?
Yes, I need to sleep waiting for a new element on either of the lists. The
missing wakeup is in the second list - it's possible that the element will
be added (under mtx2 lock) and the wakeup called after the LIST_EMPTY(&list2)
returns true, but before calling sleep().
> If you do need the notification for the list2, use &list1 as the wakeup
> channel for it.
Sure, but it still doesn't fix the problem above.
More information about the freebsd-hackers
mailing list