diff options
author | Mateusz Guzik <mjg@FreeBSD.org> | 2018-02-14 20:37:33 +0000 |
---|---|---|
committer | Mateusz Guzik <mjg@FreeBSD.org> | 2018-02-14 20:37:33 +0000 |
commit | f795032b470b280d60ea7c99722428e6b2257375 (patch) | |
tree | fd93244cadeb3240f6ebd1bb96cb474921870e67 /sys | |
parent | 834063202a16592e1ef5c3a9fbd04ca5f1df3ed0 (diff) | |
download | src-f795032b470b280d60ea7c99722428e6b2257375.tar.gz src-f795032b470b280d60ea7c99722428e6b2257375.zip |
rwlock: diff-reduction of runlock compared to sx sunlock
Notes
Notes:
svn path=/head/; revision=329276
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_rwlock.c | 26 |
1 files changed, 12 insertions, 14 deletions
diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c index 7459cde5e283..3a7cbb71e893 100644 --- a/sys/kern/kern_rwlock.c +++ b/sys/kern/kern_rwlock.c @@ -760,22 +760,19 @@ __rw_runlock_hard(struct rwlock *rw, struct thread *td, uintptr_t v if (SCHEDULER_STOPPED()) return; + if (__rw_runlock_try(rw, td, &v)) + goto out_lockstat; + + /* + * Ok, we know we have waiters and we think we are the + * last reader, so grab the turnstile lock. + */ + turnstile_chain_lock(&rw->lock_object); + v = RW_READ_VALUE(rw); for (;;) { if (__rw_runlock_try(rw, td, &v)) break; - /* - * Ok, we know we have waiters and we think we are the - * last reader, so grab the turnstile lock. - */ - turnstile_chain_lock(&rw->lock_object); - v = RW_READ_VALUE(rw); -retry_ts: - if (__rw_runlock_try(rw, td, &v)) { - turnstile_chain_unlock(&rw->lock_object); - break; - } - v &= (RW_LOCK_WAITERS | RW_LOCK_WRITE_SPINNER); MPASS(v & RW_LOCK_WAITERS); @@ -803,7 +800,7 @@ retry_ts: } v |= RW_READERS_LOCK(1); if (!atomic_fcmpset_rel_ptr(&rw->rw_lock, &v, setv)) - goto retry_ts; + continue; if (LOCK_LOG_TEST(&rw->lock_object, 0)) CTR2(KTR_LOCK, "%s: %p last succeeded with waiters", __func__, rw); @@ -819,10 +816,11 @@ retry_ts: MPASS(ts != NULL); turnstile_broadcast(ts, queue); turnstile_unpend(ts, TS_SHARED_LOCK); - turnstile_chain_unlock(&rw->lock_object); td->td_rw_rlocks--; break; } + turnstile_chain_unlock(&rw->lock_object); +out_lockstat: LOCKSTAT_PROFILE_RELEASE_RWLOCK(rw__release, rw, LOCKSTAT_READER); } |