This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch azanella/bz12683 created. glibc-2.22-293-gd776932


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, azanella/bz12683 has been created
        at  d776932cfb55b5456d352c316471a2ea80faeaaa (commit)

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d776932cfb55b5456d352c316471a2ea80faeaaa

commit d776932cfb55b5456d352c316471a2ea80faeaaa
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Fri Sep 11 17:39:46 2015 -0300

    nptl: Cancellation fields synchronization cleanup
    
    GLIBC sets threads cancellation internal state (canceled, exiting,
    terminated, and setxid), pthread type (deferred/asynchrnonous), and
    state (enable/disable) in only one variable (cancelhandling).
    All accesses to any field require atomic operations, since the
    internal state might be concurrently accessed and changed by
    different pthread functions.
    
    This patch rewrite how internal pthread cancellation fields are handled
    and accessed in concurrent environments.  The pthread type and state
    are moved to different struct members and since they are accessed
    only in own thread context there is no need to more atomic operations.
    
    The internal state is still in the same variable and accessed used
    atomic operations.

diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index 753da61..1b658e8 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -237,6 +237,8 @@ get_cached_stack (size_t *sizep, void **memp)
 
   /* Cancellation handling is back to the default.  */
   result->cancelhandling = 0;
+  result->cancelstate = PTHREAD_CANCEL_ENABLE;
+  result->canceltype = PTHREAD_CANCEL_DEFERRED;
   result->cleanup = NULL;
 
   /* No pending event.  */
diff --git a/nptl/cleanup_defer.c b/nptl/cleanup_defer.c
index 26b955e..387e9ff 100644
--- a/nptl/cleanup_defer.c
+++ b/nptl/cleanup_defer.c
@@ -31,27 +31,8 @@ __pthread_register_cancel_defer (__pthread_unwind_buf_t *buf)
   ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
   ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup);
 
-  int cancelhandling = THREAD_GETMEM (self, cancelhandling);
-
-  /* Disable asynchronous cancellation for now.  */
-  if (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK))
-    while (1)
-      {
-	int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
-						cancelhandling
-						& ~CANCELTYPE_BITMASK,
-						cancelhandling);
-	if (__glibc_likely (curval == cancelhandling))
-	  /* Successfully replaced the value.  */
-	  break;
-
-	/* Prepare for the next round.  */
-	cancelhandling = curval;
-      }
-
-  ibuf->priv.data.canceltype = (cancelhandling & CANCELTYPE_BITMASK
-				? PTHREAD_CANCEL_ASYNCHRONOUS
-				: PTHREAD_CANCEL_DEFERRED);
+  ibuf->priv.data.canceltype = THREAD_GETMEM (self, canceltype);
+  self->canceltype = PTHREAD_CANCEL_DEFERRED;
 
   /* Store the new cleanup handler info.  */
   THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf);
@@ -67,24 +48,10 @@ __pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf)
 
   THREAD_SETMEM (self, cleanup_jmp_buf, ibuf->priv.data.prev);
 
-  int cancelhandling;
-  if (ibuf->priv.data.canceltype != PTHREAD_CANCEL_DEFERRED
-      && ((cancelhandling = THREAD_GETMEM (self, cancelhandling))
-	  & CANCELTYPE_BITMASK) == 0)
+  if ((ibuf->priv.data.canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
+      && (self->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS))
     {
-      while (1)
-	{
-	  int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
-						  cancelhandling
-						  | CANCELTYPE_BITMASK,
-						  cancelhandling);
-	  if (__glibc_likely (curval == cancelhandling))
-	    /* Successfully replaced the value.  */
-	    break;
-
-	  /* Prepare for the next round.  */
-	  cancelhandling = curval;
-	}
+      self->canceltype = PTHREAD_CANCEL_ASYNCHRONOUS;
 
       CANCELLATION_P (self);
     }
diff --git a/nptl/cleanup_defer_compat.c b/nptl/cleanup_defer_compat.c
index bd70b89..f0cfbee 100644
--- a/nptl/cleanup_defer_compat.c
+++ b/nptl/cleanup_defer_compat.c
@@ -20,10 +20,8 @@
 
 
 void
-_pthread_cleanup_push_defer (buffer, routine, arg)
-     struct _pthread_cleanup_buffer *buffer;
-     void (*routine) (void *);
-     void *arg;
+_pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, 
+			     void (*routine) (void *), void *arg)
 {
   struct pthread *self = THREAD_SELF;
 
@@ -31,27 +29,8 @@ _pthread_cleanup_push_defer (buffer, routine, arg)
   buffer->__arg = arg;
   buffer->__prev = THREAD_GETMEM (self, cleanup);
 
-  int cancelhandling = THREAD_GETMEM (self, cancelhandling);
-
-  /* Disable asynchronous cancellation for now.  */
-  if (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK))
-    while (1)
-      {
-	int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
-						cancelhandling
-						& ~CANCELTYPE_BITMASK,
-						cancelhandling);
-	if (__glibc_likely (curval == cancelhandling))
-	  /* Successfully replaced the value.  */
-	  break;
-
-	/* Prepare for the next round.  */
-	cancelhandling = curval;
-      }
-
-  buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK
-			  ? PTHREAD_CANCEL_ASYNCHRONOUS
-			  : PTHREAD_CANCEL_DEFERRED);
+  buffer->__canceltype = THREAD_GETMEM (self, canceltype);
+  self->canceltype = PTHREAD_CANCEL_DEFERRED;
 
   THREAD_SETMEM (self, cleanup, buffer);
 }
@@ -59,32 +38,17 @@ strong_alias (_pthread_cleanup_push_defer, __pthread_cleanup_push_defer)
 
 
 void
-_pthread_cleanup_pop_restore (buffer, execute)
-     struct _pthread_cleanup_buffer *buffer;
-     int execute;
+_pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
+			      int execute)
 {
   struct pthread *self = THREAD_SELF;
 
   THREAD_SETMEM (self, cleanup, buffer->__prev);
 
-  int cancelhandling;
-  if (__builtin_expect (buffer->__canceltype != PTHREAD_CANCEL_DEFERRED, 0)
-      && ((cancelhandling = THREAD_GETMEM (self, cancelhandling))
-	  & CANCELTYPE_BITMASK) == 0)
+  if (__glibc_unlikely (buffer->__canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
+      && (self->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS))
     {
-      while (1)
-	{
-	  int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
-						  cancelhandling
-						  | CANCELTYPE_BITMASK,
-						  cancelhandling);
-	  if (__glibc_likely (curval == cancelhandling))
-	    /* Successfully replaced the value.  */
-	    break;
-
-	  /* Prepare for the next round.  */
-	  cancelhandling = curval;
-	}
+      self->canceltype = PTHREAD_CANCEL_ASYNCHRONOUS;
 
       CANCELLATION_P (self);
     }
diff --git a/nptl/descr.h b/nptl/descr.h
index 6eb0036..868690e 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -255,14 +255,9 @@ struct pthread
   struct pthread_unwind_buf *cleanup_jmp_buf;
 #define HAVE_CLEANUP_JMP_BUF
 
-  /* Flags determining processing of cancellation.  */
+  /* Flags determining processing of cancellation.  This flags might be
+     accessed concurrently, so atomic operations are required.  */
   int cancelhandling;
-  /* Bit set if cancellation is disabled.  */
-#define CANCELSTATE_BIT		0
-#define CANCELSTATE_BITMASK	(0x01 << CANCELSTATE_BIT)
-  /* Bit set if asynchronous cancellation mode is selected.  */
-#define CANCELTYPE_BIT		1
-#define CANCELTYPE_BITMASK	(0x01 << CANCELTYPE_BIT)
   /* Bit set if threads is canceled.  */
 #define CANCELED_BIT		2
 #define CANCELED_BITMASK	(0x01 << CANCELED_BIT)
@@ -275,16 +270,29 @@ struct pthread
   /* Bit set if thread is supposed to change XID.  */
 #define SETXID_BIT		5
 #define SETXID_BITMASK		(0x01 << SETXID_BIT)
-  /* Mask for the rest.  Helps the compiler to optimize.  */
-#define CANCEL_RESTMASK		0xffffffc0
-
-#define CANCEL_ENABLED_AND_CANCELED(value) \
-  (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK	      \
-	       | CANCEL_RESTMASK | TERMINATED_BITMASK)) == CANCELED_BITMASK)
-#define CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS(value) \
-  (((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK    \
-	       | EXITING_BITMASK | CANCEL_RESTMASK | TERMINATED_BITMASK))     \
-   == (CANCELTYPE_BITMASK | CANCELED_BITMASK))
+
+  /* Cancellation type (deferred/asynchrnonous) and state (enable/disable).
+     Both members are accessed only in the context of the own thread, either
+     by the change functions (pthread_setcancel{type,state}), but thread
+     initialization routine or by the cancellation signal handler
+     (sigcancel_handler).  */
+  int canceltype;
+  int cancelstate;
+
+  /* These helper macros should be used only in context of its own thread,
+     since they access non atomic members (canceltype and cancelstate).  */
+#define CANCEL_CANCELED(self)						     \
+   ((self->cancelhandling & (CANCELED_BITMASK | EXITING_BITMASK		     \
+                             | TERMINATED_BITMASK)) == CANCELED_BITMASK)
+
+#define CANCEL_ENABLED_AND_CANCELED(self)				     \
+   ((THREAD_GETMEM (self, cancelstate) == PTHREAD_CANCEL_ENABLE)	     \
+     && CANCEL_CANCELED(self))
+
+#define CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS(self)		     \
+   ((THREAD_GETMEM (self, cancelstate) == PTHREAD_CANCEL_ENABLE)	     \
+     && (THREAD_GETMEM (self, canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)    \
+     && CANCEL_CANCELED(self))
 
   /* Flags.  Including those copied from the thread attribute.  */
   int flags;
diff --git a/nptl/libc-cancellation.c b/nptl/libc-cancellation.c
index 70f7f66..2694d87 100644
--- a/nptl/libc-cancellation.c
+++ b/nptl/libc-cancellation.c
@@ -50,7 +50,7 @@ __syscall_cancel (__syscall_arg_t nr, __syscall_arg_t a1,
   long int result;
 
   /* If cancellation is not enabled, call the syscall directly.  */
-  if (pd->cancelhandling & CANCELSTATE_BITMASK)
+  if (pd->cancelstate == PTHREAD_CANCEL_DISABLE)
     {
       INTERNAL_SYSCALL_DECL (err);
       result = INTERNAL_SYSCALL_NCS (nr, err, 6, a1, a2, a3, a4, a5, a6);
@@ -66,7 +66,7 @@ __syscall_cancel (__syscall_arg_t nr, __syscall_arg_t a1,
 
   if ((result == -EINTR)
       && (pd->cancelhandling & CANCELED_BITMASK)
-      && !(pd->cancelhandling & CANCELSTATE_BITMASK))
+      && (pd->cancelstate == PTHREAD_CANCEL_ENABLE))
     __do_cancel ();
 
   return result;
diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
index 3c5e3b7..c23119b 100644
--- a/nptl/nptl-init.c
+++ b/nptl/nptl-init.c
@@ -208,7 +208,7 @@ sigcancel_handler (int sig, siginfo_t *si, void *ctx)
   extern const char __syscall_cancel_arch_start[1];
   extern const char __syscall_cancel_arch_end[1];
 
-  if (((pd->cancelhandling & (CANCELSTATE_BITMASK)) != 0)
+  if ((pd->cancelstate == PTHREAD_CANCEL_DISABLE)
       || ((pd->cancelhandling & CANCELED_BITMASK) == 0))
     return;
 
@@ -220,7 +220,7 @@ sigcancel_handler (int sig, siginfo_t *si, void *ctx)
      reads or writes, for instance), the kernel will set the IP to after
      '__syscall_cancel_arch_end', thus disabling the cancellation and allowing
      the process to handle such conditions.  */
-  if (pd->cancelhandling & CANCELTYPE_BITMASK ||
+  if ((pd->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) ||
       (tip >= __syscall_cancel_arch_start && tip < __syscall_cancel_arch_end))
     {
       THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 41ed84d..25160d2 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -230,11 +230,11 @@ extern int __pthread_debug attribute_hidden;
 #endif
 
 
-/* Cancellation test.  */
+/* Cancellation test.  This macro should be used only in the context of the
+   own thread, since it accesses non atomic members.  */
 #define CANCELLATION_P(self) \
   do {									      \
-    int cancelhandling = THREAD_GETMEM (self, cancelhandling);		      \
-    if (CANCEL_ENABLED_AND_CANCELED (cancelhandling))			      \
+    if (CANCEL_ENABLED_AND_CANCELED(self))				      \
       {									      \
 	THREAD_SETMEM (self, result, PTHREAD_CANCELED);			      \
 	__do_cancel ();							      \
@@ -277,23 +277,8 @@ __do_cancel (void)
 {
   struct pthread *self = THREAD_SELF;
 
-  /* Make sure we get no more cancellations by clearing the cancel
-     state.  */
-  int oldval = THREAD_GETMEM (self, cancelhandling);
-  while (1)
-    {
-      int newval = (oldval | CANCELSTATE_BITMASK);
-      newval &= ~(CANCELTYPE_BITMASK);
-      if (oldval == newval)
-	break;
-
-      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
-					  oldval);
-      if (__glibc_likely (curval == oldval))
-	break;
-      oldval = curval;
-    }
-  THREAD_ATOMIC_BIT_SET (self, cancelhandling, 
+  /* Make sure we get no more cancellations.  */
+  self->cancelstate = PTHREAD_CANCEL_DISABLE;
 
   THREAD_SETMEM (self, result, PTHREAD_CANCELED);
 
diff --git a/nptl/pthread_join.c b/nptl/pthread_join.c
index 2c8ce0c..eb4e35f 100644
--- a/nptl/pthread_join.c
+++ b/nptl/pthread_join.c
@@ -66,7 +66,7 @@ pthread_join (pthread_t threadid, void **thread_return)
 	   && (pd->cancelhandling
 	       & (CANCELED_BITMASK | EXITING_BITMASK
 		  | TERMINATED_BITMASK)) == 0))
-      && !CANCEL_ENABLED_AND_CANCELED (self->cancelhandling))
+      && !CANCEL_ENABLED_AND_CANCELED (self))
     /* This is a deadlock situation.  The threads are waiting for each
        other to finish.  Note that this is a "may" error.  To be 100%
        sure we catch this error we would have to lock the data
diff --git a/nptl/pthread_setcancelstate.c b/nptl/pthread_setcancelstate.c
index c8bc8b8..e011516 100644
--- a/nptl/pthread_setcancelstate.c
+++ b/nptl/pthread_setcancelstate.c
@@ -33,39 +33,13 @@ __pthread_setcancelstate (state, oldstate)
 
   self = THREAD_SELF;
 
-  int oldval = THREAD_GETMEM (self, cancelhandling);
-  while (1)
-    {
-      int newval = (state == PTHREAD_CANCEL_DISABLE
-		    ? oldval | CANCELSTATE_BITMASK
-		    : oldval & ~CANCELSTATE_BITMASK);
+  /* Store the old value.  */
+  if (oldstate != NULL)
+    *oldstate = THREAD_GETMEM (self, cancelstate);
+  self->cancelstate = state;
 
-      /* Store the old value.  */
-      if (oldstate != NULL)
-	*oldstate = ((oldval & CANCELSTATE_BITMASK)
-		     ? PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE);
-
-      /* Avoid doing unnecessary work.  The atomic operation can
-	 potentially be expensive if the memory has to be locked and
-	 remote cache lines have to be invalidated.  */
-      if (oldval == newval)
-	break;
-
-      /* Update the cancel handling word.  This has to be done
-	 atomically since other bits could be modified as well.  */
-      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
-					      oldval);
-      if (__glibc_likely (curval == oldval))
-	{
-	  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
-	    __do_cancel ();
-
-	  break;
-	}
-
-      /* Prepare for the next round.  */
-      oldval = curval;
-    }
+  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (self))
+    __do_cancel ();
 
   return 0;
 }
diff --git a/nptl/pthread_setcanceltype.c b/nptl/pthread_setcanceltype.c
index 11eff86..9190385 100644
--- a/nptl/pthread_setcanceltype.c
+++ b/nptl/pthread_setcanceltype.c
@@ -22,9 +22,7 @@
 
 
 int
-__pthread_setcanceltype (type, oldtype)
-     int type;
-     int *oldtype;
+__pthread_setcanceltype (int type, int *oldtype)
 {
   if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS)
     return EINVAL;
@@ -35,42 +33,14 @@ __pthread_setcanceltype (type, oldtype)
 #endif
 
   volatile struct pthread *self = THREAD_SELF;
+  if (oldtype != NULL)
+    *oldtype = THREAD_GETMEM (self, canceltype);
+  self->canceltype = type;
 
-  int oldval = THREAD_GETMEM (self, cancelhandling);
-  while (1)
+  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (self))
     {
-      int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS
-		    ? oldval | CANCELTYPE_BITMASK
-		    : oldval & ~CANCELTYPE_BITMASK);
-
-      /* Store the old value.  */
-      if (oldtype != NULL)
-	*oldtype = ((oldval & CANCELTYPE_BITMASK)
-		    ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED);
-
-      /* Avoid doing unnecessary work.  The atomic operation can
-	 potentially be expensive if the memory has to be locked and
-	 remote cache lines have to be invalidated.  */
-      if (oldval == newval)
-	break;
-
-      /* Update the cancel handling word.  This has to be done
-	 atomically since other bits could be modified as well.  */
-      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
-					      oldval);
-      if (__glibc_likely (curval == oldval))
-	{
-	  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
-	    {
-	      THREAD_SETMEM (self, result, PTHREAD_CANCELED);
-	      __do_cancel ();
-	    }
-
-	  break;
-	}
-
-      /* Prepare for the next round.  */
-      oldval = curval;
+      THREAD_SETMEM (self, result, PTHREAD_CANCELED);
+      __do_cancel ();
     }
 
   return 0;
diff --git a/sysdeps/x86_64/nptl/tcb-offsets.sym b/sysdeps/x86_64/nptl/tcb-offsets.sym
index 01c5ff7..44b2733 100644
--- a/sysdeps/x86_64/nptl/tcb-offsets.sym
+++ b/sysdeps/x86_64/nptl/tcb-offsets.sym
@@ -18,10 +18,7 @@ PRIVATE_FUTEX		offsetof (tcbhead_t, private_futex)
 #endif
 
 -- Not strictly offsets, but these values are also used in the TCB.
-TCB_CANCELSTATE_BITMASK	 CANCELSTATE_BITMASK
-TCB_CANCELTYPE_BITMASK	 CANCELTYPE_BITMASK
 TCB_CANCELED_BITMASK	 CANCELED_BITMASK
 TCB_EXITING_BITMASK	 EXITING_BITMASK
-TCB_CANCEL_RESTMASK	 CANCEL_RESTMASK
 TCB_TERMINATED_BITMASK	 TERMINATED_BITMASK
 TCB_PTHREAD_CANCELED	 PTHREAD_CANCELED

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c3ad343a459905f2efa3fa8108841bdb9c40cead

commit c3ad343a459905f2efa3fa8108841bdb9c40cead
Author: Adhemerval Zanella <adhemerval.zanella@linaro.com>
Date:   Wed Aug 12 11:13:21 2015 -0300

    nptl: s390x: Fix Race conditions in pthread cancellation (BZ#12683)
    
    This patch adds the s390 modifications required for the BZ#12683 fix.
    It basically removes the enable_asynccancel/disable_asynccancel function
    usage on code, provide a arch-specific symbol that contains global
    markers to be used in SIGCANCEL handler.
    
        * sysdeps/unix/sysv/linux/s390/s390-64/syscall_cancel.S: New file.
        * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): Redefine
         to call __syscall_cancel function for cancellable syscalls.
         (__pthread_get_ip): Add implementation.
        * sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h (SYSCALL_CANCEL_ERROR): Add
        definition.
        (SYSCALL_CANCEL_ERRNO): Likewise.

diff --git a/ChangeLog b/ChangeLog
index 8417b48..f31cecc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,14 @@
 2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 	    Stefan Liebler  <stli@linux.vnet.ibm.com>
 
+	* sysdeps/unix/sysv/linux/s390/s390-64/syscall_cancel.S: New file.
+	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): Redefine
+	to call __syscall_cancel function for cancellable syscalls.
+	(__pthread_get_ip): Add implementation.
+	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h (SYSCALL_CANCEL_ERROR): Add
+	definition.
+	(SYSCALL_CANCEL_ERRNO): Likewise.
+
 	* sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S: New file.
 	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Redefine
 	to call __syscall_cancel function for cancellable syscalls.
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/syscall_cancel.S b/sysdeps/unix/sysv/linux/s390/s390-64/syscall_cancel.S
new file mode 100644
index 0000000..2da44a5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/syscall_cancel.S
@@ -0,0 +1,87 @@
+/* Cancellable syscall wrapper - s390x version.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+/* long int [r2] __syscall_cancel_arch (int *cancelhandling [r2],
+					long int nr   [r3],
+					long int arg1 [r4],
+					long int arg2 [r5],
+					long int arg3 [r6],
+					long int arg4 [SP+160],
+					long int arg5 [SP+168],
+					long int arg6 [SP+176])  */
+
+ENTRY (__syscall_cancel_arch)
+
+	/* Save registers and setup stack.  */
+	stmg	%r6,%r15,48(%r15)  /* Save registers.  */
+	cfi_offset (%r15,-40)
+	cfi_offset (%r14,-48)
+	cfi_offset (%r13,-56)
+	cfi_offset (%r12,-64)
+	cfi_offset (%r11,-72)
+	cfi_offset (%r10,-80)
+	cfi_offset (%r9,-88)
+	cfi_offset (%r8,-96)
+	cfi_offset (%r7,-104)
+	cfi_offset (%r6,-112)
+	lgr	%r1,%r15
+	lg	%r0,8(%r15)	   /* Load eos.	 */
+	aghi	%r15,-160	   /* Buy stack space.	*/
+	cfi_adjust_cfa_offset (160)
+	stg	%r1,0(%r15)	   /* Store back chain.	 */
+	stg	%r0,8(%r15)	   /* Store eos.  */
+
+	.globl __syscall_cancel_arch_start
+	.type  __syscall_cancel_arch_start,@function
+__syscall_cancel_arch_start:
+
+	/* if (*cancelhandling & CANCELED_BITMASK)
+	     __syscall_do_cancel()  */
+	tm	3(%r2),4
+	jne	1f
+
+	/* Issue a 6 argument syscall  */
+	lgr	%r1,%r3		/* Move syscall number.  */
+	lgr	%r2,%r4		/* First parameter.  */
+	lgr	%r3,%r5		/* Second parameter.  */
+	lgr	%r4,%r6		/* Third parameter.  */
+	lg	%r5,320(%r15)	/* Fourth parameter.  */
+	lg	%r6,328(%r15)	/* Fifth parameter.  */
+	lg	%r7,336(%r15)	/* Sixth parameter.  */
+
+	svc	0		/* svc number is always in r1.  */
+
+	.globl __syscall_cancel_arch_end
+	.type  __syscall_cancel_arch_end,@function
+__syscall_cancel_arch_end:
+	lg	%r15,0(%r15)	/* load back chain */
+	cfi_adjust_cfa_offset (-160)
+	lmg	%r6,%r15,48(%r15) /* Load registers.  */
+
+	br	%r14
+
+	/* Branch to __syscall_do_cancel  */
+1:
+	lg	%r15,0(%r15)	/* load back chain */
+	cfi_adjust_cfa_offset (-160)
+	lmg	%r6,%r15,48(%r15) /* Load registers.  */
+	jg	__syscall_do_cancel
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
index e054dc9..d8da8c2 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
@@ -24,93 +24,85 @@
 
 #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
 
+# if IS_IN (libc)
+#  define JMP_SYSCALL_CANCEL HIDDEN_JUMPTARGET(__syscall_cancel)
+# else
+#  define JMP_SYSCALL_CANCEL __syscall_cancel@plt
+# endif
+
+# define STORE_0 /* Nothing */
+# define STORE_1 /* Nothing */
+# define STORE_2 /* Nothing */
+# define STORE_3 /* Nothing */
+# define STORE_4 stg %r6,48(%r15);		\
+ cfi_offset (%r6,-112);
+# define STORE_5 STORE_4
+# define STORE_6 STORE_4
+
+# define LOAD_0 /* Nothing */
+# define LOAD_1 /* Nothing */
+# define LOAD_2 /* Nothing */
+# define LOAD_3 /* Nothing */
+# define LOAD_4 lg %r6,48(%r15);
+# define LOAD_5 LOAD_4
+# define LOAD_6 LOAD_4
+
+# define MOVE_ARGS_0
+# define MOVE_ARGS_1 lgr %r3,%r2;		\
+	 MOVE_ARGS_0
+# define MOVE_ARGS_2 lgr %r4,%r3;		\
+	 MOVE_ARGS_1
+# define MOVE_ARGS_3 lgr %r5,%r4;		\
+	 MOVE_ARGS_2
+# define MOVE_ARGS_4 lgr %r6,%r5;		\
+	 MOVE_ARGS_3
+# define MOVE_ARGS_5 stg %r6,160(%r15);		\
+	 MOVE_ARGS_4
+# define MOVE_ARGS_6 lg %r14,160(%r14);		\
+	 stg %r14,168(%r15);			\
+	 MOVE_ARGS_5
+
+
 # undef PSEUDO
 # define PSEUDO(name, syscall_name, args)				      \
 	.text;								      \
 L(pseudo_cancel):							      \
 	cfi_startproc;							      \
-	STM_##args							      \
-	stmg	%r13,%r15,104(%r15);					      \
+	stmg	%r14,%r15,112(%r15);					      \
 	cfi_offset (%r15,-40);						      \
 	cfi_offset (%r14,-48);						      \
-	cfi_offset (%r13,-56);						      \
+	STORE_##args							      \
 	lgr	%r14,%r15;						      \
-	aghi	%r15,-160;						      \
-	cfi_adjust_cfa_offset (160);					      \
+	aghi	%r15,-176;						      \
+	cfi_adjust_cfa_offset (176);					      \
 	stg	%r14,0(%r15);						      \
-	brasl	%r14,CENABLE;						      \
-	lgr	%r0,%r2;						      \
-	LM_##args							      \
-	.if SYS_ify (syscall_name) < 256;				      \
-	svc SYS_ify (syscall_name);					      \
-	.else;								      \
-	lghi %r1,SYS_ify (syscall_name);				      \
-	svc 0;								      \
-	.endif;								      \
-	LR7_##args							      \
-	lgr	%r13,%r2;						      \
-	lgr	%r2,%r0;						      \
-	brasl	%r14,CDISABLE;						      \
-	lgr	%r2,%r13;						      \
-	lmg	%r13,%r15,104+160(%r15);				      \
+	MOVE_ARGS_##args						      \
+	lghi	%r2,SYS_ify (syscall_name);				      \
+	brasl	%r14,JMP_SYSCALL_CANCEL;				      \
+	lmg	%r14,%r15,112+176(%r15);			      	      \
+	cfi_restore (%r14);						      \
+	cfi_restore (%r15);						      \
+	LOAD_##args							      \
 	cfi_endproc;							      \
 	j	L(pseudo_check);					      \
 ENTRY(name)								      \
 	SINGLE_THREAD_P							      \
 	jne	L(pseudo_cancel);					      \
-.type	__##syscall_name##_nocancel,@function;				      \
-.globl	__##syscall_name##_nocancel;					      \
-__##syscall_name##_nocancel:						      \
 	DO_CALL(syscall_name, args);					      \
 L(pseudo_check):							      \
 	lghi	%r4,-4095;						      \
 	clgr	%r2,%r4;						      \
 	jgnl	SYSCALL_ERROR_LABEL;					      \
-.size	__##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \
 L(pseudo_end):
 
 # if IS_IN (libpthread)
-#  define CENABLE	__pthread_enable_asynccancel
-#  define CDISABLE	__pthread_disable_asynccancel
 #  define __local_multiple_threads	__pthread_multiple_threads
 # elif IS_IN (libc)
-#  define CENABLE	__libc_enable_asynccancel
-#  define CDISABLE	__libc_disable_asynccancel
 #  define __local_multiple_threads	__libc_multiple_threads
-# elif IS_IN (librt)
-#  define CENABLE	__librt_enable_asynccancel
-#  define CDISABLE	__librt_disable_asynccancel
-# else
+# elif !IS_IN (librt)
 #  error Unsupported library
 # endif
 
-#define STM_0		/* Nothing */
-#define STM_1		stg %r2,16(%r15);
-#define STM_2		stmg %r2,%r3,16(%r15);
-#define STM_3		stmg %r2,%r4,16(%r15);
-#define STM_4		stmg %r2,%r5,16(%r15);
-#define STM_5		stmg %r2,%r5,16(%r15);
-#define STM_6		stmg %r2,%r7,16(%r15);
-
-#define LM_0		/* Nothing */
-#define LM_1		lg %r2,16+160(%r15);
-#define LM_2		lmg %r2,%r3,16+160(%r15);
-#define LM_3		lmg %r2,%r4,16+160(%r15);
-#define LM_4		lmg %r2,%r5,16+160(%r15);
-#define LM_5		lmg %r2,%r5,16+160(%r15);
-#define LM_6		lmg %r2,%r5,16+160(%r15); \
-			cfi_offset (%r7, -104); \
-			lg %r7,160+160(%r15);
-
-#define LR7_0		/* Nothing */
-#define LR7_1		/* Nothing */
-#define LR7_2		/* Nothing */
-#define LR7_3		/* Nothing */
-#define LR7_4		/* Nothing */
-#define LR7_5		/* Nothing */
-#define LR7_6		lg %r7,56+160(%r15); \
-			cfi_restore (%r7);
-
 # if IS_IN (libpthread) || IS_IN (libc)
 #  ifndef __ASSEMBLER__
 extern int __local_multiple_threads attribute_hidden;
@@ -149,4 +141,10 @@ extern int __local_multiple_threads attribute_hidden;
 # define RTLD_SINGLE_THREAD_P \
   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
 				   header.multiple_threads) == 0, 1)
+
+static inline
+long int __pthread_get_ip (const struct ucontext *uc)
+{
+  return uc->uc_mcontext.psw.addr;
+}
 #endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
index c041153..4be051e 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
@@ -249,6 +249,14 @@
 #undef INTERNAL_SYSCALL_ERRNO
 #define INTERNAL_SYSCALL_ERRNO(val, err)	(-(val))
 
+#undef SYSCALL_CANCEL_ERROR
+#define SYSCALL_CANCEL_ERROR(__val)		\
+  ((unsigned long) (__val) >= -4095UL)
+
+#undef SYSCALL_CANCEL_ERRNO
+#define SYSCALL_CANCEL_ERRNO(__val) \
+  (-(__val))
+
 #define DECLARGS_0()
 #define DECLARGS_1(arg1) \
 	register unsigned long gpr2 asm ("2") = (unsigned long)(arg1);

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=66fbd551e5317849daf98b2b18e929bfefe44400

commit 66fbd551e5317849daf98b2b18e929bfefe44400
Author: Adhemerval Zanella <adhemerval.zanella@linaro.com>
Date:   Wed Aug 12 10:51:38 2015 -0300

    nptl: s390: Fix Race conditions in pthread cancellation (BZ#12683)
    
    This patch adds the s390 modifications required for the BZ#12683 fix.
    It basically removes the enable_asynccancel/disable_asynccancel function
    usage on code, provide a arch-specific symbol that contains global
    markers to be used in SIGCANCEL handler.
    
        * sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S: New file.
        * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Redefine
        to call __syscall_cancel function for cancellable syscalls.
        (__pthread_get_ip): Add implementation.
        * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h (SYSCALL_CANCEL_ERROR): Add
        definition.
        (SYSCALL_CANCEL_ERRNO): Likewise.

diff --git a/ChangeLog b/ChangeLog
index dfb9d6a..8417b48 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,15 @@
 2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+	    Stefan Liebler  <stli@linux.vnet.ibm.com>
+
+	* sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S: New file.
+	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Redefine
+	to call __syscall_cancel function for cancellable syscalls.
+	(__pthread_get_ip): Add implementation.
+	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h (SYSCALL_CANCEL_ERROR): Add
+	definition.
+	(SYSCALL_CANCEL_ERRNO): Likewise.
+
+2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
 	* sysdeps/unix/sysv/linux/arm/syscall_cancel.S: New file.
 	* sysdeps/unix/sysv/linux/arm/sysdep-cancel.h (PSEUDO): Redefine
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S b/sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S
new file mode 100644
index 0000000..bf90acd
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/syscall_cancel.S
@@ -0,0 +1,85 @@
+/* Cancellable syscall wrapper - s390 version.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+/* long int [r2] __syscall_cancel_arch (int *cancelhandling [r2],
+					long int nr   [r3],
+					long int arg1 [r4],
+					long int arg2 [r5],
+					long int arg3 [r6],
+					long int arg4 [SP+96],
+					long int arg5 [SP+100],
+					long int arg6 [SP+104])  */
+
+ENTRY (__syscall_cancel_arch)
+	/* Save registers and setup stack.  */
+	stm     %r6,%r15,24(%r15)	/* Save registers */
+	cfi_offset (%r15, -36)
+	cfi_offset (%r14, -40)
+	cfi_offset (%r13, -44)
+	cfi_offset (%r12, -48)
+	cfi_offset (%r11, -52)
+	cfi_offset (%r10, -56)
+	cfi_offset (%r9, -60)
+	cfi_offset (%r8, -64)
+	cfi_offset (%r7, -68)
+	cfi_offset (%r6, -72)
+	lr      %r1,%r15
+	l       %r0,4(0,%r15)		/* Load eos */
+	ahi     %r15,-96		/* Buy stack space */
+	cfi_adjust_cfa_offset (96)
+	st      %r1,0(0,%r15)		/* Store back chain */
+	st      %r0,4(0,%r15)		/* Store eos */
+
+	.globl __syscall_cancel_arch_start
+	.type  __syscall_cancel_arch_start,@function
+__syscall_cancel_arch_start:
+
+	/* if (*cancelhandling & CANCELED_BITMASK)
+	     __syscall_do_cancel()  */
+	tm	3(%r2),4
+	jne	1f
+
+	/* Issue a 6 argument syscall  */
+	lr	%r1,%r3			/* Move syscall number.  */
+	lr	%r2,%r4			/* First parameter.  */
+	lr	%r3,%r5			/* Second parameter.  */
+	lr	%r4,%r6			/* Third parameter.  */
+	l	%r5,192(%r15)		/* Fourth parameter.  */
+	l	%r6,196(%r15)		/* Fifth parameter.  */
+	l	%r7,200(%r15)		/* Sixth parameter.  */
+
+	svc	0			/* svc number is always in r1.  */
+	.globl __syscall_cancel_arch_end
+	.type  __syscall_cancel_arch_end,@function
+__syscall_cancel_arch_end:
+	l	%r15,0(%r15)		/* Load back chain.  */
+	cfi_adjust_cfa_offset (-96)
+	lm	%r6,15,24(%r15)		/* Load registers.  */
+
+	br	%r14
+
+	/* Branch to __syscall_do_cancel  */
+1:
+	l	%r15,0(%r15)		/* Load back chain.  */
+	cfi_adjust_cfa_offset (-96)
+	lm	%r6,%r15,24(%r15)	/* Load registers.  */
+	jg	__syscall_do_cancel
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
index 17b7aaa..1ed57f0 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
@@ -24,97 +24,90 @@
 
 #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
 
+# if IS_IN (libc)
+#  define PREPARE_CALL
+#  define PREPARE_GOT
+#  define JMP_SYSCALL_CANCEL HIDDEN_JUMPTARGET(__syscall_cancel)
+# else
+#  define PREPARE_CALL l %r12,2f-0b(%r13);			\
+  la %r12,0(%r12,%r13);
+#  define PREPARE_GOT 2: .long _GLOBAL_OFFSET_TABLE_-0b;
+#  define JMP_SYSCALL_CANCEL __syscall_cancel@plt
+# endif
+
+# define STORE_0 /* Nothing */
+# define STORE_1 /* Nothing */
+# define STORE_2 /* Nothing */
+# define STORE_3 /* Nothing */
+# define STORE_4 st %r6,24(%r15);		\
+ cfi_offset (%r6,-72);
+# define STORE_5 STORE_4
+# define STORE_6 STORE_4
+
+# define LOAD_0 /* Nothing */
+# define LOAD_1 /* Nothing */
+# define LOAD_2 /* Nothing */
+# define LOAD_3 /* Nothing */
+# define LOAD_4 l %r6,24(%r15);
+# define LOAD_5 LOAD_4
+# define LOAD_6 LOAD_4
+
+# define MOVE_ARGS_0
+# define MOVE_ARGS_1 lr %r3,%r2;		\
+	 MOVE_ARGS_0
+# define MOVE_ARGS_2 lr %r4,%r3;		\
+	 MOVE_ARGS_1
+# define MOVE_ARGS_3 lr %r5,%r4;		\
+	 MOVE_ARGS_2
+# define MOVE_ARGS_4 lr %r6,%r5;		\
+	 MOVE_ARGS_3
+# define MOVE_ARGS_5 st %r6,96(%r15);		\
+	 MOVE_ARGS_4
+# define MOVE_ARGS_6 l %r14,96(%r14);		\
+	 st %r14,100(%r15);			\
+	 MOVE_ARGS_5
+
 # undef PSEUDO
 # define PSEUDO(name, syscall_name, args)				      \
 	.text;								      \
 L(pseudo_cancel):							      \
 	cfi_startproc;							      \
-	STM_##args							      \
 	stm	%r12,%r15,48(%r15);					      \
 	cfi_offset (%r15, -36);						      \
 	cfi_offset (%r14, -40);						      \
 	cfi_offset (%r13, -44);						      \
 	cfi_offset (%r12, -48);						      \
+	STORE_##args							      \
 	lr	%r14,%r15;						      \
-	ahi	%r15,-96;						      \
-	cfi_adjust_cfa_offset (96);					      \
+	ahi	%r15,-104;						      \
+	cfi_adjust_cfa_offset (104);					      \
 	st	%r14,0(%r15);						      \
+	MOVE_ARGS_##args						      \
+	lhi	%r2,SYS_ify (syscall_name);				      \
 	basr    %r13,0;							      \
 0:	l	%r1,1f-0b(%r13);					      \
+	PREPARE_CALL							      \
 	bas	%r14,0(%r1,%r13);					      \
-	lr	%r0,%r2;						      \
-	LM_##args							      \
-	.if SYS_ify (syscall_name) < 256;				      \
-	svc SYS_ify (syscall_name);					      \
-	.else;								      \
-	lhi %r1,SYS_ify (syscall_name);					      \
-	svc 0;								      \
-	.endif;								      \
-	LR7_##args							      \
-	l	%r1,2f-0b(%r13);					      \
-	lr	%r12,%r2;						      \
-	lr	%r2,%r0;						      \
-	bas	%r14,0(%r1,%r13);					      \
-	lr	%r2,%r12;						      \
-	lm	%r12,%r15,48+96(%r15);					      \
+	lm	%r12,%r15,48+104(%r15);					      \
+	cfi_restore (%r12);						      \
+	cfi_restore (%r13);						      \
+	cfi_restore (%r14);						      \
+	cfi_restore (%r15);						      \
+	LOAD_##args							      \
 	cfi_endproc;							      \
 	j	L(pseudo_check);					      \
-1:	.long	CENABLE-0b;						      \
-2:	.long	CDISABLE-0b;						      \
+1:	.long	JMP_SYSCALL_CANCEL-0b;					      \
+	PREPARE_GOT							      \
 ENTRY(name)								      \
 	SINGLE_THREAD_P(%r1)						      \
 	jne	L(pseudo_cancel);					      \
-.type	__##syscall_name##_nocancel,@function;				      \
-.globl	__##syscall_name##_nocancel;					      \
-__##syscall_name##_nocancel:						      \
 	DO_CALL(syscall_name, args);					      \
 L(pseudo_check):							      \
 	lhi	%r4,-4095;						      \
 	clr	%r2,%r4;						      \
 	jnl	SYSCALL_ERROR_LABEL;					      \
-.size	__##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \
 L(pseudo_end):
 
-# if IS_IN (libpthread)
-#  define CENABLE	__pthread_enable_asynccancel
-#  define CDISABLE	__pthread_disable_asynccancel
-# elif IS_IN (libc)
-#  define CENABLE	__libc_enable_asynccancel
-#  define CDISABLE	__libc_disable_asynccancel
-# elif IS_IN (librt)
-#  define CENABLE	__librt_enable_asynccancel
-#  define CDISABLE	__librt_disable_asynccancel
-# else
-#  error Unsupported library
-# endif
-
-#define STM_0		/* Nothing */
-#define STM_1		st %r2,8(%r15);
-#define STM_2		stm %r2,%r3,8(%r15);
-#define STM_3		stm %r2,%r4,8(%r15);
-#define STM_4		stm %r2,%r5,8(%r15);
-#define STM_5		stm %r2,%r5,8(%r15);
-#define STM_6		stm %r2,%r7,8(%r15);
-
-#define LM_0		/* Nothing */
-#define LM_1		l %r2,8+96(%r15);
-#define LM_2		lm %r2,%r3,8+96(%r15);
-#define LM_3		lm %r2,%r4,8+96(%r15);
-#define LM_4		lm %r2,%r5,8+96(%r15);
-#define LM_5		lm %r2,%r5,8+96(%r15);
-#define LM_6		lm %r2,%r5,8+96(%r15); \
-			cfi_offset (%r7, -68); \
-			l %r7,96+96(%r15);
-
-#define LR7_0		/* Nothing */
-#define LR7_1		/* Nothing */
-#define LR7_2		/* Nothing */
-#define LR7_3		/* Nothing */
-#define LR7_4		/* Nothing */
-#define LR7_5		/* Nothing */
-#define LR7_6		l %r7,28+96(%r15); \
-			cfi_restore (%r7);
-
 # ifndef __ASSEMBLER__
 #  define SINGLE_THREAD_P \
   __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \
@@ -136,4 +129,11 @@ L(pseudo_end):
 # define RTLD_SINGLE_THREAD_P \
   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
 				   header.multiple_threads) == 0, 1)
