public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Fix semaphore destruction (BZ #12674)
@ 2014-12-05 18:37 Torvald Riegel
  2014-12-05 18:53 ` [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6 Torvald Riegel
                   ` (3 more replies)
  0 siblings, 4 replies; 19+ messages in thread
From: Torvald Riegel @ 2014-12-05 18:37 UTC (permalink / raw)
  To: GLIBC Devel

This patch set fixes
https://sourceware.org/bugzilla/show_bug.cgi?id=12674 by either using
64b atomic operations (where available), or by using two separate fields
when only 32b atomic operations are available.  In the latter case, we
keep a conservative estimate of whether there are any waiting threads in
one bit of the field that counts the number of available tokens, thus
allowing sem_post to atomically both add a token and determine whether
it needs to call futex_wake.

The first two patches are changes to the tests, the last big patch is
where the actual fix resides.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6.
  2014-12-05 18:37 [PATCH 0/3] Fix semaphore destruction (BZ #12674) Torvald Riegel
@ 2014-12-05 18:53 ` Torvald Riegel
  2014-12-06 13:50   ` Ondřej Bílka
  2014-12-05 19:03 ` [PATCH 2/3] Fix nptl/tst-sem4: always start with a fresh semaphore Torvald Riegel
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 19+ messages in thread
From: Torvald Riegel @ 2014-12-05 18:53 UTC (permalink / raw)
  To: GLIBC Devel

[-- Attachment #1: Type: text/plain, Size: 523 bytes --]

This makes the nptl/tst-sem6 interrupt sem_wait reliably by letting the
signal handler call sem_post.  This ensures that if the signal handler
should happen to run before sem_wait actually starts, sem_wait will find
an available token and return.  This is necessary if a program does not
want to rely on timing nor on forward progress / fairness guarantees of
the OS scheduler.

It's needed so that Patch 3/3 can do the right thing in face of a
FUTEX_WAIT that may return EINTR on either signal interruption or
spuriously.

[-- Attachment #2: sem-test1.patch --]
[-- Type: text/x-patch, Size: 1389 bytes --]

commit a819010e2a625eafc66fb1bf1301fcba5c05e5e6
Author: Torvald Riegel <triegel@redhat.com>
Date:   Thu Dec 4 20:43:22 2014 +0100

    Use reliable sem_wait signal interruption in tst-sem6

diff --git a/nptl/tst-sem6.c b/nptl/tst-sem6.c
index 2d9f1ab..3efd4eb 100644
--- a/nptl/tst-sem6.c
+++ b/nptl/tst-sem6.c
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <unistd.h>
 
+sem_t s;
 
 static void
 handler (int sig)
@@ -34,6 +35,10 @@ handler (int sig)
 
   sigaction (SIGALRM, &sa, NULL);
 
+  /* Correctly interrupting a sem_wait without relying on timing assumptions
+     requires using sem_post in the handler.  */
+  sem_post (&s);
+
   /* Rearm the timer.  */
   alarm (1);
 }
@@ -42,7 +47,6 @@ handler (int sig)
 static int
 do_test (void)
 {
-  sem_t s;
   struct sigaction sa;
 
   sa.sa_handler = handler;
@@ -61,14 +65,12 @@ do_test (void)
   alarm (1);
 
   int res = sem_wait (&s);
-  if (res == 0)
-    {
-      puts ("wait succeeded");
-      return 1;
-    }
-  if (res != -1 || errno != EINTR)
+  /* We accept all allowed behavior: Implementations that return EINTR and
+     those that rely on correct interruption through signals to use sem_post
+     in the signal handler.  */
+  if (res != 0 && !(res == -1 && errno == EINTR))
     {
-      puts ("wait didn't fail with EINTR");
+      puts ("wait neiter succeeded nor failed with EINTR");
       return 1;
     }
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 2/3] Fix nptl/tst-sem4: always start with a fresh semaphore.
  2014-12-05 18:37 [PATCH 0/3] Fix semaphore destruction (BZ #12674) Torvald Riegel
  2014-12-05 18:53 ` [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6 Torvald Riegel
@ 2014-12-05 19:03 ` Torvald Riegel
  2014-12-06 13:55   ` Ondřej Bílka
  2014-12-05 19:24 ` [PATCH 3/3] Update to new generic semaphore algorithm Torvald Riegel
  2014-12-05 20:30 ` [PATCH 0/3] Fix semaphore destruction (BZ #12674) Rich Felker
  3 siblings, 1 reply; 19+ messages in thread
From: Torvald Riegel @ 2014-12-05 19:03 UTC (permalink / raw)
  To: GLIBC Devel

[-- Attachment #1: Type: text/plain, Size: 98 bytes --]

This just makes sure that if this test fails, new runs of the test will
start from a fresh state.

[-- Attachment #2: sem-test2.patch --]
[-- Type: text/x-patch, Size: 1001 bytes --]

commit 1ba62510cc2f1459147ec31dda28d45c2ee96abf
Author: Torvald Riegel <triegel@redhat.com>
Date:   Tue Jul 29 21:44:58 2014 +0200

    Fix nptl/tst-sem4: always start with a fresh semaphore.

diff --git a/nptl/tst-sem4.c b/nptl/tst-sem4.c
index 72ed97d..5e17d03 100644
--- a/nptl/tst-sem4.c
+++ b/nptl/tst-sem4.c
@@ -39,6 +39,12 @@ do_test (void)
   pid_t pid;
   int val;
 
+  /* Start with a clean slate and register a clean-up action.  No need to
+     act if sem_unlink fails because well catch the same problem during the
+     sem_open below.  */
+  sem_unlink ("/glibc-tst-sem4");
+  on_exit (remove_sem, (void *) "/glibc-tst-sem4");
+
   s = sem_open ("/glibc-tst-sem4", O_CREAT, 0600, 1);
   if (s == SEM_FAILED)
     {
@@ -59,8 +65,6 @@ do_test (void)
       return 1;
     }
 
-  on_exit (remove_sem, (void *) "/glibc-tst-sem4");
-
   /* We have the semaphore object.  Now try again with O_EXCL, this
      should fail.  */
   s2 = sem_open ("/glibc-tst-sem4", O_CREAT | O_EXCL, 0600, 1);

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] Update to new generic semaphore algorithm.
  2014-12-05 18:37 [PATCH 0/3] Fix semaphore destruction (BZ #12674) Torvald Riegel
  2014-12-05 18:53 ` [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6 Torvald Riegel
  2014-12-05 19:03 ` [PATCH 2/3] Fix nptl/tst-sem4: always start with a fresh semaphore Torvald Riegel
@ 2014-12-05 19:24 ` Torvald Riegel
  2014-12-15 21:59   ` Torvald Riegel
  2018-05-08 14:00   ` Andreas Schwab
  2014-12-05 20:30 ` [PATCH 0/3] Fix semaphore destruction (BZ #12674) Rich Felker
  3 siblings, 2 replies; 19+ messages in thread
From: Torvald Riegel @ 2014-12-05 19:24 UTC (permalink / raw)
  To: GLIBC Devel

[-- Attachment #1: Type: text/plain, Size: 5361 bytes --]

This changes the generic C implementation of semaphores to use different
algorithms.  The core issue of the old implementation was that it kept
two fields for both the value of the semaphore (ie, how many tokens it
has that can be acquired by sem_wait calls) and the number of threads
waiting to acquire a token using a futex_wait.  We want to track the
latter to be able to avoid calling futex_wake if there is actually no
waiter.  We can't put both of these counters into one 32b field because
of the number of threads and or tokens we need to support.

When users try to use sem_wait in the way discussed in
http://austingroupbugs.net/view.php?id=811 then one thread calls
sem_post, and another calls sem_wait *and* expects that once it has the
token (ie, sem_wait has returned), it can call sem_destroy.

Therefore, the implementation needs to ensure that sem_post makes no
access to the semaphore data structure after it has provided a token.
If we have 64b atomic operations, we can atomically increment the value
of the semaphore and load the field counting the number of waiters.
If we just have 32b operations, we need to do something more involved.
The key here is to track a conservative value for the number of waiters
in one bit of the value, and use that.  Because it's a conservative
value, it may be wrong and we may call futex_wake unnecessarily under
some conditions.  When we reset this bit (ie, speculate that there are
no other waiters), we can be wrong but can make this misspeculation
harmless if we wake as many waiters as there are tokens available.  We
do all these latter steps in sem_wait to still satisfy the requirement
for sem_post regarding not accessing the semaphore after providing a
token.
Detailed comments can be found in the patch itself; see nptl/sem_wait.c.

The semaphore data structure is adapted accordingly, as are other
related functions: sem_open, sem_init, sem_getvalue, sem_trywait,
sem_timedwait.
because sem_trywait and sem_timedwait are very small, it seemed best to
simply put them all into sem_wait.c

I removed nptl/DESIGN-sem.txt because it was outdated and the comments
in the code provide much more detail.

The changes to tst-sem11 and tst-sem13 are simple adaptions; they peek
inside the semaphore data structure.

The custom assembler implementations on x86, x86_64, and sh have been
removed.

alpha and powerpc had custom sem_post implementations, but all that
those were lacking compared to the generic version was a write barrier
in sem_post.  The new algorithm is correctly synchronized; for the old
version of sem_post, I have added a call to atomic_write_barrier
directly.  This allows us to remove the custom alpha and powerpc
variants.

sparc still has its own semaphore implementation.  I'd like to get
feedback from sparc maintainers regarding what should happen with it.

Note that this patch set is on top of the patch providing a new internal
futex API: https://sourceware.org/ml/libc-alpha/2014-12/msg00154.html

Tested on x86 and x86_64.  I have not tested the old versions
(__old_sem*) yet.



	[BZ #12674]
	* nptl/sem_wait.c(__new_sem_wait_fast): New function.  Implement
	new semaphore algorithms.
	(__new_sem_wait_slow): New function.
	(__sem_wait_32_finish): New function.
	(__sem_wait_cleanup): Adapt.
	(do_futex_wait_inner): Adapt.
	(do_futex_wait): Adapt.
	(__new_sem_wait): Adapt.
	(sem_timedwait): New function.
	(__new_sem_trywait): New function.
	(__old_sem_trywait): Moved here from nptl/sem_trywait.c.
	* nptl/sem_post.c (__new_sem_post): Adapt.
	(__old_sem_post): Add release fence.
	* nptl/sem_open.c (sem_open): Adapt.
	* nptl/sem_init.c (__new_sem_init): Adapt.
	* nptl/sem_getvalue.c (__new_sem_getvalue): Adapt.
	(__old_sem_getvalue): Add using previous code.
	* sysdeps/nptl/internaltypes.h: Adapt.
	* nptl/tst-sem13.c (do_test): Adapt.
	* nptl/tst-sem11.c (main): Adapt.
	* nptl/sem_timedwait.c: Remove.
	* nptl/sem_trywait.c: Remove.
	* nptl/DESIGN-sem.txt: Remove.
	* nptl/Makefile (libpthread-routines): Remove sem_trywait, sem_wait.
	(gen-as-const-headers): Remove structsem.sym.
	* nptl/structsem.sym: Remove.
	* sysdeps/unix/sysv/linux/alpha/sem_post.c: Remove.
	* sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Remove.
	* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Remove.
	* sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Remove.
	* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Remove.
	* sysdeps/unix/sysv/linux/i386/i586/sem_post.S: Remove.
	* sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S: Remove.
	* sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S: Remove.
	* sysdeps/unix/sysv/linux/i386/i586/sem_wait.S: Remove.
	* sysdeps/unix/sysv/linux/i386/i686/sem_post.S: Remove.
	* sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S: Remove.
	* sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S: Remove.
	* sysdeps/unix/sysv/linux/i386/i686/sem_wait.S: Remove.
	* sysdeps/unix/sysv/linux/powerpc/sem_post.c: Remove.
	* sysdeps/unix/sysv/linux/sh/sem_post.S: Remove.
	* sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Remove.
	* sysdeps/unix/sysv/linux/sh/sem_trywait.S: Remove.
	* sysdeps/unix/sysv/linux/sh/sem_wait.S: Remove.
	* sysdeps/unix/sysv/linux/x86_64/sem_post.S: Remove.
	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Remove.
	* sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Remove.
	* sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Remove.

[-- Attachment #2: sem-new.patch --]
[-- Type: text/x-patch, Size: 99843 bytes --]

commit ccb4868ca6fabd1d44598e2c4856b9815c4f4594
Author: Torvald Riegel <triegel@redhat.com>
Date:   Tue Jul 29 21:44:31 2014 +0200

    Update to new generic semaphore algorithm.

diff --git a/nptl/DESIGN-sem.txt b/nptl/DESIGN-sem.txt
deleted file mode 100644
index 17eb0c1..0000000
--- a/nptl/DESIGN-sem.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-Semaphores pseudocode
-==============================
-
-       int sem_wait(sem_t * sem);
-       int sem_trywait(sem_t * sem);
-       int sem_post(sem_t * sem);
-       int sem_getvalue(sem_t * sem, int * sval);
-
-struct sem_t {
-
-   unsigned int count;
-         - current semaphore count, also used as a futex
-}
-
-sem_wait(sem_t *sem)
-{
-  for (;;) {
-
-    if (atomic_decrement_if_positive(sem->count))
-      break;
-
-    futex_wait(&sem->count, 0)
-  }
-}
-
-sem_post(sem_t *sem)
-{
-  n = atomic_increment(sem->count);
-  // Pass the new value of sem->count
-  futex_wake(&sem->count, n + 1);
-}
-
-sem_trywait(sem_t *sem)
-{
-  if (atomic_decrement_if_positive(sem->count)) {
-    return 0;
-  } else {
-    return EAGAIN;
-  }
-}
-
-sem_getvalue(sem_t *sem, int *sval)
-{
-  *sval = sem->count;
-  read_barrier();
-}
diff --git a/nptl/Makefile b/nptl/Makefile
index ac76596..f845f67 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -99,7 +99,7 @@ libpthread-routines = nptl-init vars events version \
 		      sem_init sem_destroy \
 		      sem_open sem_close sem_unlink \
 		      sem_getvalue \
-		      sem_wait sem_trywait sem_timedwait sem_post \
+		      sem_wait sem_post \
 		      cleanup cleanup_defer cleanup_compat \
 		      cleanup_defer_compat unwind \
 		      pt-longjmp pt-cleanup\
@@ -282,8 +282,7 @@ tests-nolibpthread = tst-unload
 gen-as-const-headers = pthread-errnos.sym \
 		       lowlevelcond.sym lowlevelrwlock.sym \
 		       lowlevelbarrier.sym unwindbuf.sym \
-		       lowlevelrobustlock.sym pthread-pi-defines.sym \
-		       structsem.sym
+		       lowlevelrobustlock.sym pthread-pi-defines.sym
 
 
 LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst
diff --git a/nptl/sem_getvalue.c b/nptl/sem_getvalue.c
index a4ab41f..a604852 100644
--- a/nptl/sem_getvalue.c
+++ b/nptl/sem_getvalue.c
@@ -19,23 +19,37 @@
 #include <semaphore.h>
 #include <shlib-compat.h>
 #include "semaphoreP.h"
+#include <atomic.h>
 
 
 int
-__new_sem_getvalue (sem, sval)
-     sem_t *sem;
-     int *sval;
+__new_sem_getvalue (sem_t *sem, int *sval)
 {
   struct new_sem *isem = (struct new_sem *) sem;
 
   /* XXX Check for valid SEM parameter.  */
-
-  *sval = isem->value;
+  /* FIXME This uses relaxed MO, even though POSIX specifies that this function
+     should be linearizable.  However, its debatable whether linearizability
+     is the right requirement.  We need to follow up with POSIX and, if
+     necessary, use a stronger MO here and elsewhere (e.g., potentially
+     release MO in all places where we consume a token).  */
+
+#if __HAVE_64B_ATOMICS
+  *sval = atomic_load_relaxed (&isem->data) & SEM_VALUE_MASK;
+#else
+  *sval = atomic_load_relaxed (&isem->value) >> SEM_VALUE_SHIFT;
+#endif
 
   return 0;
 }
 versioned_symbol (libpthread, __new_sem_getvalue, sem_getvalue, GLIBC_2_1);
 #if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
-strong_alias (__new_sem_getvalue, __old_sem_getvalue)
+int
+__old_sem_getvalue (sem_t *sem, int *sval)
+{
+  struct old_sem *isem = (struct old_sem *) sem;
+  *sval = isem->value;
+  return 0;
+}
 compat_symbol (libpthread, __old_sem_getvalue, sem_getvalue, GLIBC_2_0);
 #endif
diff --git a/nptl/sem_init.c b/nptl/sem_init.c
index 7af2775..99dcc4f 100644
--- a/nptl/sem_init.c
+++ b/nptl/sem_init.c
@@ -18,17 +18,14 @@
 
 #include <errno.h>
 #include <semaphore.h>
-#include <lowlevellock.h>
+#include <futex-internal.h>
 #include <shlib-compat.h>
 #include "semaphoreP.h"
 #include <kernel-features.h>
 
 
 int
-__new_sem_init (sem, pshared, value)
-     sem_t *sem;
-     int pshared;
-     unsigned int value;
+__new_sem_init (sem_t *sem, int pshared, unsigned int value)
 {
   /* Parameter sanity check.  */
   if (__glibc_unlikely (value > SEM_VALUE_MAX))
@@ -40,16 +37,15 @@ __new_sem_init (sem, pshared, value)
   /* Map to the internal type.  */
   struct new_sem *isem = (struct new_sem *) sem;
 
-  /* Use the values the user provided.  */
-  isem->value = value;
-#ifdef __ASSUME_PRIVATE_FUTEX
-  isem->private = pshared ? 0 : FUTEX_PRIVATE_FLAG;
+  /* Use the values the caller provided.  */
+#if __HAVE_64B_ATOMICS
+  isem->data = value;
 #else
-  isem->private = pshared ? 0 : THREAD_GETMEM (THREAD_SELF,
-					       header.private_futex);
+  isem->value = value << SEM_VALUE_SHIFT;
+  isem->nwaiters = 0;
 #endif
 
-  isem->nwaiters = 0;
+  isem->private = futex_private_if_supported (pshared);
 
   return 0;
 }
diff --git a/nptl/sem_open.c b/nptl/sem_open.c
index cf91859..11b7c0a 100644
--- a/nptl/sem_open.c
+++ b/nptl/sem_open.c
@@ -33,6 +33,7 @@
 #include <sys/statfs.h>
 #include <linux_fsinfo.h>
 #include "semaphoreP.h"
+#include <futex-internal.h>
 
 
 
@@ -309,9 +310,14 @@ sem_open (const char *name, int oflag, ...)
 	struct new_sem newsem;
       } sem;
 
-      sem.newsem.value = value;
-      sem.newsem.private = 0;
+#if __HAVE_64B_ATOMICS
+      sem.newsem.data = value;
+#else
+      sem.newsem.value = value << SEM_VALUE_SHIFT;
       sem.newsem.nwaiters = 0;
+#endif
+      /* This always is a shared semaphore.  */
+      sem.newsem.private = FUTEX_SHARED;
 
       /* Initialize the remaining bytes as well.  */
       memset ((char *) &sem.initsem + sizeof (struct new_sem), '\0',
diff --git a/nptl/sem_post.c b/nptl/sem_post.c
index 4906adf..0877774 100644
--- a/nptl/sem_post.c
+++ b/nptl/sem_post.c
@@ -21,39 +21,58 @@
 #include <errno.h>
 #include <sysdep.h>
 #include <lowlevellock.h>
+#include <futex-internal.h>
 #include <internaltypes.h>
 #include <semaphore.h>
 
 #include <shlib-compat.h>
 
+/* See sem_wait for an explanation of the algorithm.  */
 int
 __new_sem_post (sem_t *sem)
 {
   struct new_sem *isem = (struct new_sem *) sem;
+  int private = isem->private;
 
-  __typeof (isem->value) cur;
+#if __HAVE_64B_ATOMICS
+  /* Add a token to the semaphore.  We use release MO to make sure that a
+     thread acquiring this token synchronizes with us and other threads that
+     added tokens before (the release sequence includes atomic RMW operations
+     by other threads).  */
+  /* TODO Use atomic_fetch_add to make it scale better than a CAS loop?  */
+  unsigned long int d = atomic_load_relaxed (&isem->data);
   do
     {
-      cur = isem->value;
-      if (isem->value == SEM_VALUE_MAX)
+      if ((d & SEM_VALUE_MASK) == SEM_VALUE_MAX)
 	{
 	  __set_errno (EOVERFLOW);
 	  return -1;
 	}
     }
-  while (atomic_compare_and_exchange_bool_rel (&isem->value, cur + 1, cur));
+  while (!atomic_compare_exchange_weak_release (&isem->data, &d, d + 1));
 
-  atomic_full_barrier ();
-  if (isem->nwaiters > 0)
+  /* If there is any potentially blocked waiter, wake one of them.  */
+  if (d >> SEM_NWAITERS_SHIFT > 0)
+    futex_wake (((unsigned*)&isem->data) + SEM_VALUE_OFFSET, 1, private);
+#else
+  /* Add a token to the semaphore.  Similar to 64b version.  */
+  unsigned int v = atomic_load_relaxed (&isem->value);
+  do
     {
-      int err = lll_futex_wake (&isem->value, 1,
-				isem->private ^ FUTEX_PRIVATE_FLAG);
-      if (__builtin_expect (err, 0) < 0)
+      if ((v << SEM_VALUE_SHIFT) == SEM_VALUE_MAX)
 	{
-	  __set_errno (-err);
+	  __set_errno (EOVERFLOW);
 	  return -1;
 	}
     }
+  while (!atomic_compare_exchange_weak_release (&isem->value,
+      &v, v + (1 << SEM_VALUE_SHIFT)));
+
+  /* If there is any potentially blocked waiter, wake one of them.  */
+  if (v & SEM_NWAITERS_MASK != 0)
+    futex_wake (&isem->value, 1, private);
+#endif
+
   return 0;
 }
 versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1);
@@ -66,6 +85,9 @@ __old_sem_post (sem_t *sem)
 {
   int *futex = (int *) sem;
 
+  /* We must need to synchronize with consumers of this token, so the atomic
+     increment must have release MO semantics.  */
+  atomic_write_barrier ();
   (void) atomic_increment_val (futex);
   /* We always have to assume it is a shared semaphore.  */
   int err = lll_futex_wake (futex, 1, LLL_SHARED);
diff --git a/nptl/sem_timedwait.c b/nptl/sem_timedwait.c
deleted file mode 100644
index 5d4c830..0000000
--- a/nptl/sem_timedwait.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/* sem_timedwait -- wait on a semaphore.  Generic futex-using version.
-   Copyright (C) 2003-2014 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Paul Mackerras <paulus@au.ibm.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 <errno.h>
-#include <sysdep.h>
-#include <lowlevellock.h>
-#include <internaltypes.h>
-#include <semaphore.h>
-#include <sys/time.h>
-
-#include <pthreadP.h>
-#include <shlib-compat.h>
-
-
-extern void __sem_wait_cleanup (void *arg) attribute_hidden;
-
-/* This is in a seperate function in order to make sure gcc
-   puts the call site into an exception region, and thus the
-   cleanups get properly run.  */
-static int
-__attribute__ ((noinline))
-do_futex_timed_wait (struct new_sem *isem, struct timespec *rt)
-{
-  int err, oldtype = __pthread_enable_asynccancel ();
-
-  err = lll_futex_timed_wait (&isem->value, 0, rt,
-			      isem->private ^ FUTEX_PRIVATE_FLAG);
-
-  __pthread_disable_asynccancel (oldtype);
-  return err;
-}
-
-int
-sem_timedwait (sem_t *sem, const struct timespec *abstime)
-{
-  struct new_sem *isem = (struct new_sem *) sem;
-  int err;
-
-  if (atomic_decrement_if_positive (&isem->value) > 0)
-    return 0;
-
-  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  atomic_increment (&isem->nwaiters);
-
-  pthread_cleanup_push (__sem_wait_cleanup, isem);
-
-  while (1)
-    {
-      struct timeval tv;
-      struct timespec rt;
-      int sec, nsec;
-
-      /* Get the current time.  */
-      __gettimeofday (&tv, NULL);
-
-      /* Compute relative timeout.  */
-      sec = abstime->tv_sec - tv.tv_sec;
-      nsec = abstime->tv_nsec - tv.tv_usec * 1000;
-      if (nsec < 0)
-	{
-	  nsec += 1000000000;
-	  --sec;
-	}
-
-      /* Already timed out?  */
-      if (sec < 0)
-	{
-	  __set_errno (ETIMEDOUT);
-	  err = -1;
-	  break;
-	}
-
-      /* Do wait.  */
-      rt.tv_sec = sec;
-      rt.tv_nsec = nsec;
-      err = do_futex_timed_wait(isem, &rt);
-      if (err != 0 && err != -EWOULDBLOCK)
-	{
-	  __set_errno (-err);
-	  err = -1;
-	  break;
-	}
-
-      if (atomic_decrement_if_positive (&isem->value) > 0)
-	{
-	  err = 0;
-	  break;
-	}
-    }
-
-  pthread_cleanup_pop (0);
-
-  atomic_decrement (&isem->nwaiters);
-
-  return err;
-}
diff --git a/nptl/sem_trywait.c b/nptl/sem_trywait.c
deleted file mode 100644
index 94c323c..0000000
--- a/nptl/sem_trywait.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/* sem_trywait -- wait on a semaphore.  Generic futex-using version.
-   Copyright (C) 2003-2014 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Paul Mackerras <paulus@au.ibm.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 <errno.h>
-#include <sysdep.h>
-#include <lowlevellock.h>
-#include <internaltypes.h>
-#include <semaphore.h>
-#include <atomic.h>
-
-#include <shlib-compat.h>
-
-
-int
-__new_sem_trywait (sem_t *sem)
-{
-  int *futex = (int *) sem;
-  int val;
-
-  if (*futex > 0)
-    {
-      val = atomic_decrement_if_positive (futex);
-      if (val > 0)
-	return 0;
-    }
-
-  __set_errno (EAGAIN);
-  return -1;
-}
-versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1);
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
-strong_alias (__new_sem_trywait, __old_sem_trywait)
-compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0);
-#endif
diff --git a/nptl/sem_wait.c b/nptl/sem_wait.c
index b12babb..33ac60d 100644
--- a/nptl/sem_wait.c
+++ b/nptl/sem_wait.c
@@ -22,74 +22,406 @@
 #include <lowlevellock.h>
 #include <internaltypes.h>
 #include <semaphore.h>
+#include <sys/time.h>
+#include <futex-internal.h>
 
 #include <pthreadP.h>
 #include <shlib-compat.h>
 #include <atomic.h>
 
 
-void
-attribute_hidden
+/* The semaphore provides two main operations: sem_post adds a token to the
+   semaphore; sem_wait grabs a token from the semaphore, potentially waiting
+   until there is a token available.  A sem_wait needs to synchronize with
+   the sem_post that provided the token, so that whatever lead to the sem_post
+   happens before the code after sem_wait.
+
+   Conceptually, available tokens can simply be counted; let's call that the
+   value of the semaphore.  However, we also want to know whether there might
+   be a sem_wait that is blocked on the value because it was zero (using a
+   futex with the value being the futex variable); if there is no blocked
+   sem_wait, sem_post does not need to execute a futex_wake call.  Therefore,
+   we also need to count the number of potentially blocked sem_wait calls
+   (which we call nwaiters).
+
+   What makes this tricky is that POSIX requires that a semaphore can be
+   destroyed as soon as the last remaining sem_wait has returned, and no
+   other sem_wait or sem_post calls are executing concurrently.  However, the
+   sem_post call whose token was consumed by the last sem_wait is considered
+   to have finished once it provided the token to the sem_wait.
+   Thus, sem_post must not access the semaphore struct anymore after it has
+   made a token available; IOW, it needs to be able to atomically provide
+   a token and check whether any blocked sem_wait calls might exist.
+
+   This is straightforward to do if the architecture provides 64b atomics
+   because we can just put both the value and nwaiters into one variable that
+   we access atomically: This is the data field, the value is in the
+   least-significant 32 bits, and nwaiters in the other bits.  When sem_post
+   makes a value available, it can atomically check nwaiters.
+
+   If we have only 32b atomics available, we cannot put both nwaiters and
+   value into one 32b value because then we might have too few bits for both
+   of those counters.  Therefore, we need to use two distinct fields.
+
+   To allow sem_post to atomically make a token available and check for
+   blocked sem_wait calls, we use one bit in value to indicate whether
+   nwaiters is nonzero.  That allows sem_post to use basically the same
+   algorithm as with 64b atomics, but requires sem_wait to update the bit; it
+   can't do this atomically with another access to nwaiters, but it can compute
+   a conservative value for the bit because it's benign if the bit is set
+   even if nwaiters is zero (all we get is an unnecessary futex wake call by
+   sem_post).
+   Specifically, sem_wait will unset the bit speculatively if it believes that
+   there is no other concurrently executing sem_wait.  If it misspeculated,
+   it will have to clean up by waking any other sem_wait call (i.e., what
+   sem_post would do otherwise).  This does not conflict with the destruction
+   requirement because the semaphore must not be destructed while any sem_wait
+   is still executing.  */
+
+/* Set this to true if you assume that, in contrast to current futex
+   documentation, futex_wake can return -EINTR only if interrupted by a
+   signal, not spuriously due to some other reason.  */
+static const int sem_assume_only_signals_cause_futex_EINTR = 0;
+
+#if !__HAVE_64B_ATOMICS
+static void
+__sem_wait_32_finish (struct new_sem *sem);
+#endif
+
+static void
 __sem_wait_cleanup (void *arg)
 {
-  struct new_sem *isem = (struct new_sem *) arg;
+  struct new_sem *sem = (struct new_sem *) arg;
 
-  atomic_decrement (&isem->nwaiters);
+#if __HAVE_64B_ATOMICS
+  /* Stop being registered as a waiter.  See below for MO.  */
+  atomic_fetch_add_relaxed (&sem->data, -(1UL << SEM_NWAITERS_SHIFT));
+#else
+  __sem_wait_32_finish (sem);
+#endif
 }
 
-/* This is in a seperate function in order to make sure gcc
+/* This is in a separate function in order to make sure gcc
    puts the call site into an exception region, and thus the
-   cleanups get properly run.  */
+   cleanups get properly run.  TODO still necessary?  Other futex_wait
+   users don't seem to need it.  */
 static int
 __attribute__ ((noinline))
-do_futex_wait (struct new_sem *isem)
+do_futex_wait_inner (struct new_sem *sem, struct timespec *rt)
 {
   int err, oldtype = __pthread_enable_asynccancel ();
 
-  err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG);
+#if __HAVE_64B_ATOMICS
+  if (rt == NULL)
+    err = futex_wait ((unsigned*)&sem->data + SEM_VALUE_OFFSET, 0,
+	sem->private);
+  else
+    err = futex_timed_wait ((unsigned*)&sem->data + SEM_VALUE_OFFSET, 0, rt,
+	sem->private);
+#else
+  if (rt == NULL)
+    err = futex_wait (&sem->value, SEM_NWAITERS_MASK, sem->private);
+  else
+    err = futex_timed_wait (&sem->value, SEM_NWAITERS_MASK, rt, sem->private);
+#endif
 
   __pthread_disable_asynccancel (oldtype);
   return err;
 }
 
-int
-__new_sem_wait (sem_t *sem)
+/* Wait until at least one token is available, possibly with a timeout.  */
+static int
+do_futex_wait (struct new_sem *sem, const struct timespec *abstime)
 {
-  struct new_sem *isem = (struct new_sem *) sem;
-  int err;
+  struct timeval tv;
+  struct timespec rt;
+  int sec, nsec;
 
-  if (atomic_decrement_if_positive (&isem->value) > 0)
-    return 0;
+  if (abstime == NULL)
+    return do_futex_wait_inner (sem, NULL);
+
+  /* Get the current time.  */
+  __gettimeofday (&tv, NULL);
+
+  /* Compute relative timeout.  */
+  sec = abstime->tv_sec - tv.tv_sec;
+  nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+  if (nsec < 0)
+    {
+      nsec += 1000000000;
+      --sec;
+    }
 
-  atomic_increment (&isem->nwaiters);
+  /* Already timed out?  */
+  if (sec < 0)
+    return ETIMEDOUT;
 
-  pthread_cleanup_push (__sem_wait_cleanup, isem);
+  /* Do wait.  */
+  rt.tv_sec = sec;
+  rt.tv_nsec = nsec;
+  return do_futex_wait_inner (sem, &rt);
+}
 
-  while (1)
+/* Fast path: Try to grab a token without blocking.  */
+static int
+__new_sem_wait_fast (struct new_sem *sem, int definitive_result)
+{
+  /* We need acquire MO if we actually grab a token, so that this
+     synchronizes with all token providers (i.e., the RMW operation we read
+     from or all those before it in modification order; also see sem_post).
+     We do not need to guarantee any ordering if we observed that there is
+     no token (POSIX leaves it unspecified whether functions that fail
+     synchronize memory); thus, relaxed MO is sufficient for the initial load
+     and the failure path of the CAS.  If the weak CAS fails and we need a
+     definitive result, retry.  */
+#if __HAVE_64B_ATOMICS
+  unsigned long d = atomic_load_relaxed (&sem->data);
+  do
     {
-      err = do_futex_wait(isem);
-      if (err != 0 && err != -EWOULDBLOCK)
+      if ((d & SEM_VALUE_MASK) == 0)
+	break;
+      if (atomic_compare_exchange_weak_acquire (&sem->data, &d, d - 1))
+	return 0;
+    }
+  while (definitive_result);
+  return -1;
+#else
+  unsigned int v = atomic_load_relaxed (&sem->value);
+  do
+    {
+      if ((v >> SEM_VALUE_SHIFT) == 0)
+	break;
+      if (atomic_compare_exchange_weak_acquire (&sem->value,
+	  &v, v - (1 << SEM_VALUE_SHIFT)))
+	return 0;
+    }
+  while (definitive_result);
+  return -1;
+#endif
+}
+
+/* Slow path that blocks.  */
+static int
+__attribute__ ((noinline))
+__new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime)
+{
+  int err = 0;
+
+#if __HAVE_64B_ATOMICS
+  /* Add a waiter.  Relaxed MO is sufficient because we can rely on the
+     ordering provided by the RMW operations we use.  */
+  unsigned long d = atomic_fetch_add_relaxed (&sem->data,
+      1UL << SEM_NWAITERS_SHIFT);
+
+  pthread_cleanup_push (__sem_wait_cleanup, sem);
+
+  /* Wait for a token to be available.  Retry until we can grab one.  */
+  for (;;)
+    {
+      /* If there is no token available, sleep until there is.  */
+      if ((d & SEM_VALUE_MASK) == 0)
 	{
-	  __set_errno (-err);
-	  err = -1;
-	  break;
+	  err = do_futex_wait (sem, abstime);
+	  /* A futex return value of 0 or EAGAIN is due to a real or spurious
+	     wake-up, or due to a change in the number of tokens.  We retry in
+	     these cases.
+	     If we timed out, forward this to the caller.
+	     EINTR could be either due to being interrupted by a signal, or
+	     due to a spurious wake-up.  Thus, we cannot distinguish between
+	     both, and are not allowed to return EINTR to the caller but have
+	     to retry; this is because we may not have been interrupted by a
+	     signal.  However, if we assume that only signals cause a futex
+	     return of EINTR, we forward EINTR to the caller.
+
+	     Retrying on EINTR is technically always allowed because to
+	     reliably interrupt sem_wait with a signal, the signal handler
+	     must call sem_post (which is AS-Safe).  In executions where the
+	     signal handler does not do that, the implementation can correctly
+	     claim that sem_wait hadn't actually started to execute yet, and
+	     thus the signal never actually interrupted sem_wait.  We make no
+	     timing guarantees, so the program can never observe that sem_wait
+	     actually did start to execute.  Thus, in a correct program, we
+	     can expect a signal that wanted to interrupt the sem_wait to have
+	     provided a token, and can just try to grab this token if
+	     futex_wait returns EINTR.  */
+	  if (err == ETIMEDOUT ||
+	      (err == EINTR && sem_assume_only_signals_cause_futex_EINTR))
+	    {
+	      __set_errno (err);
+	      err = -1;
+	      /* Stop being registered as a waiter.  */
+	      atomic_fetch_add_relaxed (&sem->data,
+		  -(1UL << SEM_NWAITERS_SHIFT));
+	      break;
+	    }
+	  /* Relaxed MO is sufficient; see below.  */
+	  d = atomic_load_relaxed (&sem->data);
+	}
+      else
+	{
+	  /* Try to grab both a token and stop being a waiter.  We need
+	     acquire MO so this synchronizes with all token providers (i.e.,
+	     the RMW operation we read from or all those before it in
+	     modification order; also see sem_post).  On the failure path,
+	     relaxed MO is sufficient because we only eventually need the
+	     up-to-date value; the futex_wait or the CAS perform the real
+	     work.  */
+	  if (atomic_compare_exchange_weak_acquire (&sem->data,
+	      &d, d - 1 - (1UL << SEM_NWAITERS_SHIFT)))
+	    {
+	      err = 0;
+	      break;
+	    }
 	}
+    }
+
+  pthread_cleanup_pop (0);
+#else
+  /* The main difference to the 64b-atomics implementation is that we need to
+     access value and nwaiters in separate steps, and that the nwaiters bit
+     in the value can temporarily not be set even if nwaiters is nonzero.
+     We work around incorrectly unsetting the nwaiters bit by letting sem_wait
+     set the bit again and waking the number of waiters that could grab a
+     token.  There are two additional properties we need to ensure:
+     (1) We make sure that whenever unsetting the bit, we see the increment of
+     nwaiters by the other thread that set the bit.  IOW, we will notice if
+     we make a mistake.
+     (2) When setting the nwaiters bit, we make sure that we see the unsetting
+     of the bit by another waiter that happened before us.  This avoids having
+     to blindly set the bit whenever we need to block on it.  We set/unset
+     the bit while having incremented nwaiters (i.e., are a registered
+     waiter), and the problematic case only happens when one waiter indeed
+     followed another (i.e., nwaiters was never larger than 1); thus, this
+     works similarly as with a critical section using nwaiters (see the MOs
+     and related comments below).
+
+     An alternative approach would be to unset the bit after decrementing
+     nwaiters; however, that would result in needing Dekker-like
+     synchronization and thus full memory barriers.  We also would not be able
+     to prevent misspeculation, so this alternative scheme does not seem
+     beneficial.  */
+  unsigned int v;
+
+  /* Add a waiter.  We need acquire MO so this synchronizes with the release
+     MO we use when decrementing nwaiters below; it ensures that if another
+     waiter unset the bit before us, we see that and set it again.  Also see
+     property (2) above.  */
+  atomic_fetch_add_acquire (&sem->nwaiters, 1);
 
-      if (atomic_decrement_if_positive (&isem->value) > 0)
+  pthread_cleanup_push (__sem_wait_cleanup, sem);
+
+  /* Wait for a token to be available.  Retry until we can grab one.  */
+  /* We do not need any ordering wrt. to this load's reads-from, so relaxed
+     MO is sufficient.  The acquire MO above ensures that in the problematic
+     case, we do see the unsetting of the bit by another waiter.  */
+  v = atomic_load_relaxed (&sem->value);
+  do
+    {
+      do
 	{
-	  err = 0;
-	  break;
+	  /* We are about to block, so make sure that the nwaiters bit is
+	     set.  We need release MO on the CAS to ensure that when another
+	     waiter unsets the nwaiters bit, it will also observe that we
+	     incremented nwaiters in the meantime (also see the unsetting of
+	     the bit below).  Relaxed MO on CAS failure is sufficient (see
+	     above).  */
+	  do
+	    {
+	      if ((v & SEM_NWAITERS_MASK) != 0)
+		break;
+	    }
+	  while (!atomic_compare_exchange_weak_release (&sem->value,
+	      &v, v | SEM_NWAITERS_MASK));
+	  /* If there is no token, wait.  */
+	  if ((v >> SEM_VALUE_SHIFT) == 0)
+	    {
+	      /* See __HAVE_64B_ATOMICS variant.  */
+	      err = do_futex_wait(sem, abstime);
+	      if (err == ETIMEDOUT ||
+		  (err == EINTR && sem_assume_only_signals_cause_futex_EINTR))
+		{
+		  __set_errno (err);
+		  err = -1;
+		  goto error;
+		}
+	      err = 0;
+	      /* We blocked, so there might be a token now.  Relaxed MO is
+		 sufficient (see above).  */
+	      v = atomic_load_relaxed (&sem->value);
+	    }
 	}
+      /* If there is no token, we must not try to grab one.  */
+      while ((v >> SEM_VALUE_SHIFT) == 0);
     }
+  /* Try to grab a token.  We need acquire MO so this synchronizes with
+     all token providers (i.e., the RMW operation we read from or all those
+     before it in modification order; also see sem_post).  */
+  while (!atomic_compare_exchange_weak_acquire (&sem->value,
+      &v, v - (1 << SEM_VALUE_SHIFT)));
 
+error:
   pthread_cleanup_pop (0);
 
-  atomic_decrement (&isem->nwaiters);
+  __sem_wait_32_finish (sem);
+#endif
 
   return err;
 }
-versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
 
+/* Stop being a registered waiter (non-64b-atomics code only).  */
+#if !__HAVE_64B_ATOMICS
+static void
+__sem_wait_32_finish (struct new_sem *sem)
+{
+  /* The nwaiters bit is still set, try to unset it now if this seems
+     necessary.  We do this before decrementing nwaiters so that the unsetting
+     is visible to other waiters entering after us.  Relaxed MO is sufficient
+     because we are just speculating here; a stronger MO would not prevent
+     misspeculation.  */
+  unsigned int wguess = atomic_load_relaxed (&sem->nwaiters);
+  if (wguess == 1)
+    /* We might be the last waiter, so unset.  This needs acquire MO so that
+       it syncronizes with the release MO when setting the bit above; if we
+       overwrite someone else that set the bit, we'll read in the following
+       decrement of nwaiters at least from that release sequence, so we'll
+       see if the other waiter is still active or if another writer entered
+       in the meantime (i.e., using the check below).  */
+    atomic_fetch_and_acquire (&sem->value, ~SEM_NWAITERS_MASK);
+
+  /* Now stop being a waiter, and see whether our guess was correct.
+     This needs release MO so that it synchronizes with the acquire MO when
+     a waiter increments nwaiters; this makes sure that newer writers see that
+     we reset the waiters_present bit.  */
+  unsigned int wfinal = atomic_fetch_add_release (&sem->nwaiters, -1);
+  if (wfinal > 1 && wguess == 1)
+    {
+      /* We guessed wrong, and so need to clean up after the mistake and
+         unblock any waiters that could have not been woken.  There is no
+         additional ordering that we need to set up, so relaxed MO is
+         sufficient.  */
+      unsigned int v = atomic_fetch_or_relaxed (&sem->value,
+						SEM_NWAITERS_MASK);
+      /* If there are available tokens, then wake as many waiters.  If there
+         aren't any, then there is no need to wake anyone because there is
+         none to grab for another waiter.  If tokens become available
+         subsequently, then the respective sem_post calls will do the wake-up
+         due to us having set the nwaiters bit again.  */
+      v >>= SEM_VALUE_SHIFT;
+      if (v > 0)
+	futex_wake (&sem->value, v, sem->private);
+    }
+}
+#endif
+
+int
+__new_sem_wait (sem_t *sem)
+{
+  if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
+    return 0;
+  else
+    return __new_sem_wait_slow((struct new_sem *) sem, NULL);
+}
+versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
 
 #if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
 int
@@ -121,3 +453,49 @@ __old_sem_wait (sem_t *sem)
 
 compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0);
 #endif
+
+int
+sem_timedwait (sem_t *sem, const struct timespec *abstime)
+{
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
+    return 0;
+  else
+    return __new_sem_wait_slow((struct new_sem *) sem, abstime);
+}
+
+int
+__new_sem_trywait (sem_t *sem)
+{
+  /* We must not fail spuriously, so require a definitive result even if this
+     may lead to a long execution time.  */
+  if (__new_sem_wait_fast ((struct new_sem *) sem, 1) == 0)
+    return 0;
+  __set_errno (EAGAIN);
+  return -1;
+}
+versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1);
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
+int
+__old_sem_trywait (sem_t *sem)
+{
+  int *futex = (int *) sem;
+  int val;
+
+  if (*futex > 0)
+    {
+      val = atomic_decrement_if_positive (futex);
+      if (val > 0)
+	return 0;
+    }
+
+  __set_errno (EAGAIN);
+  return -1;
+}
+compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0);
+#endif
diff --git a/nptl/structsem.sym b/nptl/structsem.sym
deleted file mode 100644
index 0e2a15f..0000000
--- a/nptl/structsem.sym
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <limits.h>
-#include <stddef.h>
-#include <sched.h>
-#include <bits/pthreadtypes.h>
-#include "internaltypes.h"
-
---
-
-VALUE		offsetof (struct new_sem, value)
-PRIVATE		offsetof (struct new_sem, private)
-NWAITERS	offsetof (struct new_sem, nwaiters)
-SEM_VALUE_MAX	SEM_VALUE_MAX
diff --git a/nptl/tst-sem11.c b/nptl/tst-sem11.c
index 5248eba..1a2dbaf 100644
--- a/nptl/tst-sem11.c
+++ b/nptl/tst-sem11.c
@@ -34,8 +34,11 @@ main (void)
       puts ("sem_init failed");
       return 1;
     }
-
+#if __HAVE_64B_ATOMICS
+  if ((u.ns.data >> SEM_NWAITERS_SHIFT) != 0)
+#else
   if (u.ns.nwaiters != 0)
+#endif
     {
       puts ("nwaiters not initialized");
       return 1;
@@ -68,7 +71,11 @@ main (void)
       goto again;
     }
 
+#if __HAVE_64B_ATOMICS
+  if ((u.ns.data >> SEM_NWAITERS_SHIFT) != 0)
+#else
   if (u.ns.nwaiters != 0)
+#endif
     {
       puts ("nwaiters not reset");
       return 1;
diff --git a/nptl/tst-sem13.c b/nptl/tst-sem13.c
index 068d79e..1560e91 100644
--- a/nptl/tst-sem13.c
+++ b/nptl/tst-sem13.c
@@ -33,9 +33,14 @@ do_test (void)
       perror ("sem_timedwait did not fail with EINVAL");
       return 1;
     }
-  if (u.ns.nwaiters != 0)
+#if __HAVE_64B_ATOMICS
+  unsigned int nwaiters = (u.ns.data >> SEM_NWAITERS_SHIFT);
+#else
+  unsigned int nwaiters = u.ns.nwaiters;
+#endif
+  if (nwaiters != 0)
     {
-      printf ("sem_timedwait modified nwaiters: %ld\n", u.ns.nwaiters);
+      printf ("sem_timedwait modified nwaiters: %d\n", nwaiters);
       return 1;
     }
 
@@ -52,9 +57,14 @@ do_test (void)
       perror ("2nd sem_timedwait did not fail with ETIMEDOUT");
       return 1;
     }
-  if (u.ns.nwaiters != 0)
+#if __HAVE_64B_ATOMICS
+  nwaiters = (u.ns.data >> SEM_NWAITERS_SHIFT);
+#else
+  nwaiters = u.ns.nwaiters;
+#endif
+  if (nwaiters != 0)
     {
-      printf ("2nd sem_timedwait modified nwaiters: %ld\n", u.ns.nwaiters);
+      printf ("2nd sem_timedwait modified nwaiters: %d\n", nwaiters);
       return 1;
     }
 
diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h
index d127f68..39ba18b 100644
--- a/sysdeps/nptl/internaltypes.h
+++ b/sysdeps/nptl/internaltypes.h
@@ -20,6 +20,8 @@
 #define _INTERNALTYPES_H	1
 
 #include <stdint.h>
+#include <atomic.h>
+#include <endian.h>
 
 
 struct pthread_attr
@@ -141,9 +143,29 @@ struct pthread_key_struct
 /* Semaphore variable structure.  */
 struct new_sem
 {
+#if __HAVE_64B_ATOMICS
+  /* The data field holds both value (in the least-significant 32 bytes) and
+     nwaiters.  */
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+#  define SEM_VALUE_OFFSET 0
+# elif __BYTE_ORDER == __BIG_ENDIAN
+#  define SEM_VALUE_OFFSET 1
+# else
+# error Unsupported byte order.
+# endif
+# define SEM_NWAITERS_SHIFT 32
+# define SEM_VALUE_MASK (~(unsigned int)0)
+  unsigned long int data;
+  int private;
+  int pad;
+#else
+# define SEM_VALUE_SHIFT 1
+# define SEM_NWAITERS_MASK ((unsigned int)1)
   unsigned int value;
   int private;
-  unsigned long int nwaiters;
+  int pad;
+  unsigned int nwaiters;
+#endif
 };
 
 struct old_sem
diff --git a/sysdeps/unix/sysv/linux/alpha/sem_post.c b/sysdeps/unix/sysv/linux/alpha/sem_post.c
deleted file mode 100644
index 9d44953..0000000
--- a/sysdeps/unix/sysv/linux/alpha/sem_post.c
+++ /dev/null
@@ -1,5 +0,0 @@
-/* ??? This is an ass-backwards way to do this.  We should simply define
-   the acquire/release semantics of atomic_exchange_and_add.  And even if
-   we don't do this, we should be using atomic_full_barrier or otherwise.  */
-#define __lll_rel_instr  "mb"
-#include <nptl/sem_post.c>
diff --git a/sysdeps/unix/sysv/linux/i386/i486/sem_post.S b/sysdeps/unix/sysv/linux/i386/i486/sem_post.S
deleted file mode 100644
index bc091a0..0000000
--- a/sysdeps/unix/sysv/linux/i386/i486/sem_post.S
+++ /dev/null
@@ -1,150 +0,0 @@
-/* Copyright (C) 2002-2014 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 <pthread-errnos.h>
-#include <structsem.h>
-#include <lowlevellock.h>
-
-
-	.text
-
-	.globl	__new_sem_post
-	.type	__new_sem_post,@function
-	.align	16
-__new_sem_post:
-	cfi_startproc
-	pushl	%ebx
-	cfi_adjust_cfa_offset(4)
-	cfi_offset(%ebx, -8)
-
-	movl	8(%esp), %ebx
-
-#if VALUE == 0
-	movl	(%ebx), %eax
-#else
-	movl	VALUE(%ebx), %eax
-#endif
-0:	cmpl	$SEM_VALUE_MAX, %eax
-	je	3f
-	leal	1(%eax), %edx
-	LOCK
-#if VALUE == 0
-	cmpxchgl %edx, (%ebx)
-#else
-	cmpxchgl %edx, VALUE(%ebx)
-#endif
-	jnz	0b
-
-	cmpl	$0, NWAITERS(%ebx)
-	je	2f
-
-	movl	$FUTEX_WAKE, %ecx
-	orl	PRIVATE(%ebx), %ecx
-	movl	$1, %edx
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-
-	testl	%eax, %eax
-	js	1f
-
-2:	xorl	%eax, %eax
-	popl	%ebx
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebx)
-	ret
-
-	cfi_adjust_cfa_offset(4)
-	cfi_offset(%ebx, -8)
-1:
-#ifdef PIC
-	SETUP_PIC_REG(bx)
-#else
-	movl	$4f, %ebx
-4:
-#endif
-	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
-#ifdef NO_TLS_DIRECT_SEG_REFS
-	movl	errno@gotntpoff(%ebx), %edx
-	addl	%gs:0, %edx
-	movl	$EINVAL, (%edx)
-#else
-	movl	errno@gotntpoff(%ebx), %edx
-	movl	$EINVAL, %gs:(%edx)
-#endif
-
-	orl	$-1, %eax
-	popl	%ebx
-	ret
-
-3:
-#ifdef PIC
-	SETUP_PIC_REG(bx)
-#else
-	movl	$5f, %ebx
-5:
-#endif
-	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
-#ifdef NO_TLS_DIRECT_SEG_REFS
-	movl	errno@gotntpoff(%ebx), %edx
-	addl	%gs:0, %edx
-	movl	$EOVERFLOW, (%edx)
-#else
-	movl	errno@gotntpoff(%ebx), %edx
-	movl	$EOVERFLOW, %gs:(%edx)
-#endif
-
-	orl	$-1, %eax
-	popl	%ebx
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebx)
-	ret
-	cfi_endproc
-	.size	__new_sem_post,.-__new_sem_post
-	versioned_symbol(libpthread, __new_sem_post, sem_post, GLIBC_2_1)
-#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
-	.global	__old_sem_post
-	.type	__old_sem_post,@function
-__old_sem_post:
-	cfi_startproc
-	pushl	%ebx
-	cfi_adjust_cfa_offset(4)
-	cfi_offset(%ebx, -8)
-
-	movl	8(%esp), %ebx
-	LOCK
-	addl	$1, (%ebx)
-
-	movl	$SYS_futex, %eax
-	movl	$FUTEX_WAKE, %ecx
-	movl	$1, %edx
-	ENTER_KERNEL
-
-	testl	%eax, %eax
-	js	1b
-
-	xorl	%eax, %eax
-	popl	%ebx
-	cfi_adjust_cfa_offset(-4)
-	cfi_restore(%ebx)
-	ret
-	cfi_endproc
-	.size	__old_sem_post,.-__old_sem_post
-	compat_symbol(libpthread, __old_sem_post, sem_post, GLIBC_2_0)
-#endif
diff --git a/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S b/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
deleted file mode 100644
index 94d052a..0000000
--- a/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
+++ /dev/null
@@ -1,327 +0,0 @@
-/* Copyright (C) 2002-2014 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 <pthread-errnos.h>
-#include <structsem.h>
-#include <lowlevellock.h>
-
-
-#if VALUE != 0
-# error "code needs to be rewritten for VALUE != 0"
-#endif
-
-
-	.text
-
-	.globl	sem_timedwait
-	.type	sem_timedwait,@function
-	.align	16
-sem_timedwait:
-.LSTARTCODE:
-	movl	4(%esp), %ecx
-
-	movl	(%ecx), %eax
-2:	testl	%eax, %eax
-	je	1f
-
-	leal	-1(%eax), %edx
-	LOCK
-	cmpxchgl %edx, (%ecx)
-	jne	2b
-
-	xorl	%eax, %eax
-	ret
-
-	/* Check whether the timeout value is valid.  */
-1:	pushl	%esi
-.Lpush_esi:
-	pushl	%edi
-.Lpush_edi:
-	pushl	%ebx
-.Lpush_ebx:
-	subl	$12, %esp
-.Lsub_esp:
-
-	movl	32(%esp), %edi
-
-	/* Check for invalid nanosecond field.  */
-	cmpl	$1000000000, 4(%edi)
-	movl	$EINVAL, %esi
-	jae	.Lerrno_exit
-
-	LOCK
-	incl	NWAITERS(%ecx)
-
-7:	xorl	%ecx, %ecx
-	movl	%esp, %ebx
-	movl	%ecx, %edx
-	movl	$__NR_gettimeofday, %eax
-	ENTER_KERNEL
-
-	/* Compute relative timeout.  */
-	movl	4(%esp), %eax
-	movl	$1000, %edx
-	mul	%edx		/* Milli seconds to nano seconds.  */
-	movl	(%edi), %ecx
-	movl	4(%edi), %edx
-	subl	(%esp), %ecx
-	subl	%eax, %edx
-	jns	5f
-	addl	$1000000000, %edx
-	subl	$1, %ecx
-5:	testl	%ecx, %ecx
-	movl	$ETIMEDOUT, %esi
-	js	6f		/* Time is already up.  */
-
-	movl	%ecx, (%esp)	/* Store relative timeout.  */
-	movl	%edx, 4(%esp)
-
-.LcleanupSTART:
-	call	__pthread_enable_asynccancel
-	movl	%eax, 8(%esp)
-
-	movl	28(%esp), %ebx	/* Load semaphore address.  */
-#if FUTEX_WAIT == 0
-	movl	PRIVATE(%ebx), %ecx
-#else
-	movl	$FUTEX_WAIT, %ecx
-	orl	PRIVATE(%ebx), %ecx
-#endif
-	movl	%esp, %esi
-	xorl	%edx, %edx
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	movl	%eax, %esi
-
-	movl	8(%esp), %eax
-	call	__pthread_disable_asynccancel
-.LcleanupEND:
-
-	testl	%esi, %esi
-	je	9f
-	cmpl	$-EWOULDBLOCK, %esi
-	jne	3f
-
-9:	movl	(%ebx), %eax
-8:	testl	%eax, %eax
-	je	7b
-
-	leal	-1(%eax), %ecx
-	LOCK
-	cmpxchgl %ecx, (%ebx)
-	jne	8b
-
-	xorl	%eax, %eax
-
-	LOCK
-	decl	NWAITERS(%ebx)
-
-10:	addl	$12, %esp
-.Ladd_esp:
-	popl	%ebx
-.Lpop_ebx:
-	popl	%edi
-.Lpop_edi:
-	popl	%esi
-.Lpop_esi:
-	ret
-
-.Lafter_ret:
-3:	negl	%esi
-6:
-	movl	28(%esp), %ebx	/* Load semaphore address.  */
-	LOCK
-	decl	NWAITERS(%ebx)
-.Lerrno_exit:
-#ifdef PIC
-	SETUP_PIC_REG(bx)
-#else
-	movl	$4f, %ebx
-4:
-#endif
-	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
-#ifdef NO_TLS_DIRECT_SEG_REFS
-	movl	errno@gotntpoff(%ebx), %edx
-	addl	%gs:0, %edx
-	movl	%esi, (%edx)
-#else
-	movl	errno@gotntpoff(%ebx), %edx
-	movl	%esi, %gs:(%edx)
-#endif
-
-	orl	$-1, %eax
-	jmp	10b
-	.size	sem_timedwait,.-sem_timedwait
-
-
-	.type	sem_wait_cleanup,@function
-sem_wait_cleanup:
-	LOCK
-	decl	NWAITERS(%ebx)
-	movl	%eax, (%esp)
-.LcallUR:
-	call	_Unwind_Resume@PLT
-	hlt
-.LENDCODE:
-	.size	sem_wait_cleanup,.-sem_wait_cleanup
-
-
-	.section .gcc_except_table,"a",@progbits
-.LexceptSTART:
-	.byte	0xff				# @LPStart format (omit)
-	.byte	0xff				# @TType format (omit)
-	.byte	0x01				# call-site format
-						# DW_EH_PE_uleb128
-	.uleb128 .Lcstend-.Lcstbegin
-.Lcstbegin:
-	.uleb128 .LcleanupSTART-.LSTARTCODE
-	.uleb128 .LcleanupEND-.LcleanupSTART
-	.uleb128 sem_wait_cleanup-.LSTARTCODE
-	.uleb128  0
-	.uleb128 .LcallUR-.LSTARTCODE
-	.uleb128 .LENDCODE-.LcallUR
-	.uleb128 0
-	.uleb128  0
-.Lcstend:
-
-
-	.section .eh_frame,"a",@progbits
-.LSTARTFRAME:
-	.long	.LENDCIE-.LSTARTCIE		# Length of the CIE.
-.LSTARTCIE:
-	.long	0				# CIE ID.
-	.byte	1				# Version number.
-#ifdef SHARED
-	.string	"zPLR"				# NUL-terminated augmentation
-						# string.
-#else
-	.string	"zPL"				# NUL-terminated augmentation
-						# string.
-#endif
-	.uleb128 1				# Code alignment factor.
-	.sleb128 -4				# Data alignment factor.
-	.byte	8				# Return address register
-						# column.
-#ifdef SHARED
-	.uleb128 7				# Augmentation value length.
-	.byte	0x9b				# Personality: DW_EH_PE_pcrel
-						# + DW_EH_PE_sdata4
-						# + DW_EH_PE_indirect
-	.long	DW.ref.__gcc_personality_v0-.
-	.byte	0x1b				# LSDA Encoding: DW_EH_PE_pcrel
-						# + DW_EH_PE_sdata4.
-	.byte	0x1b				# FDE Encoding: DW_EH_PE_pcrel
-						# + DW_EH_PE_sdata4.
-#else
-	.uleb128 6				# Augmentation value length.
-	.byte	0x0				# Personality: absolute
-	.long	__gcc_personality_v0
-	.byte	0x0				# LSDA Encoding: absolute
-#endif
-	.byte 0x0c				# DW_CFA_def_cfa
-	.uleb128 4
-	.uleb128 4
-	.byte	0x88				# DW_CFA_offset, column 0x10
-	.uleb128 1
-	.align 4
-.LENDCIE:
-
-	.long	.LENDFDE-.LSTARTFDE		# Length of the FDE.
-.LSTARTFDE:
-	.long	.LSTARTFDE-.LSTARTFRAME		# CIE pointer.
-#ifdef SHARED
-	.long	.LSTARTCODE-.			# PC-relative start address
-						# of the code.
-#else
-	.long	.LSTARTCODE			# Start address of the code.
-#endif
-	.long	.LENDCODE-.LSTARTCODE		# Length of the code.
-	.uleb128 4				# Augmentation size
-#ifdef SHARED
-	.long	.LexceptSTART-.
-#else
-	.long	.LexceptSTART
-#endif
-
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lpush_esi-.LSTARTCODE
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 8
-	.byte   0x86				# DW_CFA_offset %esi
-	.uleb128 2
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lpush_edi-.Lpush_esi
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 12
-	.byte   0x87				# DW_CFA_offset %edi
-	.uleb128 3
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lpush_ebx-.Lpush_edi
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 16
-	.byte   0x83				# DW_CFA_offset %ebx
-	.uleb128 4
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lsub_esp-.Lpush_ebx
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 28
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Ladd_esp-.Lsub_esp
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 16
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lpop_ebx-.Ladd_esp
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 12
-	.byte	0xc3				# DW_CFA_restore %ebx
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lpop_edi-.Lpop_ebx
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 8
-	.byte	0xc7				# DW_CFA_restore %edi
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lpop_esi-.Lpop_edi
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 4
-	.byte	0xc6				# DW_CFA_restore %esi
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lafter_ret-.Lpop_esi
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 28
-	.byte   0x86				# DW_CFA_offset %esi
-	.uleb128 2
-	.byte   0x87				# DW_CFA_offset %edi
-	.uleb128 3
-	.byte   0x83				# DW_CFA_offset %ebx
-	.uleb128 4
-	.align	4
-.LENDFDE:
-
-
-#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/sem_trywait.S b/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S
deleted file mode 100644
index 69611ea..0000000
--- a/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright (C) 2002-2014 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 <pthread-errnos.h>
-#include <lowlevellock.h>
-
-	.text
-
-	.globl	__new_sem_trywait
-	.type	__new_sem_trywait,@function
-	.align	16
-__new_sem_trywait:
-	movl	4(%esp), %ecx
-
-	movl	(%ecx), %eax
-2:	testl	%eax, %eax
-	jz	1f
-
-	leal	-1(%eax), %edx
-	LOCK
-	cmpxchgl %edx, (%ecx)
-	jne	2b
-	xorl	%eax, %eax
-	ret
-
-1:
-#ifdef PIC
-	SETUP_PIC_REG(cx)
-#else
-	movl	$3f, %ecx
-3:
-#endif
-	addl	$_GLOBAL_OFFSET_TABLE_, %ecx
-#ifdef NO_TLS_DIRECT_SEG_REFS
-	movl	errno@gotntpoff(%ecx), %edx
-	addl	%gs:0, %edx
-	movl	$EAGAIN, (%edx)
-#else
-	movl	errno@gotntpoff(%ecx), %edx
-	movl	$EAGAIN, %gs:(%edx)
-#endif
-	orl	$-1, %eax
-	ret
-	.size	__new_sem_trywait,.-__new_sem_trywait
-	versioned_symbol(libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1)
-#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
-	.global	__old_sem_trywait
-__old_sem_trywait = __new_sem_trywait
-	compat_symbol(libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0)
-#endif
diff --git a/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S b/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
deleted file mode 100644
index 14d616f..0000000
--- a/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
+++ /dev/null
@@ -1,343 +0,0 @@
-/* Copyright (C) 2002-2014 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 <pthread-errnos.h>
-#include <structsem.h>
-#include <lowlevellock.h>
-
-
-#if VALUE != 0
-# error "code needs to be rewritten for VALUE != 0"
-#endif
-
-	.text
-
-	.globl	__new_sem_wait
-	.type	__new_sem_wait,@function
-	.align	16
-__new_sem_wait:
-.LSTARTCODE:
-	pushl	%ebx
-.Lpush_ebx:
-	pushl	%esi
-.Lpush_esi:
-	subl	$4, %esp
-.Lsub_esp:
-
-	movl	16(%esp), %ebx
-
-	movl	(%ebx), %eax
-2:	testl	%eax, %eax
-	je	1f
-
-	leal	-1(%eax), %edx
-	LOCK
-	cmpxchgl %edx, (%ebx)
-	jne	2b
-7:	xorl	%eax, %eax
-
-9:	movl	4(%esp), %esi
-	movl	8(%esp), %ebx
-	addl	$12, %esp
-.Ladd_esp:
-	ret
-
-.Lafter_ret:
-1:	LOCK
-	incl	NWAITERS(%ebx)
-
-.LcleanupSTART:
-6:	call	__pthread_enable_asynccancel
-	movl	%eax, (%esp)
-
-#if FUTEX_WAIT == 0
-	movl	PRIVATE(%ebx), %ecx
-#else
-	movl	$FUTEX_WAIT, %ecx
-	orl	PRIVATE(%ebx), %ecx
-#endif
-	xorl	%esi, %esi
-	xorl	%edx, %edx
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	movl	%eax, %esi
-
-	movl	(%esp), %eax
-	call	__pthread_disable_asynccancel
-.LcleanupEND:
-
-	testl	%esi, %esi
-	je	3f
-	cmpl	$-EWOULDBLOCK, %esi
-	jne	4f
-
-3:
-	movl	(%ebx), %eax
-5:	testl	%eax, %eax
-	je	6b
-
-	leal	-1(%eax), %edx
-	LOCK
-	cmpxchgl %edx, (%ebx)
-	jne	5b
-
-	LOCK
-	decl	NWAITERS(%ebx)
-	jmp	7b
-
-4:	LOCK
-	decl	NWAITERS(%ebx)
-
-	negl	%esi
-#ifdef PIC
-	SETUP_PIC_REG(bx)
-#else
-	movl	$8f, %ebx
-8:
-#endif
-	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
-#ifdef NO_TLS_DIRECT_SEG_REFS
-	movl	errno@gotntpoff(%ebx), %edx
-	addl	%gs:0, %edx
-	movl	%esi, (%edx)
-#else
-	movl	errno@gotntpoff(%ebx), %edx
-	movl	%esi, %gs:(%edx)
-#endif
-	orl	$-1, %eax
-
-	jmp	9b
-	.size	__new_sem_wait,.-__new_sem_wait
-	versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1)
-
-
-	.type	sem_wait_cleanup,@function
-sem_wait_cleanup:
-	LOCK
-	decl	NWAITERS(%ebx)
-	movl	%eax, (%esp)
-.LcallUR:
-	call	_Unwind_Resume@PLT
-	hlt
-.LENDCODE:
-	.size	sem_wait_cleanup,.-sem_wait_cleanup
-
-
-	.section .gcc_except_table,"a",@progbits
-.LexceptSTART:
-	.byte	0xff				# @LPStart format (omit)
-	.byte	0xff				# @TType format (omit)
-	.byte	0x01				# call-site format
-						# DW_EH_PE_uleb128
-	.uleb128 .Lcstend-.Lcstbegin
-.Lcstbegin:
-	.uleb128 .LcleanupSTART-.LSTARTCODE
-	.uleb128 .LcleanupEND-.LcleanupSTART
-	.uleb128 sem_wait_cleanup-.LSTARTCODE
-	.uleb128  0
-	.uleb128 .LcallUR-.LSTARTCODE
-	.uleb128 .LENDCODE-.LcallUR
-	.uleb128 0
-	.uleb128  0
-.Lcstend:
-
-
-	.section .eh_frame,"a",@progbits
-.LSTARTFRAME:
-	.long	.LENDCIE-.LSTARTCIE		# Length of the CIE.
-.LSTARTCIE:
-	.long	0				# CIE ID.
-	.byte	1				# Version number.
-#ifdef SHARED
-	.string	"zPLR"				# NUL-terminated augmentation
-						# string.
-#else
-	.string	"zPL"				# NUL-terminated augmentation
-						# string.
-#endif
-	.uleb128 1				# Code alignment factor.
-	.sleb128 -4				# Data alignment factor.
-	.byte	8				# Return address register
-						# column.
-#ifdef SHARED
-	.uleb128 7				# Augmentation value length.
-	.byte	0x9b				# Personality: DW_EH_PE_pcrel
-						# + DW_EH_PE_sdata4
-						# + DW_EH_PE_indirect
-	.long	DW.ref.__gcc_personality_v0-.
-	.byte	0x1b				# LSDA Encoding: DW_EH_PE_pcrel
-						# + DW_EH_PE_sdata4.
-	.byte	0x1b				# FDE Encoding: DW_EH_PE_pcrel
-						# + DW_EH_PE_sdata4.
-#else
-	.uleb128 6				# Augmentation value length.
-	.byte	0x0				# Personality: absolute
-	.long	__gcc_personality_v0
-	.byte	0x0				# LSDA Encoding: absolute
-#endif
-	.byte 0x0c				# DW_CFA_def_cfa
-	.uleb128 4
-	.uleb128 4
-	.byte	0x88				# DW_CFA_offset, column 0x10
-	.uleb128 1
-	.align 4
-.LENDCIE:
-
-	.long	.LENDFDE-.LSTARTFDE		# Length of the FDE.
-.LSTARTFDE:
-	.long	.LSTARTFDE-.LSTARTFRAME		# CIE pointer.
-#ifdef SHARED
-	.long	.LSTARTCODE-.			# PC-relative start address
-						# of the code.
-#else
-	.long	.LSTARTCODE			# Start address of the code.
-#endif
-	.long	.LENDCODE-.LSTARTCODE		# Length of the code.
-	.uleb128 4				# Augmentation size
-#ifdef SHARED
-	.long	.LexceptSTART-.
-#else
-	.long	.LexceptSTART
-#endif
-
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lpush_ebx-.LSTARTCODE
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 8
-	.byte   0x83				# DW_CFA_offset %ebx
-	.uleb128 2
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lpush_esi-.Lpush_ebx
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 12
-	.byte   0x86				# DW_CFA_offset %esi
-	.uleb128 3
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lsub_esp-.Lpush_esi
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 16
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Ladd_esp-.Lsub_esp
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 4
-	.byte	0xc3				# DW_CFA_restore %ebx
-	.byte	0xc6				# DW_CFA_restore %esi
-	.byte	4				# DW_CFA_advance_loc4
-	.long	.Lafter_ret-.Ladd_esp
-	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 16
-	.byte   0x83				# DW_CFA_offset %ebx
-	.uleb128 2
-	.byte   0x86				# DW_CFA_offset %esi
-	.uleb128 3
-	.align	4
-.LENDFDE:
-
-
-#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
-
-
-#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
-	.section ".text.compat", "ax"
-	.global	__old_sem_wait
-	.type	__old_sem_wait,@function
-	.align	16
-	cfi_startproc
-__old_sem_wait:
-	pushl	%ebx
-	cfi_adjust_cfa_offset(4)
-	pushl	%esi
-	cfi_adjust_cfa_offset(4)
-	subl	$4, %esp
-	cfi_adjust_cfa_offset(4)
-
-	movl	16(%esp), %ebx
-	cfi_offset(ebx, -8)
-
-	cfi_offset(esi, -12)
-3:	movl	(%ebx), %eax
-2:	testl	%eax, %eax
-	je	1f
-
-	leal	-1(%eax), %edx
-	LOCK
-	cmpxchgl %edx, (%ebx)
-	jne	2b
-	xorl	%eax, %eax
-
-5:	movl	4(%esp), %esi
-	movl	8(%esp), %ebx
-	addl	$12, %esp
-	cfi_restore(ebx)
-	cfi_restore(esi)
-	cfi_adjust_cfa_offset(-12)
-	ret
-
-	cfi_adjust_cfa_offset(12)
-	cfi_offset(ebx, -8)
-	cfi_offset(esi, -12)
-1:	call	__pthread_enable_asynccancel
-	movl	%eax, (%esp)
-
-	xorl	%esi, %esi
-	movl	$SYS_futex, %eax
-	movl	%esi, %ecx
-	movl	%esi, %edx
-	ENTER_KERNEL
-	movl	%eax, %esi
-
-	movl	(%esp), %eax
-	call	__pthread_disable_asynccancel
-
-	testl	%esi, %esi
-	je	3b
-	cmpl	$-EWOULDBLOCK, %esi
-	je	3b
-	negl	%esi
-#ifdef PIC
-	SETUP_PIC_REG(bx)
-#else
-	movl	$4f, %ebx
-4:
-#endif
-	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
-#ifdef NO_TLS_DIRECT_SEG_REFS
-	movl	errno@gotntpoff(%ebx), %edx
-	addl	%gs:0, %edx
-	movl	%esi, (%edx)
-#else
-	movl	errno@gotntpoff(%ebx), %edx
-	movl	%esi, %gs:(%edx)
-#endif
-	orl	$-1, %eax
-	jmp	5b
-	cfi_endproc
-	.size	__old_sem_wait,.-__old_sem_wait
-	compat_symbol(libpthread, __old_sem_wait, sem_wait, GLIBC_2_0)
-#endif
diff --git a/sysdeps/unix/sysv/linux/i386/i586/sem_post.S b/sysdeps/unix/sysv/linux/i386/i586/sem_post.S
deleted file mode 100644
index 28ebd27..0000000
--- a/sysdeps/unix/sysv/linux/i386/i586/sem_post.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2003-2014 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/sem_post.S"
diff --git a/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S b/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S
deleted file mode 100644
index 46f1959..0000000
--- a/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2003-2014 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/sem_timedwait.S"
diff --git a/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S b/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S
deleted file mode 100644
index bce1cbc..0000000
--- a/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2003-2014 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/sem_trywait.S"
diff --git a/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S b/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S
deleted file mode 100644
index abe0e9f..0000000
--- a/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2003-2014 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/sem_wait.S"
diff --git a/sysdeps/unix/sysv/linux/i386/i686/sem_post.S b/sysdeps/unix/sysv/linux/i386/i686/sem_post.S
deleted file mode 100644
index 28ebd27..0000000
--- a/sysdeps/unix/sysv/linux/i386/i686/sem_post.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2003-2014 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/sem_post.S"
diff --git a/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S b/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S
deleted file mode 100644
index 46f1959..0000000
--- a/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2003-2014 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/sem_timedwait.S"
diff --git a/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S b/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S
deleted file mode 100644
index bce1cbc..0000000
--- a/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2003-2014 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/sem_trywait.S"
diff --git a/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S b/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S
deleted file mode 100644
index abe0e9f..0000000
--- a/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2003-2014 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/sem_wait.S"
diff --git a/sysdeps/unix/sysv/linux/powerpc/sem_post.c b/sysdeps/unix/sysv/linux/powerpc/sem_post.c
deleted file mode 100644
index 831a8dd..0000000
--- a/sysdeps/unix/sysv/linux/powerpc/sem_post.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* sem_post -- post to a POSIX semaphore.  Powerpc version.
-   Copyright (C) 2003-2014 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Paul Mackerras <paulus@au.ibm.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 <errno.h>
-#include <sysdep.h>
-#include <lowlevellock.h>
-#include <internaltypes.h>
-#include <semaphore.h>
-
-#include <shlib-compat.h>
-
-int
-__new_sem_post (sem_t *sem)
-{
-  struct new_sem *isem = (struct new_sem *) sem;
-
-  __asm __volatile (__ARCH_REL_INSTR ::: "memory");
-  atomic_increment (&isem->value);
-  __asm __volatile (__ARCH_ACQ_INSTR ::: "memory");
-  if (isem->nwaiters > 0)
-    {
-      int err = lll_futex_wake (&isem->value, 1,
-				isem->private ^ FUTEX_PRIVATE_FLAG);
-      if (__builtin_expect (err, 0) < 0)
-	{
-	  __set_errno (-err);
-	  return -1;
-	}
-    }
-  return 0;
-}
-versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1);
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
-
-int
-attribute_compat_text_section
-__old_sem_post (sem_t *sem)
-{
-  int *futex = (int *) sem;
-
-  __asm __volatile (__ARCH_REL_INSTR ::: "memory");
-  (void) atomic_increment_val (futex);
-  /* We always have to assume it is a shared semaphore.  */
-  int err = lll_futex_wake (futex, 1, LLL_SHARED);
-  if (__builtin_expect (err, 0) < 0)
-    {
-      __set_errno (-err);
-      return -1;
-    }
-  return 0;
-}
-
-compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0);
-#endif
diff --git a/sysdeps/unix/sysv/linux/sh/sem_post.S b/sysdeps/unix/sysv/linux/sh/sem_post.S
deleted file mode 100644
index ccc6255..0000000
--- a/sysdeps/unix/sysv/linux/sh/sem_post.S
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Copyright (C) 2003-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>
-#include <shlib-compat.h>
-#include <pthread-errnos.h>
-#include <structsem.h>
-#include <lowlevellock.h>
-#include "lowlevel-atomic.h"
-
-
-	.text
-
-	.globl	__new_sem_post
-	.type	__new_sem_post,@function
-	.align	5
-	cfi_startproc
-__new_sem_post:
-	mov.l	@(VALUE,r4), r2
-0:
-	mov.l	.Lmax, r1
-	cmp/eq	r1, r2
-	bt/s	3f
-	 mov	r2, r3
-	mov	r3, r5
-	add	#1, r5
-	CMPXCHG (r3, @(VALUE,r4), r5, r2)
-	bf	0b
-	mov.l	@(NWAITERS,r4), r2
-	tst	r2, r2
-	bt	2f
-	mov	#FUTEX_WAKE, r5
-	mov.l	@(PRIVATE,r4), r1
-	or	r1, r5
-	mov	#1, r6
-	mov	#0, r7
-	mov	#SYS_futex, r3
-	extu.b	r3, r3
-	trapa	#0x14
-	SYSCALL_INST_PAD
-
-	cmp/pz	r0
-	bf	1f
-2:
-	rts
-	 mov	#0, r0
-
-1:
-	bra	4f
-	 mov	#EINVAL, r2
-
-3:
-	mov	#EOVERFLOW, r2
-4:
-	mov.l	r12, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (r12, 0)
-	mov.l	r8, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (r8, 0)
-	sts.l	pr, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (pr, 0)
-	mova	.Lgot3, r0
-	mov.l	.Lgot3, r12
-	add	r0, r12
-
-	mov.l	.Lerrno3, r0
-	stc	gbr, r1
-	mov.l	@(r0, r12), r0
-	bra	.Lexit
-	 add	r1, r0
-	.align	2
-.Lerrno3:
-	.long	errno@GOTTPOFF
-.Lexit:
-	mov.l	r2, @r0
-	lds.l	@r15+, pr
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (pr)
-	mov.l	@r15+, r8
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (r8)
-	mov.l	@r15+, r12
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (r12)
-	rts
-	 mov	#-1, r0
-	cfi_endproc
-
-	.align	2
-.Lmax:
-	.long	SEM_VALUE_MAX
-.Lgot3:
-	.long	_GLOBAL_OFFSET_TABLE_
-	.size	__new_sem_post,.-__new_sem_post
-	versioned_symbol(libpthread, __new_sem_post, sem_post, GLIBC_2_1)
diff --git a/sysdeps/unix/sysv/linux/sh/sem_timedwait.S b/sysdeps/unix/sysv/linux/sh/sem_timedwait.S
deleted file mode 100644
index 4803d03..0000000
--- a/sysdeps/unix/sysv/linux/sh/sem_timedwait.S
+++ /dev/null
@@ -1,281 +0,0 @@
-/* Copyright (C) 2003-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>
-#include <shlib-compat.h>
-#include <pthread-errnos.h>
-#include <tcb-offsets.h>
-#include <structsem.h>
-#include <lowlevellock.h>
-#include "lowlevel-atomic.h"
-
-
-#if VALUE != 0
-# error "code needs to be rewritten for VALUE != 0"
-#endif
-
-	.text
-
-	.globl	sem_timedwait
-	.type	sem_timedwait,@function
-	.align	5
-	cfi_startproc
-sem_timedwait:
-.LSTARTCODE:
-#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_absptr, __gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_absptr, .LexceptSTART)
-#endif
-	mov.l	@r4, r0
-2:
-	tst	r0, r0
-	bt	1f
-	mov	r0, r3
-	mov	r0, r6
-	add	#-1, r3
-	CMPXCHG (r6, @r4, r3, r2)
-	bf/s	2b
-	 mov	r2, r0
-	rts
-	 mov	#0, r0
-
-1:
-	/* Check whether the timeout value is valid.  */
-	mov.l	r8, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (r8, 0)
-	mov.l	r9, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (r9, 0)
-	mov.l	r10, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (r10, 0)
-	mov.l	r12, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (r12, 0)
-	sts.l	pr, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (pr, 0)
-	add	#-8, r15
-	cfi_adjust_cfa_offset (8)
-
-	mov	r4, r8
-	mov	r5, r9
-
-	/* Check for invalid nanosecond field.  */
-	mov.l	@(4,r9), r0
-	mov.l	.L1g, r1
-	cmp/hs	r1, r0
-	bt/s	.Lerrno_exit
-	 mov	#EINVAL, r10
-	INC (@(NWAITERS,r8),r2)
-
-7:
-	/* Compute relative timeout.  */
-	mov	r15, r4
-	mov	#0, r5
-	mov	#__NR_gettimeofday, r3
-	trapa	#0x12
-	SYSCALL_INST_PAD
-
-	mov.l	@(4,r15), r0
-	mov.w	.L1k, r1
-	dmulu.l	r0, r1		/* Milli seconds to nano seconds.  */
-	mov.l	@r9, r2
-	mov.l	@(4,r9), r3
-	mov.l	@r15, r0
-	sts	macl, r1
-	sub	r0, r2
-	clrt
-	subc	r1, r3
-	bf	5f
-	mov.l	.L1g, r1
-	add	r1, r3
-	add	#-1, r2
-5:
-	cmp/pz	r2
-	bf/s	6f		/* Time is already up.  */
-	 mov	#ETIMEDOUT, r0
-
-	/* Store relative timeout.  */
-	mov.l	r2, @r15
-	mov.l	r3, @(4,r15)
-
-.LcleanupSTART:
-	mov.l	.Lenable0, r1
-	bsrf	r1
-	 nop
-.Lenable0b:
-	mov	r0, r10
-
-	mov	r8, r4
-#if FUTEX_WAIT == 0
-	mov.l	@(PRIVATE,r8), r5
-#else
-	mov.l	@(PRIVATE,r8), r5
-	mov	#FUTEX_WAIT, r0
-	or	r0, r5
-#endif
-	mov	#0, r6
-	mov	r15, r7
-	mov	#SYS_futex, r3
-	extu.b	r3, r3
-	trapa	#0x14
-	SYSCALL_INST_PAD
-
-	mov.l	.Ldisable0, r1
-	mov	r10, r4
-	bsrf	r1
-	 mov	r0, r10
-.Ldisable0b:
-	mov	r10, r0
-.LcleanupEND:
-
-	tst	r0, r0
-	bt	9f
-	cmp/eq	#-EWOULDBLOCK, r0
-	bf	3f
-9:
-	mov.l	@r8, r0
-8:
-	tst	r0, r0
-	bt	7b
-
-	mov	r0, r3
-	mov	r0, r4
-	add	#-1, r3
-	CMPXCHG (r4, @r8, r3, r2)
-	bf/s	8b
-	 mov	r2, r0
-
-	DEC (@(NWAITERS,r8), r2)
-	mov	#0, r0
-
-10:
-	cfi_remember_state
-	add	#8, r15
-	cfi_adjust_cfa_offset (-8)
-	lds.l	@r15+, pr
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (pr)
-	mov.l	@r15+, r12
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (r12)
-	mov.l	@r15+, r10
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (r10)
-	mov.l	@r15+, r9
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (r9)
-	mov.l	@r15+, r8
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (r8)
-	rts
-	 nop
-	cfi_restore_state
-
-3:
-	neg	r0, r0
-6:
-	mov	r0, r10
-	DEC (@(NWAITERS,r8), r2)
-.Lerrno_exit:
-	mova	.Lgot2, r0
-	mov.l	.Lgot2, r12
-	add	r0, r12
-
-	mov.l	.Lerrno2, r0
-	stc	gbr, r1
-	mov.l	@(r0, r12), r0
-	bra	.Lexit
-	 add	r1, r0
-	.align	2
-.Lerrno2:
-	.long	errno@GOTTPOFF
-.Lexit:
-	mov.l	r10, @r0
-	bra	10b
-	 mov	#-1, r0
-
-.L1k:
-	.word	1000
-	.align	2
-.L1g:
-	.long	1000000000
-.Lgot2:
-	.long	_GLOBAL_OFFSET_TABLE_
-.Lenable0:
-	.long	__pthread_enable_asynccancel-.Lenable0b
-.Ldisable0:
-	.long	__pthread_disable_asynccancel-.Ldisable0b
-	.size	sem_timedwait,.-sem_timedwait
-
-	.type	sem_wait_cleanup,@function
-sem_wait_cleanup:
-	DEC (@(NWAITERS,r8), r2)
-.LcallUR:
-	mov.l	.Lresume, r1
-#ifdef PIC
-	add	r12, r1
-#endif
-	jsr	@r1
-	 nop
-	sleep
-
-	.align	2
-.Lresume:
-#ifdef PIC
-	.long	_Unwind_Resume@GOTOFF
-#else
-	.long	_Unwind_Resume
-#endif
-.LENDCODE:
-	cfi_endproc
-	.size	sem_wait_cleanup,.-sem_wait_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_uleb128		! call-site format
-	.uleb128 .Lcstend-.Lcstbegin
-.Lcstbegin:
-	.uleb128 .LcleanupSTART-.LSTARTCODE
-	.uleb128 .LcleanupEND-.LcleanupSTART
-	.uleb128 sem_wait_cleanup-.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	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/sh/sem_trywait.S b/sysdeps/unix/sysv/linux/sh/sem_trywait.S
deleted file mode 100644
index 8ff8792..0000000
--- a/sysdeps/unix/sysv/linux/sh/sem_trywait.S
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Copyright (C) 2003-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>
-#include <shlib-compat.h>
-#include <pthread-errnos.h>
-#include <lowlevellock.h>
-#include "lowlevel-atomic.h"
-
-
-	.text
-
-	.globl	__new_sem_trywait
-	.type	__new_sem_trywait,@function
-	.align	5
-	cfi_startproc
-__new_sem_trywait:
-	mov.l	r12, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (r12, 0)
-	mov.l	r8, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (r8, 0)
-	sts.l	pr, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (pr, 0)
-	mov	r4, r8
-	mov.l	@r8, r0
-2:
-	tst	r0, r0
-	bt	1f
-
-	mov	r0, r3
-	mov	r0, r4
-	add	#-1, r3
-	CMPXCHG (r4, @r8, r3, r2)
-	bf/s	2b
-	 mov	r2, r0
-
-	cfi_remember_state
-	lds.l	@r15+, pr
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (pr)
-	mov.l	@r15+, r8
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (r8)
-	mov.l	@r15+, r12
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (r12)
-	rts
-	 mov	#0, r0
-	cfi_restore_state
-
-1:
-	mov	#EAGAIN, r8
-	mova	.Lgot1, r0
-	mov.l	.Lgot1, r12
-	add	r0, r12
-
-	mov.l	.Lerrno1, r0
-	stc	gbr, r1
-	mov.l	@(r0, r12), r0
-	bra	.Lexit
-	 add	r1, r0
-	.align	2
-.Lerrno1:
-	.long	errno@GOTTPOFF
-.Lexit:
-	mov.l	r8, @r0
-	lds.l	@r15+, pr
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (pr)
-	mov.l	@r15+, r8
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (r8)
-	mov.l	@r15+, r12
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (r12)
-	rts
-	 mov	#-1, r0
-
-	cfi_endproc
-
-	.align	2
-.Lgot1:
-	.long	_GLOBAL_OFFSET_TABLE_
-	.size	__new_sem_trywait,.-__new_sem_trywait
-	versioned_symbol(libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1)
diff --git a/sysdeps/unix/sysv/linux/sh/sem_wait.S b/sysdeps/unix/sysv/linux/sh/sem_wait.S
deleted file mode 100644
index 04a6a40..0000000
--- a/sysdeps/unix/sysv/linux/sh/sem_wait.S
+++ /dev/null
@@ -1,229 +0,0 @@
-/* Copyright (C) 2003-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>
-#include <shlib-compat.h>
-#include <pthread-errnos.h>
-#include <tcb-offsets.h>
-#include <structsem.h>
-#include <lowlevellock.h>
-#include "lowlevel-atomic.h"
-
-
-#if VALUE != 0
-# error "code needs to be rewritten for VALUE != 0"
-#endif
-
-	.text
-
-	.globl	__new_sem_wait
-	.type	__new_sem_wait,@function
-	.align	5
-	cfi_startproc
-__new_sem_wait:
-.LSTARTCODE:
-#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_absptr, __gcc_personality_v0)
-	cfi_lsda(DW_EH_PE_absptr, .LexceptSTART)
-#endif
-	mov.l	r8, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (r8, 0)
-	mov.l	r10, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (r10, 0)
-	mov.l	r12, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (r12, 0)
-	sts.l	pr, @-r15
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (pr, 0)
-
-	mov	r4, r8
-	mov.l	@r8, r0
-2:
-	tst	r0, r0
-	bt	1f
-	mov	r0, r3
-	mov	r0, r4
-	add	#-1, r3
-	CMPXCHG (r4, @r8, r3, r2)
-	bf/s	2b
-	 mov	r2, r0
-7:
-	mov	#0, r0
-9:
-	cfi_remember_state
-	lds.l	@r15+, pr
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (pr)
-	mov.l	@r15+, r12
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (r12)
-	mov.l	@r15+, r10
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (r10)
-	rts
-	 mov.l	@r15+, r8
-	/* Omit CFI for restore in delay slot.  */
-	cfi_restore_state
-
-.Lafter_ret:
-1:
-	INC (@(NWAITERS,r8),r2)
-
-.LcleanupSTART:
-6:
-	mov.l	.Lenable0, r1
-	bsrf	r1
-	 nop
-.Lenable0b:
-	mov	r0, r10
-
-	mov	r8, r4
-#if FUTEX_WAIT == 0
-	mov.l	@(PRIVATE,r8), r5
-#else
-	mov.l	@(PRIVATE,r8), r5
-	mov	#FUTEX_WAIT, r0
-	or	r0, r5
-#endif
-	mov	#0, r6
-	mov	#0, r7
-	mov	#SYS_futex, r3
-	extu.b	r3, r3
-	trapa	#0x14
-	SYSCALL_INST_PAD
-
-	mov.l	.Ldisable0, r1
-	mov	r10, r4
-	bsrf	r1
-	 mov	r0, r10
-.Ldisable0b:
-	mov	r10, r0
-.LcleanupEND:
-
-	tst	r0, r0
-	bt	3f
-	cmp/eq	#-EWOULDBLOCK, r0
-	bf	4f
-
-3:
-	mov.l	@r8, r0
-5:
-	tst	r0, r0
-	bt	6b
-
-	mov	r0, r3
-	mov	r0, r4
-	add	#-1, r3
-	CMPXCHG (r4, @r8, r3, r2)
-	bf/s	5b
-	 mov	r2, r0
-
-	DEC (@(NWAITERS,r8), r2)
-	bra	7b
-	 nop
-
-4:
-	neg	r0, r0
-	mov	r0, r4
-	DEC (@(NWAITERS,r8), r2)
-	mov	r4, r8
-	mova	.Lgot0, r0
-	mov.l	.Lgot0, r12
-	add	r0, r12
-
-	mov.l	.Lerrno0, r0
-	stc	gbr, r1
-	mov.l	@(r0, r12), r0
-	bra	.Lexit
-	 add	r1, r0
-	.align	2
-.Lerrno0:
-	.long	errno@GOTTPOFF
-.Lexit:
-	mov.l	r8, @r0
-	bra	9b
-	 mov	#-1, r0
-
-	.align	2
-.Lgot0:
-	.long	_GLOBAL_OFFSET_TABLE_
-.Lenable0:
-	.long	__pthread_enable_asynccancel-.Lenable0b
-.Ldisable0:
-	.long	__pthread_disable_asynccancel-.Ldisable0b
-	.size	__new_sem_wait,.-__new_sem_wait
-	versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1)
-
-
-	.type	sem_wait_cleanup,@function
-sem_wait_cleanup:
-	DEC (@(NWAITERS,r8), r2)
-.LcallUR:
-	mov.l	.Lresume, r1
-#ifdef PIC
-	add	r12, r1
-#endif
-	jsr	@r1
-	 nop
-	sleep
-
-	.align	2
-.Lresume:
-#ifdef PIC
-	.long	_Unwind_Resume@GOTOFF
-#else
-	.long	_Unwind_Resume
-#endif
-.LENDCODE:
-	cfi_endproc
-	.size	sem_wait_cleanup,.-sem_wait_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_uleb128		! call-site format
-	.uleb128 .Lcstend-.Lcstbegin
-.Lcstbegin:
-	.uleb128 .LcleanupSTART-.LSTARTCODE
-	.uleb128 .LcleanupEND-.LcleanupSTART
-	.uleb128 sem_wait_cleanup-.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	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/x86_64/sem_post.S b/sysdeps/unix/sysv/linux/x86_64/sem_post.S
deleted file mode 100644
index 1c11600..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/sem_post.S
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Copyright (C) 2002-2014 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 <lowlevellock.h>
-#include <shlib-compat.h>
-#include <pthread-errnos.h>
-#include <structsem.h>
-
-
-	.text
-
-	.globl	sem_post
-	.type	sem_post,@function
-	.align	16
-sem_post:
-#if VALUE == 0
-	movl	(%rdi), %eax
-#else
-	movl	VALUE(%rdi), %eax
-#endif
-0:	cmpl	$SEM_VALUE_MAX, %eax
-	je	3f
-	leal	1(%rax), %esi
-	LOCK
-#if VALUE == 0
-	cmpxchgl %esi, (%rdi)
-#else
-	cmpxchgl %esi, VALUE(%rdi)
-#endif
-	jnz	0b
-
-	LP_OP(cmp) $0, NWAITERS(%rdi)
-	je	2f
-
-	movl	$SYS_futex, %eax
-	movl	$FUTEX_WAKE, %esi
-	orl	PRIVATE(%rdi), %esi
-	movl	$1, %edx
-	syscall
-
-	testq	%rax, %rax
-	js	1f
-
-2:	xorl	%eax, %eax
-	retq
-
-1:
-	movl	$EINVAL, %eax
-	jmp	4f
-
-3:
-	movl	$EOVERFLOW, %eax
-
-4:
-	movq	errno@gottpoff(%rip), %rdx
-	movl	%eax, %fs:(%rdx)
-	orl	$-1, %eax
-	retq
-	.size	sem_post,.-sem_post
diff --git a/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
deleted file mode 100644
index 880610e..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
+++ /dev/null
@@ -1,380 +0,0 @@
-/* Copyright (C) 2002-2014 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 <kernel-features.h>
-#include <lowlevellock.h>
-#include <shlib-compat.h>
-#include <pthread-errnos.h>
-#include <structsem.h>
-
-	.text
-
-	.globl	sem_timedwait
-	.type	sem_timedwait,@function
-	.align	16
-sem_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
-#if VALUE == 0
-	movl	(%rdi), %eax
-#else
-	movl	VALUE(%rdi), %eax
-#endif
-2:	testl	%eax, %eax
-	je	1f
-
-	leaq	-1(%rax), %rdx
-	LOCK
-#if VALUE == 0
-	cmpxchgl %edx, (%rdi)
-#else
-	cmpxchgl %edx, VALUE(%rdi)
-#endif
-	jne	2b
-
-	xorl	%eax, %eax
-	retq
-
-	/* Check whether the timeout value is valid.  */
-1:	cmpq	$1000000000, 8(%rsi)
-	jae	6f
-
-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
-#  ifdef PIC
-	cmpl	$0, __have_futex_clock_realtime(%rip)
-#  else
-	cmpl	$0, __have_futex_clock_realtime
-#  endif
-	je	.Lreltmo
-#endif
-
-	cmpq	$0, (%rsi)
-	js	16f
-
-	/* This push is only needed to store the sem_t pointer for the
-	   exception handler.  */
-	pushq	%rdi
-	cfi_adjust_cfa_offset(8)
-
-	movq	%rsi, %r10
-
-	LOCK
-	LP_OP(add) $1, NWAITERS(%rdi)
-
-.LcleanupSTART:
-13:	call	__pthread_enable_asynccancel
-	movl	%eax, %r8d
-
-#if VALUE != 0
-	leaq	VALUE(%rdi), %rdi
-#endif
-	movl	$0xffffffff, %r9d
-	movl	$FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi
-	orl	PRIVATE(%rdi), %esi
-	movl	$SYS_futex, %eax
-	xorl	%edx, %edx
-	syscall
-	movq	%rax, %r9
-#if VALUE != 0
-	leaq	-VALUE(%rdi), %rdi
-#endif
-
-	xchgq	%r8, %rdi
-	call	__pthread_disable_asynccancel
-.LcleanupEND:
-	movq	%r8, %rdi
-
-	testq	%r9, %r9
-	je	11f
-	cmpq	$-EWOULDBLOCK, %r9
-	jne	3f
-
-11:
-#if VALUE == 0
-	movl	(%rdi), %eax
-#else
-	movl	VALUE(%rdi), %eax
-#endif
-14:	testl	%eax, %eax
-	je	13b
-
-	leaq	-1(%rax), %rcx
-	LOCK
-#if VALUE == 0
-	cmpxchgl %ecx, (%rdi)
-#else
-	cmpxchgl %ecx, VALUE(%rdi)
-#endif
-	jne	14b
-
-	xorl	%eax, %eax
-
-15:	LOCK
-	LP_OP(sub) $1, NWAITERS(%rdi)
-
-	leaq	8(%rsp), %rsp
-	cfi_adjust_cfa_offset(-8)
-	retq
-
-	cfi_adjust_cfa_offset(8)
-3:	negq	%r9
-	movq	errno@gottpoff(%rip), %rdx
-	movl	%r9d, %fs:(%rdx)
-
-	orl	$-1, %eax
-	jmp	15b
-
-	cfi_adjust_cfa_offset(-8)
-6:
-	movq	errno@gottpoff(%rip), %rdx
-	movl	$EINVAL, %fs:(%rdx)
-
-	orl	$-1, %eax
-
-	retq
-
-16:
-	movq	errno@gottpoff(%rip), %rdx
-	movl	$ETIMEDOUT, %fs:(%rdx)
-
-	orl	$-1, %eax
-
-	retq
-
-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
-.Lreltmo:
-	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)
-
-#ifdef __ASSUME_FUTEX_CLOCK_REALTIME
-# define STACKFRAME 8
-#else
-# define STACKFRAME 24
-#endif
-	subq	$STACKFRAME, %rsp
-	cfi_adjust_cfa_offset(STACKFRAME)
-
-	movq	%rdi, %r12
-	movq	%rsi, %r13
-
-	LOCK
-	LP_OP(add) $1, NWAITERS(%r12)
-
-7:	xorl	%esi, %esi
-	movq	%rsp,%rdi
-	/* This call works because we directly jump to a system call entry
-	   which preserves all the registers.  */
-	call	JUMPTARGET(__gettimeofday)
-
-	/* Compute relative timeout.  */
-	movq	8(%rsp), %rax
-	movl	$1000, %edi
-	mul	%rdi		/* Milli seconds to nano seconds.  */
-	movq	(%r13), %rdi
-	movq	8(%r13), %rsi
-	subq	(%rsp), %rdi
-	subq	%rax, %rsi
-	jns	5f
-	addq	$1000000000, %rsi
-	decq	%rdi
-5:	testq	%rdi, %rdi
-	movl	$ETIMEDOUT, %r14d
-	js	36f		/* Time is already up.  */
-
-	movq	%rdi, (%rsp)	/* Store relative timeout.  */
-	movq	%rsi, 8(%rsp)
-
-.LcleanupSTART2:
-	call	__pthread_enable_asynccancel
-	movl	%eax, 16(%rsp)
-
-	movq	%rsp, %r10
-# if VALUE == 0
-	movq	%r12, %rdi
-# else
-	leaq	VALUE(%r12), %rdi
-# endif
-# if FUTEX_WAIT == 0
-	movl	PRIVATE(%rdi), %esi
-# else
-	movl	$FUTEX_WAIT, %esi
-	orl	PRIVATE(%rdi), %esi
-# endif
-	movl	$SYS_futex, %eax
-	xorl	%edx, %edx
-	syscall
-	movq	%rax, %r14
-
-	movl	16(%rsp), %edi
-	call	__pthread_disable_asynccancel
-.LcleanupEND2:
-
-	testq	%r14, %r14
-	je	9f
-	cmpq	$-EWOULDBLOCK, %r14
-	jne	33f
-
-9:
-# if VALUE == 0
-	movl	(%r12), %eax
-# else
-	movl	VALUE(%r12), %eax
-# endif
-8:	testl	%eax, %eax
-	je	7b
-
-	leaq	-1(%rax), %rcx
-	LOCK
-# if VALUE == 0
-	cmpxchgl %ecx, (%r12)
-# else
-	cmpxchgl %ecx, VALUE(%r12)
-# endif
-	jne	8b
-
-	xorl	%eax, %eax
-
-45:	LOCK
-	LP_OP(sub) $1, NWAITERS(%r12)
-
-	addq	$STACKFRAME, %rsp
-	cfi_adjust_cfa_offset(-STACKFRAME)
-	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_adjust_cfa_offset(STACKFRAME + 3 * 8)
-	cfi_rel_offset(%r12, STACKFRAME + 2 * 8)
-	cfi_rel_offset(%r13, STACKFRAME + 1 * 8)
-	cfi_rel_offset(%r14, STACKFRAME)
-33:	negq	%r14
-36:
-	movq	errno@gottpoff(%rip), %rdx
-	movl	%r14d, %fs:(%rdx)
-
-	orl	$-1, %eax
-	jmp	45b
-#endif
-	cfi_endproc
-	.size	sem_timedwait,.-sem_timedwait
-
-
-	.type	sem_timedwait_cleanup,@function
-sem_timedwait_cleanup:
-	cfi_startproc
-	cfi_adjust_cfa_offset(8)
-
-	movq	(%rsp), %rdi
-	LOCK
-	LP_OP(sub) $1, NWAITERS(%rdi)
-	movq	%rax, %rdi
-.LcallUR:
-	call	_Unwind_Resume@PLT
-	hlt
-.LENDCODE:
-	cfi_endproc
-	.size	sem_timedwait_cleanup,.-sem_timedwait_cleanup
-
-
-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
-	.type	sem_timedwait_cleanup2,@function
-sem_timedwait_cleanup2:
-	cfi_startproc
-	cfi_adjust_cfa_offset(STACKFRAME + 3 * 8)
-	cfi_rel_offset(%r12, STACKFRAME + 2 * 8)
-	cfi_rel_offset(%r13, STACKFRAME + 1 * 8)
-	cfi_rel_offset(%r14, STACKFRAME)
-
-	LOCK
-	LP_OP(sub) $1, NWAITERS(%r12)
-	movq	%rax, %rdi
-	movq	STACKFRAME(%rsp), %r14
-	movq	STACKFRAME+8(%rsp), %r13
-	movq	STACKFRAME+16(%rsp), %r12
-.LcallUR2:
-	call	_Unwind_Resume@PLT
-	hlt
-.LENDCODE2:
-	cfi_endproc
-	.size	sem_timedwait_cleanup2,.-sem_timedwait_cleanup2
-#endif
-
-
-	.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 sem_timedwait_cleanup-.LSTARTCODE
-	.uleb128  0
-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
-	.uleb128 .LcleanupSTART2-.LSTARTCODE
-	.uleb128 .LcleanupEND2-.LcleanupSTART2
-	.uleb128 sem_timedwait_cleanup2-.LSTARTCODE
-	.uleb128  0
-#endif
-	.uleb128 .LcallUR-.LSTARTCODE
-	.uleb128 .LENDCODE-.LcallUR
-	.uleb128 0
-	.uleb128  0
-#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
-	.uleb128 .LcallUR2-.LSTARTCODE
-	.uleb128 .LENDCODE2-.LcallUR2
-	.uleb128 0
-	.uleb128  0
-#endif
-.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/sem_trywait.S b/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S
deleted file mode 100644
index 1893a34..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright (C) 2002-2014 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 <lowlevellock.h>
-#include <shlib-compat.h>
-#include <pthread-errnos.h>
-
-	.text
-
-	.globl	sem_trywait
-	.type	sem_trywait,@function
-	.align	16
-sem_trywait:
-	movl	(%rdi), %eax
-2:	testl	%eax, %eax
-	jz	1f
-
-	leal	-1(%rax), %edx
-	LOCK
-	cmpxchgl %edx, (%rdi)
-	jne	2b
-
-	xorl	%eax, %eax
-	retq
-
-1:
-	movq	errno@gottpoff(%rip), %rdx
-	movl	$EAGAIN, %fs:(%rdx)
-	orl	$-1, %eax
-	retq
-	.size	sem_trywait,.-sem_trywait
diff --git a/sysdeps/unix/sysv/linux/x86_64/sem_wait.S b/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
deleted file mode 100644
index 8f4d068..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
+++ /dev/null
@@ -1,176 +0,0 @@
-/* Copyright (C) 2002-2014 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 <lowlevellock.h>
-#include <shlib-compat.h>
-#include <pthread-errnos.h>
-#include <structsem.h>
-
-
-	.text
-
-	.globl	sem_wait
-	.type	sem_wait,@function
-	.align	16
-sem_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
-
-#if VALUE == 0
-	movl	(%rdi), %eax
-#else
-	movl	VALUE(%rdi), %eax
-#endif
-2:	testl	%eax, %eax
-	je	1f
-
-	leal	-1(%rax), %edx
-	LOCK
-#if VALUE == 0
-	cmpxchgl %edx, (%rdi)
-#else
-	cmpxchgl %edx, VALUE(%rdi)
-#endif
-	jne	2b
-
-	xorl	%eax, %eax
-	retq
-
-	/* This push is only needed to store the sem_t pointer for the
-	   exception handler.  */
-1:	pushq	%rdi
-	cfi_adjust_cfa_offset(8)
-
-	LOCK
-	LP_OP(add) $1, NWAITERS(%rdi)
-
-.LcleanupSTART:
-6:	call	__pthread_enable_asynccancel
-	movl	%eax, %r8d
-
-	xorq	%r10, %r10
-	movl	$SYS_futex, %eax
-#if FUTEX_WAIT == 0
-	movl	PRIVATE(%rdi), %esi
-#else
-	movl	$FUTEX_WAIT, %esi
-	orl	PRIVATE(%rdi), %esi
-#endif
-	xorl	%edx, %edx
-	syscall
-	movq	%rax, %rcx
-
-	xchgq	%r8, %rdi
-	call	__pthread_disable_asynccancel
-.LcleanupEND:
-	movq	%r8, %rdi
-
-	testq	%rcx, %rcx
-	je	3f
-	cmpq	$-EWOULDBLOCK, %rcx
-	jne	4f
-
-3:
-#if VALUE == 0
-	movl	(%rdi), %eax
-#else
-	movl	VALUE(%rdi), %eax
-#endif
-5:	testl	%eax, %eax
-	je	6b
-
-	leal	-1(%rax), %edx
-	LOCK
-#if VALUE == 0
-	cmpxchgl %edx, (%rdi)
-#else
-	cmpxchgl %edx, VALUE(%rdi)
-#endif
-	jne	5b
-
-	xorl	%eax, %eax
-
-9:	LOCK
-	LP_OP(sub) $1, NWAITERS(%rdi)
-
-	leaq	8(%rsp), %rsp
-	cfi_adjust_cfa_offset(-8)
-
-	retq
-
-	cfi_adjust_cfa_offset(8)
-4:	negq	%rcx
-	movq	errno@gottpoff(%rip), %rdx
-	movl	%ecx, %fs:(%rdx)
-	orl	$-1, %eax
-
-	jmp 9b
-	.size	sem_wait,.-sem_wait
-
-
-	.type	sem_wait_cleanup,@function
-sem_wait_cleanup:
-	movq	(%rsp), %rdi
-	LOCK
-	LP_OP(sub) $1, NWAITERS(%rdi)
-	movq	%rax, %rdi
-.LcallUR:
-	call	_Unwind_Resume@PLT
-	hlt
-.LENDCODE:
-	cfi_endproc
-	.size	sem_wait_cleanup,.-sem_wait_cleanup
-
-
-	.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 sem_wait_cleanup-.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

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/3] Fix semaphore destruction (BZ #12674)
  2014-12-05 18:37 [PATCH 0/3] Fix semaphore destruction (BZ #12674) Torvald Riegel
                   ` (2 preceding siblings ...)
  2014-12-05 19:24 ` [PATCH 3/3] Update to new generic semaphore algorithm Torvald Riegel
@ 2014-12-05 20:30 ` Rich Felker
  3 siblings, 0 replies; 19+ messages in thread
From: Rich Felker @ 2014-12-05 20:30 UTC (permalink / raw)
  To: libc-alpha

On Fri, Dec 05, 2014 at 07:37:48PM +0100, Torvald Riegel wrote:
> This patch set fixes
> https://sourceware.org/bugzilla/show_bug.cgi?id=12674 by either using
> 64b atomic operations (where available), or by using two separate fields
> when only 32b atomic operations are available.  In the latter case, we
> keep a conservative estimate of whether there are any waiting threads in
> one bit of the field that counts the number of available tokens, thus
> allowing sem_post to atomically both add a token and determine whether
> it needs to call futex_wake.
> 
> The first two patches are changes to the tests, the last big patch is
> where the actual fix resides.

I haven't read the code, but per your description of the changes, the
concepts all sound correct.

Rich

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6.
  2014-12-05 18:53 ` [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6 Torvald Riegel
@ 2014-12-06 13:50   ` Ondřej Bílka
  2014-12-08 11:43     ` Torvald Riegel
  0 siblings, 1 reply; 19+ messages in thread
From: Ondřej Bílka @ 2014-12-06 13:50 UTC (permalink / raw)
  To: Torvald Riegel; +Cc: GLIBC Devel

On Fri, Dec 05, 2014 at 07:52:57PM +0100, Torvald Riegel wrote:
>    alarm (1);
>  
>    int res = sem_wait (&s);
> -  if (res == 0)
> -    {
> -      puts ("wait succeeded");
> -      return 1;
> -    }
> -  if (res != -1 || errno != EINTR)
> +  /* We accept all allowed behavior: Implementations that return EINTR and
> +     those that rely on correct interruption through signals to use sem_post
> +     in the signal handler.  */
> +  if (res != 0 && !(res == -1 && errno == EINTR))
>      {
> -      puts ("wait didn't fail with EINTR");
> +      puts ("wait neiter succeeded nor failed with EINTR");
>        return 1;
>      }
>  

That does change test logic as it originally failed when wait succeeded.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/3] Fix nptl/tst-sem4: always start with a fresh semaphore.
  2014-12-05 19:03 ` [PATCH 2/3] Fix nptl/tst-sem4: always start with a fresh semaphore Torvald Riegel
@ 2014-12-06 13:55   ` Ondřej Bílka
  0 siblings, 0 replies; 19+ messages in thread
From: Ondřej Bílka @ 2014-12-06 13:55 UTC (permalink / raw)
  To: Torvald Riegel; +Cc: GLIBC Devel

On Fri, Dec 05, 2014 at 08:03:42PM +0100, Torvald Riegel wrote:
> This just makes sure that if this test fails, new runs of the test will
> start from a fresh state.

Looks ok.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6.
  2014-12-06 13:50   ` Ondřej Bílka
@ 2014-12-08 11:43     ` Torvald Riegel
  2014-12-08 22:29       ` Ondřej Bílka
  0 siblings, 1 reply; 19+ messages in thread
From: Torvald Riegel @ 2014-12-08 11:43 UTC (permalink / raw)
  To: Ondřej Bílka; +Cc: GLIBC Devel

On Sat, 2014-12-06 at 14:50 +0100, Ondřej Bílka wrote:
> On Fri, Dec 05, 2014 at 07:52:57PM +0100, Torvald Riegel wrote:
> >    alarm (1);
> >  
> >    int res = sem_wait (&s);
> > -  if (res == 0)
> > -    {
> > -      puts ("wait succeeded");
> > -      return 1;
> > -    }
> > -  if (res != -1 || errno != EINTR)
> > +  /* We accept all allowed behavior: Implementations that return EINTR and
> > +     those that rely on correct interruption through signals to use sem_post
> > +     in the signal handler.  */
> > +  if (res != 0 && !(res == -1 && errno == EINTR))
> >      {
> > -      puts ("wait didn't fail with EINTR");
> > +      puts ("wait neiter succeeded nor failed with EINTR");
> >        return 1;
> >      }
> >  
> 
> That does change test logic as it originally failed when wait succeeded.

Yes, but why do you think that this is inconsistent?  The previous test
didn't add a token in the signal handler, so if wait succeeded, then the
test should fail.

However, the correct way to interrupt the semaphore with a signal is to
add a token.  My patch does that.  Second, if we do not want to make
timing assumptions (which the existing test would do if we add a token
to the semaphore in the signal handler), then we need to accept that the
(first) signal handler execution might happen before sem_wait actually
executes.  Therefore, we must not fail in this case.

We have to correctly interrupt with signals because as the futex
documentation stands (allowing return of EINTR on spurious wake-ups),
there's no way to implement the specific behavior of the existing
implementation (which assumes EINTR is returned *only* on signals).

IOW, the existing test does white-box testing with timing assumptions;
with this patch, we do make a slightly different black-box test with no
timing assumptions.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6.
  2014-12-08 11:43     ` Torvald Riegel
@ 2014-12-08 22:29       ` Ondřej Bílka
  2014-12-09 10:16         ` Torvald Riegel
  0 siblings, 1 reply; 19+ messages in thread
From: Ondřej Bílka @ 2014-12-08 22:29 UTC (permalink / raw)
  To: Torvald Riegel; +Cc: GLIBC Devel

On Mon, Dec 08, 2014 at 12:43:17PM +0100, Torvald Riegel wrote:
> On Sat, 2014-12-06 at 14:50 +0100, Ondřej Bílka wrote:
> > On Fri, Dec 05, 2014 at 07:52:57PM +0100, Torvald Riegel wrote:
> > >    alarm (1);
> > >  
> > >    int res = sem_wait (&s);
> > > -  if (res == 0)
> > > -    {
> > > -      puts ("wait succeeded");
> > > -      return 1;
> > > -    }
> > > -  if (res != -1 || errno != EINTR)
> > > +  /* We accept all allowed behavior: Implementations that return EINTR and
> > > +     those that rely on correct interruption through signals to use sem_post
> > > +     in the signal handler.  */
> > > +  if (res != 0 && !(res == -1 && errno == EINTR))
> > >      {
> > > -      puts ("wait didn't fail with EINTR");
> > > +      puts ("wait neiter succeeded nor failed with EINTR");
> > >        return 1;
> > >      }
> > >  
> > 
> > That does change test logic as it originally failed when wait succeeded.
> 
> Yes, but why do you think that this is inconsistent?  The previous test
> didn't add a token in the signal handler, so if wait succeeded, then the
> test should fail.
> 
> However, the correct way to interrupt the semaphore with a signal is to
> add a token.  My patch does that.  Second, if we do not want to make
> timing assumptions (which the existing test would do if we add a token
> to the semaphore in the signal handler), then we need to accept that the
> (first) signal handler execution might happen before sem_wait actually
> executes.  Therefore, we must not fail in this case.
> 
> We have to correctly interrupt with signals because as the futex
> documentation stands (allowing return of EINTR on spurious wake-ups),
> there's no way to implement the specific behavior of the existing
> implementation (which assumes EINTR is returned *only* on signals).
> 
> IOW, the existing test does white-box testing with timing assumptions;
> with this patch, we do make a slightly different black-box test with no
> timing assumptions.

Which misses point of test which is to find bugs. What if in new fooarch 
assembly one forget to return -1 on interrupt which breaks user application 
which will assume that semaphore is locked, one can deal with rare false 
positives in tests.

One does not need justify this fact by forward progress/fairness
assumptions. Just assumption that OS which keeps all CPU idle for one
second while there is suitable task is simply broken. It would be better
to add serialization so no other test runs in parallel with this.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6.
  2014-12-08 22:29       ` Ondřej Bílka
@ 2014-12-09 10:16         ` Torvald Riegel
  2014-12-09 16:50           ` Ondřej Bílka
  0 siblings, 1 reply; 19+ messages in thread
From: Torvald Riegel @ 2014-12-09 10:16 UTC (permalink / raw)
  To: Ondřej Bílka; +Cc: GLIBC Devel

On Mon, 2014-12-08 at 23:28 +0100, Ondřej Bílka wrote:
> On Mon, Dec 08, 2014 at 12:43:17PM +0100, Torvald Riegel wrote:
> > On Sat, 2014-12-06 at 14:50 +0100, Ondřej Bílka wrote:
> > > On Fri, Dec 05, 2014 at 07:52:57PM +0100, Torvald Riegel wrote:
> > > >    alarm (1);
> > > >  
> > > >    int res = sem_wait (&s);
> > > > -  if (res == 0)
> > > > -    {
> > > > -      puts ("wait succeeded");
> > > > -      return 1;
> > > > -    }
> > > > -  if (res != -1 || errno != EINTR)
> > > > +  /* We accept all allowed behavior: Implementations that return EINTR and
> > > > +     those that rely on correct interruption through signals to use sem_post
> > > > +     in the signal handler.  */
> > > > +  if (res != 0 && !(res == -1 && errno == EINTR))
> > > >      {
> > > > -      puts ("wait didn't fail with EINTR");
> > > > +      puts ("wait neiter succeeded nor failed with EINTR");
> > > >        return 1;
> > > >      }
> > > >  
> > > 
> > > That does change test logic as it originally failed when wait succeeded.
> > 
> > Yes, but why do you think that this is inconsistent?  The previous test
> > didn't add a token in the signal handler, so if wait succeeded, then the
> > test should fail.
> > 
> > However, the correct way to interrupt the semaphore with a signal is to
> > add a token.  My patch does that.  Second, if we do not want to make
> > timing assumptions (which the existing test would do if we add a token
> > to the semaphore in the signal handler), then we need to accept that the
> > (first) signal handler execution might happen before sem_wait actually
> > executes.  Therefore, we must not fail in this case.
> > 
> > We have to correctly interrupt with signals because as the futex
> > documentation stands (allowing return of EINTR on spurious wake-ups),
> > there's no way to implement the specific behavior of the existing
> > implementation (which assumes EINTR is returned *only* on signals).
> > 
> > IOW, the existing test does white-box testing with timing assumptions;
> > with this patch, we do make a slightly different black-box test with no
> > timing assumptions.
> 
> Which misses point of test which is to find bugs.

Please read the POSIX spec.  It allows both outcomes, and without timing
assumptions etc., we can't drive executions towards just one of the
outcomes.

> What if in new fooarch 
> assembly one forget to return -1 on interrupt which breaks user application 
> which will assume that semaphore is locked,

I can strengthen the test on res==0, checking whether there is no token
left.  I don't think it buys us much though.

Another option would be to disallow failure; however, this only works if
sem_assume_only_signals_cause_futex_EINTR remains 0 and not set to a
different value by a distribution (see Patch 3/3).

> one can deal with rare false 
> positives in tests.

I think you'd be creating false negatives with what you have in mind.
The false positive would be not failing when 0 is returned, incorrectly,
ie your example.

False negatives are a pain.  You can deal with them of course, but it
stands in the way of doing continuous integration and such.  what we de
facto do is just ignore all tests that we know can have false negatives,
which doesn't make the test useful at all.

> One does not need justify this fact by forward progress/fairness
> assumptions. Just assumption that OS which keeps all CPU idle for one
> second while there is suitable task is simply broken.

Well, that *is* a timing assumption.  There is nothing broken about this
in general.  Remember that we do have tests failing now and then just
because of that.  Which is awful for testing.

> It would be better
> to add serialization so no other test runs in parallel with this.

You can't prevent other load on the machine in general.

Also, please review the actual background for this change.  See patch
3/3 for that.  The change to the test is not ideal, but please see the
trade-offs.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6.
  2014-12-09 10:16         ` Torvald Riegel
@ 2014-12-09 16:50           ` Ondřej Bílka
  2014-12-09 18:25             ` Torvald Riegel
  0 siblings, 1 reply; 19+ messages in thread
From: Ondřej Bílka @ 2014-12-09 16:50 UTC (permalink / raw)
  To: Torvald Riegel; +Cc: GLIBC Devel

On Tue, Dec 09, 2014 at 11:16:00AM +0100, Torvald Riegel wrote:
> On Mon, 2014-12-08 at 23:28 +0100, Ondřej Bílka wrote:
> > On Mon, Dec 08, 2014 at 12:43:17PM +0100, Torvald Riegel wrote:
> > > On Sat, 2014-12-06 at 14:50 +0100, Ondřej Bílka wrote:
> > > > On Fri, Dec 05, 2014 at 07:52:57PM +0100, Torvald Riegel wrote:
> > > > >    alarm (1);
> > > > >  
> > > > >    int res = sem_wait (&s);
> > > > > -  if (res == 0)
> > > > > -    {
> > > > > -      puts ("wait succeeded");
> > > > > -      return 1;
> > > > > -    }
> > > > > -  if (res != -1 || errno != EINTR)
> > > > > +  /* We accept all allowed behavior: Implementations that return EINTR and
> > > > > +     those that rely on correct interruption through signals to use sem_post
> > > > > +     in the signal handler.  */
> > > > > +  if (res != 0 && !(res == -1 && errno == EINTR))
> > > > >      {
> > > > > -      puts ("wait didn't fail with EINTR");
> > > > > +      puts ("wait neiter succeeded nor failed with EINTR");
> > > > >        return 1;
> > > > >      }
> > > > >  
> > > > 
> > > > That does change test logic as it originally failed when wait succeeded.
> > > 
> > > Yes, but why do you think that this is inconsistent?  The previous test
> > > didn't add a token in the signal handler, so if wait succeeded, then the
> > > test should fail.
> > > 
> > > However, the correct way to interrupt the semaphore with a signal is to
> > > add a token.  My patch does that.  Second, if we do not want to make
> > > timing assumptions (which the existing test would do if we add a token
> > > to the semaphore in the signal handler), then we need to accept that the
> > > (first) signal handler execution might happen before sem_wait actually
> > > executes.  Therefore, we must not fail in this case.
> > > 
> > > We have to correctly interrupt with signals because as the futex
> > > documentation stands (allowing return of EINTR on spurious wake-ups),
> > > there's no way to implement the specific behavior of the existing
> > > implementation (which assumes EINTR is returned *only* on signals).
> > > 
> > > IOW, the existing test does white-box testing with timing assumptions;
> > > with this patch, we do make a slightly different black-box test with no
> > > timing assumptions.
> > 
> > Which misses point of test which is to find bugs.
> 
> Please read the POSIX spec.  It allows both outcomes, and without timing
> assumptions etc., we can't drive executions towards just one of the
> outcomes.
>
Which does not answer my objection. What extra bugs could this test catch,
compared to say tst-sem2? If there is no such bug you could just delete
that file.


> > What if in new fooarch 
> > assembly one forget to return -1 on interrupt which breaks user application 
> > which will assume that semaphore is locked,
> 
> I can strengthen the test on res==0, checking whether there is no token
> left.  I don't think it buys us much though.
> 
> Another option would be to disallow failure; however, this only works if
> sem_assume_only_signals_cause_futex_EINTR remains 0 and not set to a
> different value by a distribution (see Patch 3/3).
> 
> > one can deal with rare false 
> > positives in tests.
> 
> I think you'd be creating false negatives with what you have in mind.
> The false positive would be not failing when 0 is returned, incorrectly,
> ie your example.
>
Depends whats your default. Usually false positive means that test shows
there is disease/bug but not in reality.
 
> False negatives are a pain.  You can deal with them of course, but it
> stands in the way of doing continuous integration and such.  what we de
> facto do is just ignore all tests that we know can have false negatives,
> which doesn't make the test useful at all.
> 
> > One does not need justify this fact by forward progress/fairness
> > assumptions. Just assumption that OS which keeps all CPU idle for one
> > second while there is suitable task is simply broken.
> 
> Well, that *is* a timing assumption.  There is nothing broken about this
> in general.  Remember that we do have tests failing now and then just
> because of that.  Which is awful for testing.
> 
Without that assumption there is no guarantee that it will take more
than week to run test suite. That would make it useless.

As failing tests are concerned what is low hanging fruit? It is better
to first fix tests that fail with less load than this one and if one of these
is not worth fixing this is not either.

> > It would be better
> > to add serialization so no other test runs in parallel with this.
> 
> You can't prevent other load on the machine in general.
> 
Its not general case, its when you run test suite, its tradeoff between
how many bugs it can detect and needed mainteinance.


> Also, please review the actual background for this change.  See patch
> 3/3 for that.  The change to the test is not ideal, but please see the
> trade-offs.

The rarity of problem bugged me, as to trigger that behaviour one would
need run also highly parallel program so it looked unlikely that anybody
would report that. As it couldn't detect some bugs it previously could
its hard to see what is better. 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6.
  2014-12-09 16:50           ` Ondřej Bílka
@ 2014-12-09 18:25             ` Torvald Riegel
  2014-12-09 18:37               ` Rich Felker
  0 siblings, 1 reply; 19+ messages in thread
From: Torvald Riegel @ 2014-12-09 18:25 UTC (permalink / raw)
  To: Ondřej Bílka; +Cc: GLIBC Devel

On Tue, 2014-12-09 at 17:50 +0100, Ondřej Bílka wrote:
> On Tue, Dec 09, 2014 at 11:16:00AM +0100, Torvald Riegel wrote:
> > On Mon, 2014-12-08 at 23:28 +0100, Ondřej Bílka wrote:
> > > On Mon, Dec 08, 2014 at 12:43:17PM +0100, Torvald Riegel wrote:
> > > > On Sat, 2014-12-06 at 14:50 +0100, Ondřej Bílka wrote:
> > > > > On Fri, Dec 05, 2014 at 07:52:57PM +0100, Torvald Riegel wrote:
> > > > > >    alarm (1);
> > > > > >  
> > > > > >    int res = sem_wait (&s);
> > > > > > -  if (res == 0)
> > > > > > -    {
> > > > > > -      puts ("wait succeeded");
> > > > > > -      return 1;
> > > > > > -    }
> > > > > > -  if (res != -1 || errno != EINTR)
> > > > > > +  /* We accept all allowed behavior: Implementations that return EINTR and
> > > > > > +     those that rely on correct interruption through signals to use sem_post
> > > > > > +     in the signal handler.  */
> > > > > > +  if (res != 0 && !(res == -1 && errno == EINTR))
> > > > > >      {
> > > > > > -      puts ("wait didn't fail with EINTR");
> > > > > > +      puts ("wait neiter succeeded nor failed with EINTR");
> > > > > >        return 1;
> > > > > >      }
> > > > > >  
> > > > > 
> > > > > That does change test logic as it originally failed when wait succeeded.
> > > > 
> > > > Yes, but why do you think that this is inconsistent?  The previous test
> > > > didn't add a token in the signal handler, so if wait succeeded, then the
> > > > test should fail.
> > > > 
> > > > However, the correct way to interrupt the semaphore with a signal is to
> > > > add a token.  My patch does that.  Second, if we do not want to make
> > > > timing assumptions (which the existing test would do if we add a token
> > > > to the semaphore in the signal handler), then we need to accept that the
> > > > (first) signal handler execution might happen before sem_wait actually
> > > > executes.  Therefore, we must not fail in this case.
> > > > 
> > > > We have to correctly interrupt with signals because as the futex
> > > > documentation stands (allowing return of EINTR on spurious wake-ups),
> > > > there's no way to implement the specific behavior of the existing
> > > > implementation (which assumes EINTR is returned *only* on signals).
> > > > 
> > > > IOW, the existing test does white-box testing with timing assumptions;
> > > > with this patch, we do make a slightly different black-box test with no
> > > > timing assumptions.
> > > 
> > > Which misses point of test which is to find bugs.
> > 
> > Please read the POSIX spec.  It allows both outcomes, and without timing
> > assumptions etc., we can't drive executions towards just one of the
> > outcomes.
> >
> Which does not answer my objection. What extra bugs could this test catch,
> compared to say tst-sem2? If there is no such bug you could just delete
> that file.

tst-sem2 tests that spurious wake-ups and such don't return anything but
-1 and errno==EINTR, in particular that 0 isn't returned.

After the patch, tst-sem6 tests that a signal handler that posts a token
will make sem_wait return.  It *also* allows for sem_wait to return -1
and errno==EINTR in that case.

Thus, one possible error that the patched tst-sem6 will catch is if the
sem_wait itself just retries the futex_wait after the futex_wait
returned EINTR, instead of looking for whether there is an available
token.

> 
> > > What if in new fooarch 
> > > assembly one forget to return -1 on interrupt which breaks user application 
> > > which will assume that semaphore is locked,
> > 
> > I can strengthen the test on res==0, checking whether there is no token
> > left.  I don't think it buys us much though.
> > 
> > Another option would be to disallow failure; however, this only works if
> > sem_assume_only_signals_cause_futex_EINTR remains 0 and not set to a
> > different value by a distribution (see Patch 3/3).
> > 
> > > one can deal with rare false 
> > > positives in tests.
> > 
> > I think you'd be creating false negatives with what you have in mind.
> > The false positive would be not failing when 0 is returned, incorrectly,
> > ie your example.
> >
> Depends whats your default. Usually false positive means that test shows
> there is disease/bug but not in reality.

I disagree regarding "usually", and would say that a negative result for
a test is if the test fails, so false negative being a reportedly failed
test that was not caused by an actual fault.
Nonetheless, we seem to be on the same page regarding what we want to
avoid.

> > False negatives are a pain.  You can deal with them of course, but it
> > stands in the way of doing continuous integration and such.  what we de
> > facto do is just ignore all tests that we know can have false negatives,
> > which doesn't make the test useful at all.
> > 
> > > One does not need justify this fact by forward progress/fairness
> > > assumptions. Just assumption that OS which keeps all CPU idle for one
> > > second while there is suitable task is simply broken.
> > 
> > Well, that *is* a timing assumption.  There is nothing broken about this
> > in general.  Remember that we do have tests failing now and then just
> > because of that.  Which is awful for testing.
> > 
> Without that assumption there is no guarantee that it will take more
> than week to run test suite. That would make it useless.

There are timing assumptions that state something like "after a second,
the thread will have been scheduled".  Those are bad, because they state
a concrete bound (1s in this example).

The forward progress guarantees that make sense for us, in particular in
non-real-time systems, are instead of the form "something good will
*eventually* happen".  In other words, there's no concrete bound
promised, but that there is a (finite) bound.

That's an important difference.

> > Also, please review the actual background for this change.  See patch
> > 3/3 for that.  The change to the test is not ideal, but please see the
> > trade-offs.
> 
> The rarity of problem bugged me, as to trigger that behaviour one would
> need run also highly parallel program so it looked unlikely that anybody
> would report that. As it couldn't detect some bugs it previously could
> its hard to see what is better. 

Let me try to summarize the background behind this change again:

1) Linux documents futex_wait to return EINTR on signals *or* on
spurious wake-ups.
2) If we treat 1) as true -- which we should to unless getting
confirmation otherwise -- sem_wait must not return EINTR to the caller
anymore if futex_wait returned EINTR.
3) Because of 2), the behavior that is tested in tst-sem6 before my
patch cannot be implemented anymore.

Thus, we need to do *something*.  I proposed this patch, and variations.
If you don't see other alternatives, then I guess we'll have to pick
from the options I gave.

If you disagree with 2), then please comment on Patch 3/3, because
that's where this belongs.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6.
  2014-12-09 18:25             ` Torvald Riegel
@ 2014-12-09 18:37               ` Rich Felker
  2014-12-09 19:47                 ` Torvald Riegel
  0 siblings, 1 reply; 19+ messages in thread
From: Rich Felker @ 2014-12-09 18:37 UTC (permalink / raw)
  To: Torvald Riegel; +Cc: Ondřej Bílka, GLIBC Devel

On Tue, Dec 09, 2014 at 07:24:49PM +0100, Torvald Riegel wrote:
> > Which does not answer my objection. What extra bugs could this test catch,
> > compared to say tst-sem2? If there is no such bug you could just delete
> > that file.
> 
> tst-sem2 tests that spurious wake-ups and such don't return anything but
> -1 and errno==EINTR, in particular that 0 isn't returned.
> 
> After the patch, tst-sem6 tests that a signal handler that posts a token
> will make sem_wait return.  It *also* allows for sem_wait to return -1
> and errno==EINTR in that case.
> 
> Thus, one possible error that the patched tst-sem6 will catch is if the
> sem_wait itself just retries the futex_wait after the futex_wait
> returned EINTR, instead of looking for whether there is an available
> token.

This would not be a bug. Simply retrying the futex_wait would result
in EAGAIN, since the futex value would no longer match.

> > > Also, please review the actual background for this change.  See patch
> > > 3/3 for that.  The change to the test is not ideal, but please see the
> > > trade-offs.
> > 
> > The rarity of problem bugged me, as to trigger that behaviour one would
> > need run also highly parallel program so it looked unlikely that anybody
> > would report that. As it couldn't detect some bugs it previously could
> > its hard to see what is better. 
> 
> Let me try to summarize the background behind this change again:
> 
> 1) Linux documents futex_wait to return EINTR on signals *or* on
> spurious wake-ups.

No, the man pages document this, and they're wrong. I have not seen
any other "Linux documentation" claiming it.

> 2) If we treat 1) as true -- which we should to unless getting
> confirmation otherwise -- sem_wait must not return EINTR to the caller
> anymore if futex_wait returned EINTR.
> 3) Because of 2), the behavior that is tested in tst-sem6 before my
> patch cannot be implemented anymore.

