diff options
author | jhb <jhb@FreeBSD.org> | 2004-10-05 18:00:30 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2004-10-05 18:00:30 +0000 |
commit | 9536269a6d161e34a72dee84f6df6b4183f51be8 (patch) | |
tree | 432f43d015d8e33b5d7fa4f6e56f07fc1131e424 | |
parent | c3db025caa5e3c37bdfa5f330ce34e1a58014ed6 (diff) | |
download | FreeBSD-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)
-rw-r--r-- | sys/kern/subr_turnstile.c | 2 |
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); } |