Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 12 Apr 2014 13:48:59 +0200
From:      =?iso-8859-2?Q?Edward_Tomasz_Napiera=B3a?= <trasz@freebsd.org>
To:        John Baldwin <jhb@freebsd.org>
Cc:        freebsd-hackers@freebsd.org, hackers@freebsd.org
Subject:   Re: Multiple locks and missing wakeup.
Message-ID:  <418DC7A6-443C-4494-AFDB-1358F63564DE@freebsd.org>
In-Reply-To: <201404081412.10066.jhb@freebsd.org>
References:  <0D69A6A8-43D1-41FB-8C2D-00F5CAD9C86E@FreeBSD.org> <201404081001.31219.jhb@freebsd.org> <F18FB5F4-52AE-4787-AF6B-D0111CFFA844@freebsd.org> <201404081412.10066.jhb@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Wiadomo=B6=E6 napisana przez John Baldwin w dniu 8 kwi 2014, o godz. =
20:12:
> On Tuesday, April 08, 2014 12:45:49 pm Edward Tomasz Napiera=B3a =
wrote:
>> Wiadomo=B6=E6 napisana przez John Baldwin w dniu 8 kwi 2014, o godz. =
16:01:
>>=20
>>> On Tuesday, April 08, 2014 2:34:30 am Edward Tomasz Napiera=B3a =
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
>>> All our sleep primitives in the kernel only accept a single wait =
channel.
>>> It sounds like you want something more like select() or poll() where =
you
>>> can specify multiple wait channels.  There isn't a good way to do =
that
>>> currently.  You could write one, but it would be a bit hard to do
>>> correctly.
>>=20
>> Perhaps I should have been more clear: I'm ok with a single wait
>> channel.  The problem is that there is no way to pass more than one
>> mutex to the sleep() function, so we can miss wakeup for the list
>> protected by the second lock, if something gets enqueued between
>> releasing mtx2 and calling sleep().
>>=20
>>> In practice you'd end up implementing something that boiled
>>> down to having a single wait channel with a common lock that =
protected
>>> it so you could do something like:
>>=20
>> The whole purpose of this is to avoid locking mtx1 in the the enqueue
>> routine for the second list, for contention reasons.
>=20
> Ah, but note that I didn't lock mtx1 in the enqueue routine, I marked
> the 'combo_mtx' which is only used for the sleep/wakeup.

Ah, now I get it.  Nifty!




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?418DC7A6-443C-4494-AFDB-1358F63564DE>