about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nptl/ChangeLog14
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sem_timedwait.c26
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sem_wait.c24
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c26
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c24
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c26
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c24
7 files changed, 107 insertions, 57 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index c44ce2af6f..caae5dcf3c 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,17 @@
+2011-09-05  David S. Miller  <davem@davemloft.net>
+
+	* sysdeps/unix/sysv/linux/sem_timedwait.c (do_futex_timed_wait):
+	New function.
+	(sem_timedwait): Call it to force an exception region around
+	the async cancel enable and the futex operation.
+	* sysdeps/unix/sysv/linux/sparc/sem_timedwait.c: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c: Likewise.
+	* sysdeps/unix/sysv/linux/sem_wait.c (do_futex_wait): New function.
+	(__new_sem_wait): Call it to force an exception region around
+	the async cancel enable and the futex operation.
+	* sysdeps/unix/sysv/linux/sparc/sem_wait.c: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c: Likewise.
+
 2011-08-31  Andreas Schwab  <schwab@redhat.com>
 
 	* allocatestack.c (setxid_mark_thread): Ensure that the exiting
diff --git a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
index fdf0d74011..cb3b78fe67 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);
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);
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c
index 01952f3f9a..fdd09affea 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/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 sparc_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);
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c
index a846f20601..4a2c9357a0 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/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 sparc_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);
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 55f3e2e075..90edbc5dd0 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/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 sparc_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)
@@ -99,16 +114,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);
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
index b14f976a61..8fba4b7d7e 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
@@ -44,6 +44,20 @@ __sem_wait_cleanup (void *arg)
     }
 }
 
+/* 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 sparc_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)
@@ -77,15 +91,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);