diff options
author | attilio <attilio@FreeBSD.org> | 2009-09-30 13:26:31 +0000 |
---|---|---|
committer | attilio <attilio@FreeBSD.org> | 2009-09-30 13:26:31 +0000 |
commit | e9f2530ebfd93a31f9261bfd21bfb5c95dab3720 (patch) | |
tree | 14bb844cbbe423beb58afda22e6444bab089a43e /sys/kern/kern_sx.c | |
parent | 49524d648a66d9f3860133c520a179e25a5f35aa (diff) | |
download | FreeBSD-src-e9f2530ebfd93a31f9261bfd21bfb5c95dab3720.zip FreeBSD-src-e9f2530ebfd93a31f9261bfd21bfb5c95dab3720.tar.gz |
When releasing a read/shared lock we need to use a write memory barrier
in order to avoid, on architectures which doesn't have strong ordered
writes, CPU instructions reordering.
Diagnosed by: fabio
Reviewed by: jhb
Tested by: Giovanni Trematerra
<giovanni dot trematerra at gmail dot com>
Diffstat (limited to 'sys/kern/kern_sx.c')
-rw-r--r-- | sys/kern/kern_sx.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/sys/kern/kern_sx.c b/sys/kern/kern_sx.c index c00b267..2d777a2 100644 --- a/sys/kern/kern_sx.c +++ b/sys/kern/kern_sx.c @@ -931,7 +931,7 @@ _sx_sunlock_hard(struct sx *sx, const char *file, int line) * so, just drop one and return. */ if (SX_SHARERS(x) > 1) { - if (atomic_cmpset_ptr(&sx->sx_lock, x, + if (atomic_cmpset_rel_ptr(&sx->sx_lock, x, x - SX_ONE_SHARER)) { if (LOCK_LOG_TEST(&sx->lock_object, 0)) CTR4(KTR_LOCK, @@ -949,8 +949,8 @@ _sx_sunlock_hard(struct sx *sx, const char *file, int line) */ if (!(x & SX_LOCK_EXCLUSIVE_WAITERS)) { MPASS(x == SX_SHARERS_LOCK(1)); - if (atomic_cmpset_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1), - SX_LOCK_UNLOCKED)) { + if (atomic_cmpset_rel_ptr(&sx->sx_lock, + SX_SHARERS_LOCK(1), SX_LOCK_UNLOCKED)) { if (LOCK_LOG_TEST(&sx->lock_object, 0)) CTR2(KTR_LOCK, "%s: %p last succeeded", __func__, sx); @@ -973,7 +973,7 @@ _sx_sunlock_hard(struct sx *sx, const char *file, int line) * Note that the state of the lock could have changed, * so if it fails loop back and retry. */ - if (!atomic_cmpset_ptr(&sx->sx_lock, + if (!atomic_cmpset_rel_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS, SX_LOCK_UNLOCKED)) { sleepq_release(&sx->lock_object); |