These (2) and (3) are based on false assumptions. I agree this is a
positive change (EINTR is generally undesirable) and it may be
necessary if you want to support old kernels where the futex syscall
could fail with EINTR even when the signal handler was SA_RESTART
type, but I don't think glibc supports those kernels.

> Thus, we need to do *something*.  I proposed this patch, and variations.
> If you don't see other alternatives, then I guess we'll have to pick
> from the options I gave.
> 
> If you disagree with 2), then please comment on Patch 3/3, because
> that's where this belongs.

The most important thing to do is get clarification from the kernel
side that the man page is wrong and that there is no intent to
overload EINTR or allow incorrect/spurious EINTR from futex. This will
possibly affect other interfaces now and in the future, e.g.
aio_suspend. I agree that making sem_[timed]wait ignore EINTR is
desirable too, but I don't think there's any actual current problem
being fixed - the kernel is not generating spurious EINTR, and we just
need to keep it that way.

Rich

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6.
  2014-12-09 18:37               ` Rich Felker
@ 2014-12-09 19:47                 ` Torvald Riegel
  2014-12-09 20:19                   ` Rich Felker
  0 siblings, 1 reply; 19+ messages in thread
From: Torvald Riegel @ 2014-12-09 19:47 UTC (permalink / raw)
  To: Rich Felker; +Cc: Ondřej Bílka, GLIBC Devel

On Tue, 2014-12-09 at 13:36 -0500, Rich Felker wrote:
> On Tue, Dec 09, 2014 at 07:24:49PM +0100, Torvald Riegel wrote:
> > > Which does not answer my objection. What extra bugs could this test catch,
> > > compared to say tst-sem2? If there is no such bug you could just delete
> > > that file.
> > 
> > tst-sem2 tests that spurious wake-ups and such don't return anything but
> > -1 and errno==EINTR, in particular that 0 isn't returned.
> > 
> > After the patch, tst-sem6 tests that a signal handler that posts a token
> > will make sem_wait return.  It *also* allows for sem_wait to return -1
> > and errno==EINTR in that case.
> > 
> > Thus, one possible error that the patched tst-sem6 will catch is if the
> > sem_wait itself just retries the futex_wait after the futex_wait
> > returned EINTR, instead of looking for whether there is an available
> > token.
> 
> This would not be a bug. Simply retrying the futex_wait would result
> in EAGAIN, since the futex value would no longer match.

Right.   So it would catch a bug that did a futex_wait after loading the
new value.

> > > > Also, please review the actual background for this change.  See patch
> > > > 3/3 for that.  The change to the test is not ideal, but please see the
> > > > trade-offs.
> > > 
> > > The rarity of problem bugged me, as to trigger that behaviour one would
> > > need run also highly parallel program so it looked unlikely that anybody
> > > would report that. As it couldn't detect some bugs it previously could
> > > its hard to see what is better. 
> > 
> > Let me try to summarize the background behind this change again:
> > 
> > 1) Linux documents futex_wait to return EINTR on signals *or* on
> > spurious wake-ups.
> 
> No, the man pages document this, and they're wrong. I have not seen
> any other "Linux documentation" claiming it.

But is there other documentation than the man pages?  The sources don't
really count because that's not a guarantee nor a specification, that's
the current implementation.

Also, at least one kernel person seems to have confirmed that the
current manpage is correct: https://lkml.org/lkml/2014/5/15/356

So in absence of any other documentation, I'll follow what we have and
for which we have at least some documentation.

> > 2) If we treat 1) as true -- which we should to unless getting
> > confirmation otherwise -- sem_wait must not return EINTR to the caller
> > anymore if futex_wait returned EINTR.
> > 3) Because of 2), the behavior that is tested in tst-sem6 before my
> > patch cannot be implemented anymore.
> 
> These (2) and (3) are based on false assumptions.

I don't have any evidence to rely on something else.  Don't get me
wrong, if we get confirmation from the kernel that 1) is not true, then
I'm open to doing something else.  But until then, what should we do? 

Also, the change is within what's allowed by POSIX IMO, so we're not
inventing new behavior here.

> I agree this is a
> positive change (EINTR is generally undesirable) and it may be
> necessary if you want to support old kernels where the futex syscall
> could fail with EINTR even when the signal handler was SA_RESTART
> type, but I don't think glibc supports those kernels.
> 
> > Thus, we need to do *something*.  I proposed this patch, and variations.
> > If you don't see other alternatives, then I guess we'll have to pick
> > from the options I gave.
> > 
> > If you disagree with 2), then please comment on Patch 3/3, because
> > that's where this belongs.
> 
> The most important thing to do is get clarification from the kernel
> side that the man page is wrong and that there is no intent to
> overload EINTR or allow incorrect/spurious EINTR from futex.

Once we'll get this, I'll take care to adjust sem_wait accordingly, and
depending on the adjustment, might adapt tst-sem6 as well.

BTW, have you already asked on LKML about this?

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6.
  2014-12-09 19:47                 ` Torvald Riegel
