summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_umtx.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2010-11-22 02:42:02 +0000
committerdavidxu <davidxu@FreeBSD.org>2010-11-22 02:42:02 +0000
commitb05094dc42c002877bf4b52a97ccc4af2a03adaf (patch)
tree5bb190d7a7b8b23e088da11f360c3985ab408467 /sys/kern/kern_umtx.c
parent08a93ec3b7a224311c5ad5e352f3b55bfb349524 (diff)
downloadFreeBSD-src-b05094dc42c002877bf4b52a97ccc4af2a03adaf.zip
FreeBSD-src-b05094dc42c002877bf4b52a97ccc4af2a03adaf.tar.gz
Use atomic instruction to set _has_writer, otherwise there is a race
causes userland to not wake up a thread sleeping in kernel. MFC after: 3 days
Diffstat (limited to 'sys/kern/kern_umtx.c')
-rw-r--r--sys/kern/kern_umtx.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index 951fef6..43570ce 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -2839,7 +2839,8 @@ do_sem_wait(struct thread *td, struct _usem *sem, struct timespec *timeout)
umtxq_insert(uq);
umtxq_unlock(&uq->uq_key);
- suword32(__DEVOLATILE(uint32_t *, &sem->_has_waiters), 1);
+ if (fuword32(__DEVOLATILE(uint32_t *, &sem->_has_waiters)) == 0)
+ casuword32(__DEVOLATILE(uint32_t *, &sem->_has_waiters), 0, 1);
count = fuword32(__DEVOLATILE(uint32_t *, &sem->_count));
if (count != 0) {
OpenPOWER on IntegriCloud