diff options
author | Mateusz Guzik <mjg@FreeBSD.org> | 2017-02-09 08:19:30 +0000 |
---|---|---|
committer | Mateusz Guzik <mjg@FreeBSD.org> | 2017-02-09 08:19:30 +0000 |
commit | 3b3cf014fc98c3e3193ae117c22b60526545275d (patch) | |
tree | 712219749ad318c79630ff2eb9e326182682059b /sys/kern/kern_sx.c | |
parent | 48f4c9fb049cc82a6299c20ffb42f205eeddcb39 (diff) | |
download | src-3b3cf014fc98c3e3193ae117c22b60526545275d.tar.gz src-3b3cf014fc98c3e3193ae117c22b60526545275d.zip |
locks: tidy up unlock fallback paths
Update comments to note these functions are reachable if lockstat is
enabled.
Check if the lock has any bits set before attempting unlock, which saves
an unnecessary atomic operation.
Notes
Notes:
svn path=/head/; revision=313467
Diffstat (limited to 'sys/kern/kern_sx.c')
-rw-r--r-- | sys/kern/kern_sx.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/sys/kern/kern_sx.c b/sys/kern/kern_sx.c index 760c44e665ff..96ca4dffef28 100644 --- a/sys/kern/kern_sx.c +++ b/sys/kern/kern_sx.c @@ -749,12 +749,8 @@ _sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line) MPASS(!(sx->sx_lock & SX_LOCK_SHARED)); - if (!sx_recursed(sx)) { - LOCKSTAT_PROFILE_RELEASE_RWLOCK(sx__release, sx, - LOCKSTAT_WRITER); - if (atomic_cmpset_rel_ptr(&sx->sx_lock, tid, SX_LOCK_UNLOCKED)) - return; - } else { + x = SX_READ_VALUE(sx); + if (x & SX_LOCK_RECURSED) { /* The lock is recursed, unrecurse one level. */ if ((--sx->sx_recurse) == 0) atomic_clear_ptr(&sx->sx_lock, SX_LOCK_RECURSED); @@ -762,6 +758,12 @@ _sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line) CTR2(KTR_LOCK, "%s: %p unrecursing", __func__, sx); return; } + + LOCKSTAT_PROFILE_RELEASE_RWLOCK(sx__release, sx, LOCKSTAT_WRITER); + if (x == tid && + atomic_cmpset_rel_ptr(&sx->sx_lock, tid, SX_LOCK_UNLOCKED)) + return; + MPASS(sx->sx_lock & (SX_LOCK_SHARED_WAITERS | SX_LOCK_EXCLUSIVE_WAITERS)); if (LOCK_LOG_TEST(&sx->lock_object, 0)) |