mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-31 16:57:10 +00:00
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);
|
||||
cnt = umtxq_count(&key);
|
||||
if (cnt > 0) {
|
||||
umtxq_signal(&key, 1);
|
||||
/*
|
||||
* Check if count is greater than 0, this means the memory is
|
||||
* 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)
|
||||
error = EFAULT;
|
||||
}
|
||||
umtxq_signal(&key, 1);
|
||||
}
|
||||
umtxq_unbusy(&key);
|
||||
umtxq_unlock(&key);
|
||||
@ -3235,8 +3235,6 @@ do_sem2_wake(struct thread *td, struct _usem2 *sem)
|
||||
umtxq_busy(&key);
|
||||
cnt = umtxq_count(&key);
|
||||
if (cnt > 0) {
|
||||
umtxq_signal(&key, 1);
|
||||
|
||||
/*
|
||||
* If this was the last sleeping thread, clear the waiters
|
||||
* flag in _count.
|
||||
@ -3251,6 +3249,8 @@ do_sem2_wake(struct thread *td, struct _usem2 *sem)
|
||||
error = EFAULT;
|
||||
umtxq_lock(&key);
|
||||
}
|
||||
|
||||
umtxq_signal(&key, 1);
|
||||
}
|
||||
umtxq_unbusy(&key);
|
||||
umtxq_unlock(&key);
|
||||
|
Loading…
Reference in New Issue
Block a user