summaryrefslogtreecommitdiff
path: root/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/sem_timedwait.c')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sem_timedwait.c60
1 files changed, 23 insertions, 37 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
index 8f92d78abe..ef897c1e93 100644
--- a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
@@ -1,5 +1,5 @@
/* sem_timedwait -- wait on a semaphore. Generic futex-using version.
- Copyright (C) 2003, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
@@ -28,29 +28,28 @@
#include <shlib-compat.h>
-extern void __sem_wait_cleanup (void *arg) attribute_hidden;
-
-
int
sem_timedwait (sem_t *sem, const struct timespec *abstime)
{
- struct new_sem *isem = (struct new_sem *) sem;
- int err;
+ /* First check for cancellation. */
+ CANCELLATION_P (THREAD_SELF);
- if (atomic_decrement_if_positive (&isem->value) > 0)
- return 0;
+ int *futex = (int *) sem;
+ int val;
+ int err;
- if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+ if (*futex > 0)
{
- __set_errno (EINVAL);
- return -1;
+ val = atomic_decrement_if_positive (futex);
+ if (val > 0)
+ return 0;
}
- atomic_increment (&isem->nwaiters);
-
- pthread_cleanup_push (__sem_wait_cleanup, isem);
+ err = -EINVAL;
+ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+ goto error_return;
- while (1)
+ do
{
struct timeval tv;
struct timespec rt;
@@ -71,11 +70,7 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
/* Already timed out? */
err = -ETIMEDOUT;
if (sec < 0)
- {
- __set_errno (ETIMEDOUT);
- err = -1;
- break;
- }
+ goto error_return;
/* Do wait. */
rt.tv_sec = sec;
@@ -84,30 +79,21 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();
- err = lll_futex_timed_wait (&isem->value, 0, &rt,
- // XYZ check mutex flag
- LLL_SHARED);
+ err = lll_futex_timed_wait (futex, 0, &rt);
/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);
if (err != 0 && err != -EWOULDBLOCK)
- {
- __set_errno (-err);
- err = -1;
- break;
- }
+ goto error_return;
- if (atomic_decrement_if_positive (&isem->value) > 0)
- {
- err = 0;
- break;
- }
+ val = atomic_decrement_if_positive (futex);
}
+ while (val <= 0);
- pthread_cleanup_pop (0);
-
- atomic_decrement (&isem->nwaiters);
+ return 0;
- return err;
+ error_return:
+ __set_errno (-err);
+ return -1;
}