@ 2014-12-09 20:19                   ` Rich Felker
  2014-12-10  9:34                     ` Torvald Riegel
  0 siblings, 1 reply; 19+ messages in thread
From: Rich Felker @ 2014-12-09 20:19 UTC (permalink / raw)
  To: Torvald Riegel; +Cc: Ondřej Bílka, GLIBC Devel

On Tue, Dec 09, 2014 at 07:57:08PM +0100, Torvald Riegel wrote:
> On Tue, 2014-12-09 at 13:36 -0500, Rich Felker wrote:
> > On Tue, Dec 09, 2014 at 07:24:49PM +0100, Torvald Riegel wrote:
> > > > Which does not answer my objection. What extra bugs could this test catch,
> > > > compared to say tst-sem2? If there is no such bug you could just delete
> > > > that file.
> > > 
> > > tst-sem2 tests that spurious wake-ups and such don't return anything but
> > > -1 and errno==EINTR, in particular that 0 isn't returned.
> > > 
> > > After the patch, tst-sem6 tests that a signal handler that posts a token
> > > will make sem_wait return.  It *also* allows for sem_wait to return -1
> > > and errno==EINTR in that case.
> > > 
> > > Thus, one possible error that the patched tst-sem6 will catch is if the
> > > sem_wait itself just retries the futex_wait after the futex_wait
> > > returned EINTR, instead of looking for whether there is an available
> > > token.
> > 
> > This would not be a bug. Simply retrying the futex_wait would result
> > in EAGAIN, since the futex value would no longer match.
> 
> Right.   So it would catch a bug that did a futex_wait after loading the
> new value.