+
+static inline
+long int __pthread_get_ip (const struct ucontext *uc)
+{
+  /* We have 31bit addresses, remove bit 0.  */
+  return uc->uc_mcontext.psw.addr & 0x7FFFFFFF;
+}
 #endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
index c768df1..08e2be4 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
@@ -243,6 +243,14 @@
 #undef INTERNAL_SYSCALL_ERRNO
 #define INTERNAL_SYSCALL_ERRNO(val, err)	(-(val))
 
+#undef SYSCALL_CANCEL_ERROR
+#define SYSCALL_CANCEL_ERROR(__val) \
+  ((unsigned int) (__val) >= 0xfffff001u)
+
+#undef SYSCALL_CANCEL_ERRNO
+#define SYSCALL_CANCEL_ERRNO(__val) \
+  (-(__val))
+
 #define DECLARGS_0()
 #define DECLARGS_1(arg1) \
 	register unsigned long gpr2 asm ("2") = (unsigned long)(arg1);

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6705bcfb41b3831d21317a715c1782ead0cacd87

commit 6705bcfb41b3831d21317a715c1782ead0cacd87
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Fri May 8 17:12:31 2015 -0300

    nptl: arm: Fix Race conditions in pthread cancellation (BZ#12683)
    
    This patch adds the ARM modifications required for the BZ#12683 fix.
    It basically removes the enable_asynccancel/disable_asynccancel function
    usage on code, provide a arch-specific symbol that contains global
    markers to be used in SIGCANCEL handler.
    
    	* sysdeps/unix/sysv/linux/arm/syscall_cancel.S: New file.
    	* sysdeps/unix/sysv/linux/arm/sysdep-cancel.h (PSEUDO): Redefine
    	to call __syscall_cancel function for cancellable syscalls.
    	* sysdeps/unix/sysv/linux/arm/sysdep.h (SYSCALL_CANCEL_ERROR): Add
    	definition.
    	(SYSCALL_CANCEL_ERRNO): Likewise.

diff --git a/ChangeLog b/ChangeLog
index b361fb0..dfb9d6a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
+	* sysdeps/unix/sysv/linux/arm/syscall_cancel.S: New file.
+	* sysdeps/unix/sysv/linux/arm/sysdep-cancel.h (PSEUDO): Redefine
+	to call __syscall_cancel function for cancellable syscalls.
+	* sysdeps/unix/sysv/linux/arm/sysdep.h (SYSCALL_CANCEL_ERROR): Add
+	definition.
+	(SYSCALL_CANCEL_ERRNO): Likewise.
+
 	* sysdeps/unix/sysv/linux/aarch64/syscall_cancel.S: New file.
 	* sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h (PSEUDO): Redefine
 	to call __syscall_cancel function for cancellable syscalls.
diff --git a/sysdeps/unix/sysv/linux/arm/syscall_cancel.S b/sysdeps/unix/sysv/linux/arm/syscall_cancel.S
new file mode 100644
index 0000000..da4b454
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arm/syscall_cancel.S
@@ -0,0 +1,72 @@
+/* Cancellable syscall wrapper - arm version.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+/* long int [r0] __syscall_cancel_arch (int *cancelhandling [r0],
+					long int nr   [r1],
+					long int arg1 [r2],
+					long int arg2 [r3],
+					long int arg3 [SP],
+					long int arg4 [SP+4],
+					long int arg5 [SP+8],
+					long int arg6 [SP+12])  */
+
+#ifdef __thumb2__
+	.thumb
+#endif
+	.syntax unified
+
+ENTRY (__syscall_cancel_arch)
+	.fnstart
+        mov	ip,sp
+        stmfd	sp!,{r4,r5,r6,lr}
+	.save	{r4,r5,r6,lr}
+
+	cfi_adjust_cfa_offset (20)
+	cfi_rel_offset (lr, 16)
+
+	.globl __syscall_cancel_arch_start
+__syscall_cancel_arch_start:
+
+	/* if (*cancelhandling & CANCELED_BITMASK)
+	     __syscall_do_cancel()  */
+        ldr	r0,[r0]
+	tst	r0, #4
+        bne	1f
+
+	/* Issue a 6 argument syscall, the nr [r1] being the syscall
+	   number.  */
+        mov	r7,r1
+        mov	r0,r2
+        mov	r1,r3
+        ldmfd	ip,{r2,r3,r4,r5,r6}
+        svc	0x0
+
+	.globl __syscall_cancel_arch_end
+__syscall_cancel_arch_end:
+	ldmfd	sp!,{r4,r5,r6,lr}
+	cfi_adjust_cfa_offset (-16);
+        bx	lr
+
+1:
+	mov	lr, pc
+	b	__syscall_do_cancel
+	.fnend
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
diff --git a/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
index bdefa80..afbf07d 100644
--- a/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
+++ b/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
@@ -19,10 +19,17 @@
 #include <tls.h>
 #ifndef __ASSEMBLER__
 # include <nptl/pthreadP.h>
+# include <sys/ucontext.h>
 #endif
 
 #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
 
+# if IS_IN (libc)
+#  define JMP_SYSCALL_CANCEL  HIDDEN_JUMPTARGET(__syscall_cancel)
+# else
+#  define JMP_SYSCALL_CANCEL  __syscall_cancel(PLT)
+# endif
+
 /* NOTE: We do mark syscalls with unwind annotations, for the benefit of
    cancellation; but they're really only accurate at the point of the
    syscall.  The ARM unwind directives are not rich enough without adding
@@ -31,16 +38,10 @@
 # undef PSEUDO
 # define PSEUDO(name, syscall_name, args)				\
 	.text;								\
-  ENTRY (__##syscall_name##_nocancel);					\
-	CFI_SECTIONS;							\
-	DO_CALL (syscall_name, args);					\
-	cmn	r0, $4096;						\
-	PSEUDO_RET;							\
-  END (__##syscall_name##_nocancel);					\
   ENTRY (name);								\
 	SINGLE_THREAD_P;						\
-	DOARGS_##args;							\
 	bne .Lpseudo_cancel;						\
+	DOARGS_##args;							\
 	cfi_remember_state;						\
 	ldr	r7, =SYS_ify (syscall_name);				\
 	swi	0x0;							\
@@ -50,150 +51,36 @@
 	cfi_restore_state;						\
   .Lpseudo_cancel:							\
 	.fnstart;	/* matched by the .fnend in UNDOARGS below.  */	\
-	DOCARGS_##args;	/* save syscall args etc. around CENABLE.  */	\
-	CENABLE;							\
-	mov ip, r0;		/* put mask in safe place.  */		\
-	UNDOCARGS_##args;	/* restore syscall args.  */		\
-	ldr	r7, =SYS_ify (syscall_name);				\
-	swi	0x0;		/* do the call.  */			\
-	mov	r7, r0;		/* save syscall return value.  */	\
-	mov	r0, ip;		/* get mask back.  */			\
-	CDISABLE;							\
-	mov	r0, r7;		/* retrieve return value.  */		\
-	RESTORE_LR_##args;						\
-	UNDOARGS_##args;						\
+	push	{r4, r5, lr};						\
+	.save   {r4, r5, lr};						\
+	PSEUDO_CANCEL_BEFORE;						\
+	ldr	r0, =SYS_ify (syscall_name);				\
+	PSEUDO_CANCEL_AFTER;						\
+	pop	{r4, r5, lr};						\
+	.fnend;								\
 	cmn	r0, $4096
 
-/* DOARGS pushes eight bytes on the stack for five arguments, twelve bytes for
-   six arguments, and four bytes for fewer.  In order to preserve doubleword
-   alignment, sometimes we must save an extra register.  */
-
-# define RESTART_UNWIND				\
-	.fnend;					\
-	.fnstart;				\
-	.save	{r7};				\
-	.save	{lr}
-
-# define DOCARGS_0				\
-	.save {r7};				\
-	push	{lr};				\
-	cfi_adjust_cfa_offset (4);		\
-	cfi_rel_offset (lr, 0);			\
-	.save	{lr}
-# define UNDOCARGS_0
-# define RESTORE_LR_0				\
-	pop	{lr};				\
-	cfi_adjust_cfa_offset (-4);		\
-	cfi_restore (lr)
-
-# define DOCARGS_1				\
-	.save	{r7};				\
-	push	{r0, r1, lr};			\
-	cfi_adjust_cfa_offset (12);		\
-	cfi_rel_offset (lr, 8);			\
-	.save	{lr};				\
-	.pad	#8
-# define UNDOCARGS_1				\
-	ldr r0, [sp], #8;			\
-	cfi_adjust_cfa_offset (-8);		\
-	RESTART_UNWIND
-# define RESTORE_LR_1				\
-	RESTORE_LR_0
-
-# define DOCARGS_2				\
-	.save	{r7};				\
-	push	{r0, r1, lr};			\
-	cfi_adjust_cfa_offset (12);		\
-	cfi_rel_offset (lr, 8);			\
-	.save	{lr};				\
-	.pad	#8
-# define UNDOCARGS_2				\
-	pop	{r0, r1};			\
-	cfi_adjust_cfa_offset (-8);		\
-	RESTART_UNWIND
-# define RESTORE_LR_2				\
-	RESTORE_LR_0
-
-# define DOCARGS_3				\
-	.save	{r7};				\
-	push	{r0, r1, r2, r3, lr};		\
-	cfi_adjust_cfa_offset (20);		\
-	cfi_rel_offset (lr, 16);		\
-	.save	{lr};				\
-	.pad	#16
-# define UNDOCARGS_3				\
-	pop	{r0, r1, r2, r3};		\
-	cfi_adjust_cfa_offset (-16);		\
-	RESTART_UNWIND
-# define RESTORE_LR_3				\
-	RESTORE_LR_0
-
-# define DOCARGS_4				\
-	.save	{r7};				\
-	push	{r0, r1, r2, r3, lr};		\
-	cfi_adjust_cfa_offset (20);		\
-	cfi_rel_offset (lr, 16);		\
-	.save	{lr};				\
-	.pad	#16
-# define UNDOCARGS_4				\
-	pop	{r0, r1, r2, r3};		\
-	cfi_adjust_cfa_offset (-16);		\
-	RESTART_UNWIND
-# define RESTORE_LR_4				\
-	RESTORE_LR_0
-
-/* r4 is only stmfd'ed for correct stack alignment.  */
-# define DOCARGS_5				\
-	.save	{r4, r7};			\
-	push	{r0, r1, r2, r3, r4, lr};	\
-	cfi_adjust_cfa_offset (24);		\
-	cfi_rel_offset (lr, 20);		\
-	.save	{lr};				\
-	.pad	#20
-# define UNDOCARGS_5				\
-	pop	{r0, r1, r2, r3};		\
-	cfi_adjust_cfa_offset (-16);		\
-	.fnend;					\
-	.fnstart;				\
-	.save	{r4, r7};			\
-	.save	{lr};				\
-	.pad	#4
-# define RESTORE_LR_5				\
-	pop	{r4, lr};			\
-	cfi_adjust_cfa_offset (-8);		\
-	/* r4 will be marked as restored later.  */ \
-	cfi_restore (lr)
-
-# define DOCARGS_6				\
-	.save	{r4, r5, r7};			\
-	push	{r0, r1, r2, r3, lr};		\
-	cfi_adjust_cfa_offset (20);		\
-	cfi_rel_offset (lr, 16);		\
-	.save	{lr};				\
-	.pad	#16
-# define UNDOCARGS_6				\
-	pop	{r0, r1, r2, r3};		\
-	cfi_adjust_cfa_offset (-16);		\
-	.fnend;					\
-	.fnstart;				\
-	.save	{r4, r5, r7};			\
-	.save	{lr};
-# define RESTORE_LR_6				\
-	RESTORE_LR_0
+# define PSEUDO_CANCEL_BEFORE						\
+	.pad	#20;							\
+	sub	sp, sp, #20;						\
+	ldr	r5, [sp, #32];						\
+	ldr	r4, [sp, #36];						\
+	str	r3, [sp];						\
+	mov	r3, r2;							\
+	str	r5, [sp, #4];						\
+	mov	r2, r1;							\
+	str	r4, [sp, #8];						\
+	mov	r1, r0
+
+# define PSEUDO_CANCEL_AFTER						\
+	bl	JMP_SYSCALL_CANCEL;					\
+	add	sp, sp, #20
+
 
 # if IS_IN (libpthread)
-#  define CENABLE	bl PLTJMP(__pthread_enable_asynccancel)
-#  define CDISABLE	bl PLTJMP(__pthread_disable_asynccancel)
 #  define __local_multiple_threads __pthread_multiple_threads
 # elif IS_IN (libc)
-#  define CENABLE	bl PLTJMP(__libc_enable_asynccancel)
-#  define CDISABLE	bl PLTJMP(__libc_disable_asynccancel)
 #  define __local_multiple_threads __libc_multiple_threads
-# elif IS_IN (librt)
-#  define CENABLE	bl PLTJMP(__librt_enable_asynccancel)
-#  define CDISABLE	bl PLTJMP(__librt_disable_asynccancel)
-# else
-#  error Unsupported library
 # endif
 
 # if IS_IN (libpthread) || IS_IN (libc)
@@ -238,4 +125,10 @@ extern int __local_multiple_threads attribute_hidden;
 # define RTLD_SINGLE_THREAD_P \
   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
 				   header.multiple_threads) == 0, 1)
+
+static inline
+long int __pthread_get_ip (const struct ucontext *uc)
+{
+  return uc->uc_mcontext.arm_pc;
+}
 #endif
diff --git a/sysdeps/unix/sysv/linux/arm/sysdep.h b/sysdeps/unix/sysv/linux/arm/sysdep.h
index 200f77a..6b18e34 100644
--- a/sysdeps/unix/sysv/linux/arm/sysdep.h
+++ b/sysdeps/unix/sysv/linux/arm/sysdep.h
@@ -387,6 +387,14 @@ __local_syscall_error:						\
 #undef INTERNAL_SYSCALL_ERRNO
 #define INTERNAL_SYSCALL_ERRNO(val, err)	(-(val))
 
+#undef SYSCALL_CANCEL_ERROR
+#define SYSCALL_CANCEL_ERROR(__val) \
+  ((unsigned int) (__val) >= 0xfffff001u)
+
+#undef SYSCALL_CANCEL_ERRNO
+#define SYSCALL_CANCEL_ERRNO(__val) \
+  (-(__val))
+
 /* List of system calls which are supported as vsyscalls.  */
 #define HAVE_CLOCK_GETTIME_VSYSCALL	1
 #define HAVE_GETTIMEOFDAY_VSYSCALL	1

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=16d62cfd10288b96b0e683c7ff46094bfd181cf7

commit 16d62cfd10288b96b0e683c7ff46094bfd181cf7
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Wed May 6 17:51:29 2015 -0300

    nptl: aarch64: Fix Race conditions in pthread cancellation (BZ#12683)
    
    This patch adds the aarch64 modifications required for the BZ#12683 fix.
    It basically removes the enable_asynccancel/disable_asynccancel function
    usage on code, provide a arch-specific symbol that contains global
    markers to be used in SIGCANCEL handler.
    
    	* sysdeps/unix/sysv/linux/aarch64/syscall_cancel.S: New file.
    	* sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h (PSEUDO): Redefine
    	to call __syscall_cancel function for cancellable syscalls.
    	(__pthread_get_ip): Add implementation.
    	* sysdeps/unix/sysv/linux/aarch64/sysdep.h (SYSCALL_CANCEL_ERROR): Add
    	definition.
    	(SYSCALL_CANCEL_ERRNO): Likewise.

diff --git a/ChangeLog b/ChangeLog
index 6475a5f..b361fb0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
+	* sysdeps/unix/sysv/linux/aarch64/syscall_cancel.S: New file.
+	* sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h (PSEUDO): Redefine
+	to call __syscall_cancel function for cancellable syscalls.
+	(__pthread_get_ip): Add implementation.
+	* sysdeps/unix/sysv/linux/aarch64/sysdep.h (SYSCALL_CANCEL_ERROR): Add
+	definition.
+	(SYSCALL_CANCEL_ERRNO): Likewise.
+
 	* sysdeps/unix/sysv/linux/i386/fcntl.c (NO_CANCELLATION): Replace
 	by IS_IN (rtld).
 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (PSEUDO):
diff --git a/sysdeps/unix/sysv/linux/aarch64/syscall_cancel.S b/sysdeps/unix/sysv/linux/aarch64/syscall_cancel.S
new file mode 100644
index 0000000..56ede8e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/syscall_cancel.S
@@ -0,0 +1,61 @@
+/* Cancellable syscall wrapper - aarch64 version.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+/* long int [r0] __syscall_cancel_arch (int *cancelhandling [x0],
+					long int nr   [x1],
+					long int arg1 [x2],
+					long int arg2 [x3],
+					long int arg3 [x4],
+					long int arg4 [x5],
+					long int arg5 [x6],
+					long int arg6 [x7])  */
+
+ENTRY (__syscall_cancel_arch)
+
+	.globl __syscall_cancel_arch_start
+	.type  __syscall_cancel_arch_start,@function
+__syscall_cancel_arch_start:
+
+	/* if (*cancelhandling & CANCELED_BITMASK)
+	     __syscall_do_cancel()  */
+	ldr	w0, [x0]
+	tbnz    w0, 2, 1f
+
+	/* Issue a 6 argument syscall, the nr [x1] being the syscall
+	   number.  */
+	mov	x8, x1
+	mov	x0, x2
+	mov	x1, x3
+	mov	x2, x4
+	mov	x3, x5
+	mov	x4, x6
+	mov	x5, x7
+	svc	0x0
+
+	.globl __syscall_cancel_arch_end
+	.type  __syscall_cancel_arch_end,@function
+__syscall_cancel_arch_end:
+	ret
+
+1:
+	b	__syscall_do_cancel
+
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
diff --git a/sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h b/sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h
index 36e8e39..71207b3 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h
+++ b/sysdeps/unix/sysv/linux/aarch64/sysdep-cancel.h
@@ -20,80 +20,57 @@
 #include <tls.h>
 #ifndef __ASSEMBLER__
 # include <nptl/pthreadP.h>
+# include <sys/ucontext.h>
 #endif
 
 #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
 
+# if IS_IN (libc)
+#  define JMP_SYSCALL_CANCEL HIDDEN_JUMPTARGET(__syscall_cancel)
+# else
+#  define JMP_SYSCALL_CANCEL __syscall_cancel
+# endif
+
 # undef PSEUDO
 # define PSEUDO(name, syscall_name, args)				\
-	.section ".text";						\
-ENTRY (__##syscall_name##_nocancel);					\
-.Lpseudo_nocancel:							\
-	DO_CALL (syscall_name, args);					\
-.Lpseudo_finish:							\
-	cmn	x0, 4095;						\
-	b.cs	.Lsyscall_error;					\
-	.subsection 2;							\
-	.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
 ENTRY (name);								\
 	SINGLE_THREAD_P(16);						\
-	cbz	w16, .Lpseudo_nocancel;					\
-	/* Setup common stack frame no matter the number of args.	\
-	   Also save the first arg, since it's basically free.  */	\
-	stp	x30, x0, [sp, -64]!;					\
-	cfi_adjust_cfa_offset (64);					\
-	cfi_rel_offset (x30, 0);					\
-	DOCARGS_##args;		/* save syscall args around CENABLE.  */ \
-	CENABLE;							\
-	mov	x16, x0;	/* save mask around syscall.  */	\
-	UNDOCARGS_##args;	/* restore syscall args.  */		\
+	cbnz	w16, L(pseudo_cancel);					\
 	DO_CALL (syscall_name, args);					\
-	str	x0, [sp, 8];	/* save result around CDISABLE.  */	\
-	mov	x0, x16;	/* restore mask for CDISABLE.  */	\
-	CDISABLE;							\
-	/* Break down the stack frame, restoring result at once.  */	\
-	ldp	x30, x0, [sp], 64;					\
-	cfi_adjust_cfa_offset (-64);					\
-	cfi_restore (x30);						\
-	b	.Lpseudo_finish;					\
-	cfi_endproc;							\
-	.size	name, .-name;						\
-	.previous
+	b	L(pseudo_finish);					\
+L(pseudo_cancel):							\
+	stp     x29, x30, [sp, -16]!;					\
+	cfi_def_cfa_offset (16);					\
+	cfi_offset (29, -16);						\
+	cfi_offset (30, -8);						\
+	add	x29, sp, 0;						\
+	cfi_def_cfa_register (29);					\
+	mov	x6, x5;							\
+	mov	x5, x4;							\
+	mov	x4, x3;							\
+	mov	x3, x2;							\
+	mov	x2, x1;							\
+	mov	x1, x0;							\
+	mov	x0, SYS_ify (syscall_name);				\
+	bl	JMP_SYSCALL_CANCEL;					\
+	ldp     x29, x30, [sp], 16;					\
+	cfi_restore (30);                                               \
+	cfi_restore (29);						\
+	cfi_def_cfa (31, 0);						\
+L(pseudo_finish):							\
+        cmn     x0, 4095;                                               \
+        b.cs    L(syscall_error);
 
 # undef PSEUDO_END
 # define PSEUDO_END(name)						\
 	SYSCALL_ERROR_HANDLER;						\
-	cfi_endproc
-
-# define DOCARGS_0
-# define DOCARGS_1
-# define DOCARGS_2	str x1, [sp, 16]
-# define DOCARGS_3	stp x1, x2, [sp, 16]
-# define DOCARGS_4	DOCARGS_3; str x3, [sp, 32]
-# define DOCARGS_5	DOCARGS_3; stp x3, x4, [sp, 32]
-# define DOCARGS_6	DOCARGS_5; str x5, [sp, 48]
-
-# define UNDOCARGS_0
-# define UNDOCARGS_1	ldr x0, [sp, 8]
-# define UNDOCARGS_2	ldp x0, x1, [sp, 8]
-# define UNDOCARGS_3	UNDOCARGS_1; ldp x1, x2, [sp, 16]
-# define UNDOCARGS_4	UNDOCARGS_2; ldp x2, x3, [sp, 24]
-# define UNDOCARGS_5	UNDOCARGS_3; ldp x3, x4, [sp, 32]
-# define UNDOCARGS_6	UNDOCARGS_4; ldp x4, x5, [sp, 40]
+	cfi_endproc;							\
+	.size	name, .-name;
 
 # if IS_IN (libpthread)
-#  define CENABLE	bl __pthread_enable_asynccancel
-#  define CDISABLE	bl __pthread_disable_asynccancel
 #  define __local_multiple_threads __pthread_multiple_threads
 # elif IS_IN (libc)
-#  define CENABLE	bl __libc_enable_asynccancel
-#  define CDISABLE	bl __libc_disable_asynccancel
 #  define __local_multiple_threads __libc_multiple_threads
-# elif IS_IN (librt)
-#  define CENABLE	bl __librt_enable_asynccancel
-#  define CDISABLE	bl __librt_disable_asynccancel
-# else
-#  error Unsupported library
 # endif
 
 # if IS_IN (libpthread) || IS_IN (libc)
@@ -131,4 +108,10 @@ extern int __local_multiple_threads attribute_hidden;
 # define RTLD_SINGLE_THREAD_P \
   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
 				   header.multiple_threads) == 0, 1)
+
+static inline
+long int __pthread_get_ip (const struct ucontext *uc)
+{
+  return uc->uc_mcontext.pc;
+}
 #endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/sysdep.h b/sysdeps/unix/sysv/linux/aarch64/sysdep.h
index fe94a50..5f73b9e 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/aarch64/sysdep.h
@@ -199,6 +199,14 @@
 # undef INTERNAL_SYSCALL_ERRNO
 # define INTERNAL_SYSCALL_ERRNO(val, err)	(-(val))
 
+#undef SYSCALL_CANCEL_ERROR
+#define SYSCALL_CANCEL_ERROR(__val) \
+  ((unsigned long) (__val) >= (unsigned long) -4095)
+
+#undef SYSCALL_CANCEL_ERRNO
+#define SYSCALL_CANCEL_ERRNO(__val) \
+  (-(__val))
+
 # define LOAD_ARGS_0()				\
   register long _x0 asm ("x0");
 # define LOAD_ARGS_1(x0)			\

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4db33d57b6ad141606604574a98ccebe3ca6ef38

commit 4db33d57b6ad141606604574a98ccebe3ca6ef38
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Mon Sep 29 09:20:10 2014 -0400

    nptl: ppc32: Fix Race conditions in pthread cancellation (BZ#12683)
    
    This patches adds the ppc32 modification required for the BZ#12683
    fix.  It basically removes the enable_asynccancel/disable_asynccancel
    function usage on code used on ppc32.
    
    	* sysdeps/unix/sysv/linux/i386/fcntl.c (NO_CANCELLATION): Replace
    	by IS_IN (rtld).
    	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (PSEUDO):
    	Redefine to call __syscall_cancel function for cancellable syscalls.
    	(__pthread_get_ip): Add implementation.
    	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
    	[SYSCALL_CANCEL_ERROR]: New macro.
    	[SYSCALL_CANCEL_ERRNO]: New macro.

diff --git a/ChangeLog b/ChangeLog
index 920fd9a..6475a5f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
+	* sysdeps/unix/sysv/linux/i386/fcntl.c (NO_CANCELLATION): Replace
+	by IS_IN (rtld).
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (PSEUDO):
+	Redefine to call __syscall_cancel function for cancellable syscalls.
+	(__pthread_get_ip): Add implementation.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
+	[SYSCALL_CANCEL_ERROR]: New macro.
+	[SYSCALL_CANCEL_ERRNO]: New macro.
+
 	* sysdeps/i386/nptl/tls.h (THREAD_ATOMIC_BIT_SET): Remove macro.
 	* sysdeps/unix/sysv/linux/i386/Makefile
 	[$(subdir) = elf] (sysdep-rtld_routines): Add libc-do-syscall object.
diff --git a/sysdeps/unix/sysv/linux/i386/fcntl.c b/sysdeps/unix/sysv/linux/i386/fcntl.c
index 56f4bd1..ac5eed4 100644
--- a/sysdeps/unix/sysv/linux/i386/fcntl.c
+++ b/sysdeps/unix/sysv/linux/i386/fcntl.c
@@ -23,7 +23,7 @@
 
 #include <sys/syscall.h>
 
-#ifndef NO_CANCELLATION
+#if !IS_IN (rtld)
 int
 __fcntl_nocancel (int fd, int cmd, ...)
 {
@@ -36,7 +36,7 @@ __fcntl_nocancel (int fd, int cmd, ...)
 
   return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
 }
-#endif /* NO_CANCELLATION */
+#endif
 
 
 int
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
index dd9ff1c..d625495 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
@@ -25,94 +25,83 @@
 
 #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
 
+# if !IS_IN (libc)
+#  define SETUP_PIC							\
+    bcl     20,31,got_label;						\
+got_label:
+
+#  define CANCEL_JUMPTARGET						\
+    stw   r30,8(r1);							\
+    mflr  r30;								\
+    addis r30,r30,_GLOBAL_OFFSET_TABLE_-got_label@ha;			\
+    addi  r30,r30,_GLOBAL_OFFSET_TABLE_-got_label@l;			\
+    bl    __syscall_cancel@plt;						\
+    lwz   r30,8(r1)
+# else
+#  define SETUP_PIC
+#  if defined SHARED && defined PIC
+#   define CANCEL_JUMPTARGET						\
+    bl    __GI___syscall_cancel@locaL
+#  else
+#   define CANCEL_JUMPTARGET						\
+    bl    __syscall_cancel
+#  endif
+# endif
+
 # undef PSEUDO
 # define PSEUDO(name, syscall_name, args)				\
   .section ".text";							\
   ENTRY (name)								\
     SINGLE_THREAD_P;							\
-    bne- .Lpseudo_cancel;						\
-  .type __##syscall_name##_nocancel,@function;				\
-  .globl __##syscall_name##_nocancel;					\
-  __##syscall_name##_nocancel:						\
+    bne- L(pseudo_cancel);						\
     DO_CALL (SYS_ify (syscall_name));					\
-    PSEUDO_RET;								\
-  .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	\
-  .Lpseudo_cancel:							\
-    stwu 1,-48(1);							\
-    cfi_adjust_cfa_offset (48);						\
-    mflr 9;								\
-    stw 9,52(1);							\
+    bnslr+;								\
+    b __syscall_error@local;						\
+  L(pseudo_cancel):							\
+    stwu r1,-16(r1);							\
+    cfi_adjust_cfa_offset (16);						\
+    mflr r0;								\
+    SETUP_PIC;								\
+    stw  r0,20(r1);							\
     cfi_offset (lr, 4);							\
-    DOCARGS_##args;	/* save syscall args around CENABLE.  */	\
-    CENABLE;								\
-    stw 3,16(1);	/* store CENABLE return value (MASK).  */	\
-    UNDOCARGS_##args;	/* restore syscall args.  */			\
-    DO_CALL (SYS_ify (syscall_name));					\
-    mfcr 0;		/* save CR/R3 around CDISABLE.  */		\
-    stw 3,8(1);								\
-    stw 0,12(1);							\
-    lwz 3,16(1);	/* pass MASK to CDISABLE.  */			\
-    CDISABLE;								\
-    lwz 4,52(1);							\
-    lwz 0,12(1);	/* restore CR/R3. */				\
-    lwz 3,8(1);								\
-    mtlr 4;								\
-    mtcr 0;								\
-    addi 1,1,48;
-
-# define DOCARGS_0
-# define UNDOCARGS_0
-
-# define DOCARGS_1	stw 3,20(1); DOCARGS_0
-# define UNDOCARGS_1	lwz 3,20(1); UNDOCARGS_0
-
-# define DOCARGS_2	stw 4,24(1); DOCARGS_1
-# define UNDOCARGS_2	lwz 4,24(1); UNDOCARGS_1
-
-# define DOCARGS_3	stw 5,28(1); DOCARGS_2
-# define UNDOCARGS_3	lwz 5,28(1); UNDOCARGS_2
-
-# define DOCARGS_4	stw 6,32(1); DOCARGS_3
-# define UNDOCARGS_4	lwz 6,32(1); UNDOCARGS_3
-
-# define DOCARGS_5	stw 7,36(1); DOCARGS_4
-# define UNDOCARGS_5	lwz 7,36(1); UNDOCARGS_4
-
-# define DOCARGS_6	stw 8,40(1); DOCARGS_5
-# define UNDOCARGS_6	lwz 8,40(1); UNDOCARGS_5
-
-# if IS_IN (libpthread)
-#  define CENABLE	bl __pthread_enable_asynccancel@local
-#  define CDISABLE	bl __pthread_disable_asynccancel@local
-# elif IS_IN (libc)
-#  define CENABLE	bl __libc_enable_asynccancel@local
-#  define CDISABLE	bl __libc_disable_asynccancel@local
-# elif IS_IN (librt)
-#  define CENABLE	bl __librt_enable_asynccancel@local
-#  define CDISABLE	bl __librt_disable_asynccancel@local
-# else
-#  error Unsupported library
-# endif
+    mr   r9,r8;								\
+    mr   r8,r7;								\
+    mr   r7,r6;								\
+    mr   r6,r5;								\
+    mr   r5,r4;								\
+    mr   r4,r3;								\
+    li   r3,SYS_ify (syscall_name);					\
+    CANCEL_JUMPTARGET;							\
+    lwz  r0,20(r1);							\
+    addi r1,r1,16;							\
+    cfi_adjust_cfa_offset (-16);					\
+    mtlr r0;								\
+    cfi_restore (lr);							\
+    b    __syscall_cancel_error@local;
+
+# undef PSEUDO_RET
+# define PSEUDO_RET
 
 # ifndef __ASSEMBLER__
-#  define SINGLE_THREAD_P						\
-  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				\
-				   header.multiple_threads) == 0, 1)
+#  define SINGLE_THREAD_P                                               \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,                         \
+                                   header.multiple_threads) == 0, 1)
 # else
-#  define SINGLE_THREAD_P						\
-  lwz 10,MULTIPLE_THREADS_OFFSET(2);					\
+#  define SINGLE_THREAD_P                                               \
+  lwz 10,MULTIPLE_THREADS_OFFSET(2);                                    \
   cmpwi 10,0
 # endif
 
-#elif !defined __ASSEMBLER__
-
-# define SINGLE_THREAD_P (1)
-# define NO_CANCELLATION 1
-
 #endif
 
 #ifndef __ASSEMBLER__
 # define RTLD_SINGLE_THREAD_P \
   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
 				   header.multiple_threads) == 0, 1)
