diff options
author | Austin Foxley <austinf@cetoncorp.com> | 2010-02-16 12:27:18 -0800 |
---|---|---|
committer | Austin Foxley <austinf@cetoncorp.com> | 2010-02-16 12:27:18 -0800 |
commit | a032a6587011cbdac8c2f7e11f15dc4e592bbb55 (patch) | |
tree | b8d8dfc6abf0168e098223c2134a3e4bd7640942 /libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c | |
parent | 70f1d42b13a741f603472f405299e5d2938aa728 (diff) |
mass sync with glibc nptl
Signed-off-by: Austin Foxley <austinf@cetoncorp.com>
Diffstat (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c')
-rw-r--r-- | libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c | 54 |
1 files changed, 41 insertions, 13 deletions
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c index 416d8634b..e661e09c8 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c @@ -1,5 +1,5 @@ /* sem_wait -- wait on a semaphore. Generic futex-using version. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. @@ -23,34 +23,62 @@ #include <lowlevellock.h> #include <internaltypes.h> #include <semaphore.h> + #include <pthreadP.h> +void +attribute_hidden +__sem_wait_cleanup (void *arg) +{ + struct new_sem *isem = (struct new_sem *) arg; + + atomic_decrement (&isem->nwaiters); +} + + int __new_sem_wait (sem_t *sem) { - /* First check for cancellation. */ - CANCELLATION_P (THREAD_SELF); - - int *futex = (int *) sem; + struct new_sem *isem = (struct new_sem *) sem; int err; - do - { - if (atomic_decrement_if_positive (futex) > 0) - return 0; + if (atomic_decrement_if_positive (&isem->value) > 0) + return 0; + atomic_increment (&isem->nwaiters); + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { /* Enable asynchronous cancellation. Required by the standard. */ int oldtype = __pthread_enable_asynccancel (); - err = lll_futex_wait (futex, 0); + err = lll_futex_wait (&isem->value, 0, + isem->private ^ FUTEX_PRIVATE_FLAG); /* Disable asynchronous cancellation. */ __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (atomic_decrement_if_positive (&isem->value) > 0) + { + err = 0; + break; + } } - while (err == 0 || err == -EWOULDBLOCK); - __set_errno (-err); - return -1; + pthread_cleanup_pop (0); + + atomic_decrement (&isem->nwaiters); + + return err; } weak_alias(__new_sem_wait, sem_wait) |