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>