diff options
author | Mateusz Guzik <mjg@FreeBSD.org> | 2017-11-17 02:27:04 +0000 |
---|---|---|
committer | Mateusz Guzik <mjg@FreeBSD.org> | 2017-11-17 02:27:04 +0000 |
commit | bc24577c252dc551430ee2f7df77f5bafbe5b493 (patch) | |
tree | efa24a18ab2b0841d4b2cef7eae60f7fb346a44d /sys/kern/kern_sx.c | |
parent | 8fef6b2c67812c4e8ea667870ff1d8db3f5964d7 (diff) | |
download | src-bc24577c252dc551430ee2f7df77f5bafbe5b493.tar.gz src-bc24577c252dc551430ee2f7df77f5bafbe5b493.zip |
sx: perform a minor cleanup of the unlock slowpath
No functional changes.
Notes
Notes:
svn path=/head/; revision=325922
Diffstat (limited to 'sys/kern/kern_sx.c')
-rw-r--r-- | sys/kern/kern_sx.c | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/sys/kern/kern_sx.c b/sys/kern/kern_sx.c index f3f38cfd996c..6629b0a63fdd 100644 --- a/sys/kern/kern_sx.c +++ b/sys/kern/kern_sx.c @@ -772,7 +772,7 @@ _sx_xlock_hard(struct sx *sx, uintptr_t x, uintptr_t tid, int opts, void _sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line) { - uintptr_t x; + uintptr_t x, setx; int queue, wakeup_swapper; if (SCHEDULER_STOPPED()) @@ -801,7 +801,7 @@ _sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line) CTR2(KTR_LOCK, "%s: %p contested", __func__, sx); sleepq_lock(&sx->lock_object); - x = SX_LOCK_UNLOCKED; + x = SX_READ_VALUE(sx); /* * The wake up algorithm here is quite simple and probably not @@ -812,19 +812,21 @@ _sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line) * starvation for the threads sleeping on the exclusive queue by giving * them precedence and cleaning up the shared waiters bit anyway. */ - if ((sx->sx_lock & SX_LOCK_SHARED_WAITERS) != 0 && + setx = SX_LOCK_UNLOCKED; + queue = SQ_EXCLUSIVE_QUEUE; + if ((x & SX_LOCK_SHARED_WAITERS) != 0 && sleepq_sleepcnt(&sx->lock_object, SQ_SHARED_QUEUE) != 0) { queue = SQ_SHARED_QUEUE; - x |= (sx->sx_lock & SX_LOCK_EXCLUSIVE_WAITERS); - } else - queue = SQ_EXCLUSIVE_QUEUE; + setx |= (x & SX_LOCK_EXCLUSIVE_WAITERS); + } + atomic_store_rel_ptr(&sx->sx_lock, setx); /* Wake up all the waiters for the specific queue. */ if (LOCK_LOG_TEST(&sx->lock_object, 0)) CTR3(KTR_LOCK, "%s: %p waking up all threads on %s queue", __func__, sx, queue == SQ_SHARED_QUEUE ? "shared" : "exclusive"); - atomic_store_rel_ptr(&sx->sx_lock, x); + wakeup_swapper = sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, 0, queue); sleepq_release(&sx->lock_object); |