+
+static inline
+const char * __pthread_get_ip (const ucontext_t *uc)
+{
+  return (char *)uc->uc_mcontext.uc_regs->gregs[PT_NIP];
+}
 #endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
index dc56bea..46fd267 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
@@ -100,6 +100,14 @@
     sc_ret;								\
   })
 
+#undef SYSCALL_CANCEL_ERROR
+#define SYSCALL_CANCEL_ERROR(err)					\
+  (err > 0xfffffffffffff000UL)
+
+#undef SYSCALL_CANCEL_ERRNO
+#define SYSCALL_CANCEL_ERRNO(err)					\
+  (-err)
+
 /* Define a macro which expands inline into the wrapper code for a system
    call. This use is for internal calls that do not need to handle errors
    normally. It will never touch errno.

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=9194f182cf76da69cad5dd995f143e16746317c6

commit 9194f182cf76da69cad5dd995f143e16746317c6
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Mon May 4 16:30:13 2015 -0300

    nptl: i386: Fix Race conditions in pthread cancellation (BZ#12683)
    
    This patch adds the i386 modifications required for the BZ#12683 fix.
    It basically removes the enable_asynccancel/disable_asynccancel function
    usage on code used on x86_64, provide a arch-specific symbol that
    contains global markers to be used in SIGCANCEL handler, and add
    cancellation entrypoints in the socketcall default header.
    
    	* sysdeps/i386/nptl/tls.h (THREAD_ATOMIC_BIT_SET): Remove macro.
    	* sysdeps/unix/sysv/linux/i386/Makefile
    	[$(subdir) = elf] (sysdep-rtld_routines): Add libc-do-syscall object.
    	* sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_wait_tid): Use
    	cancellable futex syscall macro.
    	* sysdeps/unix/sysv/linux/i386/syscall_cancel.S: New file.
    	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (PSEUDO): Redefine to
    	call __syscall_cancel function for cancellable syscalls.
    	* sysdeps/unix/sysv/linux/i386/sysdep.h (SYSCALL_CANCEL_ERROR): New
    	define.
    	(SYSCALL_CANCEL_ERRNO): Likewise.
    	(INTERNAL_SYSCALL_MAIN_NCS_0): Likewise.
    	(INTERNAL_SYSCALL_MAIN_NCS_1): Likewise.
    	(INTERNAL_SYSCALL_MAIN_NCS_2): Likewise.
    	(INTERNAL_SYSCALL_MAIN_NCS_3): Likewise.
    	(INTERNAL_SYSCALL_MAIN_NCS_4): Likewise.
    	(INTERNAL_SYSCALL_MAIN_NCS_5): Likewise.
    	(INTERNAL_SYSCALL_MAIN_NCS_6): Likewise.
    	(INTERNAL_SYSCALL_NCS): Redefine to call it with 6-arguments.

diff --git a/ChangeLog b/ChangeLog
index 1857790..920fd9a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
 2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
+	* sysdeps/i386/nptl/tls.h (THREAD_ATOMIC_BIT_SET): Remove macro.
+	* sysdeps/unix/sysv/linux/i386/Makefile
+	[$(subdir) = elf] (sysdep-rtld_routines): Add libc-do-syscall object.
+	* sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_wait_tid): Use
+	cancellable futex syscall macro.
+	* sysdeps/unix/sysv/linux/i386/syscall_cancel.S: New file.
+	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (PSEUDO): Redefine to
+	call __syscall_cancel function for cancellable syscalls.
+	* sysdeps/unix/sysv/linux/i386/sysdep.h (SYSCALL_CANCEL_ERROR): New
+	define.
+	(SYSCALL_CANCEL_ERRNO): Likewise.
+	(INTERNAL_SYSCALL_MAIN_NCS_0): Likewise.
+	(INTERNAL_SYSCALL_MAIN_NCS_1): Likewise.
+	(INTERNAL_SYSCALL_MAIN_NCS_2): Likewise.
+	(INTERNAL_SYSCALL_MAIN_NCS_3): Likewise.
+	(INTERNAL_SYSCALL_MAIN_NCS_4): Likewise.
+	(INTERNAL_SYSCALL_MAIN_NCS_5): Likewise.
+	(INTERNAL_SYSCALL_MAIN_NCS_6): Likewise.
+	(INTERNAL_SYSCALL_NCS): Redefine to call it with 6-arguments.
+
 	* sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h (__syscall_arg_t):
 	Define type for x32.
 	(__SSC): Add platform specific macro.
diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h
index 829cd3a..ffac3a8 100644
--- a/sysdeps/i386/nptl/tls.h
+++ b/sysdeps/i386/nptl/tls.h
@@ -395,17 +395,6 @@ tls_fill_user_desc (union user_desc_init *desc,
 	      abort (); })
 
 
-/* Atomic set bit.  */
-#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \
-  (void) ({ if (sizeof ((descr)->member) == 4)				      \
-	      asm volatile (LOCK_PREFIX "orl %1, %%gs:%P0"		      \
-			    :: "i" (offsetof (struct pthread, member)),	      \
-			       "ir" (1 << (bit)));			      \
-	    else							      \
-	      /* Not necessary for other sizes in the moment.  */	      \
-	      abort (); })
-
-
 /* Call the user-provided thread function.  */
 #define CALL_THREAD_FCT(descr) \
   ({ void *__res;							      \
diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile
index 80da593..4f83d08 100644
--- a/sysdeps/unix/sysv/linux/i386/Makefile
+++ b/sysdeps/unix/sysv/linux/i386/Makefile
@@ -6,6 +6,7 @@ sysdep_routines += ioperm iopl vm86
 endif
 
 ifeq ($(subdir),elf)
+sysdep-rtld_routines += libc-do-syscall
 sysdep-others += lddlibc4
 install-bin += lddlibc4
 endif
diff --git a/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/sysdeps/unix/sysv/linux/i386/lowlevellock.h
index 58f5638..02ea0fc 100644
--- a/sysdeps/unix/sysv/linux/i386/lowlevellock.h
+++ b/sysdeps/unix/sysv/linux/i386/lowlevellock.h
@@ -283,7 +283,7 @@ extern int __lll_timedlock_elision (int *futex, short *adapt_count,
   do {					\
     __typeof (tid) __tid;		\
     while ((__tid = (tid)) != 0)	\
-      lll_futex_wait (&(tid), __tid, LLL_SHARED);\
+      lll_futex_wait_cancel (&(tid), __tid, LLL_SHARED);\
   } while (0)
 
 extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime)
diff --git a/sysdeps/unix/sysv/linux/i386/syscall_cancel.S b/sysdeps/unix/sysv/linux/i386/syscall_cancel.S
new file mode 100644
index 0000000..1ff6288
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/syscall_cancel.S
@@ -0,0 +1,105 @@
+/* Cancellable syscall wrapper - x86_64 version.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+/* long int [eax] __syscall_cancel_arch (int *cancelhandling [SP],
+					 long int nr   [SP+4],
+					 long int arg1 [SP+8],
+					 long int arg2 [SP+12],
+					 long int arg3 [SP+16],
+					 long int arg4 [SP+20],
+					 long int arg5 [SP+24],
+					 long int arg6 [SP+28])  */
+
+ENTRY (__syscall_cancel_arch)
+	pushl %ebp
+	cfi_def_cfa_offset (8)
+	cfi_offset (ebp, -8)
+	pushl %edi
+	cfi_def_cfa_offset (12)
+	cfi_offset (edi, -12)
+	pushl %esi
+	cfi_def_cfa_offset (16)
+	cfi_offset (esi, -16)
+	pushl %ebx
+	cfi_def_cfa_offset (20)
+	cfi_offset (ebx, -20)
+
+	.globl __syscall_cancel_arch_start
+	.type  __syscall_cancel_arch_start,@function
+__syscall_cancel_arch_start:
+
+	/* if (*cancelhandling & CANCELED_BITMASK)
+	     __syscall_do_cancel()  */
+	testb	$4, (%eax)
+	jne     1f
+
+	/* Issue a 6 argument syscall, the nr [%eax] being the syscall
+	   number.  */
+	movl    24(%esp), %eax
+	movl    28(%esp), %ebx
+	movl    32(%esp), %ecx
+	movl    36(%esp), %edx
+	movl    40(%esp), %esi
+	movl    44(%esp), %edi
+	movl    48(%esp), %ebp
+
+        /* It can not use the vDSO __kernel_vsyscall because the cancelable
+	   checks in libc-cancelation.c requires to know if the cancellation
+	   IP value that was trigger between the two
+	   __syscall_cancel_arch_{start,end} marks.  */
+	int	$128
+
+	.globl __syscall_cancel_arch_end
+	.type  __syscall_cancel_arch_end,@function
+__syscall_cancel_arch_end:
+
+	popl %ebx
+	cfi_restore (ebx)
+	cfi_def_cfa_offset (16)
+	popl %esi
+	cfi_restore (esi)
+	cfi_def_cfa_offset (12)
+	popl %edi
+	cfi_restore (edi)
+	cfi_def_cfa_offset (8)
+	popl %ebp
+	cfi_restore (ebp)
+	cfi_def_cfa_offset (4)
+        ret
+
+1:
+	/* Although the __syscall_do_cancel do not return, we need to stack
+	   being set correctly so exceptions work correctly.  */
+	popl %ebx
+	cfi_restore (ebx)
+	cfi_def_cfa_offset (16)
+	popl %esi
+	cfi_restore (esi)
+	cfi_def_cfa_offset (12)
+	popl %edi
+	cfi_restore (edi)
+	cfi_def_cfa_offset (8)
+	popl %ebp
+	cfi_restore (ebp)
+	cfi_def_cfa_offset (4)
+	jmp __syscall_do_cancel
+
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
index 1f86dae..d8cdd27 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
@@ -24,112 +24,66 @@
 
 #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
 
+# if IS_IN (libc)
+#  define JMP_STARTFUNC							      \
+    subl $16, %esp
+#  define JMP_SYSCALL_CANCEL						      \
+    HIDDEN_JUMPTARGET(__syscall_cancel)
+#  define JMP_ENDFUNC							      \
+    addl $44, %esp;							      \
+    cfi_def_cfa_offset (4)
+# else
+#  define JMP_STARTFUNC							      \
+    pushl %ebx;								      \
+    cfi_def_cfa_offset (8);						      \
+    cfi_offset (ebx, -8);						      \
+    SETUP_PIC_REG (bx);							      \
+    addl $_GLOBAL_OFFSET_TABLE_, %ebx;					      \
+    subl $12, %esp
+#  define JMP_SYSCALL_CANCEL \
+    __syscall_cancel@plt
+#  define JMP_ENDFUNC							      \
+    addl $40, %esp;							      \
+    cfi_def_cfa_offset (8);						      \
+    popl %ebx;								      \
+    cfi_restore (ebx);							      \
+    cfi_def_cfa_offset (4)
+# endif
+
 # undef PSEUDO
 # define PSEUDO(name, syscall_name, args)				      \
   .text;								      \
   ENTRY (name)								      \
     cmpl $0, %gs:MULTIPLE_THREADS_OFFSET;				      \
     jne L(pseudo_cancel);						      \
-  .type __##syscall_name##_nocancel,@function;				      \
-  .globl __##syscall_name##_nocancel;					      \
-  __##syscall_name##_nocancel:						      \
     DO_CALL (syscall_name, args);					      \
     cmpl $-4095, %eax;							      \
     jae SYSCALL_ERROR_LABEL;						      \
     ret;								      \
-  .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \
   L(pseudo_cancel):							      \
-    CENABLE								      \
-    SAVE_OLDTYPE_##args							      \
-    PUSHCARGS_##args							      \
-    DOCARGS_##args							      \
-    movl $SYS_ify (syscall_name), %eax;					      \
-    ENTER_KERNEL;							      \
-    POPCARGS_##args;							      \
-    POPSTATE_##args							      \
+    JMP_STARTFUNC;							      \
+    cfi_def_cfa_offset (20);						      \
+    pushl 40(%esp);							      \
+    cfi_def_cfa_offset (24);						      \
+    pushl 40(%esp);							      \
+    cfi_def_cfa_offset (28);						      \
+    pushl 40(%esp);							      \
+    cfi_def_cfa_offset (32);						      \
+    pushl 40(%esp);							      \
+    cfi_def_cfa_offset (36);						      \
+    pushl 40(%esp);							      \
+    cfi_def_cfa_offset (40);						      \
+    pushl 40(%esp);							      \
+    cfi_def_cfa_offset (44);						      \
+    pushl $SYS_ify (syscall_name);					      \
+    cfi_def_cfa_offset (48);						      \
+    call JMP_SYSCALL_CANCEL;						      \
+    JMP_ENDFUNC;							      \
     cmpl $-4095, %eax;							      \
     jae SYSCALL_ERROR_LABEL
 
-# define SAVE_OLDTYPE_0	movl %eax, %ecx;
-# define SAVE_OLDTYPE_1	SAVE_OLDTYPE_0
-# define SAVE_OLDTYPE_2	pushl %eax; cfi_adjust_cfa_offset (4);
-# define SAVE_OLDTYPE_3	SAVE_OLDTYPE_2
-# define SAVE_OLDTYPE_4	SAVE_OLDTYPE_2
-# define SAVE_OLDTYPE_5	SAVE_OLDTYPE_2
-# define SAVE_OLDTYPE_6	SAVE_OLDTYPE_2
-
-# define PUSHCARGS_0	/* No arguments to push.  */
-# define DOCARGS_0	/* No arguments to frob.  */
-# define POPCARGS_0	/* No arguments to pop.  */
-# define _PUSHCARGS_0	/* No arguments to push.  */
-# define _POPCARGS_0	/* No arguments to pop.  */
-
-# define PUSHCARGS_1	movl %ebx, %edx; cfi_register (ebx, edx); PUSHCARGS_0
-# define DOCARGS_1	_DOARGS_1 (4)
-# define POPCARGS_1	POPCARGS_0; movl %edx, %ebx; cfi_restore (ebx);
-# define _PUSHCARGS_1	pushl %ebx; cfi_adjust_cfa_offset (4); \
-			cfi_rel_offset (ebx, 0); _PUSHCARGS_0
-# define _POPCARGS_1	_POPCARGS_0; popl %ebx; \
-			cfi_adjust_cfa_offset (-4); cfi_restore (ebx);
-
-# define PUSHCARGS_2	PUSHCARGS_1
-# define DOCARGS_2	_DOARGS_2 (12)
-# define POPCARGS_2	POPCARGS_1
-# define _PUSHCARGS_2	_PUSHCARGS_1
-# define _POPCARGS_2	_POPCARGS_1
-
-# define PUSHCARGS_3	_PUSHCARGS_2
-# define DOCARGS_3	_DOARGS_3 (20)
-# define POPCARGS_3	_POPCARGS_3
-# define _PUSHCARGS_3	_PUSHCARGS_2
-# define _POPCARGS_3	_POPCARGS_2
-
-# define PUSHCARGS_4	_PUSHCARGS_4
-# define DOCARGS_4	_DOARGS_4 (28)
-# define POPCARGS_4	_POPCARGS_4
-# define _PUSHCARGS_4	pushl %esi; cfi_adjust_cfa_offset (4); \
-			cfi_rel_offset (esi, 0); _PUSHCARGS_3
-# define _POPCARGS_4	_POPCARGS_3; popl %esi; \
-			cfi_adjust_cfa_offset (-4); cfi_restore (esi);
-
-# define PUSHCARGS_5	_PUSHCARGS_5
-# define DOCARGS_5	_DOARGS_5 (36)
-# define POPCARGS_5	_POPCARGS_5
-# define _PUSHCARGS_5	pushl %edi; cfi_adjust_cfa_offset (4); \
-			cfi_rel_offset (edi, 0); _PUSHCARGS_4
-# define _POPCARGS_5	_POPCARGS_4; popl %edi; \
-			cfi_adjust_cfa_offset (-4); cfi_restore (edi);
-
-# define PUSHCARGS_6	_PUSHCARGS_6
-# define DOCARGS_6	_DOARGS_6 (44)
-# define POPCARGS_6	_POPCARGS_6
-# define _PUSHCARGS_6	pushl %ebp; cfi_adjust_cfa_offset (4); \
-			cfi_rel_offset (ebp, 0); _PUSHCARGS_5
-# define _POPCARGS_6	_POPCARGS_5; popl %ebp; \
-			cfi_adjust_cfa_offset (-4); cfi_restore (ebp);
-
-# if IS_IN (libpthread)
-#  define CENABLE	call __pthread_enable_asynccancel;
-#  define CDISABLE	call __pthread_disable_asynccancel
-# elif IS_IN (libc)
-#  define CENABLE	call __libc_enable_asynccancel;
-#  define CDISABLE	call __libc_disable_asynccancel
-# elif IS_IN (librt)
-#  define CENABLE	call __librt_enable_asynccancel;
-#  define CDISABLE	call __librt_disable_asynccancel
-# else
-#  error Unsupported library
-# endif
-# define POPSTATE_0 \
- pushl %eax; cfi_adjust_cfa_offset (4); movl %ecx, %eax; \
- CDISABLE; popl %eax; cfi_adjust_cfa_offset (-4);
-# define POPSTATE_1	POPSTATE_0
-# define POPSTATE_2	xchgl (%esp), %eax; CDISABLE; popl %eax; \
-			cfi_adjust_cfa_offset (-4);
-# define POPSTATE_3	POPSTATE_2
-# define POPSTATE_4	POPSTATE_3
-# define POPSTATE_5	POPSTATE_4
-# define POPSTATE_6	POPSTATE_5
+# undef PSEUDO_RET
+# define PSEUDO_RET
 
 # ifndef __ASSEMBLER__
 #  define SINGLE_THREAD_P \
@@ -150,4 +104,10 @@
 # define RTLD_SINGLE_THREAD_P \
   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
 				   header.multiple_threads) == 0, 1)
+
+static inline
+long int __pthread_get_ip (const ucontext_t *uc)
+{
+  return (long int)uc->uc_mcontext.gregs[REG_EIP];
+}
 #endif
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index d76aca5..b82e6a2 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -373,6 +373,42 @@ struct libc_do_syscall_args
     register unsigned int resultvar;					      \
     INTERNAL_SYSCALL_MAIN_##nr (name, err, args);			      \
     (int) resultvar; })
+
+/* Same as INTERNAL_SYSCALL, but for non-constant name argument.  */
+#define INTERNAL_SYSCALL_MAIN_NCS_0(name, err, args...) \
+    INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, 0, args)
+#define INTERNAL_SYSCALL_MAIN_NCS_1(name, err, args...) \
+    INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, 1, args)
+#define INTERNAL_SYSCALL_MAIN_NCS_2(name, err, args...) \
+    INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, 2, args)
+#define INTERNAL_SYSCALL_MAIN_NCS_3(name, err, args...) \
+    INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, 3, args)
+#define INTERNAL_SYSCALL_MAIN_NCS_4(name, err, args...) \
+    INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, 4, args)
+#define INTERNAL_SYSCALL_MAIN_NCS_5(name, err, args...) \
+    INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, 5, args)
+/* The NCS version is different because it has a non-constant 'name' arg
+   and then requires a different asm constraint ("0" instead of "i").  */
+#define INTERNAL_SYSCALL_MAIN_NCS_6(name, err, arg1, arg2, arg3,	\
+				arg4, arg5, arg6)			\
+  struct libc_do_syscall_args _xv =					\
+    {									\
+      (int) (arg1),							\
+      (int) (arg5),							\
+      (int) (arg6)							\
+    };									\
+    asm volatile (							\
+    "movl %1, %%eax\n\t"						\
+    "call __libc_do_syscall"						\
+    : "=a" (resultvar)							\
+    : "0" (name), "c" (arg2), "d" (arg3), "S" (arg4), "D" (&_xv)        \
+    : "memory", "cc")
+#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+  ({									      \
+    register unsigned int resultvar;					      \
+    INTERNAL_SYSCALL_MAIN_NCS_##nr (name, err, args);			      \
+    (int) resultvar; })
+
 #ifdef I386_USE_SYSENTER
 # ifdef SHARED
 #  define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
@@ -385,9 +421,7 @@ struct libc_do_syscall_args
     : "=a" (resultvar)							      \
     : "i" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo))		      \
       ASMFMT_##nr(args) : "memory", "cc")
-#  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
-  ({									      \
-    register unsigned int resultvar;					      \
+#  define INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, nr, args...) \
     EXTRAVAR_##nr							      \
     asm volatile (							      \
     LOADARGS_##nr							      \
@@ -395,8 +429,7 @@ struct libc_do_syscall_args
     RESTOREARGS_##nr							      \
     : "=a" (resultvar)							      \
     : "0" (name), "i" (offsetof (tcbhead_t, sysinfo))			      \
-      ASMFMT_##nr(args) : "memory", "cc");				      \
-    (int) resultvar; })
+      ASMFMT_##nr(args) : "memory", "cc")
 # else
 #  define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
     EXTRAVAR_##nr							      \
@@ -407,17 +440,14 @@ struct libc_do_syscall_args
     RESTOREARGS_##nr							      \
     : "=a" (resultvar)							      \
     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc")
-#  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
-  ({									      \
-    register unsigned int resultvar;					      \
+#  define INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, nr, args...) \
     EXTRAVAR_##nr							      \
     asm volatile (							      \
     LOADARGS_##nr							      \
     "call *_dl_sysinfo\n\t"						      \
     RESTOREARGS_##nr							      \
     : "=a" (resultvar)							      \
-    : "0" (name) ASMFMT_##nr(args) : "memory", "cc");			      \
-    (int) resultvar; })
+    : "0" (name) ASMFMT_##nr(args) : "memory", "cc")
 # endif
 #else
 # define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
@@ -429,17 +459,14 @@ struct libc_do_syscall_args
     RESTOREARGS_##nr							      \
     : "=a" (resultvar)							      \
     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc")
-# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
-  ({									      \
-    register unsigned int resultvar;					      \
+# define INTERNAL_SYSCALL_MAIN_INLINE_NCS(name, err, nr, args...) \
     EXTRAVAR_##nr							      \
     asm volatile (							      \
     LOADARGS_##nr							      \
     "int $0x80\n\t"							      \
     RESTOREARGS_##nr							      \
     : "=a" (resultvar)							      \
-    : "0" (name) ASMFMT_##nr(args) : "memory", "cc");			      \
-    (int) resultvar; })
+    : "0" (name) ASMFMT_##nr(args) : "memory", "cc")
 #endif
 
 #undef INTERNAL_SYSCALL_DECL
@@ -452,6 +479,14 @@ struct libc_do_syscall_args
 #undef INTERNAL_SYSCALL_ERRNO
 #define INTERNAL_SYSCALL_ERRNO(val, err)	(-(val))
 
+#undef SYSCALL_CANCEL_ERROR
+#define SYSCALL_CANCEL_ERROR(__val) \
+  ((unsigned int) (__val) >= 0xfffff001u)
+
+#undef SYSCALL_CANCEL_ERRNO
+#define SYSCALL_CANCEL_ERRNO(__val) \
+  (-(__val))
+
 #define LOADARGS_0
 #ifdef __PIC__
 # if defined I386_USE_SYSENTER && defined SHARED
diff --git a/sysdeps/unix/sysv/linux/socketcall.h b/sysdeps/unix/sysv/linux/socketcall.h
index 007acba..1bd29fe 100644
--- a/sysdeps/unix/sysv/linux/socketcall.h
+++ b/sysdeps/unix/sysv/linux/socketcall.h
@@ -86,13 +86,35 @@
     sc_ret;								\
   })
 
-#define SOCKETCALL_CANCEL(name, __a1, __a2, __a3, __a4, __a5, __a6)	\
+
+#define __SOCKETCALL_CANCEL1(__name, __a1) \
+  SYSCALL_CANCEL_NCS (socketcall, __name, \
+     ((long int [1]) { (long int) __a1 }))
+#define __SOCKETCALL_CANCEL2(__name, __a1, __a2) \
+  SYSCALL_CANCEL_NCS (socketcall, __name, \
+     ((long int [2]) { (long int) __a1, (long int) __a2 }))
+#define __SOCKETCALL_CANCEL3(__name, __a1, __a2, __a3) \
+  SYSCALL_CANCEL_NCS (socketcall, __name, \
+     ((long int [3]) { (long int) __a1, (long int) __a2, (long int) __a3 }))
+#define __SOCKETCALL_CANCEL4(__name, __a1, __a2, __a3, __a4) \
+  SYSCALL_CANCEL_NCS (socketcall, __name, \
+     ((long int [4]) { (long int) __a1, (long int) __a2, (long int) __a3, \
+                       (long int) __a4 }))
+#define __SOCKETCALL_CANCEL5(__name, __a1, __a2, __a3, __a4, __a5) \
+  SYSCALL_CANCEL_NCS (socketcall, __name, \
+     ((long int [5]) { (long int) __a1, (long int) __a2, (long int) __a3, \
+                       (long int) __a4, (long int) __a5 }))
+#define __SOCKETCALL_CANCEL6(__name, __a1, __a2, __a3, __a4, __a5, __a6) \
+  SYSCALL_CANCEL_NCS (socketcall, __name, \
+     ((long int [6]) { (long int) __a1, (long int) __a2, (long int) __a3, \
+                       (long int) __a4, (long int) __a5, (long int) __a6 }))
+
+#define __SOCKETCALL_CANCEL(...) __SOCKETCALL_DISP (__SOCKETCALL_CANCEL,\
+						    __VA_ARGS__)
+
+#define SOCKETCALL_CANCEL(name, args...)				\
   ({									\
-    __syscall_arg_t __args[6] = { __SSC (__a1), __SSC (__a2),		\
-				  __SSC (__a3), __SSC (__a4), 		\
-				  __SSC (__a5), __SSC (__a6) };		\
-    long int sc_ret = SYSCALL_CANCEL_NCS (socketcall, SOCKOP_##name,	\
-					  __args);			\
+    long int sc_ret = __SOCKETCALL_CANCEL (SOCKOP_##name, args);	\
     if (SYSCALL_CANCEL_ERROR (sc_ret))					\
       {									\
         __set_errno (SYSCALL_CANCEL_ERRNO (sc_ret));			\

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=14c5312173bc6222b2a7b03dd0689e4a2fea6162

commit 14c5312173bc6222b2a7b03dd0689e4a2fea6162
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Sat May 9 14:20:26 2015 -0300

    nptl: x32: Fix Race conditions in pthread cancellation (BZ#12683)
    
    This patches adds the x32 modification required for the BZ#12683 fix.
    It basically adjust the syscall size used to pass the arguments to
    the syscall cancel wrappers.
    
    	* sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h (__syscall_arg_t):
    	Define type for x32.
    	(__SSC): Add platform specific macro.

diff --git a/ChangeLog b/ChangeLog
index fc44f08..1857790 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
+	* sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h (__syscall_arg_t):
+	Define type for x32.
+	(__SSC): Add platform specific macro.
+
 	* sysdeps/unix/sysv/linux/x86_64/cancellation.S: Remove file.
 	* sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S: Remove file.
 	* sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S: Remove file.
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
index 2324168..f2dc8f0 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
@@ -18,6 +18,27 @@
 #ifndef _LINUX_X32_SYSDEP_H
 #define _LINUX_X32_SYSDEP_H 1
 
+#ifndef __ASSEMBLER__
+#include <libc-internal.h>
+
+typedef long long int __syscall_arg_t;
+
+/* Syscall arguments for x32 follows x86_64 size, however pointers are 32
+   bits in size.  This suppress the GCC warning "cast from pointer to 
+   integer of different size" when calling __syscall_cancel with
+   pointer as arguments.  */
+# define __SSC(__x)						\
+  ({								\
+    __syscall_arg_t __ret;					\
+    DIAG_PUSH_NEEDS_COMMENT;					\
+    DIAG_IGNORE_NEEDS_COMMENT (4.7, "-Wpointer-to-int-cast");	\
+    __ret = (sizeof(1 ? (__x) : 0ULL) < 8 ?			\
+      (unsigned long int) (__x) : (long long int) (__x));	\
+    DIAG_POP_NEEDS_COMMENT;					\
+    __ret;							\
+  })
+#endif
+
 /* There is some commonality.  */
 #include <sysdeps/unix/sysv/linux/x86_64/sysdep.h>
 #include <sysdeps/x86_64/x32/sysdep.h>

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=97dba0e781f3a36ea06648693d32877efc9033dd

commit 97dba0e781f3a36ea06648693d32877efc9033dd
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Mon Sep 29 09:48:34 2014 -0300

    nptl: x86_64: Fix Race conditions in pthread cancellation (BZ#12683)
    
    This patches adds the x86_64 modification required for the BZ#12683 fix.
    It basically removes the enable_asynccancel/disable_asynccancel function
    usage on code used on x86_64, and provide a arch-specific symbol that
    contains global markers to be used in SIGCANCEL handler.
    
    	* sysdeps/unix/sysv/linux/x86_64/cancellation.S: Remove file.
    	* sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S: Remove file.
    	* sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S: Remove file.
    	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_wait_tid):
    	Use cancellable futex wait call.
    	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (PSEUDO): Likewise.
    	* sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S: New file.
    	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (PSEUDO): Redefine to
    	call __syscall_cancel function for cancellable syscalls.
    	(CENABLE): Remove definition.
    	(CDISABLE): Likewise.
    	(__pthread_get_ip): Add implementation.
    	* sysdeps/unix/sysv/linux/x86_64/sysdep.h (SYSCALL_CANCEL_ERROR): New
    	define.
    	(SYSCALL_CANCEL_ERRNO): Likewise.
    	* sysdeps/x86_64/nptl/tcb-offsets.sym [TCB_CANCELING_BITMASK]:
    	Remove.
    	* sysdeps/x86_64/nptl/tls.h (THREAD_ATOMIC_BIT_SET): Remove
    	macro.

diff --git a/ChangeLog b/ChangeLog
index 7b7630d..fc44f08 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
 2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
+	* sysdeps/unix/sysv/linux/x86_64/cancellation.S: Remove file.
+	* sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S: Remove file.
+	* sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S: Remove file.
+	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_wait_tid):
+	Use cancellable futex wait call.
+	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (PSEUDO): Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S: New file.
+	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (PSEUDO): Redefine to
+	call __syscall_cancel function for cancellable syscalls.
+	(CENABLE): Remove definition.
+	(CDISABLE): Likewise.
+	(__pthread_get_ip): Add implementation.
+	* sysdeps/unix/sysv/linux/x86_64/sysdep.h (SYSCALL_CANCEL_ERROR): New
+	define.
+	(SYSCALL_CANCEL_ERRNO): Likewise.
+	* sysdeps/x86_64/nptl/tcb-offsets.sym [TCB_CANCELING_BITMASK]:
+	Remove.
+	* sysdeps/x86_64/nptl/tls.h (THREAD_ATOMIC_BIT_SET): Remove
+	macro.
+
 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c (__libc_fnctl):
 	Remove CANCEL_ASYNC/CANCEL_RESET usage.
 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (PSEUDO):
diff --git a/sysdeps/unix/sysv/linux/x86_64/cancellation.S b/sysdeps/unix/sysv/linux/x86_64/cancellation.S
deleted file mode 100644
index 4c34beb..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/cancellation.S
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Copyright (C) 2009-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2009.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <tcb-offsets.h>
-#include <kernel-features.h>
-#include "lowlevellock.h"
-
-#if IS_IN (libpthread)
-# if defined SHARED && !defined NO_HIDDEN
-#  define __pthread_unwind __GI___pthread_unwind
-# endif
-#else
-# ifndef SHARED
-	.weak __pthread_unwind
-# endif
-#endif
-
-
-#ifdef __ASSUME_PRIVATE_FUTEX
-# define LOAD_PRIVATE_FUTEX_WAIT(reg) \
-	movl	$(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
-#else
-# if FUTEX_WAIT == 0
-#  define LOAD_PRIVATE_FUTEX_WAIT(reg) \
-	movl	%fs:PRIVATE_FUTEX, reg
-# else
-#  define LOAD_PRIVATE_FUTEX_WAIT(reg) \
-	movl	%fs:PRIVATE_FUTEX, reg ; \
-	orl	$FUTEX_WAIT, reg
-# endif
-#endif
-
-/* It is crucial that the functions in this file don't modify registers
-   other than %rax and %r11.  The syscall wrapper code depends on this
-   because it doesn't explicitly save the other registers which hold
-   relevant values.  */
-	.text
-
-	.hidden __pthread_enable_asynccancel
-ENTRY(__pthread_enable_asynccancel)
-	movl	%fs:CANCELHANDLING, %eax
-2:	movl	%eax, %r11d
-	orl	$TCB_CANCELTYPE_BITMASK, %r11d
-	cmpl	%eax, %r11d
-	je	1f
-
-	lock
-	cmpxchgl %r11d, %fs:CANCELHANDLING
-	jnz	2b
-
-	andl	$(TCB_CANCELSTATE_BITMASK|TCB_CANCELTYPE_BITMASK|TCB_CANCELED_BITMASK|TCB_EXITING_BITMASK|TCB_CANCEL_RESTMASK|TCB_TERMINATED_BITMASK), %r11d
-	cmpl	$(TCB_CANCELTYPE_BITMASK|TCB_CANCELED_BITMASK), %r11d
-	je	3f
-
-1:	ret
-
-3:	subq	$8, %rsp
-	cfi_adjust_cfa_offset(8)
-	LP_OP(mov) $TCB_PTHREAD_CANCELED, %fs:RESULT
-	lock
-	orl	$TCB_EXITING_BITMASK, %fs:CANCELHANDLING
-	mov	%fs:CLEANUP_JMP_BUF, %RDI_LP
-#ifdef SHARED
-	call	__pthread_unwind@PLT
-#else
-	call	__pthread_unwind
-#endif
-	hlt
-END(__pthread_enable_asynccancel)
-
-
-	.hidden __pthread_disable_asynccancel
-ENTRY(__pthread_disable_asynccancel)
-	testl	$TCB_CANCELTYPE_BITMASK, %edi
-	jnz	1f
-
-	movl	%fs:CANCELHANDLING, %eax
-2:	movl	%eax, %r11d
-	andl	$~TCB_CANCELTYPE_BITMASK, %r11d
-	lock
-	cmpxchgl %r11d, %fs:CANCELHANDLING
-	jnz	2b
-
-	movl	%r11d, %eax
-3:	andl	$(TCB_CANCELING_BITMASK|TCB_CANCELED_BITMASK), %eax
-	cmpl	$TCB_CANCELING_BITMASK, %eax
-	je	4f
-1:	ret
-
-	/* Performance doesn't matter in this loop.  We will
-	   delay until the thread is canceled.  And we will unlikely
-	   enter the loop twice.  */
-4:	mov	%fs:0, %RDI_LP
-	movl	$__NR_futex, %eax
-	xorq	%r10, %r10
-	addq	$CANCELHANDLING, %rdi
-	LOAD_PRIVATE_FUTEX_WAIT (%esi)
-	syscall
-	movl	%fs:CANCELHANDLING, %eax
-	jmp	3b
-END(__pthread_disable_asynccancel)
diff --git a/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S b/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S
deleted file mode 100644
index dbb39f3..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright (C) 2009-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2009.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#define __pthread_enable_asynccancel __libc_enable_asynccancel
-#define __pthread_disable_asynccancel __libc_disable_asynccancel
-#include "cancellation.S"
diff --git a/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S b/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S
deleted file mode 100644
index 40b2986..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright (C) 2009-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2009.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#define __pthread_enable_asynccancel __librt_enable_asynccancel
-#define __pthread_disable_asynccancel __librt_disable_asynccancel
-#include "cancellation.S"
diff --git a/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
index de525cd..fbc5884 100644
--- a/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
+++ b/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
@@ -306,10 +306,10 @@ extern int __lll_timedlock_elision (int *futex, short *adapt_count,
    afterwards.  The kernel up to version 3.16.3 does not use the private futex
    operations for futex wake-up when the clone terminates.  */
 #define lll_wait_tid(tid) \
-  do {					\
-    __typeof (tid) __tid;		\
-    while ((__tid = (tid)) != 0)	\
-      lll_futex_wait (&(tid), __tid, LLL_SHARED);\
+  do {									      \
+    __typeof (tid) __tid;						      \
+    while ((__tid = (tid)) != 0)					      \
+      lll_futex_wait_cancel (&(tid), __tid, LLL_SHARED);		      \
   } while (0)
 
 extern int __lll_timedwait_tid (int *, const struct timespec *)
diff --git a/sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S b/sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S
new file mode 100644
index 0000000..3c44069
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/syscall_cancel.S
@@ -0,0 +1,62 @@
+/* Cancellable syscall wrapper - x86_64 version.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+/* long int [rax] __syscall_cancel_arch (int *cancelhandling [%rdi],
+					 long int nr   [%rsi],
+					 long int arg1 [%rdx],
+					 long int arg2 [%rcx],
+					 long int arg3 [%r8],
+					 long int arg4 [%r9],
+					 long int arg5 [SP+8],
+					 long int arg6 [SP+16])  */
+
+ENTRY (__syscall_cancel_arch)
+
+	.globl __syscall_cancel_arch_start
+	.type  __syscall_cancel_arch_start,@function
+__syscall_cancel_arch_start:
+
+	/* if (*cancelhandling & CANCELED_BITMASK)
+	     __syscall_do_cancel()  */
+        mov    (%rdi),%eax
+	testb  $4, (%rdi)
+        jne    __syscall_do_cancel
+
+	/* Issue a 6 argument syscall, the nr [%rax] being the syscall
+	   number.  */
+        mov    %rdi,%r11
+        mov    %rsi,%rax
+        mov    %rdx,%rdi
+        mov    %rcx,%rsi
+        mov    %r8,%rdx
+        mov    %r9,%r10
+        mov    8(%rsp),%r8
+        mov    16(%rsp),%r9
+        mov    %r11,8(%rsp)
+        syscall
+
+	.globl __syscall_cancel_arch_end
+	.type  __syscall_cancel_arch_end,@function
+__syscall_cancel_arch_end:
+
+	ret
+
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
index 6436ff0..a216364 100644
--- a/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
+++ b/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
@@ -24,53 +24,43 @@
 
 #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
 
-/* The code to disable cancellation depends on the fact that the called
-   functions are special.  They don't modify registers other than %rax
-   and %r11 if they return.  Therefore we don't have to preserve other
-   registers around these calls.  */
+# if IS_IN (libc)
+#  define JMP_SYSCALL_CANCEL HIDDEN_JUMPTARGET(__syscall_cancel)
+# else
+#  define JMP_SYSCALL_CANCEL __syscall_cancel@plt
+# endif
+
 # undef PSEUDO
 # define PSEUDO(name, syscall_name, args)				      \
   .text;								      \
   ENTRY (name)								      \
     SINGLE_THREAD_P;							      \
     jne L(pseudo_cancel);						      \
-  .type __##syscall_name##_nocancel,@function;				      \
-  .globl __##syscall_name##_nocancel;					      \
-  __##syscall_name##_nocancel:						      \
     DO_CALL (syscall_name, args);					      \
     cmpq $-4095, %rax;							      \
     jae SYSCALL_ERROR_LABEL;						      \
     ret;								      \
-  .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \
   L(pseudo_cancel):							      \
-    /* We always have to align the stack before calling a function.  */	      \
-    subq $8, %rsp; cfi_adjust_cfa_offset (8);				      \
-    CENABLE								      \
-    /* The return value from CENABLE is argument for CDISABLE.  */	      \
-    movq %rax, (%rsp);							      \
-    DO_CALL (syscall_name, args);					      \
-    movq (%rsp), %rdi;							      \
-    /* Save %rax since it's the error code from the syscall.  */	      \
-    movq %rax, %rdx;							      \
-    CDISABLE								      \
-    movq %rdx, %rax;							      \
-    addq $8,%rsp; cfi_adjust_cfa_offset (-8);				      \
-    cmpq $-4095, %rax;							      \
-    jae SYSCALL_ERROR_LABEL
-
+    subq  $24, %rsp;							      \
+    cfi_def_cfa_offset (32);						      \
+    movq  %r9, (%rsp);							      \
+    movq  %r8, %r9;							      \
+    movq  %rcx, %r8;							      \
+    movq  %rdx, %rcx;							      \
+    movq  %rsi, %rdx;							      \
+    movq  %rdi, %rsi;							      \
+    lea   SYS_ify (syscall_name), %edi;					      \
+    call  JMP_SYSCALL_CANCEL;						      \
+    cfi_def_cfa_offset (8);						      \
+    addq  $24, %rsp;							      \
+    cmpq  $-4095, %rax;							      \
+    jae SYSCALL_ERROR_LABEL;
 
 # if IS_IN (libpthread)
-#  define CENABLE	call __pthread_enable_asynccancel;
-#  define CDISABLE	call __pthread_disable_asynccancel;
 #  define __local_multiple_threads __pthread_multiple_threads
 # elif IS_IN (libc)
-#  define CENABLE	call __libc_enable_asynccancel;
-#  define CDISABLE	call __libc_disable_asynccancel;
 #  define __local_multiple_threads __libc_multiple_threads
-# elif IS_IN (librt)
-#  define CENABLE	call __librt_enable_asynccancel;
-#  define CDISABLE	call __librt_disable_asynccancel;
-# else
+# elif !IS_IN (librt)
 #  error Unsupported library
 # endif
 
@@ -78,7 +68,7 @@
 #  ifndef __ASSEMBLER__
 extern int __local_multiple_threads attribute_hidden;
 #   define SINGLE_THREAD_P \
-  __builtin_expect (__local_multiple_threads == 0, 1)
+	  __builtin_expect (__local_multiple_threads == 0, 1)
 #  else
 #   define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip)
 #  endif
@@ -87,18 +77,13 @@ extern int __local_multiple_threads attribute_hidden;
 
 #  ifndef __ASSEMBLER__
 #   define SINGLE_THREAD_P \
-  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
-				   header.multiple_threads) == 0, 1)
+	  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+					   header.multiple_threads) == 0, 1)
 #  else
 #   define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET
-#  endif
+#  endif /* __ASSEMBLER  */
 
-# endif
-
-#elif !defined __ASSEMBLER__
-
-# define SINGLE_THREAD_P (1)
-# define NO_CANCELLATION 1
+# endif /* IS_IN (libpthread) || IS_IN (libc)  */
 
 #endif
 
@@ -106,4 +91,10 @@ extern int __local_multiple_threads attribute_hidden;
 # define RTLD_SINGLE_THREAD_P \
   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
 				   header.multiple_threads) == 0, 1)
+
+static inline
+long int __pthread_get_ip (const ucontext_t *uc)
+{
+  return (long int)uc->uc_mcontext.gregs[REG_RIP];
+}
 #endif
diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
index 5a62cce..e4059f0 100644
--- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
@@ -252,6 +252,14 @@
 # undef INTERNAL_SYSCALL_ERRNO
 # define INTERNAL_SYSCALL_ERRNO(val, err)	(-(val))
 
+# undef SYSCALL_CANCEL_ERROR
+# define SYSCALL_CANCEL_ERROR(__val)					      \
+  ((unsigned long int) (long int) (__val) >= -4095L)
+
+# undef SYSCALL_CANCEL_ERRNO
+# define SYSCALL_CANCEL_ERRNO(__val)					      \
+  (-(__val))
+
 /* List of system calls which are supported as vsyscalls.  */
 # define HAVE_CLOCK_GETTIME_VSYSCALL    1
 # define HAVE_GETTIMEOFDAY_VSYSCALL     1
diff --git a/sysdeps/x86_64/nptl/tcb-offsets.sym b/sysdeps/x86_64/nptl/tcb-offsets.sym
index aeb7526..01c5ff7 100644
--- a/sysdeps/x86_64/nptl/tcb-offsets.sym
+++ b/sysdeps/x86_64/nptl/tcb-offsets.sym
@@ -20,7 +20,6 @@ PRIVATE_FUTEX		offsetof (tcbhead_t, private_futex)
 -- Not strictly offsets, but these values are also used in the TCB.
 TCB_CANCELSTATE_BITMASK	 CANCELSTATE_BITMASK
 TCB_CANCELTYPE_BITMASK	 CANCELTYPE_BITMASK
-TCB_CANCELING_BITMASK	 CANCELING_BITMASK
 TCB_CANCELED_BITMASK	 CANCELED_BITMASK
 TCB_EXITING_BITMASK	 EXITING_BITMASK
 TCB_CANCEL_RESTMASK	 CANCEL_RESTMASK
diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h
index b73e7ed..9caa23f 100644
--- a/sysdeps/x86_64/nptl/tls.h
+++ b/sysdeps/x86_64/nptl/tls.h
@@ -326,17 +326,6 @@ typedef struct
 	      abort (); })
 
 
