Module Name: src Committed By: bouyer Date: Sun Sep 13 14:38:20 UTC 2009
Modified Files: src/sys/kern: kern_turnstile.c Log Message: PR kern/41923: assertion "cur != owner" failed In the for(;;) loop of turnstile_block(), the lock owner can change while cur's lock is released (cur's lock is also the tschain_t's mutex). Remove the KASSERT about owner being invariant and try to deal with the fact that the owner can change instead. http://mail-index.netbsd.org/tech-kern/2009/08/24/msg005957.html and followups. To generate a diff of this commit: cvs rdiff -u -r1.24 -r1.25 src/sys/kern/kern_turnstile.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/kern/kern_turnstile.c diff -u src/sys/kern/kern_turnstile.c:1.24 src/sys/kern/kern_turnstile.c:1.25 --- src/sys/kern/kern_turnstile.c:1.24 Sat Mar 21 13:11:14 2009 +++ src/sys/kern/kern_turnstile.c Sun Sep 13 14:38:20 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_turnstile.c,v 1.24 2009/03/21 13:11:14 ad Exp $ */ +/* $NetBSD: kern_turnstile.c,v 1.25 2009/09/13 14:38:20 bouyer Exp $ */ /*- * Copyright (c) 2002, 2006, 2007, 2009 The NetBSD Foundation, Inc. @@ -60,7 +60,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_turnstile.c,v 1.24 2009/03/21 13:11:14 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_turnstile.c,v 1.25 2009/09/13 14:38:20 bouyer Exp $"); #include <sys/param.h> #include <sys/lockdebug.h> @@ -253,6 +253,7 @@ sq = &ts->ts_sleepq[q]; ts->ts_waiters[q]++; sleepq_enter(sq, l, tc->tc_mutex); + /* now tc->tc_mutex is also cur->l_mutex and l->l_mutex */ LOCKDEBUG_BARRIER(tc->tc_mutex, 1); l->l_kpriority = true; obase = l->l_kpribase; @@ -275,6 +276,7 @@ * compiling a kernel with LOCKDEBUG to pinpoint the problem. */ prio = lwp_eprio(l); + for (;;) { bool dolock; @@ -285,9 +287,24 @@ if (owner == NULL) break; - KASSERT(l != owner); - KASSERT(cur != owner); + /* The owner may have changed as we have dropped the tc lock */ + if (cur == owner) { + /* + * we own the lock: stop here, sleepq_block() + * should wake up immediatly + */ + break; + } + if (l == owner) { + /* owner has changed, restart from curlwp */ + lwp_unlock(l); + l = cur; + lwp_lock(l); + prio = lwp_eprio(l); + continue; + } + if (l->l_mutex != owner->l_mutex) dolock = true; else @@ -295,6 +312,10 @@ if (dolock && !lwp_trylock(owner)) { /* * restart from curlwp. + * Note that there may be a livelock here: + * the owner may try grabing cur's lock (which is + * the tc lock) while we're trying to grab + * the owner's lock. */ lwp_unlock(l); l = cur;