sem_post(): wake up the sleeper only after adjusting has_waiters
If the caller of sem_post() wakes up a thread sleeping via sem_wait() before it clears the has_waiters flag, the caller of sem_wait() has no way of knowing when it is safe to destroy the semaphore and reuse the memory. This is because the caller of sem_post() may be interrupted between the wake step and the clearing of has_waiters. It will then write into the has_waiters flag in userspace after being preempted for some unknown amount of time. Reviewed by: jhb, kib, vangyzen Approved by: kib (mentor), vangyzen (mentor) MFC after: 2 weeks Sponsored by: Dell Inc. Differential Revision: https://reviews.freebsd.org/D7505
This commit is contained in:
parent
ed12504ac7
commit
b0f2185bbe
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=304184
@ -3123,7 +3123,6 @@ do_sem_wake(struct thread *td, struct _usem *sem)
|
|||||||
umtxq_busy(&key);
|
umtxq_busy(&key);
|
||||||
cnt = umtxq_count(&key);
|
cnt = umtxq_count(&key);
|
||||||
if (cnt > 0) {
|
if (cnt > 0) {
|
||||||
umtxq_signal(&key, 1);
|
|
||||||
/*
|
/*
|
||||||
* Check if count is greater than 0, this means the memory is
|
* Check if count is greater than 0, this means the memory is
|
||||||
* still being referenced by user code, so we can safely
|
* still being referenced by user code, so we can safely
|
||||||
@ -3136,6 +3135,7 @@ do_sem_wake(struct thread *td, struct _usem *sem)
|
|||||||
if (error == -1)
|
if (error == -1)
|
||||||
error = EFAULT;
|
error = EFAULT;
|
||||||
}
|
}
|
||||||
|
umtxq_signal(&key, 1);
|
||||||
}
|
}
|
||||||
umtxq_unbusy(&key);
|
umtxq_unbusy(&key);
|
||||||
umtxq_unlock(&key);
|
umtxq_unlock(&key);
|
||||||
@ -3235,8 +3235,6 @@ do_sem2_wake(struct thread *td, struct _usem2 *sem)
|
|||||||
umtxq_busy(&key);
|
umtxq_busy(&key);
|
||||||
cnt = umtxq_count(&key);
|
cnt = umtxq_count(&key);
|
||||||
if (cnt > 0) {
|
if (cnt > 0) {
|
||||||
umtxq_signal(&key, 1);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this was the last sleeping thread, clear the waiters
|
* If this was the last sleeping thread, clear the waiters
|
||||||
* flag in _count.
|
* flag in _count.
|
||||||
@ -3251,6 +3249,8 @@ do_sem2_wake(struct thread *td, struct _usem2 *sem)
|
|||||||
error = EFAULT;
|
error = EFAULT;
|
||||||
umtxq_lock(&key);
|
umtxq_lock(&key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
umtxq_signal(&key, 1);
|
||||||
}
|
}
|
||||||
umtxq_unbusy(&key);
|
umtxq_unbusy(&key);
|
||||||
umtxq_unlock(&key);
|
umtxq_unlock(&key);
|
||||||
|
Loading…
Reference in New Issue
Block a user