Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Apr 2012 03:05:02 +0000 (UTC)
From:      David Xu <davidxu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r233913 - in head: lib/libc/gen sys/kern
Message-ID:  <201204050305.q35352O4037183@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: davidxu
Date: Thu Apr  5 03:05:02 2012
New Revision: 233913
URL: http://svn.freebsd.org/changeset/base/233913

Log:
  In sem_post, the field _has_waiters is no longer used, because some
  application destroys semaphore after sem_wait returns. Just enter
  kernel to wake up sleeping threads, only update _has_waiters if
  it is safe. While here, check if the value exceed SEM_VALUE_MAX and
  return EOVERFLOW if this is true.

Modified:
  head/lib/libc/gen/sem_new.c
  head/sys/kern/kern_umtx.c

Modified: head/lib/libc/gen/sem_new.c
==============================================================================
--- head/lib/libc/gen/sem_new.c	Thu Apr  5 02:24:08 2012	(r233912)
+++ head/lib/libc/gen/sem_new.c	Thu Apr  5 03:05:02 2012	(r233913)
@@ -332,9 +332,6 @@ _sem_getvalue(sem_t * __restrict sem, in
 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);
 }

Modified: head/sys/kern/kern_umtx.c
==============================================================================
--- head/sys/kern/kern_umtx.c	Thu Apr  5 02:24:08 2012	(r233912)
+++ head/sys/kern/kern_umtx.c	Thu Apr  5 03:05:02 2012	(r233913)
@@ -2840,9 +2840,7 @@ do_sem_wait(struct thread *td, struct _u
 	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 _u
 	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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204050305.q35352O4037183>