I don't follow. If I understand what type of bug you're talking about,
there's no way such a bug would arise accidentally and only affect
EINTR. It would be a break in the whole usage pattern for futex waits
and would affect EAGAIN and non-spurious wakes too unless someone
intentionally special-cased EINTR to do the wrong thing.

> > > Let me try to summarize the background behind this change again:
> > > 
> > > 1) Linux documents futex_wait to return EINTR on signals *or* on
> > > spurious wake-ups.
> > 
> > No, the man pages document this, and they're wrong. I have not seen
> > any other "Linux documentation" claiming it.
> 
> But is there other documentation than the man pages?  The sources don't
> really count because that's not a guarantee nor a specification, that's
> the current implementation.
> 
> Also, at least one kernel person seems to have confirmed that the
> current manpage is correct: https://lkml.org/lkml/2014/5/15/356

The linked mailing list message does not contain the text EINTR at
all, so I don't see where your claim that it supports the current man
page text about EINTR comes from.

> > > 2) If we treat 1) as true -- which we should to unless getting
> > > confirmation otherwise -- sem_wait must not return EINTR to the caller
> > > anymore if futex_wait returned EINTR.
> > > 3) Because of 2), the behavior that is tested in tst-sem6 before my
> > > patch cannot be implemented anymore.
> > 
> > These (2) and (3) are based on false assumptions.
> 
> I don't have any evidence to rely on something else.  Don't get me
> wrong, if we get confirmation from the kernel that 1) is not true, then
> I'm open to doing something else.  But until then, what should we do? 
> 
> Also, the change is within what's allowed by POSIX IMO, so we're not
> inventing new behavior here.