-/* Atomic set bit.  */
-# define THREAD_ATOMIC_BIT_SET(descr, member, bit) \
-  (void) ({ if (sizeof ((descr)->member) == 4)				      \
-	      asm volatile (LOCK_PREFIX "orl %1, %%fs:%P0"		      \
-			    :: "i" (offsetof (struct pthread, member)),	      \
-			       "ir" (1 << (bit)));			      \
-	    else							      \
-	      /* Not necessary for other sizes in the moment.  */	      \
-	      abort (); })
-
-
 # define CALL_THREAD_FCT(descr) \
   ({ void *__res;							      \
      asm volatile ("movq %%fs:%P2, %%rdi\n\t"				      \

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=90f3365beccf3f11e1d16e71fece19082d86d518

commit 90f3365beccf3f11e1d16e71fece19082d86d518
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Fri Sep 18 18:14:19 2015 -0300

    nptl: powerpc64: Fix Race conditions in pthread cancellation (BZ#12683)
    
    This patches adds the powerpc64 modification required for the BZ#12683 fix.
    It basically removes the enable_asynccancel/disable_asynccancel function
    usage on code used on powerpc64, and provide a arch-specific symbol that
    contains global markers to be used in SIGCANCEL handler.
    
    	 * sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c (__libc_fnctl):
    	 Remove CANCEL_ASYNC/CANCEL_RESET usage.
    	 * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (PSEUDO):
    	 Likewise.
    	 (PSEUDO_RET): Likewise.
    	 (__pthread_get_ip): Add implementation.
    	 * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
    	 (SYSCALL_CANCEL_ERROR): New define.
    	 (SYSCALL_CANCEL_ERRNO): New define.
    	 * sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S: New file:
    	 cancellable syscall.
    	 * sysdeps/unix/sysv/linux/powerpc/sysdep.c (__syscall_cancel_error):
    	 New symbol: cancellable syscall error handler.

diff --git a/ChangeLog b/ChangeLog
index c915a7c..7b7630d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c (__libc_fnctl):
+	Remove CANCEL_ASYNC/CANCEL_RESET usage.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (PSEUDO):
+	Likewise.
+	(PSEUDO_RET): Likewise.
+	(__pthread_get_ip): Add implementation.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h 
+	(SYSCALL_CANCEL_ERROR): New define. 
+	(SYSCALL_CANCEL_ERRNO): New define. 
+	* sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S: New file: 
+	cancellable syscall. 
+	* sysdeps/unix/sysv/linux/powerpc/sysdep.c (__syscall_cancel_error):
+	New symbol: cancellable syscall error handler.
+
 	* nptl/Makefile [routines]: Add syscall_cancel object.
 	[libpthread-routines]: Remove cancellation object.
 	(CFLAGS-cancellation.c): Remove -fasynchronous-unwind-tables.
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c
index 69031ba..3a10d16 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c
@@ -23,8 +23,7 @@
 
 #include <sys/syscall.h>
 
-
-#ifndef NO_CANCELLATION
+#if !IS_IN (rtld)
 int
 __fcntl_nocancel (int fd, int cmd, ...)
 {
@@ -39,7 +38,6 @@ __fcntl_nocancel (int fd, int cmd, ...)
 }
 #endif
 
-
 int
 __libc_fcntl (int fd, int cmd, ...)
 {
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
index 5cd7ddb..9381bfc 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
@@ -27,121 +27,70 @@
 
 # define DASHDASHPFX(str) __##str
 
-#if _CALL_ELF == 2
-#define CANCEL_FRAMESIZE (FRAME_MIN_SIZE+16+48)
-#define CANCEL_PARM_SAVE (FRAME_MIN_SIZE+16)
-#else
-#define CANCEL_FRAMESIZE (FRAME_MIN_SIZE+16)
-#define CANCEL_PARM_SAVE (CANCEL_FRAMESIZE+FRAME_PARM_SAVE)
-#endif
+# if !IS_IN (libc)
+#  undef HIDDEN_JUMPTARGET
+#  define HIDDEN_JUMPTARGET(__symbol) __symbol
+# endif
+
+#define CANCEL_FRAMESIZE (FRAME_MIN_SIZE)
 
 # undef PSEUDO
 # define PSEUDO(name, syscall_name, args)				\
   .section ".text";							\
   ENTRY (name)								\
     SINGLE_THREAD_P;							\
-    bne- .Lpseudo_cancel;						\
-  .type DASHDASHPFX(syscall_name##_nocancel),@function;			\
-  .globl DASHDASHPFX(syscall_name##_nocancel);				\
-  DASHDASHPFX(syscall_name##_nocancel):					\
+    bne- L(pseudo_cancel);						\
     DO_CALL (SYS_ify (syscall_name));					\
-    PSEUDO_RET;								\
-  .size DASHDASHPFX(syscall_name##_nocancel),.-DASHDASHPFX(syscall_name##_nocancel);	\
-  .Lpseudo_cancel:							\
-    stdu 1,-CANCEL_FRAMESIZE(1);					\
-    cfi_adjust_cfa_offset (CANCEL_FRAMESIZE);				\
-    mflr 9;								\
-    std  9,CANCEL_FRAMESIZE+FRAME_LR_SAVE(1);				\
+    bnslr+;								\
+    TAIL_CALL_SYSCALL_ERROR;						\
+  L(pseudo_cancel):							\
+    mflr r0;								\
+    std  r0,FRAME_LR_SAVE(r1);						\
     cfi_offset (lr, FRAME_LR_SAVE);					\
-    DOCARGS_##args;	/* save syscall args around CENABLE.  */	\
-    CENABLE;								\
-    std  3,FRAME_MIN_SIZE(1); /* store CENABLE return value (MASK).  */	\
-    UNDOCARGS_##args;	/* restore syscall args.  */			\
-    DO_CALL (SYS_ify (syscall_name));					\
-    mfcr 0;		/* save CR/R3 around CDISABLE.  */		\
-    std  3,FRAME_MIN_SIZE+8(1);						\
-    std  0,CANCEL_FRAMESIZE+FRAME_CR_SAVE(1);				\
-    cfi_offset (cr, FRAME_CR_SAVE);					\
-    ld   3,FRAME_MIN_SIZE(1); /* pass MASK to CDISABLE.  */		\
-    CDISABLE;								\
-    ld   9,CANCEL_FRAMESIZE+FRAME_LR_SAVE(1);				\
-    ld   0,CANCEL_FRAMESIZE+FRAME_CR_SAVE(1); /* restore CR/R3. */	\
-    ld   3,FRAME_MIN_SIZE+8(1);						\
-    mtlr 9;								\
-    mtcr 0;								\
-    addi 1,1,CANCEL_FRAMESIZE;						\
+    stdu r1,-CANCEL_FRAMESIZE(r1);					\
+    cfi_adjust_cfa_offset (CANCEL_FRAMESIZE);				\
+    mr   r9,r8;								\
+    mr   r8,r7;								\
+    mr   r7,r6;								\
+    mr   r6,r5;								\
+    mr   r5,r4;								\
+    mr   r4,r3;								\
+    li   r3,SYS_ify (syscall_name);					\
+    bl   HIDDEN_JUMPTARGET(__syscall_cancel);				\
+    nop;								\
+    bl   JUMPTARGET(__syscall_cancel_error);				\
+    nop;								\
+    addi r1,r1,CANCEL_FRAMESIZE;					\
     cfi_adjust_cfa_offset (-CANCEL_FRAMESIZE);				\
+    ld   r0,FRAME_LR_SAVE(r1);						\
+    mtlr r0;								\
     cfi_restore (lr);							\
-    cfi_restore (cr)
-
-# define DOCARGS_0
-# define UNDOCARGS_0
-
-# define DOCARGS_1	std 3,CANCEL_PARM_SAVE(1); DOCARGS_0
-# define UNDOCARGS_1	ld 3,CANCEL_PARM_SAVE(1); UNDOCARGS_0
-
-# define DOCARGS_2	std 4,CANCEL_PARM_SAVE+8(1); DOCARGS_1
-# define UNDOCARGS_2	ld 4,CANCEL_PARM_SAVE+8(1); UNDOCARGS_1
-
-# define DOCARGS_3	std 5,CANCEL_PARM_SAVE+16(1); DOCARGS_2
-# define UNDOCARGS_3	ld 5,CANCEL_PARM_SAVE+16(1); UNDOCARGS_2
+    blr
 
-# define DOCARGS_4	std 6,CANCEL_PARM_SAVE+24(1); DOCARGS_3
-# define UNDOCARGS_4	ld 6,CANCEL_PARM_SAVE+24(1); UNDOCARGS_3
-
-# define DOCARGS_5	std 7,CANCEL_PARM_SAVE+32(1); DOCARGS_4
-# define UNDOCARGS_5	ld 7,CANCEL_PARM_SAVE+32(1); UNDOCARGS_4
-
-# define DOCARGS_6	std 8,CANCEL_PARM_SAVE+40(1); DOCARGS_5
-# define UNDOCARGS_6	ld 8,CANCEL_PARM_SAVE+40(1); UNDOCARGS_5
-
-# if IS_IN (libpthread)
-#  ifdef SHARED
-#   define CENABLE	bl JUMPTARGET(__pthread_enable_asynccancel)
-#   define CDISABLE	bl JUMPTARGET(__pthread_disable_asynccancel)
-#  else
-#   define CENABLE	bl JUMPTARGET(__pthread_enable_asynccancel); nop
-#   define CDISABLE	bl JUMPTARGET(__pthread_disable_asynccancel); nop
-#  endif
-# elif IS_IN (libc)
-#  ifdef SHARED
-#   define CENABLE	bl JUMPTARGET(__libc_enable_asynccancel)
-#   define CDISABLE	bl JUMPTARGET(__libc_disable_asynccancel)
-#  else
-#   define CENABLE	bl JUMPTARGET(__libc_enable_asynccancel); nop
-#   define CDISABLE	bl JUMPTARGET(__libc_disable_asynccancel); nop
-#  endif
-# elif IS_IN (librt)
-#  ifdef SHARED
-#   define CENABLE	bl JUMPTARGET(__librt_enable_asynccancel)
-#   define CDISABLE	bl JUMPTARGET(__librt_disable_asynccancel)
-#  else
-#   define CENABLE	bl JUMPTARGET(__librt_enable_asynccancel); nop
-#   define CDISABLE	bl JUMPTARGET(__librt_disable_asynccancel); nop
-#  endif
-# else
-#  error Unsupported library
-# endif
+# undef PSEUDO_RET
+# define PSEUDO_RET
 
 # ifndef __ASSEMBLER__
-#  define SINGLE_THREAD_P						\
-  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				\
-				   header.multiple_threads) == 0, 1)
+#  define SINGLE_THREAD_P                                               \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,                         \
+                                   header.multiple_threads) == 0, 1)
 # else
-#   define SINGLE_THREAD_P						\
-  lwz   10,MULTIPLE_THREADS_OFFSET(13);				\
+#   define SINGLE_THREAD_P                                              \
+  lwz   10,MULTIPLE_THREADS_OFFSET(13);                         	\
   cmpwi 10,0
 # endif
 
-#elif !defined __ASSEMBLER__
-
-# define SINGLE_THREAD_P (1)
-# define NO_CANCELLATION 1
-
 #endif
 
 #ifndef __ASSEMBLER__
 # define RTLD_SINGLE_THREAD_P \
   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
 				   header.multiple_threads) == 0, 1)
+
+static inline
+const char * __pthread_get_ip (const ucontext_t *uc)
+{
+  return (char *)uc->uc_mcontext.gp_regs[PT_NIP];
+}
+
 #endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
index e2014cc..8a941f8 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
@@ -131,6 +131,15 @@
     sc_ret;								\
   })
 
+#undef SYSCALL_CANCEL_ERROR
+#define SYSCALL_CANCEL_ERROR(err)					\
+  (err > 0xfffffffffffff000UL)
+
+#undef SYSCALL_CANCEL_ERRNO
+#define SYSCALL_CANCEL_ERRNO(err)					\
+  (-err)
+
+
 /* Define a macro which expands inline into the wrapper code for a system
    call. This use is for internal calls that do not need to handle errors
    normally. It will never touch errno. This returns just what the kernel
diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S b/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S
new file mode 100644
index 0000000..c7068d3
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/syscall_cancel.S
@@ -0,0 +1,63 @@
+/* Cancellable syscall wrapper - powerpc version.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+/* long int [r3] __syscall_cancel_arch (int *cancelhandling [r3],
+					long int nr   [r4],
+					long int arg1 [r5],
+					long int arg2 [r6],
+					long int arg3 [r7],
+					long int arg4 [r8],
+					long int arg5 [r9],
+					long int arg6 [r10])  */
+
+ENTRY (__syscall_cancel_arch)
+
+	.globl __syscall_cancel_arch_start
+	.type  __syscall_cancel_arch_start,@function
+__syscall_cancel_arch_start:
+
+	/* if (*cancelhandling & CANCELED_BITMASK)
+	     __syscall_do_cancel()  */
+	lwz     r0,0(r3)
+	rldicl. r0,r0,62,63
+	beq     1f
+	b       __syscall_do_cancel
+	nop
+1:
+	/* Issue a 6 argument syscall, the nr [r4] being the syscall
+	   number.  */
+	mr      r0,r4
+	mr      r3,r5
+	mr      r4,r6
+	mr      r5,r7
+	mr      r6,r8
+	mr      r7,r9
+	mr      r8,r10
+	sc
+
+	.globl __syscall_cancel_arch_end
+	.type  __syscall_cancel_arch_end,@function
+__syscall_cancel_arch_end:
+
+	bnslr+
+	neg	r3,r3
+	blr
+END (__syscall_cancel_arch)
+libc_hidden_def (__syscall_cancel_arch)
diff --git a/sysdeps/unix/sysv/linux/powerpc/sysdep.c b/sysdeps/unix/sysv/linux/powerpc/sysdep.c
index 6dc6737..8d58fd0 100644
--- a/sysdeps/unix/sysv/linux/powerpc/sysdep.c
+++ b/sysdeps/unix/sysv/linux/powerpc/sysdep.c
@@ -26,3 +26,14 @@ __syscall_error (int err_no)
   __set_errno (err_no);
   return -1;
 }
+
+long int
+__syscall_cancel_error (unsigned long err)
+{
+  if (__glibc_unlikely ((err) & (1 << 28)))
+    {
+      __set_errno (-err);
+      return -1;
+    }
+  return err;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=38b4a8b47519dce7bb92895eb61387837b2fe35f

commit 38b4a8b47519dce7bb92895eb61387837b2fe35f
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Fri Sep 18 18:26:35 2015 -0300

    nptl: Fix Race conditions in pthread cancellation (BZ#12683)
    
    This patches fixes some race conditions in NPTL cancellation code by
    redefining how cancellable syscalls are defined and handled.  Current
    approach is to enable asynchronous cancellation prior to making the syscall
    and restore the previous cancellation type once the syscall returns.
    
    As decribed in BZ#12683, this approach shows 2 important problems:
    
    1. Cancellation can act after the syscall has returned from kernel, but
       before userspace saves the return value.  It might result in a resource
       leak if the syscall allocated a resource or a side effect (partial
       read/write), and there is no way to program handle it with cancellation
       handlers.
    
    2. If a signal is handled while the thread is blocked at a cancellable
       syscall, the entire signal handler runs with asynchronous cancellation
       enabled.  This can lead to issues if the signal handler call functions
       which are async-signal-safe but not async-cancel-safe.
    
    For cancellation to work correctly, there are 5 points at which the
    cancellation signal could arrive:
    
    1. Before the final testcancel before the syscall is made.
    2. Between the testcancel and the syscall.
    3. While the syscall is blocked and no side effects have yet taken place.
    4. While the syscall is blocked but with some side effects already having
       taken place (e.g. a partial read or write).
    5. After the syscall has returned.
    
    And GLIBC wants to act on cancellation in cases 1, 2, and 3 but not in case
    4 or 5.  The proposed solution follows:
    
    * Handling case 1 is trivial: do a conditional branch based on whether the
      thread has received a cancellation request;
    * Case 2 can be caught by the signal handler determining that the saved
      program counter (from the ucontext_t) is in some address range beginning
      just before the "testcancel" and ending with the syscall instruction.
    * In this case, except for certain syscalls that ALWAYS fail with EINTR
      even for non-interrupting signals, the kernel will reset the program
      counter to point at the syscall instruction during signal handling, so
      that the syscall is restarted when the signal handler returns. So, from
      the signal handler's standpoint, this looks the same as case 2, and thus
      it's taken care of.
    * In this case, the kernel cannot restart the syscall; when it's
      interrupted by a signal, the kernel must cause the syscall to return
      with whatever partial result it obtained (e.g. partial read or write).
    * In this case, the saved program counter points just after the syscall
      instruction, so the signal handler won't act on cancellation.
      This one is equal to 4. since the program counter is past the syscall
      instruction already.
    
    Another case that needs handling is syscalls that fail with EINTR even
    when the signal handler is non-interrupting. In this case, the syscall
    wrapper code can just check the cancellation flag when the errno result
    is EINTR, and act on cancellation if it's set.
    
    The proposed GLIBC adjustments are:
    
    1. Remove the enable_asynccancel/disable_asynccancel function usage in
       syscall definition and instead make them call a common symbol that will
       check if cancellation is enabled, call the arch-specific cancellable
       entry-point and cancel the thread when required.
    2. Provide a arch-specific symbol that contains global markers. These
       markers will be used in SIGCANCEL handler to check if the interruption
       has been called in a valid syscall and if the syscalls has been
       completed or not.
    3. Rewrite SIGCANCEL asynchronous handler to check for both cancelling type
       and if current IP from signal handler falls between the global markes
       and act accordingly.
    4. Adjust nptl/pthread_cancel.c to send an signal instead of acting
       directly. This avoid synchronization issues about updating the
       cancellation status and also focus the logic on signal handler and
       cancellation syscall code.
    5. Adjust pthread code to replace CANCEL_ASYNC/CANCEL_RESET calls to
       appropriated cancelable futex syscalls.
    6. Adjust libc code to replace LIBC_CANCEL_ASYNC/LIBC_CANCEL_RESET to
       appropriated cancelable syscalls.
    7. Adjust 'lowlevellock.h' arch-specific implementations to provide
       cancelable futex calls (used in libpthread code).
    
    This patch adds the proposed changes to NPTL.

diff --git a/ChangeLog b/ChangeLog
index 9f59dbc..c915a7c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,106 @@
 2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+	* nptl/Makefile [routines]: Add syscall_cancel object.
+	[libpthread-routines]: Remove cancellation object.
+	(CFLAGS-cancellation.c): Remove -fasynchronous-unwind-tables.
+	* nptl/Versions [GLIBC_PRIVATE] (libc): Add __syscall_cancel,
+	__syscall_cancel_arch_start, and __syscall_cancel_arch_end.
+	* nptl/cancellation.c: Remove file.
+	* nptl/descr.h (CANCELING_BIT): Remove define.
+	(CANCELING_BITMASK): Likewise.
+	(CANCEL_RESTMASK): Adjust value with CANCELED_BIT remove.
+	* nptl/libc-cancellation.c (__syscall_cancel): Add non-cancellable
+	implementation for loader and cancellable one for libc.
+	(__syscall_do_cancel): New function: cancel call for syscall wrappers.
+	* nptl/lowlevellock.c (__lll_timedwait_tid): Using cancellable futex
+	call.
+	* nptl/nptl-init.c (sigcancel_handler): Rewrite function to avoid race
+	conditions.
+	(__pthread_initialize_minimal_internal): Add SA_RESTART to SIGCANCEL
+	handler.
+	* nptl/pt-system.c [LIBC_CANCEL_HANDLED]: Remove definition.
+	* io/creat.c (LIBC_CANCEL_HANDLED): Likewise.
+	* io/ppoll.c [ppoll] (LIBC_CANCEL_HANDLED): Likewise.
+	* misc/pselect [__pselect] (LIBC_CANCEL_HANDLED): Likewise.
+	* sysdeps/posix/pause.c (LIBC_CANCEL_HANDLED): Likewise.
+	* sysdeps/unix/sysv/linux/generic/creat.c (LIBC_CANCEL_HANDLED):
+	Likewise.
+	* nptl/pthreadP.h (__do_cancel): Rewrite to both disable asynchronous
+	cancellation and setting the thread as cancelled.
+	(CANCEL_ASYNC): Remove definition.
+	(CANCEL_RESET): Likewise.
+	(LIBC_CANCEL_ASYNC): Likewise.
+	(LIBC_CANCEL_RESET): Likewise.
+	(LIBC_CANCEL_HANDLED): Likewise.
+	(__syscall_cancel_arch): Add prototype.
+	(__pthread_enable_asynccancel): Remove prototype.
+	(__pthread_disable_asynccancel): Likewise.
+	(__libc_enable_asynccancel): Likewise.
+	(__libc_disable_asynccancel): Likewise.
+	(__librt_enable_asynccancel): Likewise.
+	(__librt_disable_asynccancel): Likewise.
+	(__syscall_cancel): Add prototype.
+	* nptl/pthread_cancel.c (pthread_cancel): Rewrite to just set
+	CANCELLED_BIT and call __pthread_kill.
+	* nptl/pthread_cond_timedwait.c (__pthread_cond_timedwait): Remove
+	calls to enable/disable asynchronous cancellation and use call to
+	cancellable syscall entrypoint when required.
+	* nptl/pthread_cond_wait.c (__pthread_cond_wait): Likewise.
+	* nptl/pthread_create.c (start_thread): Likewise.
+	* nptl/pthread_timedjoin.c (pthread_timedjoin_np): Likewise.
+	* nptl/sem_timedwait.c (sem_timedwait):  Likewise.
+	* nptl/sem_wait.c (__new_sem_wait): Likewise.
+	* nptl/sem_waitcommon.c (futex_abstimed_wait): Likewise.
+	* sysdeps/nptl/aio_misc.h (AIO_MISC_WAIT): Likewise.
+	* sysdeps/nptl/gai_misc.h (GAI_MISC_WAIT): Likewise.
+	* sysdeps/posix/sigpause.c (do_sigpause): Likewise.
+	* sysdeps/posix/sigwait.c (__sigwait): Likewise.
+	* sysdeps/posix/waitid.c (__waitid): Likewise.
+	* sysdeps/nptl/lowlevellock.h (lll_wait_tid): Likewise.
+	* sysdeps/posix/open64.c (__libc_open64): Likewise.
+	* sysdeps/unix/sysv/linux/sigwait.c (__sigwait): Likewise.
+	* nptl/pthread_exit.c (pthread_exit): Rewrite to set EXITING_BIT
+	before call __pthread_unwind.
+	* nptl/pthread_join.c (pthread_join): Remove CANCEL_ASYNC/CANCEL_RESET
+	usage.
+	* rt/Makefile [CFLAGS-librt-cancellation.c]: Remove rule.
+	* sysdeps/generic/sysdep-cancel.h (LIBC_CANCEL_ASYNC): Remove define.
+	(LIBC_CANCEL_RESET): Likewise.
+	(LIBC_CANCEL_HANDLED): Likewise.
+	* sysdeps/unix/sysv/linux/clock_nanosleep.c (__clock_nanosleep):
+	Likewise.
+	* sysdeps/unix/sysv/linux/fcntl.c (__libc_fcntl): Likewise.
+	* sysdeps/unix/sysv/linux/generic/wordsize-32/fcntl.c (__libc_fcntl):
+	Likewise.
+	* sysdeps/nptl/Makefile [$(subdir) = rt] (librt-sysdep_routines):
+	Remove librt-cancellation object.
+	[$(subdir) = rt] (librt-cancellation.c): Remove rule.
+	* sysdeps/nptl/librt-cancellation.c: Remove file.
+	* sysdeps/unix/sysv/linux/lowlevellock-futex.h (lll_futex_wait_cancel):
+	New define: cancellable futex wait.
+	(lll_futex_timed_wait_cancel): New define: cancellable timed wait.
+	(lll_futex_timed_wait_bitset_cancel): New define: cancellable timed
+	wait bitset.
+	(lll_futex_wait_requeue_pi_cancel): New define: cancellable wait
+	requeue PI futex.
+	(lll_futex_timed_wait_requeue_pi_cancel): New define: cancellable time
+	wait requeue PI futex.
+	(lll_wait_tid): Use cancellable futex wait call.
+	* sysdeps/powerpc/nptl/pthreaddef.h (__pthread_get_ip): New function:
+	return ucontext_t instruction point address.
+	* sysdeps/unix/sysdep.h (SYSCALL_CANCEL): New macro: cancelable
+	syscall calls.
+	(__syscall_cancel): New prototype.
+	* sysdeps/unix/sysv/linux/socketcall.h (SOCKETCALL): Use __SSC macros.
+	(SOCKETCALL_CANCEL): Use SYSCALL_CANCEL macros.
+	* sysdeps/generic/sysdep-cancel.h (LIBC_CANCEL_ASYNC): Remove define.
+	(LIBC_CANCEL_RESET): Likewise.
+	(LIBC_CANCEL_HANDLED): Likewise.
+	* sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): Allow
+	SIGCANCEL to be sent.
+	* nptl/tst-cancel28.c: New file.
+
+2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 	    Phil Blundell <pb@pbcui.dot.net>
 
 	* nptl/Makefile [$(run-built-tests) = yes] (tests-special): Remove
diff --git a/io/creat.c b/io/creat.c
index c03810d..f602401 100644
--- a/io/creat.c
+++ b/io/creat.c
@@ -29,6 +29,3 @@ creat (file, mode)
 {
   return __open (file, O_WRONLY|O_CREAT|O_TRUNC, mode);
 }
-
-/* __open handles cancellation.  */
-LIBC_CANCEL_HANDLED ();
diff --git a/io/ppoll.c b/io/ppoll.c
index f64c737..3f08f1d 100644
--- a/io/ppoll.c
+++ b/io/ppoll.c
@@ -70,7 +70,5 @@ ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
 }
 
 #ifndef ppoll
-/* __poll handles cancellation.  */
-LIBC_CANCEL_HANDLED ();
 libc_hidden_def (ppoll);
 #endif
diff --git a/misc/pselect.c b/misc/pselect.c
index 2f8d0a3..e8d6dfd 100644
--- a/misc/pselect.c
+++ b/misc/pselect.c
@@ -73,6 +73,4 @@ __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 }
 #ifndef __pselect
 weak_alias (__pselect, pselect)
-/* __select handles cancellation.  */
-LIBC_CANCEL_HANDLED ();
 #endif
diff --git a/nptl/Makefile b/nptl/Makefile
index 39e28fd..05a4872 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -30,7 +30,7 @@ install-lib-ldscripts := libpthread.so
 
 routines = alloca_cutoff forward libc-lowlevellock libc-cancellation \
 	   libc-cleanup libc_pthread_init libc_multiple_threads \
-	   register-atfork unregister-atfork
+	   register-atfork unregister-atfork syscall_cancel
 shared-only-routines = forward
 
 libpthread-routines = nptl-init vars events version pt-interp \
@@ -104,7 +104,6 @@ libpthread-routines = nptl-init vars events version pt-interp \
 		      cleanup cleanup_defer cleanup_compat \
 		      cleanup_defer_compat unwind \
 		      pt-longjmp pt-cleanup\
-		      cancellation \
 		      lowlevellock lowlevelrobustlock \
 		      lll_timedlock_wait lll_timedwait_tid \
 		      pt-fork pt-vfork \
@@ -159,7 +158,6 @@ CFLAGS-pthread_setcanceltype.c = -fexceptions -fasynchronous-unwind-tables
 
 # These are internal functions which similar functionality as setcancelstate
 # and setcanceltype.
-CFLAGS-cancellation.c = -fasynchronous-unwind-tables
 CFLAGS-libc-cancellation.c = -fasynchronous-unwind-tables
 
 # Calling pthread_exit() must cause the registered cancel handlers to
@@ -257,7 +255,7 @@ tests = tst-typesizes \
 	tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \
 	tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \
 	tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel24 tst-cancel25 \
-	tst-cancel26 tst-cancel27 \
+	tst-cancel26 tst-cancel27 tst-cancel28 \
 	tst-cancel-self tst-cancel-self-cancelstate \
 	tst-cancel-self-canceltype tst-cancel-self-testcancel \
 	tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \
diff --git a/nptl/Versions b/nptl/Versions
index 34e4b46..863b82f 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -36,6 +36,9 @@ libc {
     __libc_pthread_init;
     __libc_current_sigrtmin_private; __libc_current_sigrtmax_private;
     __libc_allocate_rtsig_private;
+    __syscall_cancel;
+    __syscall_cancel_arch_start;
+    __syscall_cancel_arch_end;
   }
 }
 
