aboutsummaryrefslogtreecommitdiff
path: root/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-09-05 10:01:52 -0700
committerDavid S. Miller <davem@davemloft.net>2011-09-05 10:01:52 -0700
commit39c4451cecac1bc3c3bccf53521333cef18d37c6 (patch)
treec2785b3b70516e8e0f0aab0f9d38398d4a84a710 /nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
parent3b142ce5728f6d683f3375fb33099ebf243f6681 (diff)
downloadglibc-39c4451cecac1bc3c3bccf53521333cef18d37c6.zip
glibc-39c4451cecac1bc3c3bccf53521333cef18d37c6.tar.gz
glibc-39c4451cecac1bc3c3bccf53521333cef18d37c6.tar.bz2
Fix nptl semaphore cleanup invocation.
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/sem_timedwait.c')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sem_timedwait.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
index fdf0d74..cb3b78f 100644
--- a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
@@ -30,6 +30,21 @@
extern void __sem_wait_cleanup (void *arg) attribute_hidden;
+/* This is in a seperate function in order to make sure gcc
+ puts the call site into an exception region, and thus the
+ cleanups get properly run. */
+static int
+__attribute__ ((noinline))
+do_futex_timed_wait (struct new_sem *isem, struct timespec *rt)
+{
+ int err, oldtype = __pthread_enable_asynccancel ();
+
+ err = lll_futex_timed_wait (&isem->value, 0, rt,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
+
+ __pthread_disable_asynccancel (oldtype);
+ return err;
+}
int
sem_timedwait (sem_t *sem, const struct timespec *abstime)
@@ -80,16 +95,7 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
/* Do wait. */
rt.tv_sec = sec;
rt.tv_nsec = nsec;
-
- /* Enable asynchronous cancellation. Required by the standard. */
- int oldtype = __pthread_enable_asynccancel ();
-
- err = lll_futex_timed_wait (&isem->value, 0, &rt,
- isem->private ^ FUTEX_PRIVATE_FLAG);
-
- /* Disable asynchronous cancellation. */
- __pthread_disable_asynccancel (oldtype);
-
+ err = do_futex_timed_wait(isem, &rt);
if (err != 0 && err != -EWOULDBLOCK)
{
__set_errno (-err);