comments and assertions.

no functional changes.
This commit is contained in:
yamt 2012-06-15 13:51:40 +00:00
parent 403de81b16
commit f562b34504

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_turnstile.c,v 1.31 2011/12/02 12:31:53 yamt Exp $ */ /* $NetBSD: kern_turnstile.c,v 1.32 2012/06/15 13:51:40 yamt Exp $ */
/*- /*-
* Copyright (c) 2002, 2006, 2007, 2009 The NetBSD Foundation, Inc. * Copyright (c) 2002, 2006, 2007, 2009 The NetBSD Foundation, Inc.
@ -60,7 +60,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_turnstile.c,v 1.31 2011/12/02 12:31:53 yamt Exp $"); __KERNEL_RCSID(0, "$NetBSD: kern_turnstile.c,v 1.32 2012/06/15 13:51:40 yamt Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/lockdebug.h> #include <sys/lockdebug.h>
@ -199,7 +199,9 @@ turnstile_exit(wchan_t obj)
* *
* Lend our priority to lwps on the blocking chain. * Lend our priority to lwps on the blocking chain.
* *
* * If the current owner of the lock (l->l_wchan, set by sleepq_enqueue)
* has a priority lower than ours (lwp_eprio(l)), lend our priority to
* him to avoid priority inversions.
*/ */
static void static void
@ -225,29 +227,37 @@ turnstile_lendpri(lwp_t *cur)
if (l->l_wchan == NULL) if (l->l_wchan == NULL)
break; break;
/*
* Ask syncobj the owner of the lock.
*/
owner = (*l->l_syncobj->sobj_owner)(l->l_wchan); owner = (*l->l_syncobj->sobj_owner)(l->l_wchan);
if (owner == NULL) if (owner == NULL)
break; break;
/* The owner may have changed as we have dropped the tc lock */ /*
* The owner may have changed as we have dropped the tc lock.
*/
if (cur == owner) { if (cur == owner) {
/* /*
* we own the lock: stop here, sleepq_block() * We own the lock: stop here, sleepq_block()
* should wake up immediatly * should wake up immediatly.
*/ */
break; break;
} }
if (l->l_mutex != owner->l_mutex) /*
dolock = true; * Acquire owner->l_mutex if we don't have it yet.
else * Because we already have another LWP lock (l->l_mutex) held,
dolock = false; * we need to play a try lock dance to avoid deadlock.
*/
dolock = l->l_mutex != owner->l_mutex;
if (l == owner || (dolock && !lwp_trylock(owner))) { if (l == owner || (dolock && !lwp_trylock(owner))) {
/* /*
* restart from curlwp. * The owner was changed behind us or trylock failed.
* Restart from curlwp.
*
* Note that there may be a livelock here: * Note that there may be a livelock here:
* the owner may try grabing cur's lock (which is * the owner may try grabing cur's lock (which is the
* the tc lock) while we're trying to grab * tc lock) while we're trying to grab the owner's lock.
* the owner's lock.
*/ */
lwp_unlock(l); lwp_unlock(l);
l = cur; l = cur;
@ -255,11 +265,20 @@ turnstile_lendpri(lwp_t *cur)
prio = lwp_eprio(l); prio = lwp_eprio(l);
continue; continue;
} }
/*
* If the owner's priority is already higher than ours,
* there's nothing to do anymore.
*/
if (prio <= lwp_eprio(owner)) { if (prio <= lwp_eprio(owner)) {
if (dolock) if (dolock)
lwp_unlock(owner); lwp_unlock(owner);
break; break;
} }
/*
* Lend our priority to the 'owner' LWP.
*
* Update lenders info for turnstile_unlendpri.
*/
ts = l->l_ts; ts = l->l_ts;
KASSERT(ts->ts_inheritor == owner || ts->ts_inheritor == NULL); KASSERT(ts->ts_inheritor == owner || ts->ts_inheritor == NULL);
if (ts->ts_inheritor == NULL) { if (ts->ts_inheritor == NULL) {
@ -273,6 +292,7 @@ turnstile_lendpri(lwp_t *cur)
} }
if (dolock) if (dolock)
lwp_unlock(l); lwp_unlock(l);
LOCKDEBUG_BARRIER(owner->l_mutex, 1);
l = owner; l = owner;
} }
LOCKDEBUG_BARRIER(l->l_mutex, 1); LOCKDEBUG_BARRIER(l->l_mutex, 1);