diff --git a/nptl/cancellation.c b/nptl/cancellation.c
deleted file mode 100644
index 2bd3168..0000000
--- a/nptl/cancellation.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <setjmp.h>
-#include <stdlib.h>
-#include "pthreadP.h"
-#include <futex-internal.h>
-
-
-/* The next two functions are similar to pthread_setcanceltype() but
-   more specialized for the use in the cancelable functions like write().
-   They do not need to check parameters etc.  */
-int
-attribute_hidden
-__pthread_enable_asynccancel (void)
-{
-  struct pthread *self = THREAD_SELF;
-  int oldval = THREAD_GETMEM (self, cancelhandling);
-
-  while (1)
-    {
-      int newval = oldval | CANCELTYPE_BITMASK;
-
-      if (newval == oldval)
-	break;
-
-      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
-					      oldval);
-      if (__glibc_likely (curval == oldval))
-	{
-	  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
-	    {
-	      THREAD_SETMEM (self, result, PTHREAD_CANCELED);
-	      __do_cancel ();
-	    }
-
-	  break;
-	}
-
-      /* Prepare the next round.  */
-      oldval = curval;
-    }
-
-  return oldval;
-}
-
-
-void
-internal_function attribute_hidden
-__pthread_disable_asynccancel (int oldtype)
-{
-  /* If asynchronous cancellation was enabled before we do not have
-     anything to do.  */
-  if (oldtype & CANCELTYPE_BITMASK)
-    return;
-
-  struct pthread *self = THREAD_SELF;
-  int newval;
-
-  int oldval = THREAD_GETMEM (self, cancelhandling);
-
-  while (1)
-    {
-      newval = oldval & ~CANCELTYPE_BITMASK;
-
-      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
-					      oldval);
-      if (__glibc_likely (curval == oldval))
-	break;
-
-      /* Prepare the next round.  */
-      oldval = curval;
-    }
-
-  /* We cannot return when we are being canceled.  Upon return the
-     thread might be things which would have to be undone.  The
-     following loop should loop until the cancellation signal is
-     delivered.  */
-  while (__builtin_expect ((newval & (CANCELING_BITMASK | CANCELED_BITMASK))
-			   == CANCELING_BITMASK, 0))
-    {
-      futex_wait_simple ((unsigned int *) &self->cancelhandling, newval,
-			 FUTEX_PRIVATE);
-      newval = THREAD_GETMEM (self, cancelhandling);
-    }
-}
diff --git a/nptl/descr.h b/nptl/descr.h
index a502048..6eb0036 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -263,23 +263,20 @@ struct pthread
   /* Bit set if asynchronous cancellation mode is selected.  */
 #define CANCELTYPE_BIT		1
 #define CANCELTYPE_BITMASK	(0x01 << CANCELTYPE_BIT)
-  /* Bit set if canceling has been initiated.  */
-#define CANCELING_BIT		2
-#define CANCELING_BITMASK	(0x01 << CANCELING_BIT)
-  /* Bit set if canceled.  */
-#define CANCELED_BIT		3
+  /* Bit set if threads is canceled.  */
+#define CANCELED_BIT		2
 #define CANCELED_BITMASK	(0x01 << CANCELED_BIT)
   /* Bit set if thread is exiting.  */
-#define EXITING_BIT		4
+#define EXITING_BIT		3
 #define EXITING_BITMASK		(0x01 << EXITING_BIT)
   /* Bit set if thread terminated and TCB is freed.  */
-#define TERMINATED_BIT		5
+#define TERMINATED_BIT		4
 #define TERMINATED_BITMASK	(0x01 << TERMINATED_BIT)
   /* Bit set if thread is supposed to change XID.  */
-#define SETXID_BIT		6
+#define SETXID_BIT		5
 #define SETXID_BITMASK		(0x01 << SETXID_BIT)
   /* Mask for the rest.  Helps the compiler to optimize.  */
-#define CANCEL_RESTMASK		0xffffff80
+#define CANCEL_RESTMASK		0xffffffc0
 
 #define CANCEL_ENABLED_AND_CANCELED(value) \
   (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK	      \
diff --git a/nptl/libc-cancellation.c b/nptl/libc-cancellation.c
index cc9dc06..70f7f66 100644
--- a/nptl/libc-cancellation.c
+++ b/nptl/libc-cancellation.c
@@ -16,9 +16,69 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <setjmp.h>
+#include <stdlib.h>
 #include "pthreadP.h"
 
+#if IS_IN (rtld)
 
-#define __pthread_enable_asynccancel __libc_enable_asynccancel
-#define __pthread_disable_asynccancel __libc_disable_asynccancel
-#include <nptl/cancellation.c>
+long int
+__syscall_cancel (__syscall_arg_t nr, __syscall_arg_t a1,
+		  __syscall_arg_t a2, __syscall_arg_t a3,
+		  __syscall_arg_t a4, __syscall_arg_t a5,
+		  __syscall_arg_t a6)
+{
+  long int result;
+  INTERNAL_SYSCALL_DECL (err);
+  result = INTERNAL_SYSCALL_NCS (nr, err, 6, a1, a2, a3, a4, a5, a6);
+  if (INTERNAL_SYSCALL_ERROR_P (result, err))
+    return -INTERNAL_SYSCALL_ERRNO (result, err);
+  return result;
+}
+
+#else
+
+/* Cancellation function called by all cancellable syscalls.  */
+long int
+__syscall_cancel (__syscall_arg_t nr, __syscall_arg_t a1,
+		  __syscall_arg_t a2, __syscall_arg_t a3,
+		  __syscall_arg_t a4, __syscall_arg_t a5,
+		  __syscall_arg_t a6)
+{
+  pthread_t self = (pthread_t) THREAD_SELF;
+  volatile struct pthread *pd = (volatile struct pthread *) self;
+  long int result;
+
+  /* If cancellation is not enabled, call the syscall directly.  */
+  if (pd->cancelhandling & CANCELSTATE_BITMASK)
+    {
+      INTERNAL_SYSCALL_DECL (err);
+      result = INTERNAL_SYSCALL_NCS (nr, err, 6, a1, a2, a3, a4, a5, a6);
+      if (INTERNAL_SYSCALL_ERROR_P (result, err))
+	return -INTERNAL_SYSCALL_ERRNO (result, err);
+      return result;
+    }
+
+  /* Call the arch-specific entry points that contains the globals markers
+     to be checked by SIGCANCEL handler.  */
+  result = __syscall_cancel_arch (&pd->cancelhandling, nr, a1, a2, a3, a4, a5,
+			          a6);
+
+  if ((result == -EINTR)
+      && (pd->cancelhandling & CANCELED_BITMASK)
+      && !(pd->cancelhandling & CANCELSTATE_BITMASK))
+    __do_cancel ();
+
+  return result;
+}
+libc_hidden_def (__syscall_cancel)
+
+/* Since __do_cancel is a always inline function, this creates a symbol the
+   arch-specific symbol can call to cancel the thread.  */
+void
+__syscall_do_cancel (void)
+{
+  __do_cancel ();
+}
+
+#endif
diff --git a/nptl/lll_timedlock_wait.c b/nptl/lll_timedlock_wait.c
index 37cf083..a21e66c 100644
--- a/nptl/lll_timedlock_wait.c
+++ b/nptl/lll_timedlock_wait.c
@@ -52,7 +52,7 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
         return ETIMEDOUT;
 
       /* If *futex == 2, wait until woken or timeout.  */
-      lll_futex_timed_wait (futex, 2, &rt, private);
+      lll_futex_timed_wait_cancel (futex, 2, &rt, private);
     }
 
   return 0;
diff --git a/nptl/lll_timedwait_tid.c b/nptl/lll_timedwait_tid.c
index 68b4857..acb3c49 100644
--- a/nptl/lll_timedwait_tid.c
+++ b/nptl/lll_timedwait_tid.c
@@ -62,7 +62,8 @@ __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
          The kernel up to version 3.16.3 does not use the private futex
          operations for futex wake-up when the clone terminates.
       */
-      if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
+      if (lll_futex_timed_wait_cancel (tidp, tid, &rt, LLL_SHARED)
+	  == -ETIMEDOUT)
         return ETIMEDOUT;
     }
 
diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
index 79bcaab..3c5e3b7 100644
--- a/nptl/nptl-init.c
+++ b/nptl/nptl-init.c
@@ -38,6 +38,7 @@
 #include <kernel-features.h>
 #include <libc-internal.h>
 #include <pthread-pids.h>
+#include <sysdep-cancel.h>
 
 #ifndef TLS_MULTIPLE_THREADS_IN_TCB
 /* Pointer to the corresponding variable in libc.  */
@@ -200,36 +201,41 @@ sigcancel_handler (int sig, siginfo_t *si, void *ctx)
     return;
 
   struct pthread *self = THREAD_SELF;
+  volatile struct pthread *pd = (volatile struct pthread *) self;
+  ucontext_t *uc = ctx;
+  const char *tip = (const char *)__pthread_get_ip (ctx);
 
-  int oldval = THREAD_GETMEM (self, cancelhandling);
-  while (1)
+  extern const char __syscall_cancel_arch_start[1];
+  extern const char __syscall_cancel_arch_end[1];
+
+  if (((pd->cancelhandling & (CANCELSTATE_BITMASK)) != 0)
+      || ((pd->cancelhandling & CANCELED_BITMASK) == 0))
+    return;
+
+  __sigaddset (&uc->uc_sigmask, SIGCANCEL);
+
+  /* Check if asynchronous cancellation mode is set and if interrupted
+     instruction pointer falls within the cancellable syscall code.  For
+     interruptable syscalls that might generate external side-effects (partial
+     reads or writes, for instance), the kernel will set the IP to after
+     '__syscall_cancel_arch_end', thus disabling the cancellation and allowing
+     the process to handle such conditions.  */
+  if (pd->cancelhandling & CANCELTYPE_BITMASK ||
+      (tip >= __syscall_cancel_arch_start && tip < __syscall_cancel_arch_end))
     {
-      /* We are canceled now.  When canceled by another thread this flag
-	 is already set but if the signal is directly send (internally or
-	 from another process) is has to be done here.  */
-      int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
-
-      if (oldval == newval || (oldval & EXITING_BITMASK) != 0)
-	/* Already canceled or exiting.  */
-	break;
-
-      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
-					      oldval);
-      if (curval == oldval)
-	{
-	  /* Set the return value.  */
-	  THREAD_SETMEM (self, result, PTHREAD_CANCELED);
-
-	  /* Make sure asynchronous cancellation is still enabled.  */
-	  if ((newval & CANCELTYPE_BITMASK) != 0)
-	    /* Run the registered destructors and terminate the thread.  */
-	    __do_cancel ();
-
-	  break;
-	}
-
-      oldval = curval;
+      THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
+      THREAD_SETMEM (self, result, PTHREAD_CANCELED);
+
+      /* __pthread_sigmask removes SIGCANCEL from the set.  */
+      INTERNAL_SYSCALL_DECL (err);
+      INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIGCANCEL, &uc->uc_sigmask, 0,
+                        _NSIG / 8);
+
+      __do_cancel ();
     }
+
+  INLINE_SYSCALL (tgkill, 3, THREAD_GETMEM (THREAD_SELF, pid), pd->tid,
+		  SIGCANCEL);
 }
 #endif
 
@@ -400,7 +406,10 @@ __pthread_initialize_minimal_internal (void)
      cannot install the handler we do not abort.  Maybe we should, but
      it is only asynchronous cancellation which is affected.  */
   sa.sa_sigaction = sigcancel_handler;
-  sa.sa_flags = SA_SIGINFO;
+  /* The signal handle should be non-interruptible to avoid the risk of
+     spurious EINTR caused by SIGCANCEL sent to process or if pthread_cancel
+     is called while cancellation is disabled in the target thread.  */
+  sa.sa_flags = SA_SIGINFO | SA_RESTART;
   (void) __libc_sigaction (SIGCANCEL, &sa, NULL);
 # endif
 
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index b96be56..41ed84d 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -277,50 +277,35 @@ __do_cancel (void)
 {
   struct pthread *self = THREAD_SELF;
 
-  /* Make sure we get no more cancellations.  */
-  THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
+  /* Make sure we get no more cancellations by clearing the cancel
+     state.  */
+  int oldval = THREAD_GETMEM (self, cancelhandling);
+  while (1)
+    {
+      int newval = (oldval | CANCELSTATE_BITMASK);
+      newval &= ~(CANCELTYPE_BITMASK);
+      if (oldval == newval)
+	break;
+
+      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+					  oldval);
+      if (__glibc_likely (curval == oldval))
+	break;
+      oldval = curval;
+    }
+  THREAD_ATOMIC_BIT_SET (self, cancelhandling, 
+
+  THREAD_SETMEM (self, result, PTHREAD_CANCELED);
 
   __pthread_unwind ((__pthread_unwind_buf_t *)
 		    THREAD_GETMEM (self, cleanup_jmp_buf));
 }
 
 
-/* Set cancellation mode to asynchronous.  */
-#define CANCEL_ASYNC() \
-  __pthread_enable_asynccancel ()
-/* Reset to previous cancellation mode.  */
-#define CANCEL_RESET(oldtype) \
-  __pthread_disable_asynccancel (oldtype)
-
-#if IS_IN (libc)
-/* Same as CANCEL_ASYNC, but for use in libc.so.  */
-# define LIBC_CANCEL_ASYNC() \
-  __libc_enable_asynccancel ()
-/* Same as CANCEL_RESET, but for use in libc.so.  */
-# define LIBC_CANCEL_RESET(oldtype) \
-  __libc_disable_asynccancel (oldtype)
-# define LIBC_CANCEL_HANDLED() \
-  __asm (".globl " __SYMBOL_PREFIX "__libc_enable_asynccancel"); \
-  __asm (".globl " __SYMBOL_PREFIX "__libc_disable_asynccancel")
-#elif IS_IN (libpthread)
-# define LIBC_CANCEL_ASYNC() CANCEL_ASYNC ()
-# define LIBC_CANCEL_RESET(val) CANCEL_RESET (val)
-# define LIBC_CANCEL_HANDLED() \
-  __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \
-  __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel")
-#elif IS_IN (librt)
-# define LIBC_CANCEL_ASYNC() \
-  __librt_enable_asynccancel ()
-# define LIBC_CANCEL_RESET(val) \
-  __librt_disable_asynccancel (val)
-# define LIBC_CANCEL_HANDLED() \
-  __asm (".globl " __SYMBOL_PREFIX "__librt_enable_asynccancel"); \
-  __asm (".globl " __SYMBOL_PREFIX "__librt_disable_asynccancel")
-#else
-# define LIBC_CANCEL_ASYNC()	0 /* Just a dummy value.  */
-# define LIBC_CANCEL_RESET(val)	((void)(val)) /* Nothing, but evaluate it.  */
-# define LIBC_CANCEL_HANDLED()	/* Nothing.  */
-#endif
+extern long int __syscall_cancel_arch (volatile void *, __syscall_arg_t nr,
+     __syscall_arg_t arg1, __syscall_arg_t arg2, __syscall_arg_t arg3,
+     __syscall_arg_t arg4, __syscall_arg_t arg5, __syscall_arg_t arg6);
+libc_hidden_proto (__syscall_cancel_arch);
 
 
 /* Internal prototypes.  */
@@ -488,9 +473,6 @@ extern int __pthread_equal (pthread_t thread1, pthread_t thread2);
 extern int __pthread_kill (pthread_t threadid, int signo);
 extern void __pthread_exit (void *value) __attribute__ ((__noreturn__));
 extern int __pthread_setcanceltype (int type, int *oldtype);
-extern int __pthread_enable_asynccancel (void) attribute_hidden;
-extern void __pthread_disable_asynccancel (int oldtype)
-     internal_function attribute_hidden;
 
 #if IS_IN (libpthread)
 hidden_proto (__pthread_mutex_init)
@@ -521,16 +503,6 @@ extern int __pthread_cond_wait_2_0 (pthread_cond_2_0_t *cond,
 extern int __pthread_getaffinity_np (pthread_t th, size_t cpusetsize,
 				     cpu_set_t *cpuset);
 
-/* The two functions are in libc.so and not exported.  */
-extern int __libc_enable_asynccancel (void) attribute_hidden;
-extern void __libc_disable_asynccancel (int oldtype)
-     internal_function attribute_hidden;
-
-
-/* The two functions are in librt.so and not exported.  */
-extern int __librt_enable_asynccancel (void) attribute_hidden;
-extern void __librt_disable_asynccancel (int oldtype)
-     internal_function attribute_hidden;
 
 #if IS_IN (libpthread)
 /* Special versions which use non-exported functions.  */
diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c
index 981e4bc..c0776c6 100644
--- a/nptl/pthread_cancel.c
+++ b/nptl/pthread_cancel.c
@@ -23,7 +23,6 @@
 #include <atomic.h>
 #include <sysdep.h>
 
-
 int
 pthread_cancel (pthread_t th)
 {
@@ -37,75 +36,17 @@ pthread_cancel (pthread_t th)
 #ifdef SHARED
   pthread_cancel_init ();
 #endif
-  int result = 0;
-  int oldval;
-  int newval;
-  do
-    {
-    again:
-      oldval = pd->cancelhandling;
-      newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
-
-      /* Avoid doing unnecessary work.  The atomic operation can
-	 potentially be expensive if the bug has to be locked and
-	 remote cache lines have to be invalidated.  */
-      if (oldval == newval)
-	break;
-
-      /* If the cancellation is handled asynchronously just send a
-	 signal.  We avoid this if possible since it's more
-	 expensive.  */
-      if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
-	{
-	  /* Mark the cancellation as "in progress".  */
-	  if (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling,
-						    oldval | CANCELING_BITMASK,
-						    oldval))
-	    goto again;
-
-#ifdef SIGCANCEL
-	  /* The cancellation handler will take care of marking the
-	     thread as canceled.  */
-	  INTERNAL_SYSCALL_DECL (err);
-
-	  /* One comment: The PID field in the TCB can temporarily be
-	     changed (in fork).  But this must not affect this code
-	     here.  Since this function would have to be called while
-	     the thread is executing fork, it would have to happen in
-	     a signal handler.  But this is no allowed, pthread_cancel
-	     is not guaranteed to be async-safe.  */
-	  int val;
-	  val = INTERNAL_SYSCALL (tgkill, err, 3,
-				  THREAD_GETMEM (THREAD_SELF, pid), pd->tid,
-				  SIGCANCEL);
-
-	  if (INTERNAL_SYSCALL_ERROR_P (val, err))
-	    result = INTERNAL_SYSCALL_ERRNO (val, err);
-#else
-          /* It should be impossible to get here at all, since
-             pthread_setcanceltype should never have allowed
-             PTHREAD_CANCEL_ASYNCHRONOUS to be set.  */
-          abort ();
-#endif
-
-	  break;
-	}
 
-	/* A single-threaded process should be able to kill itself, since
-	   there is nothing in the POSIX specification that says that it
-	   cannot.  So we set multiple_threads to true so that cancellation
-	   points get executed.  */
-	THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
+  THREAD_ATOMIC_BIT_SET (pd, cancelhandling, CANCELED_BIT);
+  /* A single-threaded process should be able to kill itself, since there is
+     nothing in the POSIX specification that says that it cannot.  So we set
+     multiple_threads to true so that cancellation points get executed.  */
+  THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
 #ifndef TLS_MULTIPLE_THREADS_IN_TCB
-	__pthread_multiple_threads = *__libc_multiple_threads_ptr = 1;
+  __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1;
 #endif
-    }
-  /* Mark the thread as canceled.  This has to be done
-     atomically since other bits could be modified as well.  */
-  while (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling, newval,
-					       oldval));
 
-  return result;
+  return __pthread_kill (th, SIGCANCEL);
 }
 
 PTHREAD_STATIC_FN_REQUIRE (pthread_create)
diff --git a/nptl/pthread_cond_timedwait.c b/nptl/pthread_cond_timedwait.c
index 10b0a61..8c944c6 100644
--- a/nptl/pthread_cond_timedwait.c
+++ b/nptl/pthread_cond_timedwait.c
@@ -42,7 +42,6 @@ extern void __condvar_cleanup (void *arg)
 
 struct _condvar_cleanup_buffer
 {
-  int oldtype;
   pthread_cond_t *cond;
   pthread_mutex_t *mutex;
   unsigned int bc_seq;
@@ -63,7 +62,7 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
   int pshared = (cond->__data.__mutex == (void *) ~0l)
 		? LLL_SHARED : LLL_PRIVATE;
 
-#if (defined lll_futex_timed_wait_requeue_pi \
+#if (defined lll_futex_timed_wait_requeue_pi_cancel \
      && defined __ASSUME_REQUEUE_PI)
   int pi_flag = 0;
 #endif
@@ -156,12 +155,9 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
       /* Prepare to wait.  Release the condvar futex.  */
       lll_unlock (cond->__data.__lock, pshared);
 
-      /* Enable asynchronous cancellation.  Required by the standard.  */
-      cbuffer.oldtype = __pthread_enable_asynccancel ();
-
 /* REQUEUE_PI was implemented after FUTEX_CLOCK_REALTIME, so it is sufficient
    to check just the former.  */
-#if (defined lll_futex_timed_wait_requeue_pi \
+#if (defined lll_futex_timed_wait_requeue_pi_cancel \
      && defined __ASSUME_REQUEUE_PI)
       /* If pi_flag remained 1 then it means that we had the lock and the mutex
 	 but a spurious waker raced ahead of us.  Give back the mutex before
@@ -177,10 +173,11 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
 	{
 	  unsigned int clockbit = (cond->__data.__nwaiters & 1
 				   ? 0 : FUTEX_CLOCK_REALTIME);
-	  err = lll_futex_timed_wait_requeue_pi (&cond->__data.__futex,
-						 futex_val, abstime, clockbit,
-						 &mutex->__data.__lock,
-						 pshared);
+	  err = lll_futex_timed_wait_requeue_pi_cancel (&cond->__data.__futex,
+							futex_val, abstime,
+							clockbit,
+							&mutex->__data.__lock,
+							pshared);
 	  pi_flag = (err == 0);
 	}
       else
@@ -188,21 +185,19 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
 
 	{
 #if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
-     || !defined lll_futex_timed_wait_bitset)
+     || !defined lll_futex_timed_wait_bitset_cancel)
 	  /* Wait until woken by signal or broadcast.  */
-	  err = lll_futex_timed_wait (&cond->__data.__futex,
-				      futex_val, &rt, pshared);
+	  err = lll_futex_timed_wait_cancel (&cond->__data.__futex,
+					     futex_val, &rt, pshared);
 #else
 	  unsigned int clockbit = (cond->__data.__nwaiters & 1
 				   ? 0 : FUTEX_CLOCK_REALTIME);
-	  err = lll_futex_timed_wait_bitset (&cond->__data.__futex, futex_val,
-					     abstime, clockbit, pshared);
+	  err = lll_futex_timed_wait_bitset_cancel (&cond->__data.__futex,
+						    futex_val,abstime,
+						    clockbit, pshared);
 #endif
 	}
 
-      /* Disable asynchronous cancellation.  */
-      __pthread_disable_asynccancel (cbuffer.oldtype);
-
       /* We are going to look at shared data again, so get the lock.  */
       lll_lock (cond->__data.__lock, pshared);
 
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
index 0d6558b..8e7bebb 100644
--- a/nptl/pthread_cond_wait.c
+++ b/nptl/pthread_cond_wait.c
@@ -29,7 +29,6 @@
 
 struct _condvar_cleanup_buffer
 {
-  int oldtype;
   pthread_cond_t *cond;
   pthread_mutex_t *mutex;
   unsigned int bc_seq;
@@ -106,7 +105,7 @@ __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
   int pshared = (cond->__data.__mutex == (void *) ~0l)
 		? LLL_SHARED : LLL_PRIVATE;
 
-#if (defined lll_futex_wait_requeue_pi \
+#if (defined lll_futex_wait_requeue_pi_cancel \
      && defined __ASSUME_REQUEUE_PI)
   int pi_flag = 0;
 #endif
@@ -157,10 +156,7 @@ __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
       /* Prepare to wait.  Release the condvar futex.  */
       lll_unlock (cond->__data.__lock, pshared);
 
-      /* Enable asynchronous cancellation.  Required by the standard.  */
-      cbuffer.oldtype = __pthread_enable_asynccancel ();
-
-#if (defined lll_futex_wait_requeue_pi \
+#if (defined lll_futex_wait_requeue_pi_cancel \
      && defined __ASSUME_REQUEUE_PI)
       /* If pi_flag remained 1 then it means that we had the lock and the mutex
 	 but a spurious waker raced ahead of us.  Give back the mutex before
@@ -174,19 +170,17 @@ __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
 
       if (pi_flag)
 	{
-	  err = lll_futex_wait_requeue_pi (&cond->__data.__futex,
-					   futex_val, &mutex->__data.__lock,
-					   pshared);
+	  err = lll_futex_wait_requeue_pi_cancel (&cond->__data.__futex,
+						  futex_val,
+						  &mutex->__data.__lock,
+						  pshared);
 
 	  pi_flag = (err == 0);
 	}
       else
 #endif
 	  /* Wait until woken by signal or broadcast.  */
-	lll_futex_wait (&cond->__data.__futex, futex_val, pshared);
-
-      /* Disable asynchronous cancellation.  */
-      __pthread_disable_asynccancel (cbuffer.oldtype);
+	lll_futex_wait_cancel (&cond->__data.__futex, futex_val, pshared);
 
       /* We are going to look at shared data again, so get the lock.  */
       lll_lock (cond->__data.__lock, pshared);
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index d10f4ea..17436f5 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -289,7 +289,7 @@ START_THREAD_DEFN
   /* If the parent was running cancellation handlers while creating
      the thread the new thread inherited the signal mask.  Reset the
      cancellation signal mask.  */
