mtx: unlock before traversing threads to wake up
This shortens the lock hold time while not affecting corretness. All the woken up threads end up competing can lose the race against a completely unrelated thread getting the lock anyway.
This commit is contained in:
parent
d5884672d5
commit
24a0d3819f
@ -629,7 +629,8 @@ __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t v)
|
||||
#ifdef KDTRACE_HOOKS
|
||||
sleep_time -= lockstat_nsecs(&m->lock_object);
|
||||
#endif
|
||||
turnstile_wait(ts, mtx_owner(m), TS_EXCLUSIVE_QUEUE);
|
||||
MPASS(owner == mtx_owner(m));
|
||||
turnstile_wait(ts, owner, TS_EXCLUSIVE_QUEUE);
|
||||
#ifdef KDTRACE_HOOKS
|
||||
sleep_time += lockstat_nsecs(&m->lock_object);
|
||||
sleep_cnt++;
|
||||
@ -1002,7 +1003,7 @@ __mtx_unlock_sleep(volatile uintptr_t *c)
|
||||
{
|
||||
struct mtx *m;
|
||||
struct turnstile *ts;
|
||||
uintptr_t tid, v;
|
||||
uintptr_t tid;
|
||||
|
||||
if (SCHEDULER_STOPPED())
|
||||
return;
|
||||
@ -1028,12 +1029,12 @@ __mtx_unlock_sleep(volatile uintptr_t *c)
|
||||
* can be removed from the hash list if it is empty.
|
||||
*/
|
||||
turnstile_chain_lock(&m->lock_object);
|
||||
_mtx_release_lock_quick(m);
|
||||
ts = turnstile_lookup(&m->lock_object);
|
||||
MPASS(ts != NULL);
|
||||
if (LOCK_LOG_TEST(&m->lock_object, opts))
|
||||
CTR1(KTR_LOCK, "_mtx_unlock_sleep: %p contested", m);
|
||||
MPASS(ts != NULL);
|
||||
turnstile_broadcast(ts, TS_EXCLUSIVE_QUEUE);
|
||||
_mtx_release_lock_quick(m);
|
||||
|
||||
/*
|
||||
* This turnstile is now no longer associated with the mutex. We can
|
||||
|
Loading…
Reference in New Issue
Block a user