summaryrefslogtreecommitdiff
path: root/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-08-15 20:57:36 +0000
committerJakub Jelinek <jakub@redhat.com>2007-08-15 20:57:36 +0000
commit91ed9442cea3802c96b69553d6653ed01df7c990 (patch)
tree53f0dc462efd0fc02dee924f744744a39041d765 /nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
parentc67c02731b6507c5351bca70451441d9a26113ef (diff)
Updated to fedora-glibc-20070815T2049cvs/fedora-glibc-2_6_90-10
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c100
1 files changed, 66 insertions, 34 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
index efcc9e9aa8..55f3e2e075 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
@@ -1,5 +1,5 @@
/* sem_timedwait -- wait on a semaphore. SPARC version.
- Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
@@ -28,37 +28,48 @@
#include <shlib-compat.h>
+extern void __sem_wait_cleanup (void *arg) attribute_hidden;
+
+
int
sem_timedwait (sem_t *sem, const struct timespec *abstime)
{
- /* First check for cancellation. */
- CANCELLATION_P (THREAD_SELF);
-
- int *futex = (int *) sem;
- int val;
+ struct sparc_new_sem *isem = (struct sparc_new_sem *) sem;
int err;
+ int val;
- if (*futex > 0)
+ if (__atomic_is_v9)
+ val = atomic_decrement_if_positive (&isem->value);
+ else
{
- if (__atomic_is_v9)
- val = atomic_decrement_if_positive (futex);
- else
- {
- __sparc32_atomic_do_lock24 (futex + 1);
- val = *futex;
- if (val > 0)
- *futex = val - 1;
- __sparc32_atomic_do_unlock24 (futex + 1);
- }
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ val = isem->value;
if (val > 0)
- return 0;
+ isem->value = val - 1;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
}
- err = -EINVAL;
+ if (val > 0)
+ return 0;
+
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
- goto error_return;
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (__atomic_is_v9)
+ atomic_increment (&isem->nwaiters);
+ else
+ {
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ isem->nwaiters++;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
- do
+ pthread_cleanup_push (__sem_wait_cleanup, isem);
+
+ while (1)
{
struct timeval tv;
struct timespec rt;
@@ -79,7 +90,11 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
/* Already timed out? */
err = -ETIMEDOUT;
if (sec < 0)
- goto error_return;
+ {
+ __set_errno (ETIMEDOUT);
+ err = -1;
+ break;
+ }
/* Do wait. */
rt.tv_sec = sec;
@@ -88,30 +103,47 @@ 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 (futex, 0, &rt);
+ err = lll_futex_timed_wait (&isem->value, 0, &rt,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);
if (err != 0 && err != -EWOULDBLOCK)
- goto error_return;
+ {
+ __set_errno (-err);
+ err = -1;
+ break;
+ }
if (__atomic_is_v9)
- val = atomic_decrement_if_positive (futex);
+ val = atomic_decrement_if_positive (&isem->value);
else
{
- __sparc32_atomic_do_lock24 (futex + 1);
- val = *futex;
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ val = isem->value;
if (val > 0)
- *futex = val - 1;
- __sparc32_atomic_do_unlock24 (futex + 1);
+ isem->value = val - 1;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
+
+ if (val > 0)
+ {
+ err = 0;
+ break;
}
}
- while (val <= 0);
- return 0;
+ pthread_cleanup_pop (0);
+
+ if (__atomic_is_v9)
+ atomic_decrement (&isem->nwaiters);
+ else
+ {
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ isem->nwaiters--;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
- error_return:
- __set_errno (-err);
- return -1;
+ return err;
}