aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_sx.c
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2017-02-09 08:19:30 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2017-02-09 08:19:30 +0000
commit3b3cf014fc98c3e3193ae117c22b60526545275d (patch)
tree712219749ad318c79630ff2eb9e326182682059b /sys/kern/kern_sx.c
parent48f4c9fb049cc82a6299c20ffb42f205eeddcb39 (diff)
downloadsrc-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.c14
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))