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:
mjg 2017-11-17 02:25:04 +00:00
parent d5884672d5
commit 24a0d3819f

View File

@ -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