diff options
author | jhb <jhb@FreeBSD.org> | 2006-04-18 18:16:54 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2006-04-18 18:16:54 +0000 |
commit | 084bf8cc1a1db3b468061eca4b9314c8f9fc51d9 (patch) | |
tree | cb35182cca016c423a9b5a388ad7c4d74609051c /sys/kern/subr_turnstile.c | |
parent | cb88fa831f0e20f951e328ed4ddceba21a12f329 (diff) | |
download | FreeBSD-src-084bf8cc1a1db3b468061eca4b9314c8f9fc51d9.zip FreeBSD-src-084bf8cc1a1db3b468061eca4b9314c8f9fc51d9.tar.gz |
- Bring back turnstile_empty() which can check to see if an individual
queue on a turnstile is empty.
- Add a turnstile_disown() function that allows a thread to give up
ownership of a turnstile w/o waking up any waiters.
Diffstat (limited to 'sys/kern/subr_turnstile.c')
-rw-r--r-- | sys/kern/subr_turnstile.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/sys/kern/subr_turnstile.c b/sys/kern/subr_turnstile.c index 0185d4a..dd91b08 100644 --- a/sys/kern/subr_turnstile.c +++ b/sys/kern/subr_turnstile.c @@ -879,6 +879,56 @@ turnstile_unpend(struct turnstile *ts, int owner_type) } /* + * Give up ownership of a turnstile. This must be called with the + * turnstile chain locked. + */ +void +turnstile_disown(struct turnstile *ts) +{ + struct turnstile_chain *tc; + struct thread *td; + u_char cp, pri; + + MPASS(ts != NULL); + MPASS(ts->ts_owner == curthread); + tc = TC_LOOKUP(ts->ts_lockobj); + mtx_assert(&tc->tc_lock, MA_OWNED); + MPASS(TAILQ_EMPTY(&ts->ts_pending)); + MPASS(!TAILQ_EMPTY(&ts->ts_blocked[TS_EXCLUSIVE_QUEUE]) || + !TAILQ_EMPTY(&ts->ts_blocked[TS_SHARED_QUEUE])); + + /* + * Remove the turnstile from this thread's list of contested locks + * since this thread doesn't own it anymore. New threads will + * not be blocking on the turnstile until it is claimed by a new + * owner. + */ + mtx_lock_spin(&td_contested_lock); + ts->ts_owner = NULL; + LIST_REMOVE(ts, ts_link); + mtx_unlock_spin(&td_contested_lock); + mtx_unlock_spin(&tc->tc_lock); + + /* + * Adjust the priority of curthread based on other contested + * locks it owns. Don't lower the priority below the base + * priority however. + */ + td = curthread; + pri = PRI_MAX; + mtx_lock_spin(&sched_lock); + mtx_lock_spin(&td_contested_lock); + LIST_FOREACH(ts, &td->td_contested, ts_link) { + cp = turnstile_first_waiter(ts)->td_priority; + if (cp < pri) + pri = cp; + } + mtx_unlock_spin(&td_contested_lock); + sched_unlend_prio(td, pri); + mtx_unlock_spin(&sched_lock); +} + +/* * Return the first thread in a turnstile. */ struct thread * @@ -895,6 +945,23 @@ turnstile_head(struct turnstile *ts, int queue) return (TAILQ_FIRST(&ts->ts_blocked[queue])); } +/* + * Returns true if a sub-queue of a turnstile is empty. + */ +int +turnstile_empty(struct turnstile *ts, int queue) +{ +#ifdef INVARIANTS + struct turnstile_chain *tc; + + MPASS(ts != NULL); + MPASS(queue == TS_SHARED_QUEUE || queue == TS_EXCLUSIVE_QUEUE); + tc = TC_LOOKUP(ts->ts_lockobj); + mtx_assert(&tc->tc_lock, MA_OWNED); +#endif + return (TAILQ_EMPTY(&ts->ts_blocked[queue])); +} + #ifdef DDB static void print_thread(struct thread *td, const char *prefix) |