summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_turnstile.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2006-04-18 18:16:54 +0000
committerjhb <jhb@FreeBSD.org>2006-04-18 18:16:54 +0000
commit084bf8cc1a1db3b468061eca4b9314c8f9fc51d9 (patch)
treecb35182cca016c423a9b5a388ad7c4d74609051c /sys/kern/subr_turnstile.c
parentcb88fa831f0e20f951e328ed4ddceba21a12f329 (diff)
downloadFreeBSD-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.c67
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)
OpenPOWER on IntegriCloud