summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2012-03-21 07:16:58 +0000
committerdavidxu <davidxu@FreeBSD.org>2012-03-21 07:16:58 +0000
commitd02d68a8c81850f2b127b0364bb2bcf017db8c9f (patch)
tree2677654e24d040709ec04f6d55b09c5826636b1b /lib
parentfd4cb16e863d0646f3495a0cc56ac84b12e50806 (diff)
downloadFreeBSD-src-d02d68a8c81850f2b127b0364bb2bcf017db8c9f.zip
FreeBSD-src-d02d68a8c81850f2b127b0364bb2bcf017db8c9f.tar.gz
Revert previous change. It is an incomplete change from old branch. :-(
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/gen/sem_new.c99
1 files changed, 39 insertions, 60 deletions
diff --git a/lib/libc/gen/sem_new.c b/lib/libc/gen/sem_new.c
index f0d97e6..af64310 100644
--- a/lib/libc/gen/sem_new.c
+++ b/lib/libc/gen/sem_new.c
@@ -61,8 +61,7 @@ __weak_reference(_sem_unlink, sem_unlink);
__weak_reference(_sem_wait, sem_wait);
#define SEM_PREFIX "/tmp/SEMD"
-#define SEM_MAGIC1 ((u_int32_t)0x73656d31)
-#define SEM_MAGIC ((u_int32_t)0x73656d32)
+#define SEM_MAGIC ((u_int32_t)0x73656d31)
struct sem_nameinfo {
int open_count;
@@ -110,7 +109,7 @@ static inline int
sem_check_validity(sem_t *sem)
{
- if (sem->_magic == SEM_MAGIC || sem->_magic == SEM_MAGIC1)
+ if (sem->_magic == SEM_MAGIC)
return (0);
else {
errno = EINVAL;
@@ -131,7 +130,7 @@ _sem_init(sem_t *sem, int pshared, unsigned int value)
sem->_magic = SEM_MAGIC;
sem->_kern._count = (u_int32_t)value;
sem->_kern._has_waiters = 0;
- sem->_kern._flags = (pshared ? USYNC_PROCESS_SHARED : 0) | SEM_VER2;
+ sem->_kern._flags = pshared ? USYNC_PROCESS_SHARED : 0;
return (0);
}
@@ -208,7 +207,7 @@ _sem_open(const char *name, int flags, ...)
tmp._magic = SEM_MAGIC;
tmp._kern._has_waiters = 0;
tmp._kern._count = value;
- tmp._kern._flags = USYNC_PROCESS_SHARED | SEM_NAMED | SEM_VER2;
+ tmp._kern._flags = USYNC_PROCESS_SHARED | SEM_NAMED;
if (_write(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) {
flock(fd, LOCK_UN);
goto error;
@@ -326,11 +325,20 @@ _sem_getvalue(sem_t * __restrict sem, int * __restrict sval)
if (sem_check_validity(sem) != 0)
return (-1);
- *sval = (int)sem->_kern._count & ~SEM_WAITERS;
+ *sval = (int)sem->_kern._count;
return (0);
}
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);
+}
+
+static __inline int
usem_wait(struct _usem *sem, const struct timespec *abstime)
{
struct _umtx_time *tm_p, timeout;
@@ -350,51 +358,48 @@ usem_wait(struct _usem *sem, const struct timespec *abstime)
(void *)tm_size, __DECONST(void*, tm_p));
}
-static inline int
-_trywait(sem_t *sem)
-{
- int count;
-
- if ((sem->_kern._flags & SEM_VER2) != 0) {
- while (((count = sem->_kern._count) & ~SEM_WAITERS) > 0) {
- if (atomic_cmpset_acq_int(&sem->_kern._count, count, count - 1))
- return (0);
- }
- } else {
- while ((count = sem->_kern._count) > 0) {
- if (atomic_cmpset_acq_int(&sem->_kern._count, count, count - 1))
- return (0);
- }
- }
- return (EAGAIN);
-}
-
int
_sem_trywait(sem_t *sem)
{
- int status;
+ int val;
if (sem_check_validity(sem) != 0)
return (-1);
- if ((status = _trywait(sem)) == 0)
- return (0);
- errno = status;
+
+ while ((val = sem->_kern._count) > 0) {
+ if (atomic_cmpset_acq_int(&sem->_kern._count, val, val - 1))
+ return (0);
+ }
+ errno = EAGAIN;
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)
{
- int retval;
+ int val, retval;
if (sem_check_validity(sem) != 0)
return (-1);
retval = 0;
for (;;) {
- if (_trywait(sem) == 0)
- return (0);
+ while ((val = sem->_kern._count) > 0) {
+ if (atomic_cmpset_acq_int(&sem->_kern._count, val, val - 1))
+ return (0);
+ }
if (retval) {
_pthread_testcancel();
@@ -433,36 +438,10 @@ _sem_wait(sem_t *sem)
int
_sem_post(sem_t *sem)
{
- int count;
if (sem_check_validity(sem) != 0)
return (-1);
- if ((sem->_kern._flags & SEM_VER2) != 0) {
- for (;;) {
- count = sem->_kern._count;
- if ((count & SEM_WAITERS) == 0) {
- if (__predict_false(count == SEM_VALUE_MAX)) {
- errno = ERANGE;
- return (-1);
- }
- if (atomic_cmpset_rel_int(&sem->_kern._count, count, count+1))
- return (0);
- } else {
- return _umtx_op(&sem->_kern, UMTX_OP_SEM_WAKE, 0, NULL, NULL);
- }
- }
- } else {
- do {
- count = sem->_kern._count;
- if (__predict_false(count == SEM_VALUE_MAX)) {
- errno = ERANGE;
- return (-1);
- }
- } while (!atomic_cmpset_rel_int(&sem->_kern._count, count, count+1));
- rmb();
- if (!sem->_kern._has_waiters)
- return (0);
- return _umtx_op(&sem->_kern, UMTX_OP_SEM_WAKE, 0, NULL, NULL);
- }
+ atomic_add_rel_int(&sem->_kern._count, 1);
+ return usem_wake(&sem->_kern);
}
OpenPOWER on IntegriCloud