about summary refs log tree commit diff
path: root/nptl/sysdeps/unix/sysv/linux/sem_wait.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_wait.c
parent3b142ce5728f6d683f3375fb33099ebf243f6681 (diff)
downloadglibc-39c4451cecac1bc3c3bccf53521333cef18d37c6.tar.gz
glibc-39c4451cecac1bc3c3bccf53521333cef18d37c6.tar.xz
glibc-39c4451cecac1bc3c3bccf53521333cef18d37c6.zip
Fix nptl semaphore cleanup invocation.
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/sem_wait.c')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sem_wait.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sem_wait.c
index 20e2b481df..602c38246f 100644
--- a/nptl/sysdeps/unix/sysv/linux/sem_wait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sem_wait.c
@@ -37,6 +37,20 @@ __sem_wait_cleanup (void *arg)
   atomic_decrement (&isem->nwaiters);
 }
 
+/* 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_wait (struct new_sem *isem)
+{
+  int err, oldtype = __pthread_enable_asynccancel ();
+
+  err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG);
+
+  __pthread_disable_asynccancel (oldtype);
+  return err;
+}
 
 int
 __new_sem_wait (sem_t *sem)
@@ -53,15 +67,7 @@ __new_sem_wait (sem_t *sem)
 
   while (1)
     {
-      /* Enable asynchronous cancellation.  Required by the standard.  */
-      int oldtype = __pthread_enable_asynccancel ();
-
-      err = lll_futex_wait (&isem->value, 0,
-			    isem->private ^ FUTEX_PRIVATE_FLAG);
-
-      /* Disable asynchronous cancellation.  */
-      __pthread_disable_asynccancel (oldtype);
-
+      err = do_futex_wait(isem);
       if (err != 0 && err != -EWOULDBLOCK)
 	{
 	  __set_errno (-err);