Module Name: src Committed By: pooka Date: Sun Oct 4 17:40:34 UTC 2009
Modified Files: src/sys/rump/librump/rumpkern: ltsleep.c Log Message: Fix hopefully the last deadlock in the wretched piece of code: since ltsleep abuses "while (!mutex_tryenter()) continue;" for NOT releasing the kernel biglock before sleeping, we cannot do a normal mutex_enter() in the wakeup path, or otherwise we might be a situation where the sleeper holds the kernel lock and wants the sleepermutex (and will not back down) and the wakeupper holds the sleepermutex and wants the kernel lock. So introduce kernel lock backdown to the wakeup path. To generate a diff of this commit: cvs rdiff -u -r1.17 -r1.18 src/sys/rump/librump/rumpkern/ltsleep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/rump/librump/rumpkern/ltsleep.c diff -u src/sys/rump/librump/rumpkern/ltsleep.c:1.17 src/sys/rump/librump/rumpkern/ltsleep.c:1.18 --- src/sys/rump/librump/rumpkern/ltsleep.c:1.17 Fri Sep 4 16:42:19 2009 +++ src/sys/rump/librump/rumpkern/ltsleep.c Sun Oct 4 17:40:34 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: ltsleep.c,v 1.17 2009/09/04 16:42:19 pooka Exp $ */ +/* $NetBSD: ltsleep.c,v 1.18 2009/10/04 17:40:34 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -29,7 +29,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ltsleep.c,v 1.17 2009/09/04 16:42:19 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ltsleep.c,v 1.18 2009/10/04 17:40:34 pooka Exp $"); #include <sys/param.h> #include <sys/proc.h> @@ -116,33 +116,37 @@ return 0; } -void -wakeup(wchan_t ident) +static void +do_wakeup(wchan_t ident, void (*wakeupfn)(kcondvar_t *)) { struct ltsleeper *ltsp; + int nlocks; - mutex_enter(&sleepermtx); + while (!mutex_tryenter(&sleepermtx)) { + KERNEL_UNLOCK_ALL(curlwp, &nlocks); + yield(); + KERNEL_LOCK(nlocks, curlwp); + } LIST_FOREACH(ltsp, &sleepers, entries) { if (ltsp->id == ident) { - cv_broadcast(<sp->cv); + wakeupfn(<sp->cv); } } mutex_exit(&sleepermtx); } void +wakeup(wchan_t ident) +{ + + do_wakeup(ident, cv_broadcast); +} + +void wakeup_one(wchan_t ident) { - struct ltsleeper *ltsp; - mutex_enter(&sleepermtx); - LIST_FOREACH(ltsp, &sleepers, entries) { - if (ltsp->id == ident) { - cv_signal(<sp->cv); - break; - } - } - mutex_exit(&sleepermtx); + do_wakeup(ident, cv_signal); } void