When a timeshared LWP blocks on a turnstile, elevate its priority into the

PRI_KTHREAD range. This is kind of ugly, but needed because of direct handoff
with rwlocks, and because threads that block holding a mutex regularly hold
other locks/resources.

Problem addressed: priority lending works well where a thread blocking on a
turnstile has a high priority level (eg realtime). For timeshared threads
(low priority) it's unlikely to have much effect. In the latter case threads
awoken from a turnstile can and do compete for CPU time with regular waits
like disk I/O. On MP systems this can result in a feedback loop where
threads cannot quickly get access to a resource held by a thread waking from
a turnstile. The waking thread eventually runs when enough of the other
threads block waiting for it, freeing up the CPU. The end result is a lot of
idle time during builds.
This commit is contained in:
ad 2008-04-04 19:16:24 +00:00
parent 6238528d0f
commit f07d372316

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_turnstile.c,v 1.16 2008/03/17 16:54:51 ad Exp $ */
/* $NetBSD: kern_turnstile.c,v 1.17 2008/04/04 19:16:24 ad Exp $ */
/*-
* Copyright (c) 2002, 2006, 2007 The NetBSD Foundation, Inc.
@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_turnstile.c,v 1.16 2008/03/17 16:54:51 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_turnstile.c,v 1.17 2008/04/04 19:16:24 ad Exp $");
#include <sys/param.h>
#include <sys/lockdebug.h>
@ -217,7 +217,7 @@ turnstile_block(turnstile_t *ts, int q, wchan_t obj, syncobj_t *sobj)
turnstile_t *ots;
tschain_t *tc;
sleepq_t *sq;
pri_t prio;
pri_t prio, obase;
tc = &turnstile_tab[TS_HASH(obj)];
l = cur = curlwp;
@ -261,6 +261,9 @@ turnstile_block(turnstile_t *ts, int q, wchan_t obj, syncobj_t *sobj)
sleepq_enter(sq, l);
LOCKDEBUG_BARRIER(&tc->tc_mutex, 1);
l->l_kpriority = true;
obase = l->l_kpribase;
if (obase < PRI_KTHREAD)
l->l_kpribase = PRI_KTHREAD;
sleepq_enqueue(sq, obj, "tstile", sobj);
/*
@ -322,6 +325,7 @@ turnstile_block(turnstile_t *ts, int q, wchan_t obj, syncobj_t *sobj)
LOCKDEBUG_BARRIER(cur->l_mutex, 1);
sleepq_block(0, false);
cur->l_kpribase = obase;
}
/*