-  if (__glibc_unlikely (pd->parent_cancelhandling & CANCELING_BITMASK))
+  if (__glibc_unlikely (pd->parent_cancelhandling & CANCELED_BITMASK))
     {
       INTERNAL_SYSCALL_DECL (err);
       sigset_t mask;
@@ -317,14 +317,10 @@ START_THREAD_DEFN
 
       if (__glibc_unlikely (pd->stopped_start))
 	{
-	  int oldtype = CANCEL_ASYNC ();
-
 	  /* Get the lock the parent locked to force synchronization.  */
 	  lll_lock (pd->lock, LLL_PRIVATE);
 	  /* And give it up right away.  */
 	  lll_unlock (pd->lock, LLL_PRIVATE);
-
-	  CANCEL_RESET (oldtype);
 	}
 
       LIBC_PROBE (pthread_start, 3, (pthread_t) pd, pd->start_routine, pd->arg);
diff --git a/nptl/pthread_exit.c b/nptl/pthread_exit.c
index a60adbd..6976980 100644
--- a/nptl/pthread_exit.c
+++ b/nptl/pthread_exit.c
@@ -23,9 +23,14 @@
 void
 __pthread_exit (void *value)
 {
-  THREAD_SETMEM (THREAD_SELF, result, value);
+  struct pthread *self = THREAD_SELF;
 
-  __do_cancel ();
+  THREAD_SETMEM (self, result, value);
+
+  THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
+
+  __pthread_unwind ((__pthread_unwind_buf_t *)
+		    THREAD_GETMEM (self, cleanup_jmp_buf));
 }
 strong_alias (__pthread_exit, pthread_exit)
 
diff --git a/nptl/pthread_join.c b/nptl/pthread_join.c
index c841ff9..2c8ce0c 100644
--- a/nptl/pthread_join.c
+++ b/nptl/pthread_join.c
@@ -61,13 +61,10 @@ pthread_join (pthread_t threadid, void **thread_return)
      un-wait-ed for again.  */
   pthread_cleanup_push (cleanup, &pd->joinid);
 
-  /* Switch to asynchronous cancellation.  */
-  int oldtype = CANCEL_ASYNC ();
-
   if ((pd == self
        || (self->joinid == pd
 	   && (pd->cancelhandling
-	       & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
+	       & (CANCELED_BITMASK | EXITING_BITMASK
 		  | TERMINATED_BITMASK)) == 0))
       && !CANCEL_ENABLED_AND_CANCELED (self->cancelhandling))
     /* This is a deadlock situation.  The threads are waiting for each
@@ -89,10 +86,6 @@ pthread_join (pthread_t threadid, void **thread_return)
     /* Wait for the child.  */
     lll_wait_tid (pd->tid);
 
-
-  /* Restore cancellation mode.  */
-  CANCEL_RESET (oldtype);
-
   /* Remove the handler.  */
   pthread_cleanup_pop (0);
 
diff --git a/nptl/pthread_timedjoin.c b/nptl/pthread_timedjoin.c
index 10567e6..2131e95 100644
--- a/nptl/pthread_timedjoin.c
+++ b/nptl/pthread_timedjoin.c
@@ -71,17 +71,9 @@ pthread_timedjoin_np (pthread_t threadid, void **thread_return,
      un-wait-ed for again.  */
   pthread_cleanup_push (cleanup, &pd->joinid);
 
-  /* Switch to asynchronous cancellation.  */
-  int oldtype = CANCEL_ASYNC ();
-
-
   /* Wait for the child.  */
   result = lll_timedwait_tid (pd->tid, abstime);
 
-
-  /* Restore cancellation mode.  */
-  CANCEL_RESET (oldtype);
-
   /* Remove the handler.  */
   pthread_cleanup_pop (0);
 
diff --git a/nptl/sem_wait.c b/nptl/sem_wait.c
index fce7ed4..1fda284 100644
--- a/nptl/sem_wait.c
+++ b/nptl/sem_wait.c
@@ -43,14 +43,8 @@ __old_sem_wait (sem_t *sem)
       if (atomic_decrement_if_positive (futex) > 0)
 	return 0;
 
-      /* Enable asynchronous cancellation.  Required by the standard.  */
-      int oldtype = __pthread_enable_asynccancel ();
-
       /* Always assume the semaphore is shared.  */
-      err = lll_futex_wait (futex, 0, LLL_SHARED);
-
-      /* Disable asynchronous cancellation.  */
-      __pthread_disable_asynccancel (oldtype);
+      err = lll_futex_wait_cancel (futex, 0, LLL_SHARED);
     }
   while (err == 0 || err == -EWOULDBLOCK);
 
diff --git a/nptl/tst-cancel28.c b/nptl/tst-cancel28.c
new file mode 100644
index 0000000..9f474c2
--- /dev/null
+++ b/nptl/tst-cancel28.c
@@ -0,0 +1,98 @@
+/* Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This testcase checks if there is resource leakage if the syscall has
+   returned from kernelspace, but before userspace saves the return
+   value.  The 'leaker' thread should be able to close the file
+   descriptor if the resource is already allocated, meaning that
+   if the cancellation signal arrives *after* the open syscal
+   return from kernel, the side-effect should be visible to
+   application.  */
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+void *
+writeopener (void *arg)
+{
+  int fd;
+  for (;;)
+    {
+      fd = open (arg, O_WRONLY);
+      close (fd);
+    }
+}
+
+void *
+leaker (void *arg)
+{
+  int fd = open (arg, O_RDONLY);
+  pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, 0);
+  close (fd);
+  return 0;
+}
+
+
+#define ITER_COUNT 1000
+#define MAX_FILENO 1024
+
+static int
+do_test (void)
+{
+  pthread_t td, bg;
+  struct stat st;
+  char tmp[] = "/tmp/cancel_race_XXXXXX";
+  struct timespec ts;
+  int i;
+  int ret = 0;
+
+  mktemp (tmp);
+  mkfifo (tmp, 0600);
+  srand (1);
+
+  pthread_create (&bg, 0, writeopener, tmp);
+  for (i = 0; i < ITER_COUNT; i++)
+    {
+      pthread_create (&td, NULL, leaker, tmp);
+      ts.tv_nsec = rand () % 100000;
+      ts.tv_sec = 0;
+      nanosleep (&ts, NULL);
+      pthread_cancel (td);
+      pthread_join (td, NULL);
+    }
+
+  unlink (tmp);
+
+  for (i = STDERR_FILENO+1; i < MAX_FILENO; i++)
+    {
+      if (!fstat (i, &st))
+	{
+	  printf ("leaked fd %d\n", i);
+	  ret = 1;
+	}
+    }
+  return ret;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 10
+#include "../test-skeleton.c"
diff --git a/rt/Makefile b/rt/Makefile
index e62e059..11a2dd5 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -62,7 +62,6 @@ include ../Rules
 
 CFLAGS-aio_suspend.c = -fexceptions
 CFLAGS-clock_nanosleep.c = -fexceptions -fasynchronous-unwind-tables
-CFLAGS-librt-cancellation.c = -fasynchronous-unwind-tables
 
 LDFLAGS-rt.so = -Wl,--enable-new-dtags,-z,nodelete
 
diff --git a/sysdeps/generic/sysdep-cancel.h b/sysdeps/generic/sysdep-cancel.h
index ba6a1e0..5c84b44 100644
--- a/sysdeps/generic/sysdep-cancel.h
+++ b/sysdeps/generic/sysdep-cancel.h
@@ -3,6 +3,3 @@
 /* No multi-thread handling enabled.  */
 #define SINGLE_THREAD_P (1)
 #define RTLD_SINGLE_THREAD_P (1)
-#define LIBC_CANCEL_ASYNC()	0 /* Just a dummy value.  */
-#define LIBC_CANCEL_RESET(val)	((void)(val)) /* Nothing, but evaluate it.  */
-#define LIBC_CANCEL_HANDLED()	/* Nothing.  */
diff --git a/sysdeps/nptl/Makefile b/sysdeps/nptl/Makefile
index e9339a3..0d44a08 100644
--- a/sysdeps/nptl/Makefile
+++ b/sysdeps/nptl/Makefile
@@ -21,8 +21,7 @@ libpthread-sysdep_routines += errno-loc
 endif
 
 ifeq ($(subdir),rt)
-librt-sysdep_routines += timer_routines librt-cancellation
-CFLAGS-librt-cancellation.c += -fexceptions -fasynchronous-unwind-tables
+librt-sysdep_routines += timer_routines
 
 ifeq ($(have-forced-unwind),yes)
 tests += tst-mqueue8x
diff --git a/sysdeps/nptl/aio_misc.h b/sysdeps/nptl/aio_misc.h
index 4a6ebfc..e5c84cb 100644
--- a/sysdeps/nptl/aio_misc.h
+++ b/sysdeps/nptl/aio_misc.h
@@ -34,22 +34,18 @@
 
 #define AIO_MISC_WAIT(result, futex, timeout, cancel)			      \
   do {									      \
-    volatile unsigned int *futexaddr = &futex;				      \
+    unsigned int *futexaddr = (unsigned int *)&futex;			      \
     unsigned int oldval = futex;					      \
 									      \
     if (oldval != 0)							      \
       {									      \
 	pthread_mutex_unlock (&__aio_requests_mutex);			      \
 									      \
-	int oldtype;							      \
-	if (cancel)							      \
-	  oldtype = LIBC_CANCEL_ASYNC ();				      \
-									      \
 	int status;							      \
 	do								      \
 	  {								      \
-	    status = futex_reltimed_wait ((unsigned int *) futexaddr, oldval, \
-					  timeout, FUTEX_PRIVATE);	      \
+	    status = futex_reltimed_wait_cancelable (futexaddr, oldval,	      \
+						     timeout, FUTEX_PRIVATE); \
 	    if (status != EAGAIN)					      \
 	      break;							      \
 									      \
@@ -57,9 +53,6 @@
 	  }								      \
 	while (oldval != 0);						      \
 									      \
-	if (cancel)							      \
-	  LIBC_CANCEL_RESET (oldtype);					      \
-									      \
 	if (status == EINTR)						      \
 	  result = EINTR;						      \
 	else if (status == ETIMEDOUT)					      \
diff --git a/sysdeps/nptl/gai_misc.h b/sysdeps/nptl/gai_misc.h
index 96c8fa0..9efac58 100644
--- a/sysdeps/nptl/gai_misc.h
+++ b/sysdeps/nptl/gai_misc.h
@@ -35,22 +35,18 @@
 
 #define GAI_MISC_WAIT(result, futex, timeout, cancel) \
   do {									      \
-    volatile unsigned int *futexaddr = &futex;				      \
+    unsigned int *futexaddr = (unsigned int *)&futex;			      \
     unsigned int oldval = futex;					      \
 									      \
     if (oldval != 0)							      \
       {									      \
 	pthread_mutex_unlock (&__gai_requests_mutex);			      \
 									      \
-	int oldtype;							      \
-	if (cancel)							      \
-	  oldtype = LIBC_CANCEL_ASYNC ();				      \
-									      \
 	int status;							      \
 	do								      \
 	  {								      \
-	    status = futex_reltimed_wait ((unsigned int *) futexaddr, oldval, \
-					  timeout, FUTEX_PRIVATE);	      \
+	    status = futex_reltimed_wait_cancelable (futexaddr, oldval,	      \
+						     timeout, FUTEX_PRIVATE); \
 	    if (status != EAGAIN)					      \
 	      break;							      \
 									      \
@@ -58,9 +54,6 @@
 	  }								      \
 	while (oldval != 0);						      \
 									      \
-	if (cancel)							      \
-	  LIBC_CANCEL_RESET (oldtype);					      \
-									      \
 	if (status == EINTR)						      \
 	  result = EINTR;						      \
 	else if (status == ETIMEDOUT)					      \
diff --git a/sysdeps/nptl/librt-cancellation.c b/sysdeps/nptl/librt-cancellation.c
deleted file mode 100644
index facfbdb..0000000
--- a/sysdeps/nptl/librt-cancellation.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <nptl/pthreadP.h>
-
-
-#define __pthread_enable_asynccancel __librt_enable_asynccancel
-#define __pthread_disable_asynccancel __librt_disable_asynccancel
-#include <nptl/cancellation.c>
diff --git a/sysdeps/nptl/lowlevellock.h b/sysdeps/nptl/lowlevellock.h
index 27f4142..4f1b7ff 100644
--- a/sysdeps/nptl/lowlevellock.h
+++ b/sysdeps/nptl/lowlevellock.h
@@ -243,7 +243,7 @@ extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
   do {					\
     __typeof (tid) __tid;		\
     while ((__tid = (tid)) != 0)	\
-      lll_futex_wait (&(tid), __tid, LLL_SHARED);\
+      lll_futex_wait_cancel (&(tid), __tid, LLL_SHARED);\
   } while (0)
 
 extern int __lll_timedwait_tid (int *, const struct timespec *)
diff --git a/sysdeps/posix/open64.c b/sysdeps/posix/open64.c
index 74f669f..0c91963 100644
--- a/sysdeps/posix/open64.c
+++ b/sysdeps/posix/open64.c
@@ -34,16 +34,8 @@ __libc_open64 (const char *file, int oflag, ...)
       va_end (arg);
     }
 
-  if (SINGLE_THREAD_P)
-    return __libc_open (file, oflag | O_LARGEFILE, mode);
-
-  int oldtype = LIBC_CANCEL_ASYNC ();
-
-  int result = __libc_open (file, oflag | O_LARGEFILE, mode);
-
-  LIBC_CANCEL_RESET (oldtype);
-
-  return result;
+  /* __libc_open should be a cancellation point.  */
+  return __libc_open (file, oflag | O_LARGEFILE, mode);
 }
 weak_alias (__libc_open64, __open64)
 libc_hidden_weak (__open64)
diff --git a/sysdeps/posix/pause.c b/sysdeps/posix/pause.c
index 6ba4d42..bdaf1cb 100644
--- a/sysdeps/posix/pause.c
+++ b/sysdeps/posix/pause.c
@@ -38,8 +38,6 @@ __libc_pause (void)
 }
 weak_alias (__libc_pause, pause)
 
-LIBC_CANCEL_HANDLED ();		/* sigsuspend handles our cancellation.  */
-
 #ifndef NO_CANCELLATION
 # include <not-cancel.h>
 
diff --git a/sysdeps/posix/sigpause.c b/sysdeps/posix/sigpause.c
index 662640d..863b541 100644
--- a/sysdeps/posix/sigpause.c
+++ b/sysdeps/posix/sigpause.c
@@ -50,16 +50,7 @@ do_sigpause (int sig_or_mask, int is_sig)
 int
 __sigpause (int sig_or_mask, int is_sig)
 {
-  if (SINGLE_THREAD_P)
-    return do_sigpause (sig_or_mask, is_sig);
-
-  int oldtype = LIBC_CANCEL_ASYNC ();
-
-  int result = do_sigpause (sig_or_mask, is_sig);
-
-  LIBC_CANCEL_RESET (oldtype);
-
-  return result;
+  return do_sigpause (sig_or_mask, is_sig);
 }
 libc_hidden_def (__sigpause)
 
diff --git a/sysdeps/posix/sigwait.c b/sysdeps/posix/sigwait.c
index 8dc550b..f4b5d2f 100644
--- a/sysdeps/posix/sigwait.c
+++ b/sysdeps/posix/sigwait.c
@@ -88,13 +88,8 @@ __sigwait (const sigset_t *set, int *sig)
   if (SINGLE_THREAD_P)
     return do_sigwait (set, sig);
 
-  int oldtype = LIBC_CANCEL_ASYNC ();
-
-  int result = do_sigwait (set, sig);
-
-  LIBC_CANCEL_RESET (oldtype);
-
-  return result;
+  /* do_sigwait should be a cancellation point.  */
+  return do_sigwait (set, sig);
 }
 libc_hidden_def (__sigwait)
 weak_alias (__sigwait, sigwait)
diff --git a/sysdeps/posix/waitid.c b/sysdeps/posix/waitid.c
index de41227..00a7db5 100644
--- a/sysdeps/posix/waitid.c
+++ b/sysdeps/posix/waitid.c
@@ -151,16 +151,7 @@ OUR_WAITID (idtype_t idtype, id_t id, siginfo_t *infop, int options)
 int
 __waitid (idtype_t idtype, id_t id, siginfo_t *infop, int options)
 {
-  if (SINGLE_THREAD_P)
-    return do_waitid (idtype, id, infop, options);
-
-  int oldtype = LIBC_CANCEL_ASYNC ();
-
-  int result = do_waitid (idtype, id, infop, options);
-
-  LIBC_CANCEL_RESET (oldtype);
-
-  return result;
+  return do_waitid (idtype, id, infop, options);
 }
 weak_alias (__waitid, waitid)
 strong_alias (__waitid, __libc_waitid)
diff --git a/sysdeps/unix/sysdep.h b/sysdeps/unix/sysdep.h
index 52dad58..8de99f1 100644
--- a/sysdeps/unix/sysdep.h
+++ b/sysdeps/unix/sysdep.h
@@ -20,31 +20,69 @@
 #include <sys/syscall.h>
 #define	HAVE_SYSCALLS
 
+#ifndef __ASSEMBLER__
+# include <errno.h>
+
 /* Note that using a `PASTE' macro loses.  */
 #define	SYSCALL__(name, args)	PSEUDO (__##name, name, args)
 #define	SYSCALL(name, args)	PSEUDO (name, name, args)
 
 /* Cancellation macros.  */
-#define __SYSCALL_NARGS_X(a,b,c,d,e,f,g,n,...) n
+#ifndef __SSC
+typedef long int __syscall_arg_t;
+# define __SSC(__x) ((__syscall_arg_t) (__x))
+#endif
+
+#define __SYSCALL_CANCEL0(__n) \
+  (__syscall_cancel)(__n, 0, 0, 0, 0, 0, 0)
+#define __SYSCALL_CANCEL1(__n, __a) \
+  (__syscall_cancel)(__n, __SSC(__a), 0, 0, 0, 0, 0)
+#define __SYSCALL_CANCEL2(__n, __a, __b) \
+  (__syscall_cancel)(__n, __SSC(__a), __SSC(__b), 0, 0, 0, 0)
+#define __SYSCALL_CANCEL3(__n, __a, __b, __c) \
+  (__syscall_cancel)(__n, __SSC(__a), __SSC(__b), __SSC(__c), 0, 0, 0)
+#define __SYSCALL_CANCEL4(__n, __a, __b, __c, __d) \
+  (__syscall_cancel)(__n, __SSC(__a), __SSC(__b), __SSC(__c), __SSC(__d), \
+		     0, 0)
+#define __SYSCALL_CANCEL5(__n, __a, __b, __c, __d, __e) \
+  (__syscall_cancel)(__n, __SSC(__a), __SSC(__b), __SSC(__c), __SSC(__d), \
+		     __SSC(__e), 0)
+#define __SYSCALL_CANCEL6(__n, __a, __b, __c, __d, __e, __f) \
+  (__syscall_cancel)(__n, __SSC(__a), __SSC(__b), __SSC(__c), __SSC(__d), \
+		     __SSC(__e), __SSC(__f))
+
+#define __SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n
 #define __SYSCALL_NARGS(...) \
   __SYSCALL_NARGS_X (__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0,)
+#define __SYSCALL_CONCAT_X(__a,__b)	__a##__b
+#define __SYSCALL_CONCAT(__a,__b)	__SYSCALL_CONCAT_X (__a, __b)
+#define __SYSCALL_DISP(__b,...) \
+  __SYSCALL_CONCAT (__b,__SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
+
+#define __SYSCALL_CANCEL(...) __SYSCALL_DISP (__SYSCALL_CANCEL, __VA_ARGS__)
 
-#define SYSCALL_CANCEL(name, ...) \
-  ({									     \
-    long int sc_ret;							     \
-    if (SINGLE_THREAD_P) 						     \
-      sc_ret = INLINE_SYSCALL (name, __SYSCALL_NARGS(__VA_ARGS__),	     \
-			       __VA_ARGS__);				     \
-    else								     \
-      {									     \
-	int sc_cancel_oldtype = LIBC_CANCEL_ASYNC ();			     \
-	sc_ret = INLINE_SYSCALL (name, __SYSCALL_NARGS (__VA_ARGS__),	     \
-				 __VA_ARGS__);				     \
-        LIBC_CANCEL_RESET (sc_cancel_oldtype);				     \
-      }									     \
-    sc_ret;								     \
+#define SYSCALL_CANCEL_NCS(name, nr, args...)				\
+  __SYSCALL_CANCEL (__NR_##name, nr, args)
+
+#define SYSCALL_CANCEL(name, args...)					\
+  ({									\
+    long int sc_ret = SYSCALL_CANCEL_NCS (name, args);			\
+    if (SYSCALL_CANCEL_ERROR (sc_ret))					\
+      {									\
+        __set_errno (SYSCALL_CANCEL_ERRNO (sc_ret));			\
+        sc_ret = -1L;							\
+      }									\
+    sc_ret;								\
   })
 
+long int __syscall_cancel (__syscall_arg_t nr, __syscall_arg_t arg1,
+			   __syscall_arg_t arg2, __syscall_arg_t arg3,
+			   __syscall_arg_t arg4, __syscall_arg_t arg5,
+			   __syscall_arg_t arg6);
+libc_hidden_proto (__syscall_cancel);
+
+#endif
+
 /* Machine-dependent sysdep.h files are expected to define the macro
    PSEUDO (function_name, syscall_name) to emit assembly code to define the
    C-callable function FUNCTION_NAME to do system call SYSCALL_NAME.
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 69c47ca..fd96783 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -28,7 +28,6 @@ int
 __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
 		   struct timespec *rem)
 {
-  INTERNAL_SYSCALL_DECL (err);
   int r;
 
   if (clock_id == CLOCK_THREAD_CPUTIME_ID)
@@ -36,19 +35,9 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
   if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
     clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);
 
-  if (SINGLE_THREAD_P)
-    r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, rem);
-  else
-    {
-      int oldstate = LIBC_CANCEL_ASYNC ();
+  r = SYSCALL_CANCEL_NCS (clock_nanosleep, clock_id, flags, req, rem);
 
-      r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req,
-			    rem);
-
-      LIBC_CANCEL_RESET (oldstate);
-    }
-
-  return (INTERNAL_SYSCALL_ERROR_P (r, err)
-	  ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
+  return (SYSCALL_CANCEL_ERROR (r)
+	  ? SYSCALL_CANCEL_ERRNO (r) : 0);
 }
 weak_alias (__clock_nanosleep, clock_nanosleep)
diff --git a/sysdeps/unix/sysv/linux/fcntl.c b/sysdeps/unix/sysv/linux/fcntl.c
index fa184db..192e50d 100644
--- a/sysdeps/unix/sysv/linux/fcntl.c
+++ b/sysdeps/unix/sysv/linux/fcntl.c
@@ -25,7 +25,7 @@
 
 
 static int
-do_fcntl (int fd, int cmd, void *arg)
+__fcntl_common_nocancel (int fd, int cmd, void *arg)
 {
   if (cmd != F_GETOWN)
     return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg);
@@ -40,8 +40,22 @@ do_fcntl (int fd, int cmd, void *arg)
   return -1;
 }
 
+static int
+__fcntl_common_cancel (int fd, int cmd, void *arg)
+{
+  if (cmd != F_GETOWN)
+    return SYSCALL_CANCEL (fcntl, fd, cmd, arg);
 
-#ifndef NO_CANCELLATION
+  struct f_owner_ex fex;
+  int res = SYSCALL_CANCEL_NCS (fcntl, fd, F_GETOWN_EX, &fex);
+  if (!SYSCALL_CANCEL_ERROR (res))
+    return fex.type == F_OWNER_GID ? -fex.pid : fex.pid;
+
+  __set_errno (SYSCALL_CANCEL_ERRNO (res));
+  return -1;
+}
+
+#if !IS_IN (rtld)
 int
 __fcntl_nocancel (int fd, int cmd, ...)
 {
@@ -52,11 +66,10 @@ __fcntl_nocancel (int fd, int cmd, ...)
   arg = va_arg (ap, void *);
   va_end (ap);
 
-  return do_fcntl (fd, cmd, arg);
+  return __fcntl_common_nocancel (fd, cmd, arg);
 }
 #endif
 
-
 int
 __libc_fcntl (int fd, int cmd, ...)
 {
@@ -67,16 +80,10 @@ __libc_fcntl (int fd, int cmd, ...)
   arg = va_arg (ap, void *);
   va_end (ap);
 
-  if (SINGLE_THREAD_P || cmd != F_SETLKW)
-    return do_fcntl (fd, cmd, arg);
-
-  int oldtype = LIBC_CANCEL_ASYNC ();
-
-  int result = do_fcntl (fd, cmd, arg);
-
-  LIBC_CANCEL_RESET (oldtype);
+  if (cmd != F_SETLKW)
+    return __fcntl_common_nocancel (fd, cmd, arg);
 
-  return result;
+  return __fcntl_common_cancel (fd,cmd, arg);
 }
 libc_hidden_def (__libc_fcntl)
 
diff --git a/sysdeps/unix/sysv/linux/futex-internal.h b/sysdeps/unix/sysv/linux/futex-internal.h
index aca0911..260e3da 100644
--- a/sysdeps/unix/sysv/linux/futex-internal.h
+++ b/sysdeps/unix/sysv/linux/futex-internal.h
@@ -83,10 +83,7 @@ static __always_inline int
 futex_wait_cancelable (unsigned int *futex_word, unsigned int expected,
 		       int private)
 {
-  int oldtype;
-  oldtype = __pthread_enable_asynccancel ();
-  int err = lll_futex_timed_wait (futex_word, expected, NULL, private);
-  __pthread_disable_asynccancel (oldtype);
+  int err = lll_futex_timed_wait_cancel (futex_word, expected, NULL, private);
   switch (err)
     {
     case 0:
@@ -137,10 +134,7 @@ futex_reltimed_wait_cancelable (unsigned int *futex_word,
 				unsigned int expected,
 			        const struct timespec *reltime, int private)
 {
-  int oldtype;
-  oldtype = __pthread_enable_asynccancel ();
-  int err = lll_futex_timed_wait (futex_word, expected, reltime, private);
-  __pthread_disable_asynccancel (oldtype);
+  int err = lll_futex_timed_wait_cancel (futex_word, expected, reltime, private);
   switch (err)
     {
     case 0:
@@ -200,11 +194,9 @@ futex_abstimed_wait_cancelable (unsigned int *futex_word,
      despite them being valid.  */
   if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
     return ETIMEDOUT;
-  int oldtype;
-  oldtype = __pthread_enable_asynccancel ();
-  int err = lll_futex_timed_wait_bitset (futex_word, expected, abstime,
-					 FUTEX_CLOCK_REALTIME, private);
-  __pthread_disable_asynccancel (oldtype);
+  int err = lll_futex_timed_wait_bitset_cancel (futex_word, expected, abstime,
+						FUTEX_CLOCK_REALTIME,
+						private);
   switch (err)
     {
     case 0:
diff --git a/sysdeps/unix/sysv/linux/generic/creat.c b/sysdeps/unix/sysv/linux/generic/creat.c
index dc298fb..36eb4e5 100644
--- a/sysdeps/unix/sysv/linux/generic/creat.c
+++ b/sysdeps/unix/sysv/linux/generic/creat.c
@@ -29,9 +29,6 @@ creat (const char *file, mode_t mode)
   return __open (file, O_WRONLY | O_CREAT | O_TRUNC, mode);
 }
 
-/* __open handles cancellation.  */
-LIBC_CANCEL_HANDLED ();
-
 #if __WORDSIZE == 64
 weak_alias (creat, creat64)
 #endif
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fcntl.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fcntl.c
index a11bf83..80b0603 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fcntl.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fcntl.c
@@ -26,7 +26,7 @@
 
 
 static int
-do_fcntl (int fd, int cmd, void *arg)
+__fcntl_common_nocancel (int fd, int cmd, void *arg)
 {
   if (cmd != F_GETOWN)
     return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
@@ -41,8 +41,22 @@ do_fcntl (int fd, int cmd, void *arg)
   return -1;
 }
 
+static int
+__fcntl_common_cancel (int fd, int cmd, void *arg)
+{
+  if (cmd != F_GETOWN)
+    return SYSCALL_CANCEL (fcntl64, fd, cmd, arg);
+
+  struct f_owner_ex fex;
+  int res = SYSCALL_CANCEL_NCS (fcntl64, fd, F_GETOWN_EX, &fex);
+  if (!SYSCALL_CANCEL_ERROR (res))
+    return fex.type == F_OWNER_GID ? -fex.pid : fex.pid;
 
-#ifndef NO_CANCELLATION
+  __set_errno (SYSCALL_CANCEL_ERRNO (res));
+  return -1;
+}
+
+#if !IS_IN (rtld)
 int
 __fcntl_nocancel (int fd, int cmd, ...)
 {
@@ -53,7 +67,7 @@ __fcntl_nocancel (int fd, int cmd, ...)
   arg = va_arg (ap, void *);
   va_end (ap);
 
-  return do_fcntl (fd, cmd, arg);
+  return __fcntl_common_nocancel (fd, cmd, arg);
 }
 #endif
 
@@ -69,15 +83,9 @@ __libc_fcntl (int fd, int cmd, ...)
   va_end (ap);
 
   if (SINGLE_THREAD_P || cmd != F_SETLKW)
-    return do_fcntl (fd, cmd, arg);
-
-  int oldtype = LIBC_CANCEL_ASYNC ();
-
-  int result = do_fcntl (fd, cmd, arg);
-
-  LIBC_CANCEL_RESET (oldtype);
+    return __fcntl_common_nocancel (fd, cmd, arg);
 
-  return result;
+  return __fcntl_common_cancel (fd,cmd, arg);
 }
 libc_hidden_def (__libc_fcntl)
 
diff --git a/sysdeps/unix/sysv/linux/lowlevellock-futex.h b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
index 59f6627..1edb66f 100644
--- a/sysdeps/unix/sysv/linux/lowlevellock-futex.h
+++ b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
@@ -135,6 +135,50 @@
 					 private),                      \
 		     nr_wake, nr_move, mutex, val)
 
-#endif  /* !__ASSEMBLER__  */
+/* Cancellable futex macros.  */
+#define lll_futex_wait_cancel(futexp, val, private) \
+  lll_futex_timed_wait_cancel (futexp, val, NULL, private)
+
+#define lll_futex_timed_wait_cancel(futexp, val, timespec, private)	      \
+  ({									      \
+    long int __ret;							      \
+    int __op = FUTEX_WAIT;						      \
+                                                                              \
+    __ret = __syscall_cancel (__NR_futex, __SSC (futexp),		      \
+			      __SSC (__lll_private_flag (__op, private)),     \
+			      __SSC (val), __SSC (timespec), 0, 0);           \
+    __ret;								      \
+  })
+
+#define lll_futex_timed_wait_bitset_cancel(futexp, val, timespec, clockbit,   \
+					   private)			      \
+  ({                                                                          \
+    long int __ret;                                                           \
+    int __op = FUTEX_WAIT_BITSET | clockbit;                                  \
+                                                                              \
+    __ret = __syscall_cancel (__NR_futex, __SSC (futexp),		      \
+			      __SSC (__lll_private_flag (__op, private)),     \
+			      __SSC (val), __SSC (timespec), 0,	              \
+                              FUTEX_BITSET_MATCH_ANY);                        \
+    __ret;								      \
+  })
+
+#define lll_futex_wait_requeue_pi_cancel(futexp, val, mutex, private) \
+  lll_futex_timed_wait_requeue_pi_cancel (futexp, val, NULL, 0, mutex, private)
+
+#define lll_futex_timed_wait_requeue_pi_cancel(futexp, val, timespec, 	      \
+					       clockbit, mutex, private)      \
+  ({									      \
+    long int __ret;							      \
+    int __op = FUTEX_WAIT_REQUEUE_PI | clockbit;			      \
+									      \
+    __ret = __syscall_cancel (__NR_futex, __SSC (futexp),		      \
+			      __SSC (__lll_private_flag (__op, private)),     \
+			      __SSC (val), __SSC (timespec),		      \
+			      __SSC (mutex), 0); 		      	      \
+    __ret;								      \
+  })
+
+# endif  /* !__ASSEMBLER__  */
 
 #endif  /* lowlevellock-futex.h */
diff --git a/sysdeps/unix/sysv/linux/pthread_kill.c b/sysdeps/unix/sysv/linux/pthread_kill.c
index 8e8996a..f6d619c 100644
--- a/sysdeps/unix/sysv/linux/pthread_kill.c
+++ b/sysdeps/unix/sysv/linux/pthread_kill.c
@@ -41,9 +41,8 @@ __pthread_kill (pthread_t threadid, int signo)
     /* Not a valid thread handle.  */
     return ESRCH;
 
-  /* Disallow sending the signal we use for cancellation, timers,
-     for the setxid implementation.  */
-  if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID)
+  /* Disallow sending the signal we use for setxid implementation.  */
+  if (signo == SIGSETXID)
     return EINVAL;
 
   /* We have a special syscall to do the work.  */
diff --git a/sysdeps/unix/sysv/linux/sigwait.c b/sysdeps/unix/sysv/linux/sigwait.c
index 26c3241..1003e5f 100644
--- a/sysdeps/unix/sysv/linux/sigwait.c
+++ b/sysdeps/unix/sysv/linux/sigwait.c
@@ -55,32 +55,17 @@ do_sigwait (const sigset_t *set, int *sig)
 
   /* XXX The size argument hopefully will have to be changed to the
      real size of the user-level sigset_t.  */
-#ifdef INTERNAL_SYSCALL
-  INTERNAL_SYSCALL_DECL (err);
   do
-    ret = INTERNAL_SYSCALL (rt_sigtimedwait, err, 4, set,
-			    NULL, NULL, _NSIG / 8);
-  while (INTERNAL_SYSCALL_ERROR_P (ret, err)
-	 && INTERNAL_SYSCALL_ERRNO (ret, err) == EINTR);
-  if (! INTERNAL_SYSCALL_ERROR_P (ret, err))
+    ret = SYSCALL_CANCEL_NCS (rt_sigtimedwait, set, NULL, NULL, _NSIG / 8);
+  while (SYSCALL_CANCEL_ERROR (ret)
+	 && SYSCALL_CANCEL_ERRNO (ret) == EINTR);
+  if (!SYSCALL_CANCEL_ERROR (ret))
     {
       *sig = ret;
       ret = 0;
     }
   else
-    ret = INTERNAL_SYSCALL_ERRNO (ret, err);
-#else
-  do
-    ret = INLINE_SYSCALL (rt_sigtimedwait, 4, set, NULL, NULL, _NSIG / 8);
-  while (ret == -1 && errno == EINTR);
-  if (ret != -1)
-    {
-      *sig = ret;
-      ret = 0;
-    }
-  else
-    ret = errno;
-#endif
+    ret = SYSCALL_CANCEL_ERRNO (ret);
 
   return ret;
 }
@@ -88,16 +73,7 @@ do_sigwait (const sigset_t *set, int *sig)
 int
 __sigwait (const sigset_t *set, int *sig)
 {
-  if (SINGLE_THREAD_P)
-    return do_sigwait (set, sig);
-
-  int oldtype = LIBC_CANCEL_ASYNC ();
-
-  int result = do_sigwait (set, sig);
-
-  LIBC_CANCEL_RESET (oldtype);
-
-  return result;
+  return do_sigwait (set, sig);
 }
 libc_hidden_def (__sigwait)
 weak_alias (__sigwait, sigwait)
diff --git a/sysdeps/unix/sysv/linux/socketcall.h b/sysdeps/unix/sysv/linux/socketcall.h
index f652239..007acba 100644
--- a/sysdeps/unix/sysv/linux/socketcall.h
+++ b/sysdeps/unix/sysv/linux/socketcall.h
@@ -86,17 +86,18 @@
     sc_ret;								\
   })
 
-
-#if IS_IN (libc)
-# define __pthread_enable_asynccancel  __libc_enable_asynccancel
-# define __pthread_disable_asynccancel __libc_disable_asynccancel
-#endif
-
-#define SOCKETCALL_CANCEL(name, args...)				\
+#define SOCKETCALL_CANCEL(name, __a1, __a2, __a3, __a4, __a5, __a6)	\
   ({									\
-    int oldtype = LIBC_CANCEL_ASYNC ();					\
-    long int sc_ret = __SOCKETCALL (SOCKOP_##name, args);		\
-    LIBC_CANCEL_RESET (oldtype);					\
+    __syscall_arg_t __args[6] = { __SSC (__a1), __SSC (__a2),		\
+				  __SSC (__a3), __SSC (__a4), 		\
+				  __SSC (__a5), __SSC (__a6) };		\
+    long int sc_ret = SYSCALL_CANCEL_NCS (socketcall, SOCKOP_##name,	\
+					  __args);			\
+    if (SYSCALL_CANCEL_ERROR (sc_ret))					\
+      {									\
+        __set_errno (SYSCALL_CANCEL_ERRNO (sc_ret));			\
+        sc_ret = -1L;							\
+      }									\
     sc_ret;								\
   })
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a3f3e1e3a72d6f3c75143cce66bce2ff5f2ac6cb

commit a3f3e1e3a72d6f3c75143cce66bce2ff5f2ac6cb
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Wed Sep 24 20:22:05 2014 -0300

    nptl: Fix testcases for new pthread cancellation mechanism
    
    With upcoming fix for BZ#12683, pthread cancellation does not act for:
    
    1. If syscall is blocked but with some side effects already having taken
       place (e.g. a partial read or write)
    2. After the syscall has returned.
    
    It is because program need to act on such cases (for instance, to avoid
    leak of allocated resources our handling partial read/write).
    
    This patches fixes the NPTL testcase that assumes the old behavior and
    also remove the tst-cancel-wrappers.sh test (which checks for symbols
    that does not exist anymore).
    
    It also add two more testcase to check both the returned and the errno
    value on case of a cancelled syscall.
    
    	* nptl/Makefile [$(run-built-tests) = yes] (tests-special): Remove
    	tst-cancel-wrappers.sh.
    	* nptl/tst-cancel-wrappers.sh: Remove file.
    	* nptl/tst-cancel2.c (tf): Add pthread_testcancel after cancellable
    	syscall.
    	* nptl/tst-cancel20.c (sh_body): Likewise.
    	* nptl/tst-cancel21.c (sh_body): Likewise.
    	(tf_body): Likewise.
    	* nptl/tst-cancel4.c (tf_Write): Likewise.
    	(tf_send): Likewise.
    	(tf_open64): New test: check for open64 cancellable syscall.
    	(tf_pread64): New test: check for pread64 cancellable syscall.
    	(tf_pwrite64): New test: check for pwrite64 cancellable syscall.
    	* nptl/tst-cancel26.c: New file.
    	* nptl/tst-cancel27.c: New file.

diff --git a/ChangeLog b/ChangeLog
index cf84c3f..9f59dbc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,23 @@
 2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+	    Phil Blundell <pb@pbcui.dot.net>
+
+	* nptl/Makefile [$(run-built-tests) = yes] (tests-special): Remove
+	tst-cancel-wrappers.sh.
+	* nptl/tst-cancel-wrappers.sh: Remove file.
+	* nptl/tst-cancel2.c (tf): Add pthread_testcancel after cancellable
+	syscall.
+	* nptl/tst-cancel20.c (sh_body): Likewise.
+	* nptl/tst-cancel21.c (sh_body): Likewise.
+	(tf_body): Likewise.
+	* nptl/tst-cancel4.c (tf_Write): Likewise.
+	(tf_send): Likewise.
+	(tf_open64): New test: check for open64 cancellable syscall.
+	(tf_pread64): New test: check for pread64 cancellable syscall.
+	(tf_pwrite64): New test: check for pwrite64 cancellable syscall.
+	* nptl/tst-cancel26.c: New file.
+	* nptl/tst-cancel27.c: New file.
+
+2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
 	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Remove file.
 	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise.
diff --git a/nptl/Makefile b/nptl/Makefile
index aaca0a4..39e28fd 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -257,6 +257,7 @@ tests = tst-typesizes \
 	tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \
 	tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \
 	tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel24 tst-cancel25 \
+	tst-cancel26 tst-cancel27 \
 	tst-cancel-self tst-cancel-self-cancelstate \
 	tst-cancel-self-canceltype tst-cancel-self-testcancel \
 	tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \
@@ -394,8 +395,7 @@ tests-reverse += tst-cancel5 tst-cancel23 tst-vfork1x tst-vfork2x
 ifeq ($(run-built-tests),yes)
 tests-special += $(objpfx)tst-stack3-mem.out $(objpfx)tst-oddstacklimit.out
 ifeq ($(build-shared),yes)
-tests-special += $(objpfx)tst-tls6.out $(objpfx)tst-cleanup0-cmp.out \
-		 $(objpfx)tst-cancel-wrappers.out
+tests-special += $(objpfx)tst-tls6.out $(objpfx)tst-cleanup0-cmp.out
 endif
 endif
 
@@ -607,7 +607,7 @@ $(objpfx)$(multidir)/crtn.o: $(objpfx)crtn.o $(objpfx)$(multidir)/
 endif
 
 generated += libpthread_nonshared.a \
-	     multidir.mk tst-atfork2.mtrace tst-cancel-wrappers.out \
+	     multidir.mk tst-atfork2.mtrace \
 	     tst-tls6.out
 
 generated += $(objpfx)tst-atfork2.mtrace \
@@ -624,18 +624,6 @@ LDFLAGS-pthread.so += -e __nptl_main
 $(objpfx)pt-interp.os: $(common-objpfx)runtime-linker.h
 endif
 
-ifeq ($(run-built-tests),yes)
-ifeq (yes,$(build-shared))
-$(objpfx)tst-cancel-wrappers.out: tst-cancel-wrappers.sh
-	$(SHELL) $< '$(NM)' \
-		    $(common-objpfx)libc_pic.a \
-		    $(common-objpfx)libc.a \
-		    $(objpfx)libpthread_pic.a \
-		    $(objpfx)libpthread.a > $@; \
-	$(evaluate-test)
-endif
-endif
-
 tst-exec4-ARGS = $(host-test-program-cmd)
 
 $(objpfx)tst-execstack: $(libdl)
diff --git a/nptl/tst-cancel-wrappers.sh b/nptl/tst-cancel-wrappers.sh
deleted file mode 100644
index d492a54..0000000
--- a/nptl/tst-cancel-wrappers.sh
+++ /dev/null
@@ -1,92 +0,0 @@
-#! /bin/sh
-# Test whether all cancelable functions are cancelable.
-# Copyright (C) 2002-2015 Free Software Foundation, Inc.
-# This file is part of the GNU C Library.
-# Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
-
-# The GNU C Library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-
-# The GNU C Library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Lesser General Public License for more details.
-
-# You should have received a copy of the GNU Lesser General Public
-# License along with the GNU C Library; if not, see
-# <http://www.gnu.org/licenses/>.
-
-NM="$1"; shift
-while [ $# -gt 0 ]; do
-  ( $NM -P $1; echo 'end[end]:' ) | gawk ' BEGIN {
-C["accept"]=1
-C["close"]=1
-C["connect"]=1
-C["creat"]=1
-C["fcntl"]=1
-C["fdatasync"]=1
-C["fsync"]=1
-C["msgrcv"]=1
-C["msgsnd"]=1
-C["msync"]=1
-C["nanosleep"]=1
-C["open"]=1
-C["open64"]=1
-C["pause"]=1
-C["poll"]=1
-C["pread"]=1
-C["pread64"]=1
-C["pselect"]=1
-C["pwrite"]=1
-C["pwrite64"]=1
-C["read"]=1
-C["readv"]=1
-C["recv"]=1
-C["recvfrom"]=1
-C["recvmsg"]=1
-C["select"]=1
-C["send"]=1
-C["sendmsg"]=1
-C["sendto"]=1
-C["sigpause"]=1
-C["sigsuspend"]=1
-C["sigwait"]=1
-C["sigwaitinfo"]=1
-C["tcdrain"]=1
-C["wait"]=1
-C["waitid"]=1
-C["waitpid"]=1
-C["write"]=1
-C["writev"]=1
-C["__xpg_sigpause"]=1
-}
-/:$/ {
-  if (seen)
-    {
-      if (!seen_enable || !seen_disable)
-	{
-	  printf "in '$1'(%s) %s'\''s cancellation missing\n", object, seen
-	  ret = 1
-	}
-    }
-  seen=""
-  seen_enable=""
-  seen_disable=""
-  object=gensub(/^.*\[(.*)\]:$/, "\\1", 1, $0)
-  next
-}
-{
-  if (C[$1] && $2 ~ /^[TW]$/)
-    seen=$1
-  else if ($1 ~ /^([.]|)__(libc|pthread)_enable_asynccancel$/ && $2 == "U")
-    seen_enable=1
-  else if ($1 ~ /^([.]|)__(libc|pthread)_disable_asynccancel$/ && $2 == "U")
-    seen_disable=1
-}
-END {
-  exit ret
-}' || exit
-  shift
-done
diff --git a/nptl/tst-cancel2.c b/nptl/tst-cancel2.c
index 1a74992..3d34169 100644
--- a/nptl/tst-cancel2.c
+++ b/nptl/tst-cancel2.c
@@ -33,6 +33,9 @@ tf (void *arg)
   char buf[100000];
 
   while (write (fd[1], buf, sizeof (buf)) > 0);
+  /* The write can return a value higher than 0 (meaning partial write)
+     due the SIGCANCEL, but the thread may still pending cancellation.  */
+  pthread_testcancel ();
 
   return (void *) 42l;
 }
diff --git a/nptl/tst-cancel20.c b/nptl/tst-cancel20.c
index 51b558e..614708a 100644
--- a/nptl/tst-cancel20.c
+++ b/nptl/tst-cancel20.c
@@ -49,6 +49,9 @@ sh_body (void)
       puts ("read succeeded");
       exit (1);
     }
+  /* The read can return a value higher than 0 (meaning partial reads)
+     due the SIGCANCEL, but the thread may still pending cancellation.  */
+  pthread_testcancel ();
 
   pthread_cleanup_pop (0);
 }
@@ -84,7 +87,8 @@ tf_body (void)
       puts ("read succeeded");
       exit (1);
     }
-
+  /* Check for partial read.  */
+  pthread_testcancel ();
   read (fd[0], &c, 1);
 
   pthread_cleanup_pop (0);
diff --git a/nptl/tst-cancel21.c b/nptl/tst-cancel21.c
index b54f236..b1370e1 100644
--- a/nptl/tst-cancel21.c
+++ b/nptl/tst-cancel21.c
@@ -50,6 +50,9 @@ sh_body (void)
       puts ("read succeeded");
       exit (1);
     }
+  /* The write can return a value higher than 0 (meaning partial write)
+     due the SIGCANCEL, but the thread may still pending cancellation.  */
+  pthread_testcancel ();
 
   pthread_cleanup_pop (0);
 }
@@ -85,6 +88,8 @@ tf_body (void)
       puts ("read succeeded");
       exit (1);
     }
+  /* Check partial read.  */
+  pthread_testcancel ();
 
   read (fd[0], &c, 1);
 
diff --git a/nptl/tst-cancel2.c b/nptl/tst-cancel26.c
similarity index 54%
copy from nptl/tst-cancel2.c
copy to nptl/tst-cancel26.c
index 1a74992..9a370d0 100644
--- a/nptl/tst-cancel2.c
+++ b/nptl/tst-cancel26.c
@@ -1,6 +1,5 @@
-/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
+/* Copyright (C) 2015 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -16,76 +15,50 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <errno.h>
 #include <pthread.h>
-#include <signal.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
-
-static int fd[2];
-
-
 static void *
 tf (void *arg)
 {
-  /* The buffer size must be larger than the pipe size so that the
-     write blocks.  */
-  char buf[100000];
+  int e, r;
 
-  while (write (fd[1], buf, sizeof (buf)) > 0);
+  errno = 0;
 
-  return (void *) 42l;
-}
+  /* This is a cancellation point, but we should not be cancelled.  */
+  r = write (-1, 0, 0);
+  e = errno;
+
+  /* Check that the cancelling syscall wrapper has handled the error correctly.  */
+  if (r != -1 || errno != EBADF)
+    {
+      printf ("write returned %d, errno %d\n", r, e);
+      exit (1);
+    }
 
+  return NULL;
+}
 
 static int
 do_test (void)
 {
   pthread_t th;
-  void *r;
-  struct sigaction sa;
-
-  sa.sa_handler = SIG_IGN;
-  sigemptyset (&sa.sa_mask);
-  sa.sa_flags = 0;
-
-  if (sigaction (SIGPIPE, &sa, NULL) != 0)
-    {
-      puts ("sigaction failed");
-      return 1;
-    }
-
-  if (pipe (fd) != 0)
-    {
-      puts ("pipe failed");
-      return 1;
-    }
 
   if (pthread_create (&th, NULL, tf, NULL) != 0)
     {
       puts ("create failed");
-      return 1;
-    }
-
-  if (pthread_cancel (th) != 0)
-    {
-      puts ("cancel failed");
-      return 1;
+      exit (1);
     }
 
-  /* This will cause the write in the child to return.  */
-  close (fd[0]);
-
+  void *r;
   if (pthread_join (th, &r) != 0)
     {
       puts ("join failed");
-      return 1;
-    }
-
-  if (r != PTHREAD_CANCELED)
-    {
-      printf ("result is wrong: expected %p, got %p\n", PTHREAD_CANCELED, r);
-      return 1;
+      exit (1);
     }
 
   return 0;
diff --git a/nptl/tst-cancel2.c b/nptl/tst-cancel27.c
similarity index 54%
copy from nptl/tst-cancel2.c
copy to nptl/tst-cancel27.c
index 1a74992..aee25c9 100644
--- a/nptl/tst-cancel2.c
+++ b/nptl/tst-cancel27.c
@@ -1,6 +1,5 @@
-/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
+/* Copyright (C) 2015 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -16,76 +15,52 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <errno.h>
 #include <pthread.h>
-#include <signal.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
-
-static int fd[2];
-
-
 static void *
 tf (void *arg)
 {
-  /* The buffer size must be larger than the pipe size so that the
-     write blocks.  */
-  char buf[100000];
+  int e, r;
 
-  while (write (fd[1], buf, sizeof (buf)) > 0);
+  errno = 0;
 
-  return (void *) 42l;
-}
+  pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
 
