- 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.
This commit is contained in:
John Baldwin 2006-04-18 18:16:54 +00:00
parent 7734a577e3
commit f1a4b852dc
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=157844
2 changed files with 69 additions and 0 deletions

View File

@ -878,6 +878,56 @@ turnstile_unpend(struct turnstile *ts, int owner_type)
mtx_unlock_spin(&sched_lock);
}
/*
* 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.
*/
@ -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)

View File

@ -85,6 +85,8 @@ void turnstile_adjust(struct thread *, u_char);
struct turnstile *turnstile_alloc(void);
void turnstile_broadcast(struct turnstile *, int);
void turnstile_claim(struct lock_object *);
void turnstile_disown(struct turnstile *);
int turnstile_empty(struct turnstile *ts, int queue);
void turnstile_free(struct turnstile *);
struct thread *turnstile_head(struct turnstile *, int);
void turnstile_lock(struct lock_object *);