Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/rump/librump/rumpkern Fix hopefully the last deadlock in...



details:   https://anonhg.NetBSD.org/src/rev/f1c081af07e0
branches:  trunk
changeset: 747882:f1c081af07e0
user:      pooka <pooka%NetBSD.org@localhost>
date:      Sun Oct 04 17:40:34 2009 +0000

description:
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.

diffstat:

 sys/rump/librump/rumpkern/ltsleep.c |  34 +++++++++++++++++++---------------
 1 files changed, 19 insertions(+), 15 deletions(-)

diffs (69 lines):

diff -r e83cf9b9b90f -r f1c081af07e0 sys/rump/librump/rumpkern/ltsleep.c
--- a/sys/rump/librump/rumpkern/ltsleep.c       Sun Oct 04 17:00:31 2009 +0000
+++ b/sys/rump/librump/rumpkern/ltsleep.c       Sun Oct 04 17:40:34 2009 +0000
@@ -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(&ltsp->cv);
+                       wakeupfn(&ltsp->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(&ltsp->cv);
-                       break;
-               }
-       }
-       mutex_exit(&sleepermtx);
+       do_wakeup(ident, cv_signal);
 }
 
 void



Home | Main Index | Thread Index | Old Index