It's allowed by POSIX, yes, and as I've said before, I agree it's
better behavior -- programming with interrupting signal handlers is a
backwards, bogus practice, and from a hardening standpoint it seems
preferable not to have sem_wait fail at all. I just don't think the
"spurious EINTR is documented" argument should be used to justify such
a change, because accepting spurious EINTR is going to come back to
bite us if there are ever other interfaces (I believe aio_suspend
already is one?) that need to be implemented with futex and need to
report EINTR.

Rich

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6.
  2014-12-09 20:19                   ` Rich Felker
@ 2014-12-10  9:34                     ` Torvald Riegel
  0 siblings, 0 replies; 19+ messages in thread
From: Torvald Riegel @ 2014-12-10  9:34 UTC (permalink / raw)
  To: Rich Felker; +Cc: Ondřej Bílka, GLIBC Devel

On Tue, 2014-12-09 at 15:19 -0500, Rich Felker wrote:
> On Tue, Dec 09, 2014 at 07:57:08PM +0100, Torvald Riegel wrote:
> > On Tue, 2014-12-09 at 13:36 -0500, Rich Felker wrote:
> > > On Tue, Dec 09, 2014 at 07:24:49PM +0100, Torvald Riegel wrote:
> > > > > Which does not answer my objection. What extra bugs could this test catch,
> > > > > compared to say tst-sem2? If there is no such bug you could just delete
> > > > > that file.
> > > > 
> > > > tst-sem2 tests that spurious wake-ups and such don't return anything but
> > > > -1 and errno==EINTR, in particular that 0 isn't returned.
> > > > 
> > > > After the patch, tst-sem6 tests that a signal handler that posts a token
> > > > will make sem_wait return.  It *also* allows for sem_wait to return -1
> > > > and errno==EINTR in that case.
> > > > 
> > > > Thus, one possible error that the patched tst-sem6 will catch is if the
> > > > sem_wait itself just retries the futex_wait after the futex_wait
> > > > returned EINTR, instead of looking for whether there is an available
> > > > token.
> > > 
> > > This would not be a bug. Simply retrying the futex_wait would result
> > > in EAGAIN, since the futex value would no longer match.
> > 
> > Right.   So it would catch a bug that did a futex_wait after loading the
> > new value.
> 
> I don't follow. If I understand what type of bug you're talking about,
> there's no way such a bug would arise accidentally and only affect
> EINTR. It would be a break in the whole usage pattern for futex waits
> and would affect EAGAIN and non-spurious wakes too unless someone
> intentionally special-cased EINTR to do the wrong thing.
> 
> > > > Let me try to summarize the background behind this change again:
> > > > 
> > > > 1) Linux documents futex_wait to return EINTR on signals *or* on
> > > > spurious wake-ups.
> > > 
> > > No, the man pages document this, and they're wrong. I have not seen
> > > any other "Linux documentation" claiming it.
> > 
> > But is there other documentation than the man pages?  The sources don't
> > really count because that's not a guarantee nor a specification, that's
> > the current implementation.
> > 
> > Also, at least one kernel person seems to have confirmed that the
> > current manpage is correct: https://lkml.org/lkml/2014/5/15/356
> 
> The linked mailing list message does not contain the text EINTR at
> all, so I don't see where your claim that it supports the current man
> page text about EINTR comes from.