+  /* This is a cancellation point, but we should not be cancelled.  */
+  r = write (-1, 0, 0);
+  e = errno;
+
+  /* Check that the cancelling syscall wrapper has handled the error correctly.  */
+  if (r != -1 || errno != EBADF)
+    {
+      printf ("write returned %d, errno %d\n", r, e);
+      exit (1);
+    }
+
+  return NULL;
+}
 
 static int
 do_test (void)
 {
   pthread_t th;
-  void *r;
-  struct sigaction sa;
-
-  sa.sa_handler = SIG_IGN;
-  sigemptyset (&sa.sa_mask);
-  sa.sa_flags = 0;
-
-  if (sigaction (SIGPIPE, &sa, NULL) != 0)
-    {
-      puts ("sigaction failed");
-      return 1;
-    }
-
-  if (pipe (fd) != 0)
-    {
-      puts ("pipe failed");
-      return 1;
-    }
 
   if (pthread_create (&th, NULL, tf, NULL) != 0)
     {
       puts ("create failed");
-      return 1;
-    }
-
-  if (pthread_cancel (th) != 0)
-    {
-      puts ("cancel failed");
-      return 1;
+      exit (1);
     }
 
-  /* This will cause the write in the child to return.  */
-  close (fd[0]);
-
+  void *r;
   if (pthread_join (th, &r) != 0)
     {
       puts ("join failed");
-      return 1;
-    }
-
-  if (r != PTHREAD_CANCELED)
-    {
-      printf ("result is wrong: expected %p, got %p\n", PTHREAD_CANCELED, r);
-      return 1;
+      exit (1);
     }
 
   return 0;
diff --git a/nptl/tst-cancel4.c b/nptl/tst-cancel4.c
index e50afd7..0a41d95 100644
--- a/nptl/tst-cancel4.c
+++ b/nptl/tst-cancel4.c
@@ -38,8 +38,10 @@
 #include <sys/un.h>
 #include <sys/wait.h>
 
-#include "pthreadP.h"
-
+/* The signal used for asynchronous cancelation.  */
+#ifndef SIGCANCEL
+# define SIGCANCEL       __SIGRTMIN
+#endif
 
 /* Since STREAMS are not supported in the standard Linux kernel and
    there we don't advertise STREAMS as supported is no need to test
@@ -247,6 +249,9 @@ tf_write  (void *arg)
   char buf[WRITE_BUFFER_SIZE];
   memset (buf, '\0', sizeof (buf));
   s = write (fd, buf, sizeof (buf));
+  /* The write can return a value higher than 0 (meaning partial write)
+     due the SIGCANCEL, but the thread may still pending cancellation.  */
+  pthread_testcancel ();
 
   pthread_cleanup_pop (0);
 
@@ -1143,6 +1148,8 @@ tf_send (void *arg)
   char mem[700000];
 
   send (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0);
+  /* Check for partial send.  */
+  pthread_testcancel ();
 
   pthread_cleanup_pop (0);
 
@@ -1425,6 +1432,38 @@ tf_open (void *arg)
   exit (1);
 }
 
+static void *
+tf_open64 (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which open()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  open64 ("Makefile", O_RDONLY);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: open returned\n", __FUNCTION__);
+
+  exit (1);
+}
 
 static void *
 tf_close (void *arg)
@@ -1510,6 +1549,46 @@ tf_pread (void *arg)
   exit (1);
 }
 
