Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 8 Apr 2014 18:38:19 +0200
From:      =?iso-8859-2?Q?Edward_Tomasz_Napiera=B3a?= <trasz@FreeBSD.org>
To:        Konstantin Belousov <kostikbel@gmail.com>
Cc:        hackers@freebsd.org
Subject:   Re: Multiple locks and missing wakeup.
Message-ID:  <E9777F0E-DC5B-43B1-B741-AF1804FBE335@FreeBSD.org>
In-Reply-To: <20140408085156.GR21331@kib.kiev.ua>
References:  <0D69A6A8-43D1-41FB-8C2D-00F5CAD9C86E@FreeBSD.org> <20140408085156.GR21331@kib.kiev.ua>

next in thread | previous in thread | raw e-mail | index | archive | help
Wiadomo=B6=E6 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:
>>=20
>> mtx_lock(&mtx1);
>> for (;;) {
>> 	while (!LIST_EMPTY(&list1)) {
>> 		elt =3D LIST_FIRST(&list1);
>> 		do_stuff(elt);
>> 		LIST_REMOVE(&list1, elt);
>> 	}
>> 	sleep(&list1, &mtx1);
>> }
>> mtx_unlock(&mtx1);
>>=20
>> 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:
>>=20
>> mtx_lock(&mtx1);
>> for (;;) {
>> 	while (!LIST_EMPTY(&list1)) {
>> 		elt =3D 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 =3D LIST_FIRST(&list2);
>> 		do_other_stuff(elt);
>> 		LIST_REMOVE(&list2, elt);
>> 	}
>> 	mtx_unlock(&mtx2);
>>=20
>> 	sleep(&list1, &mtx1);
>> }
>> mtx_unlock(&mtx1);
>=20
> 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.




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E9777F0E-DC5B-43B1-B741-AF1804FBE335>