The mail states:

FUTEX_WAIT

	< Existing blurb seems ok >

... and then it goes on providing revised documentation for some of the
previously documented error codes and adds documentation for a few
additional ones.  It doesn't mention 0 or EINTR otherwise, so I read
this as meaning that the docs for 0 and EINTR are correct.

> > > > 2) If we treat 1) as true -- which we should to unless getting
> > > > confirmation otherwise -- sem_wait must not return EINTR to the caller
> > > > anymore if futex_wait returned EINTR.
> > > > 3) Because of 2), the behavior that is tested in tst-sem6 before my
> > > > patch cannot be implemented anymore.
> > > 
> > > These (2) and (3) are based on false assumptions.
> > 
> > I don't have any evidence to rely on something else.  Don't get me
> > wrong, if we get confirmation from the kernel that 1) is not true, then
> > I'm open to doing something else.  But until then, what should we do? 
> > 
> > Also, the change is within what's allowed by POSIX IMO, so we're not
> > inventing new behavior here.
> 
> It's allowed by POSIX, yes, and as I've said before, I agree it's
> better behavior -- programming with interrupting signal handlers is a
> backwards, bogus practice, and from a hardening standpoint it seems
> preferable not to have sem_wait fail at all.

Okay.

> I just don't think the
> "spurious EINTR is documented" argument should be used to justify such
> a change, because accepting spurious EINTR is going to come back to
> bite us if there are ever other interfaces (I believe aio_suspend
> already is one?) that need to be implemented with futex and need to
> report EINTR.