+static void *
+tf_pread64 (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which pread()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  tempfd = open64 ("Makefile", O_RDONLY);
+  if (tempfd == -1)
+    {
+      printf ("%s: cannot open64 Makefile\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  char mem[10];
+  pread64 (tempfd, mem, sizeof (mem), 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: pread64 returned\n", __FUNCTION__);
+
+  exit (1);
+}
 
 static void *
 tf_pwrite (void *arg)
@@ -1554,6 +1633,48 @@ tf_pwrite (void *arg)
   exit (1);
 }
 
+static void *
+tf_pwrite64 (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which pwrite()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+  tempfd = mkstemp (fname);
+  if (tempfd == -1)
+    {
+      printf ("%s: mkstemp failed\n", __FUNCTION__);
+      exit (1);
+    }
+  unlink (fname);
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  char mem[10];
+  pwrite64 (tempfd, mem, sizeof (mem), 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: pwrite64 returned\n", __FUNCTION__);
+
+  exit (1);
+}
 
 static void *
 tf_fsync (void *arg)
@@ -2141,9 +2262,12 @@ static struct
   ADD_TEST (recvfrom, 2, 0),
   ADD_TEST (recvmsg, 2, 0),
   ADD_TEST (open, 2, 1),
+  ADD_TEST (open64, 2, 1),
   ADD_TEST (close, 2, 1),
   ADD_TEST (pread, 2, 1),
+  ADD_TEST (pread64, 2, 1),
   ADD_TEST (pwrite, 2, 1),
+  ADD_TEST (pwrite64, 2, 1),
   ADD_TEST (fsync, 2, 1),
   ADD_TEST (fdatasync, 2, 1),
   ADD_TEST (msync, 2, 1),

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=3a4e0d38e41f45af9e296f8e3c5ea7405df1b3a3

commit 3a4e0d38e41f45af9e296f8e3c5ea7405df1b3a3
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Wed Sep 24 21:52:07 2014 -0300

    nptl: x86_64: Remove assembly pthread_cond_{timed}wait.S implementation
    
    This patch removes the x86_64 assembly implementation for
    pthread_cond_timedwait and pthread_cond_wait for upcoming BZ#12683 fix.
    The patch requires that cancellable futex calls to be called through
    __syscall_cancel. Although it not strictly require, the remove of the
    x86_64 specific implementation follows the rationale:
    
    1. The adjustments required to this fix is extensive (parameters
       save, functions calls, etc.) and there is little gain in keep an
       alternate implementation for x86_64 in term of maintanability.
    2. There is no pthread_cond benchmark that shows these implementations
       are more 'optimized' that what current compilers can produce using
       generic C code.
    3. The changes required also can change the exact gains this optimized is
       intended to provide.

diff --git a/ChangeLog b/ChangeLog
index 07cc222..cf84c3f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
+	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Remove file.
+	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise.
+
 	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Remove
 	file.
 	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise.
diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
deleted file mode 100644
index 15b872d..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+++ /dev/null
@@ -1,623 +0,0 @@
-/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-#include <lowlevellock.h>
-#include <lowlevelcond.h>
-#include <pthread-pi-defines.h>
-#include <pthread-errnos.h>
-#include <stap-probe.h>
-
-#include <kernel-features.h>
-
-
-	.text
-
-
-/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
-			       const struct timespec *abstime)  */
-	.globl	__pthread_cond_timedwait
-	.type	__pthread_cond_timedwait, @function
-	.align	16
-__pthread_cond_timedwait:
-.LSTARTCODE:
-	cfi_startproc
-#ifdef SHARED
-	cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
-			DW.ref.__gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
-#else
-	cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
-#endif
-
-	pushq	%r12
-	cfi_adjust_cfa_offset(8)
-	cfi_rel_offset(%r12, 0)
-	pushq	%r13
-	cfi_adjust_cfa_offset(8)
-	cfi_rel_offset(%r13, 0)
-	pushq	%r14
-	cfi_adjust_cfa_offset(8)
-	cfi_rel_offset(%r14, 0)
-	pushq	%r15
-	cfi_adjust_cfa_offset(8)
-	cfi_rel_offset(%r15, 0)
-#define FRAME_SIZE (32+8)
-	subq	$FRAME_SIZE, %rsp
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-	cfi_remember_state
-
-	LIBC_PROBE (cond_timedwait, 3, %rdi, %rsi, %rdx)
-
-	cmpq	$1000000000, 8(%rdx)
-	movl	$EINVAL, %eax
-	jae	48f
-
-	/* Stack frame:
-
-	   rsp + 48
-		    +--------------------------+
-	   rsp + 32 | timeout value            |
-		    +--------------------------+
-	   rsp + 24 | old wake_seq value       |
-		    +--------------------------+
-	   rsp + 16 | mutex pointer            |
-		    +--------------------------+
-	   rsp +  8 | condvar pointer          |
-		    +--------------------------+
-	   rsp +  4 | old broadcast_seq value  |
-		    +--------------------------+
-	   rsp +  0 | old cancellation mode    |
-		    +--------------------------+
-	*/
-
-	LP_OP(cmp) $-1, dep_mutex(%rdi)
-
-	/* Prepare structure passed to cancellation handler.  */
-	movq	%rdi, 8(%rsp)
-	movq	%rsi, 16(%rsp)
-	movq	%rdx, %r13
-
-	je	22f
-	mov	%RSI_LP, dep_mutex(%rdi)
-
-22:
-	xorb	%r15b, %r15b
-
-	/* Get internal lock.  */
-	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jnz	31f
-
-	/* Unlock the mutex.  */
-32:	movq	16(%rsp), %rdi
-	xorl	%esi, %esi
-	callq	__pthread_mutex_unlock_usercnt
-
-	testl	%eax, %eax
-	jne	46f
-
-	movq	8(%rsp), %rdi
-	incq	total_seq(%rdi)
-	incl	cond_futex(%rdi)
-	addl	$(1 << nwaiters_shift), cond_nwaiters(%rdi)
-
-	/* Get and store current wakeup_seq value.  */
-	movq	8(%rsp), %rdi
-	movq	wakeup_seq(%rdi), %r9
-	movl	broadcast_seq(%rdi), %edx
-	movq	%r9, 24(%rsp)
-	movl	%edx, 4(%rsp)
-
-	cmpq	$0, (%r13)
-	movq	$-ETIMEDOUT, %r14
-	js	36f
-
-38:	movl	cond_futex(%rdi), %r12d
-
-	/* Unlock.  */
-	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	jne	33f
-
-.LcleanupSTART1:
-34:	callq	__pthread_enable_asynccancel
-	movl	%eax, (%rsp)
-
-	movq	%r13, %r10
-	movl	$FUTEX_WAIT_BITSET, %esi
-	LP_OP(cmp) $-1, dep_mutex(%rdi)
-	je	60f
-
-	mov	dep_mutex(%rdi), %R8_LP
-	/* Requeue to a non-robust PI mutex if the PI bit is set and
-	the robust bit is not set.  */
-	movl	MUTEX_KIND(%r8), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	jne	61f
-
-	movl	$(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
-	xorl	%eax, %eax
-	/* The following only works like this because we only support
-	   two clocks, represented using a single bit.  */
-	testl	$1, cond_nwaiters(%rdi)
-	movl	$FUTEX_CLOCK_REALTIME, %edx
-	cmove	%edx, %eax
-	orl	%eax, %esi
-	movq	%r12, %rdx
-	addq	$cond_futex, %rdi
-	movl	$SYS_futex, %eax
-	syscall
-
-	cmpl	$0, %eax
-	sete	%r15b
-
-#ifdef __ASSUME_REQUEUE_PI
-	jmp	62f
-#else
-	je	62f
-
-	/* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns
-	   successfully, it has already locked the mutex for us and the
-	   pi_flag (%r15b) is set to denote that fact.  However, if another
-	   thread changed the futex value before we entered the wait, the
-	   syscall may return an EAGAIN and the mutex is not locked.  We go
-	   ahead with a success anyway since later we look at the pi_flag to
-	   decide if we got the mutex or not.  The sequence numbers then make
-	   sure that only one of the threads actually wake up.  We retry using
-	   normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal
-	   and PI futexes don't mix.
-
-	   Note that we don't check for EAGAIN specifically; we assume that the
-	   only other error the futex function could return is EAGAIN (barring
-	   the ETIMEOUT of course, for the timeout case in futex) since
-	   anything else would mean an error in our function.  It is too
-	   expensive to do that check for every call (which is  quite common in
-	   case of a large number of threads), so it has been skipped.  */
-	cmpl    $-ENOSYS, %eax
-	jne     62f
-
-	subq	$cond_futex, %rdi
-#endif
-
-61:	movl	$(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi
-60:	xorb	%r15b, %r15b
-	xorl	%eax, %eax
-	/* The following only works like this because we only support
-	   two clocks, represented using a single bit.  */
-	testl	$1, cond_nwaiters(%rdi)
-	movl	$FUTEX_CLOCK_REALTIME, %edx
-	movl	$0xffffffff, %r9d
-	cmove	%edx, %eax
-	orl	%eax, %esi
-	movq	%r12, %rdx
-	addq	$cond_futex, %rdi
-	movl	$SYS_futex, %eax
-	syscall
-62:	movq	%rax, %r14
-
-	movl	(%rsp), %edi
-	callq	__pthread_disable_asynccancel
-.LcleanupEND1:
-
-	/* Lock.  */
-	movq	8(%rsp), %rdi
-	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jne	35f
-
-36:	movl	broadcast_seq(%rdi), %edx
-
-	movq	woken_seq(%rdi), %rax
-
-	movq	wakeup_seq(%rdi), %r9
-
-	cmpl	4(%rsp), %edx
-	jne	53f
-
-	cmpq	24(%rsp), %r9
-	jbe	45f
-
-	cmpq	%rax, %r9
-	ja	39f
-
-45:	cmpq	$-ETIMEDOUT, %r14
-	je	99f
-
-	/* We need to go back to futex_wait.  If we're using requeue_pi, then
-	   release the mutex we had acquired and go back.  */
-	test	%r15b, %r15b
-	jz	38b
-
-	/* Adjust the mutex values first and then unlock it.  The unlock
-	   should always succeed or else the kernel did not lock the
-	   mutex correctly.  */
-	movq	%r8, %rdi
-	callq	__pthread_mutex_cond_lock_adjust
-	xorl	%esi, %esi
-	callq	__pthread_mutex_unlock_usercnt
-	/* Reload cond_var.  */
-	movq	8(%rsp), %rdi
-	jmp	38b
-
-99:	incq	wakeup_seq(%rdi)
-	incl	cond_futex(%rdi)
-	movl	$ETIMEDOUT, %r14d
-	jmp	44f
-
-53:	xorq	%r14, %r14
-	jmp	54f
-
-39:	xorq	%r14, %r14
-44:	incq	woken_seq(%rdi)
-
-54:	subl	$(1 << nwaiters_shift), cond_nwaiters(%rdi)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	cmpq	$0xffffffffffffffff, total_seq(%rdi)
-	jne	55f
-	movl	cond_nwaiters(%rdi), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	55f
-
-	addq	$cond_nwaiters, %rdi
-	LP_OP(cmp) $-1, dep_mutex-cond_nwaiters(%rdi)
-	movl	$1, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-	subq	$cond_nwaiters, %rdi
-
-55:	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	jne	40f
-
-	/* If requeue_pi is used the kernel performs the locking of the
-	   mutex. */
-41:	movq	16(%rsp), %rdi
-	testb	%r15b, %r15b
-	jnz	64f
-
-	callq	__pthread_mutex_cond_lock
-
-63:	testq	%rax, %rax
-	cmoveq	%r14, %rax
-
-48:	addq	$FRAME_SIZE, %rsp
-	cfi_adjust_cfa_offset(-FRAME_SIZE)
-	popq	%r15
-	cfi_adjust_cfa_offset(-8)
-	cfi_restore(%r15)
-	popq	%r14
-	cfi_adjust_cfa_offset(-8)
-	cfi_restore(%r14)
-	popq	%r13
-	cfi_adjust_cfa_offset(-8)
-	cfi_restore(%r13)
-	popq	%r12
-	cfi_adjust_cfa_offset(-8)
-	cfi_restore(%r12)
-
-	retq
-
-	cfi_restore_state
-
-64:	callq	__pthread_mutex_cond_lock_adjust
-	movq	%r14, %rax
-	jmp	48b
-
-	/* Initial locking failed.  */
-31:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-	jmp	32b
-
-	/* Unlock in loop requires wakeup.  */
-33:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-	jmp	34b
-
-	/* Locking in loop failed.  */
-35:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-#if cond_lock != 0
-	subq	$cond_lock, %rdi
-#endif
-	jmp	36b
-
-	/* Unlock after loop requires wakeup.  */
-40:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-	jmp	41b
-
-	/* The initial unlocking of the mutex failed.  */
-46:	movq	8(%rsp), %rdi
-	movq	%rax, (%rsp)
-	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	jne	47f
-
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-
-47:	movq	(%rsp), %rax
-	jmp	48b
-
-	.size	__pthread_cond_timedwait, .-__pthread_cond_timedwait
-versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
-		  GLIBC_2_3_2)
-
-
-	.align	16
-	.type	__condvar_cleanup2, @function
-__condvar_cleanup2:
-	/* Stack frame:
-
-	   rsp + 72
-		    +--------------------------+
-	   rsp + 64 | %r12                     |
-		    +--------------------------+
-	   rsp + 56 | %r13                     |
-		    +--------------------------+
-	   rsp + 48 | %r14                     |
-		    +--------------------------+
-	   rsp + 24 | unused                   |
-		    +--------------------------+
-	   rsp + 16 | mutex pointer            |
-		    +--------------------------+
-	   rsp +  8 | condvar pointer          |
-		    +--------------------------+
-	   rsp +  4 | old broadcast_seq value  |
-		    +--------------------------+
-	   rsp +  0 | old cancellation mode    |
-		    +--------------------------+
-	*/
-
-	movq	%rax, 24(%rsp)
-
-	/* Get internal lock.  */
-	movq	8(%rsp), %rdi
-	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jz	1f
-
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-#if cond_lock != 0
-	subq	$cond_lock, %rdi
-#endif
-
-1:	movl	broadcast_seq(%rdi), %edx
-	cmpl	4(%rsp), %edx
-	jne	3f
-
-	/* We increment the wakeup_seq counter only if it is lower than
-	   total_seq.  If this is not the case the thread was woken and
-	   then canceled.  In this case we ignore the signal.  */
-	movq	total_seq(%rdi), %rax
-	cmpq	wakeup_seq(%rdi), %rax
-	jbe	6f
-	incq	wakeup_seq(%rdi)
-	incl	cond_futex(%rdi)
-6:	incq	woken_seq(%rdi)
-
-3:	subl	$(1 << nwaiters_shift), cond_nwaiters(%rdi)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	xorq	%r12, %r12
-	cmpq	$0xffffffffffffffff, total_seq(%rdi)
-	jne	4f
-	movl	cond_nwaiters(%rdi), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	4f
-
-	LP_OP(cmp) $-1, dep_mutex(%rdi)
-	leaq	cond_nwaiters(%rdi), %rdi
-	movl	$1, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-	subq	$cond_nwaiters, %rdi
-	movl	$1, %r12d
-
-4:	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	je	2f
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-
-	/* Wake up all waiters to make sure no signal gets lost.  */
-2:	testq	%r12, %r12
-	jnz	5f
-	addq	$cond_futex, %rdi
-	LP_OP(cmp) $-1, dep_mutex-cond_futex(%rdi)
-	movl	$0x7fffffff, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-
-	/* Lock the mutex only if we don't own it already.  This only happens
-	   in case of PI mutexes, if we got cancelled after a successful
-	   return of the futex syscall and before disabling async
-	   cancellation.  */
-5:	movq	16(%rsp), %rdi
-	movl	MUTEX_KIND(%rdi), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	jne	7f
-
-	movl	(%rdi), %eax
-	andl	$TID_MASK, %eax
-	cmpl	%eax, %fs:TID
-	jne	7f
-	/* We managed to get the lock.  Fix it up before returning.  */
-	callq	__pthread_mutex_cond_lock_adjust
-	jmp	8f
-
-7:	callq	__pthread_mutex_cond_lock
-
-8:	movq	24(%rsp), %rdi
-	movq	FRAME_SIZE(%rsp), %r15
-	movq	FRAME_SIZE+8(%rsp), %r14
-	movq	FRAME_SIZE+16(%rsp), %r13
-	movq	FRAME_SIZE+24(%rsp), %r12
-.LcallUR:
-	call	_Unwind_Resume@PLT
-	hlt
-.LENDCODE:
-	cfi_endproc
-	.size	__condvar_cleanup2, .-__condvar_cleanup2
-
-
-	.section .gcc_except_table,"a",@progbits
-.LexceptSTART:
-	.byte	DW_EH_PE_omit			# @LPStart format
-	.byte	DW_EH_PE_omit			# @TType format
-	.byte	DW_EH_PE_uleb128		# call-site format
-	.uleb128 .Lcstend-.Lcstbegin
-.Lcstbegin:
-	.uleb128 .LcleanupSTART1-.LSTARTCODE
-	.uleb128 .LcleanupEND1-.LcleanupSTART1
-	.uleb128 __condvar_cleanup2-.LSTARTCODE
-	.uleb128  0
-	.uleb128 .LcallUR-.LSTARTCODE
-	.uleb128 .LENDCODE-.LcallUR
-	.uleb128 0
-	.uleb128  0
-.Lcstend:
-
-
-#ifdef SHARED
-	.hidden	DW.ref.__gcc_personality_v0
-	.weak	DW.ref.__gcc_personality_v0
-	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
-	.align	LP_SIZE
-	.type	DW.ref.__gcc_personality_v0, @object
-	.size	DW.ref.__gcc_personality_v0, LP_SIZE
-DW.ref.__gcc_personality_v0:
-	ASM_ADDR __gcc_personality_v0
-#endif
diff --git a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
deleted file mode 100644
index 2e564a7..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+++ /dev/null
@@ -1,555 +0,0 @@
-/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-#include <lowlevellock.h>
-#include <lowlevelcond.h>
-#include <tcb-offsets.h>
-#include <pthread-pi-defines.h>
-#include <pthread-errnos.h>
-#include <stap-probe.h>
-
-#include <kernel-features.h>
-
-
-	.text
-
-/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
-	.globl	__pthread_cond_wait
-	.type	__pthread_cond_wait, @function
-	.align	16
-__pthread_cond_wait:
-.LSTARTCODE:
-	cfi_startproc
-#ifdef SHARED
-	cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
-			DW.ref.__gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
-#else
-	cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
-#endif
-
-#define FRAME_SIZE (32+8)
-	leaq	-FRAME_SIZE(%rsp), %rsp
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-
-	/* Stack frame:
-
-	   rsp + 32
-		    +--------------------------+
-	   rsp + 24 | old wake_seq value       |
-		    +--------------------------+
-	   rsp + 16 | mutex pointer            |
-		    +--------------------------+
-	   rsp +  8 | condvar pointer          |
-		    +--------------------------+
-	   rsp +  4 | old broadcast_seq value  |
-		    +--------------------------+
-	   rsp +  0 | old cancellation mode    |
-		    +--------------------------+
-	*/
-
-	LIBC_PROBE (cond_wait, 2, %rdi, %rsi)
-
-	LP_OP(cmp) $-1, dep_mutex(%rdi)
-
-	/* Prepare structure passed to cancellation handler.  */
-	movq	%rdi, 8(%rsp)
-	movq	%rsi, 16(%rsp)
-
-	je	15f
-	mov	%RSI_LP, dep_mutex(%rdi)
-
-	/* Get internal lock.  */
-15:	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jne	1f
-
-	/* Unlock the mutex.  */
-2:	movq	16(%rsp), %rdi
-	xorl	%esi, %esi
-	callq	__pthread_mutex_unlock_usercnt
-
-	testl	%eax, %eax
-	jne	12f
-
-	movq	8(%rsp), %rdi
-	incq	total_seq(%rdi)
-	incl	cond_futex(%rdi)
-	addl	$(1 << nwaiters_shift), cond_nwaiters(%rdi)
-
-	/* Get and store current wakeup_seq value.  */
-	movq	8(%rsp), %rdi
-	movq	wakeup_seq(%rdi), %r9
-	movl	broadcast_seq(%rdi), %edx
-	movq	%r9, 24(%rsp)
-	movl	%edx, 4(%rsp)
-
-	/* Unlock.  */
-8:	movl	cond_futex(%rdi), %edx
-	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	jne	3f
-
-.LcleanupSTART:
-4:	callq	__pthread_enable_asynccancel
-	movl	%eax, (%rsp)
-
-	xorq	%r10, %r10
-	LP_OP(cmp) $-1, dep_mutex(%rdi)
-	leaq	cond_futex(%rdi), %rdi
-	movl	$FUTEX_WAIT, %esi
-	je	60f
-
-	mov	dep_mutex-cond_futex(%rdi), %R8_LP
-	/* Requeue to a non-robust PI mutex if the PI bit is set and
-	the robust bit is not set.  */
-	movl	MUTEX_KIND(%r8), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	jne	61f
-
-	movl	$(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
-	movl	$SYS_futex, %eax
-	syscall
-
-	cmpl	$0, %eax
-	sete	%r8b
-
-#ifdef __ASSUME_REQUEUE_PI
-	jmp	62f
-#else
-	je	62f
-
-	/* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns
-	   successfully, it has already locked the mutex for us and the
-	   pi_flag (%r8b) is set to denote that fact.  However, if another
-	   thread changed the futex value before we entered the wait, the
-	   syscall may return an EAGAIN and the mutex is not locked.  We go
-	   ahead with a success anyway since later we look at the pi_flag to
-	   decide if we got the mutex or not.  The sequence numbers then make
-	   sure that only one of the threads actually wake up.  We retry using
-	   normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal
-	   and PI futexes don't mix.
-
-	   Note that we don't check for EAGAIN specifically; we assume that the
-	   only other error the futex function could return is EAGAIN since
-	   anything else would mean an error in our function.  It is too
-	   expensive to do that check for every call (which is 	quite common in
-	   case of a large number of threads), so it has been skipped.  */
-	cmpl	$-ENOSYS, %eax
-	jne	62f
-
-# ifndef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAIT, %esi
-# endif
-#endif
-
-61:
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), %esi
-#else
-	orl	%fs:PRIVATE_FUTEX, %esi
-#endif
-60:	xorb	%r8b, %r8b
-	movl	$SYS_futex, %eax
-	syscall
-
-62:	movl	(%rsp), %edi
-	callq	__pthread_disable_asynccancel
-.LcleanupEND:
-
-	/* Lock.  */
-	movq	8(%rsp), %rdi
-	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jnz	5f
-
-6:	movl	broadcast_seq(%rdi), %edx
-
-	movq	woken_seq(%rdi), %rax
-
-	movq	wakeup_seq(%rdi), %r9
-
-	cmpl	4(%rsp), %edx
-	jne	16f
-
-	cmpq	24(%rsp), %r9
-	jbe	19f
-
-	cmpq	%rax, %r9
-	jna	19f
-
-	incq	woken_seq(%rdi)
-
-	/* Unlock */
-16:	subl	$(1 << nwaiters_shift), cond_nwaiters(%rdi)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	cmpq	$0xffffffffffffffff, total_seq(%rdi)
-	jne	17f
-	movl	cond_nwaiters(%rdi), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	17f
-
-	addq	$cond_nwaiters, %rdi
-	LP_OP(cmp) $-1, dep_mutex-cond_nwaiters(%rdi)
-	movl	$1, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-	subq	$cond_nwaiters, %rdi
-
-17:	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	jne	10f
-
-	/* If requeue_pi is used the kernel performs the locking of the
-	   mutex. */
-11:	movq	16(%rsp), %rdi
-	testb	%r8b, %r8b
-	jnz	18f
-
-	callq	__pthread_mutex_cond_lock
-
-14:	leaq	FRAME_SIZE(%rsp), %rsp
-	cfi_adjust_cfa_offset(-FRAME_SIZE)
-
-	/* We return the result of the mutex_lock operation.  */
-	retq
-
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-
-18:	callq	__pthread_mutex_cond_lock_adjust
-	xorl	%eax, %eax
-	jmp	14b
-
-	/* We need to go back to futex_wait.  If we're using requeue_pi, then
-	   release the mutex we had acquired and go back.  */
-19:	testb	%r8b, %r8b
-	jz	8b
-
-	/* Adjust the mutex values first and then unlock it.  The unlock
-	   should always succeed or else the kernel did not lock the mutex
-	   correctly.  */
-	movq	16(%rsp), %rdi
-	callq	__pthread_mutex_cond_lock_adjust
-	movq	%rdi, %r8
-	xorl	%esi, %esi
-	callq	__pthread_mutex_unlock_usercnt
-	/* Reload cond_var.  */
-	movq	8(%rsp), %rdi
-	jmp	8b
-
-	/* Initial locking failed.  */
-1:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-	jmp	2b
-
-	/* Unlock in loop requires wakeup.  */
-3:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	/* The call preserves %rdx.  */
-	callq	__lll_unlock_wake
-#if cond_lock != 0
-	subq	$cond_lock, %rdi
-#endif
-	jmp	4b
-
-	/* Locking in loop failed.  */
-5:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-#if cond_lock != 0
-	subq	$cond_lock, %rdi
-#endif
-	jmp	6b
-
-	/* Unlock after loop requires wakeup.  */
-10:
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-	jmp	11b
-
-	/* The initial unlocking of the mutex failed.  */
-12:	movq	%rax, %r10
-	movq	8(%rsp), %rdi
-	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	je	13f
-
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_unlock_wake
-
-13:	movq	%r10, %rax
-	jmp	14b
-
-	.size	__pthread_cond_wait, .-__pthread_cond_wait
-versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
-		  GLIBC_2_3_2)
-
-
-	.align	16
-	.type	__condvar_cleanup1, @function
-	.globl	__condvar_cleanup1
-	.hidden	__condvar_cleanup1
-__condvar_cleanup1:
-	/* Stack frame:
-
-	   rsp + 32
-		    +--------------------------+
-	   rsp + 24 | unused                   |
-		    +--------------------------+
-	   rsp + 16 | mutex pointer            |
-		    +--------------------------+
-	   rsp +  8 | condvar pointer          |
-		    +--------------------------+
-	   rsp +  4 | old broadcast_seq value  |
-		    +--------------------------+
-	   rsp +  0 | old cancellation mode    |
-		    +--------------------------+
-	*/
-
-	movq	%rax, 24(%rsp)
-
-	/* Get internal lock.  */
-	movq	8(%rsp), %rdi
-	movl	$1, %esi
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, cond_lock(%rdi)
-#endif
-	jz	1f
-
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	callq	__lll_lock_wait
-#if cond_lock != 0
-	subq	$cond_lock, %rdi
-#endif
-
-1:	movl	broadcast_seq(%rdi), %edx
-	cmpl	4(%rsp), %edx
-	jne	3f
-
-	/* We increment the wakeup_seq counter only if it is lower than
-	   total_seq.  If this is not the case the thread was woken and
-	   then canceled.  In this case we ignore the signal.  */
-	movq	total_seq(%rdi), %rax
-	cmpq	wakeup_seq(%rdi), %rax
-	jbe	6f
-	incq	wakeup_seq(%rdi)
-	incl	cond_futex(%rdi)
-6:	incq	woken_seq(%rdi)
-
-3:	subl	$(1 << nwaiters_shift), cond_nwaiters(%rdi)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	xorl	%ecx, %ecx
-	cmpq	$0xffffffffffffffff, total_seq(%rdi)
-	jne	4f
-	movl	cond_nwaiters(%rdi), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	4f
-
-	LP_OP(cmp) $-1, dep_mutex(%rdi)
-	leaq	cond_nwaiters(%rdi), %rdi
-	movl	$1, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-	subq	$cond_nwaiters, %rdi
-	movl	$1, %ecx
-
-4:	LOCK
-#if cond_lock == 0
-	decl	(%rdi)
-#else
-	decl	cond_lock(%rdi)
-#endif
-	je	2f
-#if cond_lock != 0
-	addq	$cond_lock, %rdi
-#endif
-	LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
-	movl	$LLL_PRIVATE, %eax
-	movl	$LLL_SHARED, %esi
-	cmovne	%eax, %esi
-	/* The call preserves %rcx.  */
-	callq	__lll_unlock_wake
-
-	/* Wake up all waiters to make sure no signal gets lost.  */
-2:	testl	%ecx, %ecx
-	jnz	5f
-	addq	$cond_futex, %rdi
-	LP_OP(cmp) $-1, dep_mutex-cond_futex(%rdi)
-	movl	$0x7fffffff, %edx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	movl	$FUTEX_WAKE, %eax
-	movl	$(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
-	cmove	%eax, %esi
-#else
-	movl	$0, %eax
-	movl	%fs:PRIVATE_FUTEX, %esi
-	cmove	%eax, %esi
-	orl	$FUTEX_WAKE, %esi
-#endif
-	movl	$SYS_futex, %eax
-	syscall
-
-	/* Lock the mutex only if we don't own it already.  This only happens
-	   in case of PI mutexes, if we got cancelled after a successful
-	   return of the futex syscall and before disabling async
-	   cancellation.  */
-5:	movq	16(%rsp), %rdi
-	movl	MUTEX_KIND(%rdi), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	jne	7f
-
-	movl	(%rdi), %eax
-	andl	$TID_MASK, %eax
-	cmpl	%eax, %fs:TID
-	jne	7f
-	/* We managed to get the lock.  Fix it up before returning.  */
-	callq	__pthread_mutex_cond_lock_adjust
-	jmp	8f
-
-
-7:	callq	__pthread_mutex_cond_lock
-
-8:	movq	24(%rsp), %rdi
-.LcallUR:
-	call	_Unwind_Resume@PLT
-	hlt
-.LENDCODE:
-	cfi_endproc
-	.size	__condvar_cleanup1, .-__condvar_cleanup1
-
-
-	.section .gcc_except_table,"a",@progbits
-.LexceptSTART:
-	.byte	DW_EH_PE_omit			# @LPStart format
-	.byte	DW_EH_PE_omit			# @TType format
-	.byte	DW_EH_PE_uleb128		# call-site format
-	.uleb128 .Lcstend-.Lcstbegin
-.Lcstbegin:
-	.uleb128 .LcleanupSTART-.LSTARTCODE
-	.uleb128 .LcleanupEND-.LcleanupSTART
-	.uleb128 __condvar_cleanup1-.LSTARTCODE
-	.uleb128 0
-	.uleb128 .LcallUR-.LSTARTCODE
-	.uleb128 .LENDCODE-.LcallUR
-	.uleb128 0
-	.uleb128 0
-.Lcstend:
-
-
-#ifdef SHARED
-	.hidden	DW.ref.__gcc_personality_v0
-	.weak	DW.ref.__gcc_personality_v0
-	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
-	.align	LP_SIZE
-	.type	DW.ref.__gcc_personality_v0, @object
-	.size	DW.ref.__gcc_personality_v0, LP_SIZE
-DW.ref.__gcc_personality_v0:
-	ASM_ADDR __gcc_personality_v0
-#endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=bce17c1ac8dd377b2d4104d21ef201cbd9e4d7ce

commit bce17c1ac8dd377b2d4104d21ef201cbd9e4d7ce
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Mon May 4 11:37:02 2015 -0300

    i386: Remove assembly pthread_cond_{timed}wait.S implementation
    
    With i386 support to call six-argument syscall through C code, it can use
    the default C NPTL pthread_cond_{timed}wait implementation. This patch
    removes the i386 assembly implementation for pthread_cond_timedwait and
    pthread_cond_wait for upcoming BZ#12683 fix.
    
    The patch requires that cancellable futex calls to be called through
    __syscall_cancel instead. Although it not strictly require, the remove
    of the i386 specific implementation follows the rationale:
    
    1. The adjustments required to this fix is extensive (parameters
       save, functions calls, etc.) and there is little gain in keep an
       alternate implementation for i386 in term of maintanability.
    2. There is no pthread_cond benchmark that shows these implementations
       are more 'optimized' that what current compilers can produce using
       generic C code.
    3. The changes required also can change the exact gains this optimized is
       intended to provide.

diff --git a/ChangeLog b/ChangeLog
index 565c3ca..07cc222 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2015-09-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Remove
+	file.
+	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise.
+	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S: Likewise.
+	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S: Likewise.
+	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S: Likewise.
+	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S: Likewise.
+
 2015-09-19  Samuel Thibault  <samuel.thibault@ens-lyon.org>
 
 	Really fix sysdeps/i386/fpu/s_scalbn.S build
diff --git a/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
deleted file mode 100644
index 130c090..0000000
--- a/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+++ /dev/null
@@ -1,973 +0,0 @@
-/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-#include <lowlevellock.h>
-#include <lowlevelcond.h>
-#include <pthread-errnos.h>
-#include <pthread-pi-defines.h>
-#include <kernel-features.h>
-#include <stap-probe.h>
-
-	.text
-
-/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
-			       const struct timespec *abstime)  */
-	.globl	__pthread_cond_timedwait
-	.type	__pthread_cond_timedwait, @function
-	.align	16
-__pthread_cond_timedwait:
-.LSTARTCODE:
-	cfi_startproc
-#ifdef SHARED
-	cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
-			DW.ref.__gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
-#else
-	cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
-#endif
-
-	pushl	%ebp
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebp, 0)
-	pushl	%edi
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%edi, 0)
-	pushl	%esi
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%esi, 0)
-	pushl	%ebx
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebx, 0)
-
-	movl	20(%esp), %ebx
-	movl	28(%esp), %ebp
-
-	LIBC_PROBE (cond_timedwait, 3, %ebx, 24(%esp), %ebp)
-
-	cmpl	$1000000000, 4(%ebp)
-	movl	$EINVAL, %eax
-	jae	18f
-
-	/* Stack frame:
-
-	   esp + 32
-		    +--------------------------+
-	   esp + 24 | timeout value            |
-		    +--------------------------+
-	   esp + 20 | futex pointer            |
-		    +--------------------------+
-	   esp + 16 | pi-requeued flag         |
-		    +--------------------------+
-	   esp + 12 | old broadcast_seq value  |
-		    +--------------------------+
-	   esp +  4 | old wake_seq value       |
-		    +--------------------------+
-	   esp +  0 | old cancellation mode    |
-		    +--------------------------+
-	*/
-
-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
-# ifdef PIC
-	LOAD_PIC_REG (cx)
-	cmpl	$0, __have_futex_clock_realtime@GOTOFF(%ecx)
-# else
-	cmpl	$0, __have_futex_clock_realtime
-# endif
-	je	.Lreltmo
-#endif
-
-	/* Get internal lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jnz	1f
-
-	/* Store the reference to the mutex.  If there is already a
-	   different value in there this is a bad user bug.  */
-2:	cmpl	$-1, dep_mutex(%ebx)
-	movl	24(%esp), %eax
-	je	17f
-	movl	%eax, dep_mutex(%ebx)
-
-	/* Unlock the mutex.  */
-17:	xorl	%edx, %edx
-	call	__pthread_mutex_unlock_usercnt
-
-	testl	%eax, %eax
-	jne	16f
-
-	addl	$1, total_seq(%ebx)
-	adcl	$0, total_seq+4(%ebx)
-	addl	$1, cond_futex(%ebx)
-	addl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-#ifdef __ASSUME_FUTEX_CLOCK_REALTIME
-# define FRAME_SIZE 24
-#else
-# define FRAME_SIZE 32
-#endif
-	subl	$FRAME_SIZE, %esp
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-	cfi_remember_state
-
-	/* Get and store current wakeup_seq value.  */
-	movl	wakeup_seq(%ebx), %edi
-	movl	wakeup_seq+4(%ebx), %edx
-	movl	broadcast_seq(%ebx), %eax
-	movl	%edi, 4(%esp)
-	movl	%edx, 8(%esp)
-	movl	%eax, 12(%esp)
-
-	/* Reset the pi-requeued flag.  */
-	movl	$0, 16(%esp)
-
-	cmpl	$0, (%ebp)
-	movl	$-ETIMEDOUT, %esi
-	js	6f
-
-8:	movl	cond_futex(%ebx), %edi
-	movl	%edi, 20(%esp)
-
-	/* Unlock.  */
-	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	jne	3f
-
-.LcleanupSTART:
-4:	call	__pthread_enable_asynccancel
-	movl	%eax, (%esp)
-
-	leal	(%ebp), %esi
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	sete	%cl
-	je	40f
-
-	movl	dep_mutex(%ebx), %edi
-	/* Requeue to a non-robust PI mutex if the PI bit is set and
-	   the robust bit is not set.  */
-	movl	MUTEX_KIND(%edi), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	jne	40f
-
-	movl	$(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
-	/* The following only works like this because we only support
-	   two clocks, represented using a single bit.  */
-	testl	$1, cond_nwaiters(%ebx)
-	/* XXX Need to implement using sete instead of a jump.  */
-	jne	42f
-	orl	$FUTEX_CLOCK_REALTIME, %ecx
-
-42:	movl	20(%esp), %edx
-	addl	$cond_futex, %ebx
-.Ladd_cond_futex_pi:
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	subl	$cond_futex, %ebx
-.Lsub_cond_futex_pi:
-	movl	%eax, %esi
-	/* Set the pi-requeued flag only if the kernel has returned 0. The
-	   kernel does not hold the mutex on ETIMEDOUT or any other error.  */
-	cmpl	$0, %eax
-	sete	16(%esp)
-	je	41f
-
-	/* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns
-	   successfully, it has already locked the mutex for us and the
-	   pi_flag (16(%esp)) is set to denote that fact.  However, if another
-	   thread changed the futex value before we entered the wait, the
-	   syscall may return an EAGAIN and the mutex is not locked.  We go
-	   ahead with a success anyway since later we look at the pi_flag to
-	   decide if we got the mutex or not.  The sequence numbers then make
-	   sure that only one of the threads actually wake up.  We retry using
-	   normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal
-	   and PI futexes don't mix.
-
-	   Note that we don't check for EAGAIN specifically; we assume that the
-	   only other error the futex function could return is EAGAIN (barring
-	   the ETIMEOUT of course, for the timeout case in futex) since
-	   anything else would mean an error in our function.  It is too
-	   expensive to do that check for every call (which is  quite common in
-	   case of a large number of threads), so it has been skipped.  */
-	cmpl	$-ENOSYS, %eax
-	jne	41f
-	xorl	%ecx, %ecx
-
-40:	subl	$1, %ecx
-	movl	$0, 16(%esp)
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAIT_BITSET, %ecx
-	/* The following only works like this because we only support
-	   two clocks, represented using a single bit.  */
-	testl	$1, cond_nwaiters(%ebx)
-	jne	30f
-	orl	$FUTEX_CLOCK_REALTIME, %ecx
-30:
-	movl	20(%esp), %edx
-	movl	$0xffffffff, %ebp
-	addl	$cond_futex, %ebx
-.Ladd_cond_futex:
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	subl	$cond_futex, %ebx
-.Lsub_cond_futex:
-	movl	28+FRAME_SIZE(%esp), %ebp
-	movl	%eax, %esi
-
-41:	movl	(%esp), %eax
-	call	__pthread_disable_asynccancel
-.LcleanupEND:
-
-	/* Lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jnz	5f
-
-6:	movl	broadcast_seq(%ebx), %eax
-	cmpl	12(%esp), %eax
-	jne	23f
-
-	movl	woken_seq(%ebx), %eax
-	movl	woken_seq+4(%ebx), %ecx
-
-	movl	wakeup_seq(%ebx), %edi
-	movl	wakeup_seq+4(%ebx), %edx
-
-	cmpl	8(%esp), %edx
-	jne	7f
-	cmpl	4(%esp), %edi
-	je	15f
-
-7:	cmpl	%ecx, %edx
-	jne	9f
-	cmp	%eax, %edi
-	jne	9f
-
-15:	cmpl	$-ETIMEDOUT, %esi
-	je	28f
-
-	/* We need to go back to futex_wait.  If we're using requeue_pi, then
-	   release the mutex we had acquired and go back.  */
-	movl	16(%esp), %edx
-	test	%edx, %edx
-	jz	8b
-
-	/* Adjust the mutex values first and then unlock it.  The unlock
-	   should always succeed or else the kernel did not lock the mutex
-	   correctly.  */
-	movl	dep_mutex(%ebx), %eax
-	call	__pthread_mutex_cond_lock_adjust
-	xorl	%edx, %edx
-	call	__pthread_mutex_unlock_usercnt
-	jmp	8b
-
-28:	addl	$1, wakeup_seq(%ebx)
-	adcl	$0, wakeup_seq+4(%ebx)
-	addl	$1, cond_futex(%ebx)
-	movl	$ETIMEDOUT, %esi
-	jmp	14f
-
-23:	xorl	%esi, %esi
-	jmp	24f
-
-9:	xorl	%esi, %esi
-14:	addl	$1, woken_seq(%ebx)
-	adcl	$0, woken_seq+4(%ebx)
-
-24:	subl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	movl	total_seq(%ebx), %eax
-	andl	total_seq+4(%ebx), %eax
-	cmpl	$0xffffffff, %eax
-	jne	25f
-	movl	cond_nwaiters(%ebx), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	25f
-
-	addl	$cond_nwaiters, %ebx
-	movl	$SYS_futex, %eax
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_nwaiters(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$1, %edx
-	ENTER_KERNEL
-	subl	$cond_nwaiters, %ebx
-
-25:	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	jne	10f
-
-11:	movl	24+FRAME_SIZE(%esp), %eax
-	/* With requeue_pi, the mutex lock is held in the kernel.  */
-	movl	16(%esp), %ecx
-	testl	%ecx, %ecx
-	jnz	27f
-
-	call	__pthread_mutex_cond_lock
-26:	addl	$FRAME_SIZE, %esp
-	cfi_adjust_cfa_offset(-FRAME_SIZE)
-
-	/* We return the result of the mutex_lock operation if it failed.  */
-	testl	%eax, %eax
-#ifdef HAVE_CMOV
-	cmovel	%esi, %eax
-#else
-	jne	22f
-	movl	%esi, %eax
-22:
-#endif
-
-18:	popl	%ebx
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebx)
-	popl	%esi
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%esi)
-	popl	%edi
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%edi)
-	popl	%ebp
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebp)
-
-	ret
-
-	cfi_restore_state
-
-27:	call	__pthread_mutex_cond_lock_adjust
-	xorl	%eax, %eax
-	jmp	26b
-
-	cfi_adjust_cfa_offset(-FRAME_SIZE);
-	/* Initial locking failed.  */
-1:
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-	jmp	2b
-
-	/* The initial unlocking of the mutex failed.  */
-16:
-	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	jne	18b
-
-	movl	%eax, %esi
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-
-	movl	%esi, %eax
-	jmp	18b
-
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-
-	/* Unlock in loop requires wakeup.  */
-3:
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-	jmp	4b
-
-	/* Locking in loop failed.  */
-5:
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-	jmp	6b
-
-	/* Unlock after loop requires wakeup.  */
-10:
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-	jmp	11b
-
-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
-	cfi_adjust_cfa_offset(-FRAME_SIZE)
-.Lreltmo:
-	/* Get internal lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-# if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-# else
-	cmpxchgl %edx, cond_lock(%ebx)
-# endif
-	jnz	101f
-
-	/* Store the reference to the mutex.  If there is already a
-	   different value in there this is a bad user bug.  */
-102:	cmpl	$-1, dep_mutex(%ebx)
-	movl	24(%esp), %eax
-	je	117f
-	movl	%eax, dep_mutex(%ebx)
-
-	/* Unlock the mutex.  */
-117:	xorl	%edx, %edx
-	call	__pthread_mutex_unlock_usercnt
-
-	testl	%eax, %eax
-	jne	16b
-
-	addl	$1, total_seq(%ebx)
-	adcl	$0, total_seq+4(%ebx)
-	addl	$1, cond_futex(%ebx)
-	addl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-	subl	$FRAME_SIZE, %esp
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-
-	/* Get and store current wakeup_seq value.  */
-	movl	wakeup_seq(%ebx), %edi
-	movl	wakeup_seq+4(%ebx), %edx
-	movl	broadcast_seq(%ebx), %eax
-	movl	%edi, 4(%esp)
-	movl	%edx, 8(%esp)
-	movl	%eax, 12(%esp)
-
-	/* Reset the pi-requeued flag.  */
-	movl	$0, 16(%esp)
-
-	/* Get the current time.  */
-108:	movl	%ebx, %edx
-# ifdef __NR_clock_gettime
-	/* Get the clock number.  */
-	movl	cond_nwaiters(%ebx), %ebx
-	andl	$((1 << nwaiters_shift) - 1), %ebx
-	/* Only clocks 0 and 1 are allowed so far.  Both are handled in the
-	   kernel.  */
-	leal	24(%esp), %ecx
-	movl	$__NR_clock_gettime, %eax
-	ENTER_KERNEL
-	movl	%edx, %ebx
-
-	/* Compute relative timeout.  */
-	movl	(%ebp), %ecx
-	movl	4(%ebp), %edx
-	subl	24(%esp), %ecx
-	subl	28(%esp), %edx
-# else
-	/* Get the current time.  */
-	leal	24(%esp), %ebx
-	xorl	%ecx, %ecx
-	movl	$__NR_gettimeofday, %eax
-	ENTER_KERNEL
-	movl	%edx, %ebx
-
-	/* Compute relative timeout.  */
-	movl	28(%esp), %eax
-	movl	$1000, %edx
-	mul	%edx		/* Milli seconds to nano seconds.  */
-	movl	(%ebp), %ecx
-	movl	4(%ebp), %edx
-	subl	24(%esp), %ecx
-	subl	%eax, %edx
-# endif
-	jns	112f
-	addl	$1000000000, %edx
-	subl	$1, %ecx
-112:	testl	%ecx, %ecx
-	movl	$-ETIMEDOUT, %esi
-	js	106f
-
-	/* Store relative timeout.  */
-121:	movl	%ecx, 24(%esp)
-	movl	%edx, 28(%esp)
-
-	movl	cond_futex(%ebx), %edi
-	movl	%edi, 20(%esp)
-
-	/* Unlock.  */
-	LOCK
-# if cond_lock == 0
-	subl	$1, (%ebx)
-# else
-	subl	$1, cond_lock(%ebx)
-# endif
-	jne	103f
-
-.LcleanupSTART2:
-104:	call	__pthread_enable_asynccancel
-	movl	%eax, (%esp)
-
-	leal	24(%esp), %esi
-# if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-# endif
-	cmpl	$-1, dep_mutex(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-# ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-# else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-# endif
-# if FUTEX_WAIT != 0
-	addl	$FUTEX_WAIT, %ecx
-# endif
-	movl	20(%esp), %edx
-	addl	$cond_futex, %ebx
-.Ladd_cond_futex2:
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	subl	$cond_futex, %ebx
-.Lsub_cond_futex2:
-	movl	%eax, %esi
-
-141:	movl	(%esp), %eax
-	call	__pthread_disable_asynccancel
-.LcleanupEND2:
-
-
-	/* Lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-# if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-# else
-	cmpxchgl %edx, cond_lock(%ebx)
-# endif
-	jnz	105f
-
-106:	movl	broadcast_seq(%ebx), %eax
-	cmpl	12(%esp), %eax
-	jne	23b
-
-	movl	woken_seq(%ebx), %eax
-	movl	woken_seq+4(%ebx), %ecx
-
-	movl	wakeup_seq(%ebx), %edi
-	movl	wakeup_seq+4(%ebx), %edx
-
-	cmpl	8(%esp), %edx
-	jne	107f
-	cmpl	4(%esp), %edi
-	je	115f
-
-107:	cmpl	%ecx, %edx
-	jne	9b
-	cmp	%eax, %edi
-	jne	9b
-
-115:	cmpl	$-ETIMEDOUT, %esi
-	je	28b
-
-	jmp	8b
-
-	cfi_adjust_cfa_offset(-FRAME_SIZE)
-	/* Initial locking failed.  */
-101:
-# if cond_lock == 0
-	movl	%ebx, %edx
-# else
-	leal	cond_lock(%ebx), %edx
-# endif
-# if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-# endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-# if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-# endif
-	call	__lll_lock_wait
-	jmp	102b
-
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-
-	/* Unlock in loop requires wakeup.  */
-103:
-# if cond_lock == 0
-	movl	%ebx, %eax
-# else
-	leal	cond_lock(%ebx), %eax
-# endif
-# if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-# endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-# if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-# endif
-	call	__lll_unlock_wake
-	jmp	104b
-
-	/* Locking in loop failed.  */
-105:
-# if cond_lock == 0
-	movl	%ebx, %edx
-# else
-	leal	cond_lock(%ebx), %edx
-# endif
-# if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-# endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-# if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-# endif
-	call	__lll_lock_wait
-	jmp	106b
-#endif
-
-	.size	__pthread_cond_timedwait, .-__pthread_cond_timedwait
-versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
-		  GLIBC_2_3_2)
-
-
-	.type	__condvar_tw_cleanup2, @function
-__condvar_tw_cleanup2:
-	subl	$cond_futex, %ebx
-	.size	__condvar_tw_cleanup2, .-__condvar_tw_cleanup2
-	.type	__condvar_tw_cleanup, @function
-__condvar_tw_cleanup:
-	movl	%eax, %esi
-
-	/* Get internal lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jz	1f
-
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-
-1:	movl	broadcast_seq(%ebx), %eax
-	cmpl	12(%esp), %eax
-	jne	3f
-
-	/* We increment the wakeup_seq counter only if it is lower than
-	   total_seq.  If this is not the case the thread was woken and
-	   then canceled.  In this case we ignore the signal.  */
-	movl	total_seq(%ebx), %eax
-	movl	total_seq+4(%ebx), %edi
-	cmpl	wakeup_seq+4(%ebx), %edi
-	jb	6f
-	ja	7f
-	cmpl	wakeup_seq(%ebx), %eax
-	jbe	7f
-
-6:	addl	$1, wakeup_seq(%ebx)
-	adcl	$0, wakeup_seq+4(%ebx)
-	addl	$1, cond_futex(%ebx)
-
-7:	addl	$1, woken_seq(%ebx)
-	adcl	$0, woken_seq+4(%ebx)
-
-3:	subl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	xorl	%edi, %edi
-	movl	total_seq(%ebx), %eax
-	andl	total_seq+4(%ebx), %eax
-	cmpl	$0xffffffff, %eax
-	jne	4f
-	movl	cond_nwaiters(%ebx), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	4f
-
-	addl	$cond_nwaiters, %ebx
-	movl	$SYS_futex, %eax
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_nwaiters(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$1, %edx
-	ENTER_KERNEL
-	subl	$cond_nwaiters, %ebx
-	movl	$1, %edi
-
-4:	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	je	2f
-
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-
-	/* Wake up all waiters to make sure no signal gets lost.  */
-2:	testl	%edi, %edi
-	jnz	5f
-	addl	$cond_futex, %ebx
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_futex(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$SYS_futex, %eax
-	movl	$0x7fffffff, %edx
-	ENTER_KERNEL
-
-	/* Lock the mutex only if we don't own it already.  This only happens
-	   in case of PI mutexes, if we got cancelled after a successful
-	   return of the futex syscall and before disabling async
-	   cancellation.  */
-5:	movl	24+FRAME_SIZE(%esp), %eax
-	movl	MUTEX_KIND(%eax), %ebx
-	andl	$(ROBUST_BIT|PI_BIT), %ebx
-	cmpl	$PI_BIT, %ebx
-	jne	8f
-
-	movl	(%eax), %ebx
-	andl	$TID_MASK, %ebx
-	cmpl	%ebx, %gs:TID
-	jne	8f
-	/* We managed to get the lock.  Fix it up before returning.  */
-	call	__pthread_mutex_cond_lock_adjust
-	jmp	9f
-
-8:	call	__pthread_mutex_cond_lock
-
-9:	movl	%esi, (%esp)
-.LcallUR:
-	call	_Unwind_Resume
-	hlt
-.LENDCODE:
-	cfi_endproc
-	.size	__condvar_tw_cleanup, .-__condvar_tw_cleanup
-
-
-	.section .gcc_except_table,"a",@progbits
-.LexceptSTART:
-	.byte	DW_EH_PE_omit			# @LPStart format (omit)
-	.byte	DW_EH_PE_omit			# @TType format (omit)
-	.byte	DW_EH_PE_sdata4			# call-site format
-						# DW_EH_PE_sdata4
-	.uleb128 .Lcstend-.Lcstbegin
-.Lcstbegin:
-	.long	.LcleanupSTART-.LSTARTCODE
-	.long	.Ladd_cond_futex_pi-.LcleanupSTART
-	.long	__condvar_tw_cleanup-.LSTARTCODE
-	.uleb128  0
-	.long	.Ladd_cond_futex_pi-.LSTARTCODE
-	.long	.Lsub_cond_futex_pi-.Ladd_cond_futex_pi
-	.long	__condvar_tw_cleanup2-.LSTARTCODE
-	.uleb128  0
-	.long	.Lsub_cond_futex_pi-.LSTARTCODE
-	.long	.Ladd_cond_futex-.Lsub_cond_futex_pi
-	.long	__condvar_tw_cleanup-.LSTARTCODE
-	.uleb128  0
-	.long	.Ladd_cond_futex-.LSTARTCODE
-	.long	.Lsub_cond_futex-.Ladd_cond_futex
-	.long	__condvar_tw_cleanup2-.LSTARTCODE
-	.uleb128  0
-	.long	.Lsub_cond_futex-.LSTARTCODE
-	.long	.LcleanupEND-.Lsub_cond_futex
-	.long	__condvar_tw_cleanup-.LSTARTCODE
-	.uleb128  0
-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
-	.long	.LcleanupSTART2-.LSTARTCODE
-	.long	.Ladd_cond_futex2-.LcleanupSTART2
-	.long	__condvar_tw_cleanup-.LSTARTCODE
-	.uleb128  0
-	.long	.Ladd_cond_futex2-.LSTARTCODE
-	.long	.Lsub_cond_futex2-.Ladd_cond_futex2
-	.long	__condvar_tw_cleanup2-.LSTARTCODE
-	.uleb128  0
-	.long	.Lsub_cond_futex2-.LSTARTCODE
-	.long	.LcleanupEND2-.Lsub_cond_futex2
-	.long	__condvar_tw_cleanup-.LSTARTCODE
-	.uleb128  0
-#endif
-	.long	.LcallUR-.LSTARTCODE
-	.long	.LENDCODE-.LcallUR
-	.long	0
-	.uleb128  0
-.Lcstend:
-
-
-#ifdef SHARED
-	.hidden DW.ref.__gcc_personality_v0
-	.weak	DW.ref.__gcc_personality_v0
-	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
-	.align	4
-	.type	DW.ref.__gcc_personality_v0, @object
-	.size	DW.ref.__gcc_personality_v0, 4
-DW.ref.__gcc_personality_v0:
-	.long   __gcc_personality_v0
-#endif
diff --git a/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
deleted file mode 100644
index ec3538f..0000000
--- a/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+++ /dev/null
@@ -1,641 +0,0 @@
-/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-#include <lowlevellock.h>
-#include <lowlevelcond.h>
-#include <tcb-offsets.h>
-#include <pthread-errnos.h>
-#include <pthread-pi-defines.h>
-#include <kernel-features.h>
-#include <stap-probe.h>
-
-
-	.text
-
-/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
-	.globl	__pthread_cond_wait
-	.type	__pthread_cond_wait, @function
-	.align	16
-__pthread_cond_wait:
-.LSTARTCODE:
-	cfi_startproc
-#ifdef SHARED
-	cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
-			DW.ref.__gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
-#else
-	cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
-#endif
-
-	pushl	%ebp
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebp, 0)
-	pushl	%edi
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%edi, 0)
-	pushl	%esi
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%esi, 0)
-	pushl	%ebx
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebx, 0)
-
-	xorl	%esi, %esi
-	movl	20(%esp), %ebx
-
-	LIBC_PROBE (cond_wait, 2, 24(%esp), %ebx)
-
-	/* Get internal lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jnz	1f
-
-	/* Store the reference to the mutex.  If there is already a
-	   different value in there this is a bad user bug.  */
-2:	cmpl	$-1, dep_mutex(%ebx)
-	movl	24(%esp), %eax
-	je	15f
-	movl	%eax, dep_mutex(%ebx)
-
-	/* Unlock the mutex.  */
-15:	xorl	%edx, %edx
-	call	__pthread_mutex_unlock_usercnt
-
-	testl	%eax, %eax
-	jne	12f
-
-	addl	$1, total_seq(%ebx)
-	adcl	$0, total_seq+4(%ebx)
-	addl	$1, cond_futex(%ebx)
-	addl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-#define FRAME_SIZE 20
-	subl	$FRAME_SIZE, %esp
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-	cfi_remember_state
-
-	/* Get and store current wakeup_seq value.  */
-	movl	wakeup_seq(%ebx), %edi
-	movl	wakeup_seq+4(%ebx), %edx
-	movl	broadcast_seq(%ebx), %eax
-	movl	%edi, 4(%esp)
-	movl	%edx, 8(%esp)
-	movl	%eax, 12(%esp)
-
-	/* Reset the pi-requeued flag.  */
-8:	movl	$0, 16(%esp)
-	movl	cond_futex(%ebx), %ebp
-
-	/* Unlock.  */
-	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	jne	3f
-
-.LcleanupSTART:
-4:	call	__pthread_enable_asynccancel
-	movl	%eax, (%esp)
-
-	xorl	%ecx, %ecx
-	cmpl	$-1, dep_mutex(%ebx)
-	sete	%cl
-	je	18f
-
-	movl	dep_mutex(%ebx), %edi
-	/* Requeue to a non-robust PI mutex if the PI bit is set and
-	   the robust bit is not set.  */
-	movl	MUTEX_KIND(%edi), %eax
-	andl	$(ROBUST_BIT|PI_BIT), %eax
-	cmpl	$PI_BIT, %eax
-	jne	18f
-
-	movl	$(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
-	movl	%ebp, %edx
-	xorl	%esi, %esi
-	addl	$cond_futex, %ebx
-.Ladd_cond_futex_pi:
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	subl	$cond_futex, %ebx
-.Lsub_cond_futex_pi:
-	/* Set the pi-requeued flag only if the kernel has returned 0. The
-	   kernel does not hold the mutex on error.  */
-	cmpl	$0, %eax
-	sete	16(%esp)
-	je	19f
-
-	/* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns
-	   successfully, it has already locked the mutex for us and the
-	   pi_flag (16(%esp)) is set to denote that fact.  However, if another
-	   thread changed the futex value before we entered the wait, the
-	   syscall may return an EAGAIN and the mutex is not locked.  We go
-	   ahead with a success anyway since later we look at the pi_flag to
-	   decide if we got the mutex or not.  The sequence numbers then make
-	   sure that only one of the threads actually wake up.  We retry using
-	   normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal
-	   and PI futexes don't mix.
-
-	   Note that we don't check for EAGAIN specifically; we assume that the
-	   only other error the futex function could return is EAGAIN since
-	   anything else would mean an error in our function.  It is too
-	   expensive to do that check for every call (which is 	quite common in
-	   case of a large number of threads), so it has been skipped.  */
-	cmpl	$-ENOSYS, %eax
-	jne	19f
-	xorl	%ecx, %ecx
-
-18:	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-#if FUTEX_WAIT != 0
-	addl	$FUTEX_WAIT, %ecx
-#endif
-	movl	%ebp, %edx
-	addl	$cond_futex, %ebx
-.Ladd_cond_futex:
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	subl	$cond_futex, %ebx
-.Lsub_cond_futex:
-
-19:	movl	(%esp), %eax
-	call	__pthread_disable_asynccancel
-.LcleanupEND:
-
-	/* Lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jnz	5f
-
-6:	movl	broadcast_seq(%ebx), %eax
-	cmpl	12(%esp), %eax
-	jne	16f
-
-	movl	woken_seq(%ebx), %eax
-	movl	woken_seq+4(%ebx), %ecx
-
-	movl	wakeup_seq(%ebx), %edi
-	movl	wakeup_seq+4(%ebx), %edx
-
-	cmpl	8(%esp), %edx
-	jne	7f
-	cmpl	4(%esp), %edi
-	je	22f
-
-7:	cmpl	%ecx, %edx
-	jne	9f
-	cmp	%eax, %edi
-	je	22f
-
-9:	addl	$1, woken_seq(%ebx)
-	adcl	$0, woken_seq+4(%ebx)
-
-	/* Unlock */
-16:	subl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	movl	total_seq(%ebx), %eax
-	andl	total_seq+4(%ebx), %eax
-	cmpl	$0xffffffff, %eax
-	jne	17f
-	movl	cond_nwaiters(%ebx), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	17f
-
-	addl	$cond_nwaiters, %ebx
-	movl	$SYS_futex, %eax
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_nwaiters(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$1, %edx
-	ENTER_KERNEL
-	subl	$cond_nwaiters, %ebx
-
-17:	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	jne	10f
-
-	/* With requeue_pi, the mutex lock is held in the kernel.  */
-11:	movl	24+FRAME_SIZE(%esp), %eax
-	movl	16(%esp), %ecx
-	testl	%ecx, %ecx
-	jnz	21f
-
-	call	__pthread_mutex_cond_lock
-20:	addl	$FRAME_SIZE, %esp
-	cfi_adjust_cfa_offset(-FRAME_SIZE);
-
-14:	popl	%ebx
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebx)
-	popl	%esi
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%esi)
-	popl	%edi
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%edi)
-	popl	%ebp
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebp)
-
-	/* We return the result of the mutex_lock operation.  */
-	ret
-
-	cfi_restore_state
-
-21:	call	__pthread_mutex_cond_lock_adjust
-	xorl	%eax, %eax
-	jmp	20b
-
-	cfi_adjust_cfa_offset(-FRAME_SIZE);
-
-	/* We need to go back to futex_wait.  If we're using requeue_pi, then
-	   release the mutex we had acquired and go back.  */
-22:	movl	16(%esp), %edx
-	test	%edx, %edx
-	jz	8b
-
-	/* Adjust the mutex values first and then unlock it.  The unlock
-	   should always succeed or else the kernel did not lock the mutex
-	   correctly.  */
-	movl	dep_mutex(%ebx), %eax
-	call    __pthread_mutex_cond_lock_adjust
-	xorl	%edx, %edx
-	call	__pthread_mutex_unlock_usercnt
-	jmp	8b
-
-	/* Initial locking failed.  */
-1:
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-	jmp	2b
-
-	/* The initial unlocking of the mutex failed.  */
-12:
-	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	jne	14b
-
-	movl	%eax, %esi
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-
-	movl	%esi, %eax
-	jmp	14b
-
-	cfi_adjust_cfa_offset(FRAME_SIZE)
-
-	/* Unlock in loop requires wakeup.  */
-3:
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-	jmp	4b
-
-	/* Locking in loop failed.  */
-5:
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-	jmp	6b
-
-	/* Unlock after loop requires wakeup.  */
-10:
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-	jmp	11b
-
-	.size	__pthread_cond_wait, .-__pthread_cond_wait
-versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
-		  GLIBC_2_3_2)
-
-
-	.type	__condvar_w_cleanup2, @function
-__condvar_w_cleanup2:
-	subl	$cond_futex, %ebx
-	.size	__condvar_w_cleanup2, .-__condvar_w_cleanup2
-.LSbl4:
-	.type	__condvar_w_cleanup, @function
-__condvar_w_cleanup:
-	movl	%eax, %esi
-
-	/* Get internal lock.  */
-	movl	$1, %edx
-	xorl	%eax, %eax
-	LOCK
-#if cond_lock == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, cond_lock(%ebx)
-#endif
-	jz	1f
-
-#if cond_lock == 0
-	movl	%ebx, %edx
-#else
-	leal	cond_lock(%ebx), %edx
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_lock_wait
-
-1:	movl	broadcast_seq(%ebx), %eax
-	cmpl	12(%esp), %eax
-	jne	3f
-
-	/* We increment the wakeup_seq counter only if it is lower than
-	   total_seq.  If this is not the case the thread was woken and
-	   then canceled.  In this case we ignore the signal.  */
-	movl	total_seq(%ebx), %eax
-	movl	total_seq+4(%ebx), %edi
-	cmpl	wakeup_seq+4(%ebx), %edi
-	jb	6f
-	ja	7f
-	cmpl	wakeup_seq(%ebx), %eax
-	jbe	7f
-
-6:	addl	$1, wakeup_seq(%ebx)
-	adcl	$0, wakeup_seq+4(%ebx)
-	addl	$1, cond_futex(%ebx)
-
-7:	addl	$1, woken_seq(%ebx)
-	adcl	$0, woken_seq+4(%ebx)
-
-3:	subl	$(1 << nwaiters_shift), cond_nwaiters(%ebx)
-
-	/* Wake up a thread which wants to destroy the condvar object.  */
-	xorl	%edi, %edi
-	movl	total_seq(%ebx), %eax
-	andl	total_seq+4(%ebx), %eax
-	cmpl	$0xffffffff, %eax
-	jne	4f
-	movl	cond_nwaiters(%ebx), %eax
-	andl	$~((1 << nwaiters_shift) - 1), %eax
-	jne	4f
-
-	addl	$cond_nwaiters, %ebx
-	movl	$SYS_futex, %eax
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_nwaiters(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$1, %edx
-	ENTER_KERNEL
-	subl	$cond_nwaiters, %ebx
-	movl	$1, %edi
-
-4:	LOCK
-#if cond_lock == 0
-	subl	$1, (%ebx)
-#else
-	subl	$1, cond_lock(%ebx)
-#endif
-	je	2f
-
-#if cond_lock == 0
-	movl	%ebx, %eax
-#else
-	leal	cond_lock(%ebx), %eax
-#endif
-#if (LLL_SHARED-LLL_PRIVATE) > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex(%ebx)
-	setne	%cl
-	subl	$1, %ecx
-	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
-#if LLL_PRIVATE != 0
-	addl	$LLL_PRIVATE, %ecx
-#endif
-	call	__lll_unlock_wake
-
-	/* Wake up all waiters to make sure no signal gets lost.  */
-2:	testl	%edi, %edi
-	jnz	5f
-	addl	$cond_futex, %ebx
-#if FUTEX_PRIVATE_FLAG > 255
-	xorl	%ecx, %ecx
-#endif
-	cmpl	$-1, dep_mutex-cond_futex(%ebx)
-	sete	%cl
-	subl	$1, %ecx
-#ifdef __ASSUME_PRIVATE_FUTEX
-	andl	$FUTEX_PRIVATE_FLAG, %ecx
-#else
-	andl	%gs:PRIVATE_FUTEX, %ecx
-#endif
-	addl	$FUTEX_WAKE, %ecx
-	movl	$SYS_futex, %eax
-	movl	$0x7fffffff, %edx
-	ENTER_KERNEL
-
-	/* Lock the mutex only if we don't own it already.  This only happens
-	   in case of PI mutexes, if we got cancelled after a successful
-	   return of the futex syscall and before disabling async
-	   cancellation.  */
-5:	movl	24+FRAME_SIZE(%esp), %eax
-	movl	MUTEX_KIND(%eax), %ebx
-	andl	$(ROBUST_BIT|PI_BIT), %ebx
-	cmpl	$PI_BIT, %ebx
-	jne	8f
-
-	movl	(%eax), %ebx
-	andl	$TID_MASK, %ebx
-	cmpl	%ebx, %gs:TID
-	jne	8f
-	/* We managed to get the lock.  Fix it up before returning.  */
-	call	__pthread_mutex_cond_lock_adjust
-	jmp	9f
-
-8:	call	__pthread_mutex_cond_lock
-
-9:	movl	%esi, (%esp)
-.LcallUR:
-	call	_Unwind_Resume
-	hlt
-.LENDCODE:
-	cfi_endproc
-	.size	__condvar_w_cleanup, .-__condvar_w_cleanup
-
-
-	.section .gcc_except_table,"a",@progbits
-.LexceptSTART:
-	.byte	DW_EH_PE_omit			# @LPStart format (omit)
-	.byte	DW_EH_PE_omit			# @TType format (omit)
-	.byte	DW_EH_PE_sdata4			# call-site format
-						# DW_EH_PE_sdata4
-	.uleb128 .Lcstend-.Lcstbegin
-.Lcstbegin:
-	.long	.LcleanupSTART-.LSTARTCODE
-	.long	.Ladd_cond_futex_pi-.LcleanupSTART
-	.long	__condvar_w_cleanup-.LSTARTCODE
-	.uleb128  0
-	.long	.Ladd_cond_futex_pi-.LSTARTCODE
-	.long	.Lsub_cond_futex_pi-.Ladd_cond_futex_pi
-	.long	__condvar_w_cleanup2-.LSTARTCODE
-	.uleb128  0
-	.long	.Lsub_cond_futex_pi-.LSTARTCODE
-	.long	.Ladd_cond_futex-.Lsub_cond_futex_pi
-	.long	__condvar_w_cleanup-.LSTARTCODE
-	.uleb128  0
-	.long	.Ladd_cond_futex-.LSTARTCODE
-	.long	.Lsub_cond_futex-.Ladd_cond_futex
-	.long	__condvar_w_cleanup2-.LSTARTCODE
-	.uleb128  0
-	.long	.Lsub_cond_futex-.LSTARTCODE
-	.long	.LcleanupEND-.Lsub_cond_futex
-	.long	__condvar_w_cleanup-.LSTARTCODE
-	.uleb128  0
-	.long	.LcallUR-.LSTARTCODE
-	.long	.LENDCODE-.LcallUR
-	.long	0
-	.uleb128  0
-.Lcstend:
-
-#ifdef SHARED
-	.hidden DW.ref.__gcc_personality_v0
-	.weak   DW.ref.__gcc_personality_v0
-	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
-	.align 4
-	.type   DW.ref.__gcc_personality_v0, @object
-	.size   DW.ref.__gcc_personality_v0, 4
-DW.ref.__gcc_personality_v0:
-	.long   __gcc_personality_v0
-#endif
diff --git a/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S
deleted file mode 100644
index d96af08..0000000
--- a/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2003-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include "../i486/pthread_cond_timedwait.S"
diff --git a/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S b/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S
deleted file mode 100644
index 9696972..0000000
--- a/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2003-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include "../i486/pthread_cond_wait.S"
diff --git a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S b/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S
deleted file mode 100644
index 0e8d7ff..0000000
--- a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Copyright (C) 2003-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#define HAVE_CMOV 1
-#include "../i486/pthread_cond_timedwait.S"
diff --git a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S b/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S
deleted file mode 100644
index 9696972..0000000
--- a/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2003-2015 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include "../i486/pthread_cond_wait.S"

-----------------------------------------------------------------------


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]