summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_turnstile.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2004-10-05 18:00:30 +0000
committerjhb <jhb@FreeBSD.org>2004-10-05 18:00:30 +0000
commit9536269a6d161e34a72dee84f6df6b4183f51be8 (patch)
tree432f43d015d8e33b5d7fa4f6e56f07fc1131e424 /sys/kern/subr_turnstile.c
parentc3db025caa5e3c37bdfa5f330ce34e1a58014ed6 (diff)
downloadFreeBSD-src-9536269a6d161e34a72dee84f6df6b4183f51be8.zip
FreeBSD-src-9536269a6d161e34a72dee84f6df6b4183f51be8.tar.gz
Add a critical section in turnstile_unpend() from before dropping the
turnstile chain lock until after making all the awakened threads runnable. First, this fixes a priority inversion race. Second, this attempts to finish waking up all of the threads waiting on a turnstile before doing a preemption. Reviewed by: Stephan Uphoff (who found the priority inversion race)
Diffstat (limited to 'sys/kern/subr_turnstile.c')
-rw-r--r--sys/kern/subr_turnstile.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/sys/kern/subr_turnstile.c b/sys/kern/subr_turnstile.c
index 58f9c44..980a517 100644
--- a/sys/kern/subr_turnstile.c
+++ b/sys/kern/subr_turnstile.c
@@ -699,6 +699,7 @@ turnstile_unpend(struct turnstile *ts)
ts->ts_owner = NULL;
LIST_REMOVE(ts, ts_link);
mtx_unlock_spin(&td_contested_lock);
+ critical_enter();
mtx_unlock_spin(&tc->tc_lock);
/*
@@ -742,6 +743,7 @@ turnstile_unpend(struct turnstile *ts)
MPASS(TD_IS_RUNNING(td) || TD_ON_RUNQ(td));
}
}
+ critical_exit();
mtx_unlock_spin(&sched_lock);
}
OpenPOWER on IntegriCloud