I don't want to argue against that.  But we need to separate the issues
here.  This topic is something that the kernel has to decide, so we can
only discuss this with them.  Whether or not glibc sem_wait follows
what's currently documented doesn't change that other decision at all.

Thus, let's keep those separate topics separate.  We can try to clarify
with the kernel folks re EINTR before we agree on the new semaphore
implementation, but I wouldn't like to hold up the new semaphore just
because we can't agree with the kernel soon enough.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] Update to new generic semaphore algorithm.
  2014-12-05 19:24 ` [PATCH 3/3] Update to new generic semaphore algorithm Torvald Riegel
@ 2014-12-15 21:59   ` Torvald Riegel
  2018-05-08 14:00   ` Andreas Schwab
  1 sibling, 0 replies; 19+ messages in thread
From: Torvald Riegel @ 2014-12-15 21:59 UTC (permalink / raw)
  To: GLIBC Devel

Ping.

I'm aware I'm still discussing the futex API patches with Roland, but
this patch here is the core of this patch set and just needs *some* way
to do futex syscalls.  (IOW, whatever the outcome of the futex API
patch, this patch will not be significantly affected.)

On Fri, 2014-12-05 at 20:24 +0100, Torvald Riegel wrote:
> This changes the generic C implementation of semaphores to use different
> algorithms.  The core issue of the old implementation was that it kept
> two fields for both the value of the semaphore (ie, how many tokens it
> has that can be acquired by sem_wait calls) and the number of threads
> waiting to acquire a token using a futex_wait.  We want to track the
> latter to be able to avoid calling futex_wake if there is actually no
> waiter.  We can't put both of these counters into one 32b field because
> of the number of threads and or tokens we need to support.
> 
> When users try to use sem_wait in the way discussed in
> http://austingroupbugs.net/view.php?id=811 then one thread calls
> sem_post, and another calls sem_wait *and* expects that once it has the
> token (ie, sem_wait has returned), it can call sem_destroy.
> 
> Therefore, the implementation needs to ensure that sem_post makes no
> access to the semaphore data structure after it has provided a token.
> If we have 64b atomic operations, we can atomically increment the value
> of the semaphore and load the field counting the number of waiters.
> If we just have 32b operations, we need to do something more involved.
> The key here is to track a conservative value for the number of waiters
> in one bit of the value, and use that.  Because it's a conservative
> value, it may be wrong and we may call futex_wake unnecessarily under
> some conditions.  When we reset this bit (ie, speculate that there are
> no other waiters), we can be wrong but can make this misspeculation
> harmless if we wake as many waiters as there are tokens available.  We
> do all these latter steps in sem_wait to still satisfy the requirement
> for sem_post regarding not accessing the semaphore after providing a
> token.
> Detailed comments can be found in the patch itself; see nptl/sem_wait.c.
> 
> The semaphore data structure is adapted accordingly, as are other
> related functions: sem_open, sem_init, sem_getvalue, sem_trywait,
> sem_timedwait.
> because sem_trywait and sem_timedwait are very small, it seemed best to
> simply put them all into sem_wait.c
> 
> I removed nptl/DESIGN-sem.txt because it was outdated and the comments
> in the code provide much more detail.
> 
> The changes to tst-sem11 and tst-sem13 are simple adaptions; they peek
> inside the semaphore data structure.
> 
> The custom assembler implementations on x86, x86_64, and sh have been
> removed.
> 
> alpha and powerpc had custom sem_post implementations, but all that
> those were lacking compared to the generic version was a write barrier
> in sem_post.  The new algorithm is correctly synchronized; for the old
> version of sem_post, I have added a call to atomic_write_barrier
> directly.  This allows us to remove the custom alpha and powerpc
> variants.
> 
> sparc still has its own semaphore implementation.  I'd like to get
> feedback from sparc maintainers regarding what should happen with it.
> 
> Note that this patch set is on top of the patch providing a new internal
> futex API: https://sourceware.org/ml/libc-alpha/2014-12/msg00154.html
> 
> Tested on x86 and x86_64.  I have not tested the old versions
> (__old_sem*) yet.
> 
> 
> 
> 	[BZ #12674]
> 	* nptl/sem_wait.c(__new_sem_wait_fast): New function.  Implement
> 	new semaphore algorithms.
> 	(__new_sem_wait_slow): New function.
> 	(__sem_wait_32_finish): New function.
> 	(__sem_wait_cleanup): Adapt.
> 	(do_futex_wait_inner): Adapt.
> 	(do_futex_wait): Adapt.
> 	(__new_sem_wait): Adapt.
> 	(sem_timedwait): New function.
> 	(__new_sem_trywait): New function.
> 	(__old_sem_trywait): Moved here from nptl/sem_trywait.c.
> 	* nptl/sem_post.c (__new_sem_post): Adapt.
> 	(__old_sem_post): Add release fence.
> 	* nptl/sem_open.c (sem_open): Adapt.
> 	* nptl/sem_init.c (__new_sem_init): Adapt.
> 	* nptl/sem_getvalue.c (__new_sem_getvalue): Adapt.
> 	(__old_sem_getvalue): Add using previous code.
> 	* sysdeps/nptl/internaltypes.h: Adapt.
> 	* nptl/tst-sem13.c (do_test): Adapt.
> 	* nptl/tst-sem11.c (main): Adapt.
> 	* nptl/sem_timedwait.c: Remove.
> 	* nptl/sem_trywait.c: Remove.
> 	* nptl/DESIGN-sem.txt: Remove.
> 	* nptl/Makefile (libpthread-routines): Remove sem_trywait, sem_wait.
> 	(gen-as-const-headers): Remove structsem.sym.
> 	* nptl/structsem.sym: Remove.
> 	* sysdeps/unix/sysv/linux/alpha/sem_post.c: Remove.
> 	* sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Remove.
> 	* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Remove.
> 	* sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Remove.
> 	* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Remove.
> 	* sysdeps/unix/sysv/linux/i386/i586/sem_post.S: Remove.
> 	* sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S: Remove.
> 	* sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S: Remove.
> 	* sysdeps/unix/sysv/linux/i386/i586/sem_wait.S: Remove.
> 	* sysdeps/unix/sysv/linux/i386/i686/sem_post.S: Remove.
> 	* sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S: Remove.
> 	* sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S: Remove.
> 	* sysdeps/unix/sysv/linux/i386/i686/sem_wait.S: Remove.
> 	* sysdeps/unix/sysv/linux/powerpc/sem_post.c: Remove.
> 	* sysdeps/unix/sysv/linux/sh/sem_post.S: Remove.
> 	* sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Remove.
> 	* sysdeps/unix/sysv/linux/sh/sem_trywait.S: Remove.
> 	* sysdeps/unix/sysv/linux/sh/sem_wait.S: Remove.
> 	* sysdeps/unix/sysv/linux/x86_64/sem_post.S: Remove.
> 	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Remove.
> 	* sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Remove.
> 	* sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Remove.



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] Update to new generic semaphore algorithm.
  2014-12-05 19:24 ` [PATCH 3/3] Update to new generic semaphore algorithm Torvald Riegel
  2014-12-15 21:59   ` Torvald Riegel
@ 2018-05-08 14:00   ` Andreas Schwab
  2018-05-08 14:22     ` Torvald Riegel
  1 sibling, 1 reply; 19+ messages in thread
From: Andreas Schwab @ 2018-05-08 14:00 UTC (permalink / raw)
  To: Torvald Riegel; +Cc: GLIBC Devel

On Dez 05 2014, Torvald Riegel <triegel@redhat.com> wrote:

> diff --git a/nptl/sem_post.c b/nptl/sem_post.c
> index 4906adf..0877774 100644
> --- a/nptl/sem_post.c
> +++ b/nptl/sem_post.c

> +#else
> +  /* Add a token to the semaphore.  Similar to 64b version.  */
> +  unsigned int v = atomic_load_relaxed (&isem->value);
> +  do
>      {
> -      int err = lll_futex_wake (&isem->value, 1,
> -				isem->private ^ FUTEX_PRIVATE_FLAG);
> -      if (__builtin_expect (err, 0) < 0)
> +      if ((v << SEM_VALUE_SHIFT) == SEM_VALUE_MAX)

This can never be true because SEM_VALUE_MAX is uneven.  Did you mean
(v >> SEM_VALUE_SHIFT)?

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] Update to new generic semaphore algorithm.
  2018-05-08 14:00   ` Andreas Schwab
