aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libc/gen/sem_new.c24
-rw-r--r--sys/kern/kern_umtx.c23
2 files changed, 22 insertions, 25 deletions
diff --git a/lib/libc/gen/sem_new.c b/lib/libc/gen/sem_new.c
index af64310c6d8f..222a46528db6 100644
--- a/lib/libc/gen/sem_new.c
+++ b/lib/libc/gen/sem_new.c
@@ -332,9 +332,6 @@ _sem_getvalue(sem_t * __restrict sem, int * __restrict sval)
static __inline int
usem_wake(struct _usem *sem)
{
- rmb();
- if (!sem->_has_waiters)
- return (0);
return _umtx_op(sem, UMTX_OP_SEM_WAKE, 0, NULL, NULL);
}
@@ -374,17 +371,6 @@ _sem_trywait(sem_t *sem)
return (-1);
}
-#define TIMESPEC_SUB(dst, src, val) \
- do { \
- (dst)->tv_sec = (src)->tv_sec - (val)->tv_sec; \
- (dst)->tv_nsec = (src)->tv_nsec - (val)->tv_nsec; \
- if ((dst)->tv_nsec < 0) { \
- (dst)->tv_sec--; \
- (dst)->tv_nsec += 1000000000; \
- } \
- } while (0)
-
-
int
_sem_timedwait(sem_t * __restrict sem,
const struct timespec * __restrict abstime)
@@ -438,10 +424,16 @@ _sem_wait(sem_t *sem)
int
_sem_post(sem_t *sem)
{
+ unsigned int count;
if (sem_check_validity(sem) != 0)
return (-1);
- atomic_add_rel_int(&sem->_kern._count, 1);
- return usem_wake(&sem->_kern);
+ do {
+ count = sem->_kern._count;
+ if (count + 1 > SEM_VALUE_MAX)
+ return (EOVERFLOW);
+ } while(!atomic_cmpset_rel_int(&sem->_kern._count, count, count+1));
+ (void)usem_wake(&sem->_kern);
+ return (0);
}
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index 71b19e7b3184..c2f5ca313dff 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -2840,9 +2840,7 @@ do_sem_wait(struct thread *td, struct _usem *sem, struct _umtx_time *timeout)
umtxq_busy(&uq->uq_key);
umtxq_insert(uq);
umtxq_unlock(&uq->uq_key);
-
casuword32(__DEVOLATILE(uint32_t *, &sem->_has_waiters), 0, 1);
- rmb();
count = fuword32(__DEVOLATILE(uint32_t *, &sem->_count));
if (count != 0) {
umtxq_lock(&uq->uq_key);
@@ -2876,7 +2874,7 @@ static int
do_sem_wake(struct thread *td, struct _usem *sem)
{
struct umtx_key key;
- int error, cnt, nwake;
+ int error, cnt;
uint32_t flags;
flags = fuword32(&sem->_flags);
@@ -2885,12 +2883,19 @@ do_sem_wake(struct thread *td, struct _usem *sem)
umtxq_lock(&key);
umtxq_busy(&key);
cnt = umtxq_count(&key);
- nwake = umtxq_signal(&key, 1);
- if (cnt <= nwake) {
- umtxq_unlock(&key);
- error = suword32(
- __DEVOLATILE(uint32_t *, &sem->_has_waiters), 0);
- umtxq_lock(&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
+ * update _has_waiters flag.
+ */
+ if (cnt == 1) {
+ umtxq_unlock(&key);
+ error = suword32(
+ __DEVOLATILE(uint32_t *, &sem->_has_waiters), 0);
+ umtxq_lock(&key);
+ }
}
umtxq_unbusy(&key);
umtxq_unlock(&key);