@ 2018-05-08 14:22     ` Torvald Riegel
  0 siblings, 0 replies; 19+ messages in thread
From: Torvald Riegel @ 2018-05-08 14:22 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: GLIBC Devel

On Tue, 2018-05-08 at 16:00 +0200, Andreas Schwab wrote:
> On Dez 05 2014, Torvald Riegel <triegel@redhat.com> wrote:
> 
> > diff --git a/nptl/sem_post.c b/nptl/sem_post.c
> > index 4906adf..0877774 100644
> > --- a/nptl/sem_post.c
> > +++ b/nptl/sem_post.c
> 
> > +#else
> > +  /* Add a token to the semaphore.  Similar to 64b version.  */
> > +  unsigned int v = atomic_load_relaxed (&isem->value);
> > +  do
> >      {
> > -      int err = lll_futex_wake (&isem->value, 1,
> > -				isem->private ^ FUTEX_PRIVATE_FLAG);
> > -      if (__builtin_expect (err, 0) < 0)
> > +      if ((v << SEM_VALUE_SHIFT) == SEM_VALUE_MAX)
> 
> This can never be true because SEM_VALUE_MAX is uneven.  Did you mean
> (v >> SEM_VALUE_SHIFT)?

This has already been fixed in 88ed594f5d431d855256edbe7e886c8cf4b575dc.

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2018-05-08 14:22 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-05 18:37 [PATCH 0/3] Fix semaphore destruction (BZ #12674) Torvald Riegel
2014-12-05 18:53 ` [PATCH 1/3] Use reliable sem_wait interruption in nptl/tst-sem6 Torvald Riegel
2014-12-06 13:50   ` Ondřej Bílka
2014-12-08 11:43     ` Torvald Riegel
2014-12-08 22:29       ` Ondřej Bílka
2014-12-09 10:16         ` Torvald Riegel
2014-12-09 16:50           ` Ondřej Bílka
2014-12-09 18:25             ` Torvald Riegel
2014-12-09 18:37               ` Rich Felker
2014-12-09 19:47                 ` Torvald Riegel
2014-12-09 20:19                   ` Rich Felker
2014-12-10  9:34                     ` Torvald Riegel
2014-12-05 19:03 ` [PATCH 2/3] Fix nptl/tst-sem4: always start with a fresh semaphore Torvald Riegel
2014-12-06 13:55   ` Ondřej Bílka
2014-12-05 19:24 ` [PATCH 3/3] Update to new generic semaphore algorithm Torvald Riegel
2014-12-15 21:59   ` Torvald Riegel
2018-05-08 14:00   ` Andreas Schwab
2018-05-08 14:22     ` Torvald Riegel
2014-12-05 20:30 ` [PATCH 0/3] Fix semaphore destruction (BZ #12674) Rich Felker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).