about summary refs log tree commit diff
path: root/nptl
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2020-02-09 20:07:51 +0000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2020-02-09 20:07:51 +0000
commitd5ec049d44f019deaeed8adc0bd10819e5569e93 (patch)
tree26b03705007a5b239c5239124f8c9381dd83001a /nptl
parent28c30a6232aa9a54783c146590498a061fc0112a (diff)
downloadglibc-d5ec049d44f019deaeed8adc0bd10819e5569e93.tar.gz
glibc-d5ec049d44f019deaeed8adc0bd10819e5569e93.tar.xz
glibc-d5ec049d44f019deaeed8adc0bd10819e5569e93.zip
pthread: Move some rwlock tests from nptl to sysdeps/pthread
So they can be checked with htl too.
Diffstat (limited to 'nptl')
-rw-r--r--nptl/Makefile9
-rw-r--r--nptl/tst-rwlock-tryrdlock-stall.c355
-rw-r--r--nptl/tst-rwlock-trywrlock-stall.c108
-rw-r--r--nptl/tst-rwlock1.c116
-rw-r--r--nptl/tst-rwlock13.c70
-rw-r--r--nptl/tst-rwlock16.c182
-rw-r--r--nptl/tst-rwlock4.c189
-rw-r--r--nptl/tst-rwlock5.c84
8 files changed, 4 insertions, 1109 deletions
diff --git a/nptl/Makefile b/nptl/Makefile
index bf21413c26..3ad3024a39 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -244,10 +244,10 @@ tests = tst-attr2 tst-attr3 tst-default-attr \
 	tst-robust6 tst-robust7 tst-robust8 tst-robust9 \
 	tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 tst-robustpi5 \
 	tst-robustpi6 tst-robustpi7 tst-robustpi8 tst-robustpi9 \
-	tst-rwlock1 tst-rwlock2 tst-rwlock2a tst-rwlock2b tst-rwlock3 \
-	tst-rwlock4 tst-rwlock5 tst-rwlock6 tst-rwlock7 tst-rwlock8 \
-	tst-rwlock9 tst-rwlock10 tst-rwlock11 tst-rwlock12 tst-rwlock13 \
-	tst-rwlock14 tst-rwlock15 tst-rwlock16 tst-rwlock17 tst-rwlock18 \
+	tst-rwlock2 tst-rwlock2a tst-rwlock2b tst-rwlock3 \
+	tst-rwlock6 tst-rwlock7 tst-rwlock8 \
+	tst-rwlock9 tst-rwlock10 tst-rwlock11 tst-rwlock12 \
+	tst-rwlock14 tst-rwlock15 tst-rwlock17 tst-rwlock18 \
 	tst-once5 \
 	tst-key1 tst-key2 tst-key3 tst-key4 \
 	tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
@@ -306,7 +306,6 @@ tests = tst-attr2 tst-attr3 tst-default-attr \
 	tst-thread-exit-clobber tst-minstack-cancel tst-minstack-exit \
 	tst-minstack-throw \
 	tst-rwlock-pwn \
-	tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall \
 	tst-unwind-thread
 
 tests-container =  tst-pthread-getattr
diff --git a/nptl/tst-rwlock-tryrdlock-stall.c b/nptl/tst-rwlock-tryrdlock-stall.c
deleted file mode 100644
index bb2a64f301..0000000000
--- a/nptl/tst-rwlock-tryrdlock-stall.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/* Bug 23844: Test for pthread_rwlock_tryrdlock stalls.
-   Copyright (C) 2019-2020 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
-   <https://www.gnu.org/licenses/>.  */
-
-/* For a full analysis see comment:
-   https://sourceware.org/bugzilla/show_bug.cgi?id=23844#c14
-
-   Provided here for reference:
-
-   --- Analysis of pthread_rwlock_tryrdlock() stall ---
-   A read lock begins to execute.
-
-   In __pthread_rwlock_rdlock_full:
-
-   We can attempt a read lock, but find that the lock is
-   in a write phase (PTHREAD_RWLOCK_WRPHASE, or WP-bit
-   is set), and the lock is held by a primary writer
-   (PTHREAD_RWLOCK_WRLOCKED is set). In this case we must
-   wait for explicit hand over from the writer to us or
-   one of the other waiters. The read lock threads are
-   about to execute:
-
-   341   r = (atomic_fetch_add_acquire (&rwlock->__data.__readers,
-   342                                  (1 << PTHREAD_RWLOCK_READER_SHIFT))
-   343        + (1 << PTHREAD_RWLOCK_READER_SHIFT));
-
-   An unlock beings to execute.
-
-   Then in __pthread_rwlock_wrunlock:
-
-   547   unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
-   ...
-   549   while (!atomic_compare_exchange_weak_release
-   550          (&rwlock->__data.__readers, &r,
-   551           ((r ^ PTHREAD_RWLOCK_WRLOCKED)
-   552            ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
-   553               : PTHREAD_RWLOCK_WRPHASE))))
-   554     {
-   ...
-   556     }
-
-   We clear PTHREAD_RWLOCK_WRLOCKED, and if there are
-   no readers so we leave the lock in PTHRAD_RWLOCK_WRPHASE.
-
-   Back in the read lock.
-
-   The read lock adjusts __readres as above.
-
-   383   while ((r & PTHREAD_RWLOCK_WRPHASE) != 0
-   384          && (r & PTHREAD_RWLOCK_WRLOCKED) == 0)
-   385     {
-   ...
-   390       if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r,
-   391                                                 r ^ PTHREAD_RWLOCK_WRPHASE))
-   392         {
-
-   And then attemps to start the read phase.
-
-   Assume there happens to be a tryrdlock at this point, noting
-   that PTHREAD_RWLOCK_WRLOCKED is clear, and PTHREAD_RWLOCK_WRPHASE
-   is 1. So the try lock attemps to start the read phase.
-
-   In __pthread_rwlock_tryrdlock:
-
-    44       if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
-    45         {
-   ...
-    49           if (((r & PTHREAD_RWLOCK_WRLOCKED) != 0)
-    50               && (rwlock->__data.__flags
-    51                   == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP))
-    52             return EBUSY;
-    53           rnew = r + (1 << PTHREAD_RWLOCK_READER_SHIFT);
-    54         }
-   ...
-    89   while (!atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers,
-    90       &r, rnew));
-
-   And succeeds.
-
-   Back in the write unlock:
-
-   557   if ((r >> PTHREAD_RWLOCK_READER_SHIFT) != 0)
-   558     {
-   ...
-   563       if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
-   564            & PTHREAD_RWLOCK_FUTEX_USED) != 0)
-   565         futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
-   566     }
-
-   We note that PTHREAD_RWLOCK_FUTEX_USED is non-zero
-   and don't wake anyone. This is OK because we handed
-   over to the trylock. It will be the trylock's responsibility
-   to wake any waiters.
-
-   Back in the read lock:
-
-   The read lock fails to install PTHRAD_REWLOCK_WRPHASE as 0 because
-   the __readers value was adjusted by the trylock, and so it falls through
-   to waiting on the lock for explicit handover from either a new writer
-   or a new reader.
-
-   448           int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
-   449                                          1 | PTHREAD_RWLOCK_FUTEX_USED,
-   450                                          abstime, private);
-
-   We use PTHREAD_RWLOCK_FUTEX_USED to indicate the futex
-   is in use.
-
-   At this point we have readers waiting on the read lock
-   to unlock. The wrlock is done. The trylock is finishing
-   the installation of the read phase.
-
-    92   if ((r & PTHREAD_RWLOCK_WRPHASE) != 0)
-    93     {
-   ...
-   105       atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
-   106     }
-
-   The trylock does note that we were the one that
-   installed the read phase, but the comments are not
-   correct, the execution ordering above shows that
-   readers might indeed be waiting, and they are.
-
-   The atomic_store_relaxed throws away PTHREAD_RWLOCK_FUTEX_USED,
-   and the waiting reader is never worken becuase as noted
-   above it is conditional on the futex being used.
-
-   The solution is for the trylock thread to inspect
-   PTHREAD_RWLOCK_FUTEX_USED and wake the waiting readers.
-
-   --- Analysis of pthread_rwlock_trywrlock() stall ---
-
-   A write lock begins to execute, takes the write lock,
-   and then releases the lock...
-
-   In pthread_rwlock_wrunlock():
-
-   547   unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
-   ...
-   549   while (!atomic_compare_exchange_weak_release
-   550          (&rwlock->__data.__readers, &r,
-   551           ((r ^ PTHREAD_RWLOCK_WRLOCKED)
-   552            ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
-   553               : PTHREAD_RWLOCK_WRPHASE))))
-   554     {
-   ...
-   556     }
-
-   ... leaving it in the write phase with zero readers
-   (the case where we leave the write phase in place
-   during a write unlock).
-
-   A write trylock begins to execute.
-
-   In __pthread_rwlock_trywrlock:
-
-    40   while (((r & PTHREAD_RWLOCK_WRLOCKED) == 0)
-    41       && (((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0)
-    42           || (prefer_writer && ((r & PTHREAD_RWLOCK_WRPHASE) != 0))))
-    43     {
-
-   The lock is not locked.
-
-   There are no readers.
-
-    45       if (atomic_compare_exchange_weak_acquire (
-    46           &rwlock->__data.__readers, &r,
-    47           r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED))
-
-   We atomically install the write phase and we take the
-   exclusive write lock.
-
-    48         {
-    49           atomic_store_relaxed (&rwlock->__data.__writers_futex, 1);
-
-   We get this far.
-
-   A reader lock begins to execute.
-
-   In pthread_rwlock_rdlock:
-
-   437   for (;;)
-   438     {
-   439       while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
-   440               | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
-   441         {
-   442           int private = __pthread_rwlock_get_private (rwlock);
-   443           if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
-   444               && (!atomic_compare_exchange_weak_relaxed
-   445                   (&rwlock->__data.__wrphase_futex,
-   446                    &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED)))
-   447             continue;
-   448           int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
-   449                                          1 | PTHREAD_RWLOCK_FUTEX_USED,
-   450                                          abstime, private);
-
-   We are in a write phase, so the while() on line 439 is true.
-
-   The value of wpf does not have PTHREAD_RWLOCK_FUTEX_USED set
-   since this is the first reader to lock.
-
-   The atomic operation sets wpf with PTHREAD_RELOCK_FUTEX_USED
-   on the expectation that this reader will be woken during
-   the handoff.
-
-   Back in pthread_rwlock_trywrlock:
-
-    50           atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
-    51           atomic_store_relaxed (&rwlock->__data.__cur_writer,
-    52               THREAD_GETMEM (THREAD_SELF, tid));
-    53           return 0;
-    54         }
-   ...
-    57     }
-
-   We write 1 to __wrphase_futex discarding PTHREAD_RWLOCK_FUTEX_USED,
-   and so in the unlock we will not awaken the waiting reader.
-
-   The solution to this is to realize that if we did not start the write
-   phase we need not write 1 or any other value to __wrphase_futex.
-   This ensures that any readers (which saw __wrphase_futex != 0) can
-   set PTHREAD_RWLOCK_FUTEX_USED and this can be used at unlock to
-   wake them.
-
-   If we installed the write phase then all other readers are looping
-   here:
-
-   In __pthread_rwlock_rdlock_full:
-
-   437   for (;;)
-   438     {
-   439       while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
-   440               | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
-   441         {
-   ...
-   508     }
-
-   waiting for the write phase to be installed or removed before they
-   can begin waiting on __wrphase_futex (part of the algorithm), or
-   taking a concurrent read lock, and thus we can safely write 1 to
-   __wrphase_futex.
-
-   If we did not install the write phase then the readers may already
-   be waiting on the futex, the original writer wrote 1 to __wrphase_futex
-   as part of starting the write phase, and we cannot also write 1
-   without loosing the PTHREAD_RWLOCK_FUTEX_USED bit.
-
-   ---
-
-   Summary for the pthread_rwlock_tryrdlock() stall:
-
-   The stall is caused by pthread_rwlock_tryrdlock failing to check
-   that PTHREAD_RWLOCK_FUTEX_USED is set in the __wrphase_futex futex
-   and then waking the futex.
-
-   The fix for bug 23844 ensures that waiters on __wrphase_futex are
-   correctly woken.  Before the fix the test stalls as readers can
-   wait forever on __wrphase_futex.  */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <support/xthread.h>
-#include <errno.h>
-
-/* We need only one lock to reproduce the issue. We will need multiple
-   threads to get the exact case where we have a read, try, and unlock
-   all interleaving to produce the case where the readers are waiting
-   and the try fails to wake them.  */
-pthread_rwlock_t onelock;
-
-/* The number of threads is arbitrary but empirically chosen to have
-   enough threads that we see the condition where waiting readers are
-   not woken by a successful tryrdlock.  */
-#define NTHREADS 32
-
-_Atomic int do_exit;
-
-void *
-run_loop (void *arg)
-{
-  int i = 0, ret;
-  while (!do_exit)
-    {
-      /* Arbitrarily choose if we are the writer or reader.  Choose a
-	 high enough ratio of readers to writers to make it likely
-	 that readers block (and eventually are susceptable to
-	 stalling).
-
-         If we are a writer, take the write lock, and then unlock.
-	 If we are a reader, try the lock, then lock, then unlock.  */
-      if ((i % 8) != 0)
-	xpthread_rwlock_wrlock (&onelock);
-      else
-	{
-	  if ((ret = pthread_rwlock_tryrdlock (&onelock)) != 0)
-	    {
-	      if (ret == EBUSY)
-		xpthread_rwlock_rdlock (&onelock);
-	      else
-		exit (EXIT_FAILURE);
-	    }
-	}
-      /* Thread does some work and then unlocks.  */
-      xpthread_rwlock_unlock (&onelock);
-      i++;
-    }
-  return NULL;
-}
-
-int
-do_test (void)
-{
-  int i;
-  pthread_t tids[NTHREADS];
-  xpthread_rwlock_init (&onelock, NULL);
-  for (i = 0; i < NTHREADS; i++)
-    tids[i] = xpthread_create (NULL, run_loop, NULL);
-  /* Run for some amount of time.  Empirically speaking exercising
-     the stall via pthread_rwlock_tryrdlock is much harder, and on
-     a 3.5GHz 4 core x86_64 VM system it takes somewhere around
-     20-200s to stall, approaching 100% stall past 200s.  We can't
-     wait that long for a regression test so we just test for 20s,
-     and expect the stall to happen with a 5-10% chance (enough for
-     developers to see).  */
-  sleep (20);
-  /* Then exit.  */
-  printf ("INFO: Exiting...\n");
-  do_exit = 1;
-  /* If any readers stalled then we will timeout waiting for them.  */
-  for (i = 0; i < NTHREADS; i++)
-    xpthread_join (tids[i]);
-  printf ("INFO: Done.\n");
-  xpthread_rwlock_destroy (&onelock);
-  printf ("PASS: No pthread_rwlock_tryrdlock stalls detected.\n");
-  return 0;
-}
-
-#define TIMEOUT 30
-#include <support/test-driver.c>
diff --git a/nptl/tst-rwlock-trywrlock-stall.c b/nptl/tst-rwlock-trywrlock-stall.c
deleted file mode 100644
index b4e60c5af3..0000000000
--- a/nptl/tst-rwlock-trywrlock-stall.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* Bug 23844: Test for pthread_rwlock_trywrlock stalls.
-   Copyright (C) 2019-2020 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
-   <https://www.gnu.org/licenses/>.  */
-
-/* For a full analysis see comments in tst-rwlock-tryrdlock-stall.c.
-
-   Summary for the pthread_rwlock_trywrlock() stall:
-
-   The stall is caused by pthread_rwlock_trywrlock setting
-   __wrphase_futex futex to 1 and loosing the
-   PTHREAD_RWLOCK_FUTEX_USED bit.
-
-   The fix for bug 23844 ensures that waiters on __wrphase_futex are
-   correctly woken.  Before the fix the test stalls as readers can
-   wait forever on  __wrphase_futex.  */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <support/xthread.h>
-#include <errno.h>
-
-/* We need only one lock to reproduce the issue. We will need multiple
-   threads to get the exact case where we have a read, try, and unlock
-   all interleaving to produce the case where the readers are waiting
-   and the try clears the PTHREAD_RWLOCK_FUTEX_USED bit and a
-   subsequent unlock fails to wake them.  */
-pthread_rwlock_t onelock;
-
-/* The number of threads is arbitrary but empirically chosen to have
-   enough threads that we see the condition where waiting readers are
-   not woken by a successful unlock.  */
-#define NTHREADS 32
-
-_Atomic int do_exit;
-
-void *
-run_loop (void *arg)
-{
-  int i = 0, ret;
-  while (!do_exit)
-    {
-      /* Arbitrarily choose if we are the writer or reader.  Choose a
-	 high enough ratio of readers to writers to make it likely
-	 that readers block (and eventually are susceptable to
-	 stalling).
-
-         If we are a writer, take the write lock, and then unlock.
-	 If we are a reader, try the lock, then lock, then unlock.  */
-      if ((i % 8) != 0)
-	{
-	  if ((ret = pthread_rwlock_trywrlock (&onelock)) != 0)
-	    {
-	      if (ret == EBUSY)
-		xpthread_rwlock_wrlock (&onelock);
-	      else
-		exit (EXIT_FAILURE);
-	    }
-	}
-      else
-	xpthread_rwlock_rdlock (&onelock);
-      /* Thread does some work and then unlocks.  */
-      xpthread_rwlock_unlock (&onelock);
-      i++;
-    }
-  return NULL;
-}
-
-int
-do_test (void)
-{
-  int i;
-  pthread_t tids[NTHREADS];
-  xpthread_rwlock_init (&onelock, NULL);
-  for (i = 0; i < NTHREADS; i++)
-    tids[i] = xpthread_create (NULL, run_loop, NULL);
-  /* Run for some amount of time.  The pthread_rwlock_tryrwlock stall
-     is very easy to trigger and happens in seconds under the test
-     conditions.  */
-  sleep (10);
-  /* Then exit.  */
-  printf ("INFO: Exiting...\n");
-  do_exit = 1;
-  /* If any readers stalled then we will timeout waiting for them.  */
-  for (i = 0; i < NTHREADS; i++)
-    xpthread_join (tids[i]);
-  printf ("INFO: Done.\n");
-  xpthread_rwlock_destroy (&onelock);
-  printf ("PASS: No pthread_rwlock_tryrwlock stalls detected.\n");
-  return 0;
-}
-
-#include <support/test-driver.c>
diff --git a/nptl/tst-rwlock1.c b/nptl/tst-rwlock1.c
deleted file mode 100644
index d14d3036a2..0000000000
--- a/nptl/tst-rwlock1.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Copyright (C) 2002-2020 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
-   <https://www.gnu.org/licenses/>.  */
-
-#include <pthread.h>
-#include <stdio.h>
-
-
-static int
-do_test (void)
-{
-  pthread_rwlock_t r;
-
-  if (pthread_rwlock_init (&r, NULL) != 0)
-    {
-      puts ("rwlock_init failed");
-      return 1;
-    }
-  puts ("rwlock_init succeeded");
-
-  if (pthread_rwlock_rdlock (&r) != 0)
-    {
-      puts ("1st rwlock_rdlock failed");
-      return 1;
-    }
-  puts ("1st rwlock_rdlock succeeded");
-
-  if (pthread_rwlock_rdlock (&r) != 0)
-    {
-      puts ("2nd rwlock_rdlock failed");
-      return 1;
-    }
-  puts ("2nd rwlock_rdlock succeeded");
-
-  if (pthread_rwlock_unlock (&r) != 0)
-    {
-      puts ("1st rwlock_unlock failed");
-      return 1;
-    }
-  puts ("1st rwlock_unlock succeeded");
-
-  if (pthread_rwlock_unlock (&r) != 0)
-    {
-      puts ("2nd rwlock_unlock failed");
-      return 1;
-    }
-  puts ("2nd rwlock_unlock succeeded");
-
-  if (pthread_rwlock_wrlock (&r) != 0)
-    {
-      puts ("1st rwlock_wrlock failed");
-      return 1;
-    }
-  puts ("1st rwlock_wrlock succeeded");
-
-  if (pthread_rwlock_unlock (&r) != 0)
-    {
-      puts ("3rd rwlock_unlock failed");
-      return 1;
-    }
-  puts ("3rd rwlock_unlock succeeded");
-
-  if (pthread_rwlock_wrlock (&r) != 0)
-    {
-      puts ("2nd rwlock_wrlock failed");
-      return 1;
-    }
-  puts ("2nd rwlock_wrlock succeeded");
-
-  if (pthread_rwlock_unlock (&r) != 0)
-    {
-      puts ("4th rwlock_unlock failed");
-      return 1;
-    }
-  puts ("4th rwlock_unlock succeeded");
-
-  if (pthread_rwlock_rdlock (&r) != 0)
-    {
-      puts ("3rd rwlock_rdlock failed");
-      return 1;
-    }
-  puts ("3rd rwlock_rdlock succeeded");
-
-  if (pthread_rwlock_unlock (&r) != 0)
-    {
-      puts ("5th rwlock_unlock failed");
-      return 1;
-    }
-  puts ("5th rwlock_unlock succeeded");
-
-  if (pthread_rwlock_destroy (&r) != 0)
-    {
-      puts ("rwlock_destroy failed");
-      return 1;
-    }
-  puts ("rwlock_destroy succeeded");
-
-  return 0;
-}
-
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
diff --git a/nptl/tst-rwlock13.c b/nptl/tst-rwlock13.c
deleted file mode 100644
index 749ec4b621..0000000000
--- a/nptl/tst-rwlock13.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright (C) 2004-2020 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
-   <https://www.gnu.org/licenses/>.  */
-
-#include <pthread.h>
-#include <stdio.h>
-#include <string.h>
-
-
-static int
-do_test (void)
-{
-  pthread_rwlock_t r;
-  int ret;
-
-  memset (&r, 0xaa, sizeof (r));
-  if ((ret = pthread_rwlock_init (&r, NULL)) != 0)
-    {
-      printf ("rwlock_init failed: %d\n", ret);
-      return 1;
-    }
-
-  if ((ret = pthread_rwlock_rdlock (&r)) != 0)
-    {
-      printf ("rwlock_rdlock failed: %d\n", ret);
-      return 1;
-    }
-
-  if ((ret = pthread_rwlock_unlock (&r)) != 0)
-    {
-      printf ("rwlock_unlock failed: %d\n", ret);
-      return 1;
-    }
-
-  if ((ret = pthread_rwlock_wrlock (&r)) != 0)
-    {
-      printf ("rwlock_wrlock failed: %d\n", ret);
-      return 1;
-    }
-
-  if ((ret = pthread_rwlock_unlock (&r)) != 0)
-    {
-      printf ("second rwlock_unlock failed: %d\n", ret);
-      return 1;
-    }
-
-  if ((ret = pthread_rwlock_destroy (&r)) != 0)
-    {
-      printf ("second rwlock_destroy failed: %d\n", ret);
-      return 1;
-    }
-
-  return 0;
-}
-
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
diff --git a/nptl/tst-rwlock16.c b/nptl/tst-rwlock16.c
deleted file mode 100644
index 29720c9d8d..0000000000
--- a/nptl/tst-rwlock16.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/* Copyright (C) 2015-2020 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
-   <https://www.gnu.org/licenses/>.  */
-
-/* This tests that with a reader-preferring rwlock, all readers are woken if
-   one reader "steals" lock ownership from a blocked writer.  */
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <semaphore.h>
-#include <unistd.h>
-
-/* If we strictly prefer writers over readers, a program must not expect
-   that, in the presence of concurrent writers, one reader will also acquire
-   the lock when another reader has already done so.  Thus, use the
-   default rwlock type that does not strictly prefer writers.  */
-static pthread_rwlock_t r = PTHREAD_RWLOCK_INITIALIZER;
-
-static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
-
-/* Avoid using glibc-internal atomic operations.  */
-static sem_t stop;
-static int consumer_stop = 0;
-
-static void *
-writer (void *arg)
-{
-  int s;
-
-  do
-    {
-      if (pthread_rwlock_wrlock (&r) != 0)
-	{
-	  puts ("wrlock failed");
-	  exit (EXIT_FAILURE);
-	}
-      if (pthread_rwlock_unlock (&r) != 0)
-	{
-	  puts ("unlock failed");
-	  exit (EXIT_FAILURE);
-	}
-      sem_getvalue (&stop, &s);
-    }
-  while (s == 0);
-  return NULL;
-}
-
-static void *
-reader_producer (void *arg)
-{
-  int s;
-
-  do
-    {
-      if (pthread_rwlock_rdlock (&r) != 0)
-	{
-	  puts ("rdlock reader failed");
-	  exit (EXIT_FAILURE);
-	}
-
-      sem_getvalue (&stop, &s);
-
-      pthread_mutex_lock (&m);
-      if (s != 0)
-	consumer_stop = 1;
-      pthread_cond_signal (&cv);
-      pthread_mutex_unlock (&m);
-
-      if (pthread_rwlock_unlock (&r) != 0)
-	{
-	  puts ("unlock reader failed");
-	  exit (EXIT_FAILURE);
-	}
-    }
-  while (s == 0);
-  puts ("producer finished");
-  return NULL;
-}
-
-static void *
-reader_consumer (void *arg)
-{
-  int s;
-
-  do
-    {
-      if (pthread_rwlock_rdlock (&r) != 0)
-	{
-	  puts ("rdlock reader failed");
-	  exit (EXIT_FAILURE);
-	}
-
-      pthread_mutex_lock (&m);
-      s = consumer_stop;
-      if (s == 0)
-	pthread_cond_wait (&cv, &m);
-      pthread_mutex_unlock (&m);
-
-      if (pthread_rwlock_unlock (&r) != 0)
-	{
-	  puts ("unlock reader failed");
-	  exit (EXIT_FAILURE);
-	}
-    }
-  while (s == 0);
-    puts ("consumer finished");
-  return NULL;
-}
-
-
-static int
-do_test (void)
-{
-  pthread_t w1, w2, rp, rc;
-
-  if (pthread_create (&w1, NULL, writer, NULL) != 0)
-    {
-      puts ("create failed");
-      return 1;
-    }
-  if (pthread_create (&w2, NULL, writer, NULL) != 0)
-    {
-      puts ("create failed");
-      return 1;
-    }
-  if (pthread_create (&rc, NULL, reader_consumer, NULL) != 0)
-    {
-      puts ("create failed");
-      return 1;
-    }
-  if (pthread_create (&rp, NULL, reader_producer, NULL) != 0)
-    {
-      puts ("create failed");
-      return 1;
-    }
-
-  sleep (2);
-  sem_post (&stop);
-
-  if (pthread_join (w1, NULL) != 0)
-    {
-      puts ("w1 join failed");
-      return 1;
-    }
-  if (pthread_join (w2, NULL) != 0)
-    {
-      puts ("w2 join failed");
-      return 1;
-    }
-  if (pthread_join (rp, NULL) != 0)
-    {
-      puts ("reader_producer join failed");
-      return 1;
-    }
-  if (pthread_join (rc, NULL) != 0)
-    {
-      puts ("reader_consumer join failed");
-      return 1;
-    }
-
-  return 0;
-}
-
-
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
diff --git a/nptl/tst-rwlock4.c b/nptl/tst-rwlock4.c
deleted file mode 100644
index 479107a5f2..0000000000
--- a/nptl/tst-rwlock4.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/* Copyright (C) 2002-2020 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
-   <https://www.gnu.org/licenses/>.  */
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/wait.h>
-
-
-static int
-do_test (void)
-{
-  size_t ps = sysconf (_SC_PAGESIZE);
-  char tmpfname[] = "/tmp/tst-rwlock4.XXXXXX";
-  char data[ps];
-  void *mem;
-  int fd;
-  pthread_rwlock_t *r;
-  pthread_rwlockattr_t a;
-  pid_t pid;
-  char *p;
-  int err;
-  int s;
-
-  fd = mkstemp (tmpfname);
-  if (fd == -1)
-    {
-      printf ("cannot open temporary file: %m\n");
-      return 1;
-    }
-
-  /* Make sure it is always removed.  */
-  unlink (tmpfname);
-
-  /* Create one page of data.  */
-  memset (data, '\0', ps);
-
-  /* Write the data to the file.  */
-  if (write (fd, data, ps) != (ssize_t) ps)
-    {
-      puts ("short write");
-      return 1;
-    }
-
-  mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-  if (mem == MAP_FAILED)
-    {
-      printf ("mmap failed: %m\n");
-      return 1;
-    }
-
-  r = (pthread_rwlock_t *) (((uintptr_t) mem + __alignof (pthread_rwlock_t))
-			    & ~(__alignof (pthread_rwlock_t) - 1));
-  p = (char *) (r + 1);
-
-  if (pthread_rwlockattr_init (&a) != 0)
-    {
-      puts ("rwlockattr_init failed");
-      return 1;
-    }
-
-  if (pthread_rwlockattr_getpshared (&a, &s) != 0)
-    {
-      puts ("1st rwlockattr_getpshared failed");
-      return 1;
-    }
-
-  if (s != PTHREAD_PROCESS_PRIVATE)
-    {
-      puts ("default pshared value wrong");
-      return 1;
-    }
-
-  if (pthread_rwlockattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
-    {
-      puts ("rwlockattr_setpshared failed");
-      return 1;
-    }
-
-  if (pthread_rwlockattr_getpshared (&a, &s) != 0)
-    {
-      puts ("2nd rwlockattr_getpshared failed");
-      return 1;
-    }
-
-  if (s != PTHREAD_PROCESS_SHARED)
-    {
-      puts ("pshared value after setpshared call wrong");
-      return 1;
-    }
-
-  if (pthread_rwlock_init (r, &a) != 0)
-    {
-      puts ("rwlock_init failed");
-      return 1;
-    }
-
-  if (pthread_rwlock_rdlock (r) != 0)
-    {
-      puts ("rwlock_rdlock failed");
-      return 1;
-    }
-
-  if (pthread_rwlockattr_destroy (&a) != 0)
-    {
-      puts ("rwlockattr_destroy failed");
-      return 1;
-    }
-
-  err = pthread_rwlock_trywrlock (r);
-  if (err == 0)
-    {
-      puts ("rwlock_trywrlock succeeded");
-      return 1;
-    }
-  else if (err != EBUSY)
-    {
-      puts ("rwlock_trywrlock didn't return EBUSY");
-      return 1;
-    }
-
-  *p = 0;
-
-  puts ("going to fork now");
-  pid = fork ();
-  if (pid == -1)
-    {
-      puts ("fork failed");
-      return 1;
-    }
-  else if (pid == 0)
-    {
-      /* Play some lock ping-pong.  It's our turn to unlock first.  */
-      if ((*p)++ != 0)
-	{
-	  puts ("child: *p != 0");
-	  return 1;
-	}
-
-      if (pthread_rwlock_unlock (r) != 0)
-	{
-	  puts ("child: 1st rwlock_unlock failed");
-	  return 1;
-	}
-
-      puts ("child done");
-    }
-  else
-    {
-      if (pthread_rwlock_wrlock (r) != 0)
-	{
-	  puts ("parent: rwlock_wrlock failed");
-	  return 1;
-	}
-
-      if (*p != 1)
-	{
-	  puts ("*p != 1");
-	  return 1;
-	}
-
-      puts ("parent done");
-    }
-
-  return 0;
-}
-
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
diff --git a/nptl/tst-rwlock5.c b/nptl/tst-rwlock5.c
deleted file mode 100644
index c589764196..0000000000
--- a/nptl/tst-rwlock5.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Copyright (C) 2002-2020 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
-   <https://www.gnu.org/licenses/>.  */
-
-#include <pthread.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-static int do_test (void);
-
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
-
-static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
-static pthread_rwlock_t r;
-
-
-static void *
-tf (void *arg)
-{
-  if (pthread_rwlock_wrlock (&r) == 0)
-    {
-      puts ("child: rwlock_wrlock succeeded");
-      exit (1);
-    }
-
-  puts ("child: rwlock_wrlock returned");
-
-  exit (1);
-}
-
-
-static int
-do_test (void)
-{
-  pthread_t th;
-
-  if (pthread_rwlock_init (&r, NULL) != 0)
-    {
-      puts ("rwlock_init failed");
-      return 1;
-    }
-
-  if (pthread_rwlock_wrlock (&r) != 0)
-    {
-      puts ("rwlock_wrlock failed");
-      return 1;
-    }
-
-  if (pthread_mutex_lock (&m) != 0)
-    {
-      puts ("mutex_lock failed");
-      return 1;
-    }
-
-  if (pthread_create (&th, NULL, tf, NULL) != 0)
-    {
-      puts ("create failed");
-      return 1;
-    }
-
-  delayed_exit (1);
-  /* This call should never return.  */
-  xpthread_mutex_lock (&m);
-
-  puts ("2nd mutex_lock returned");
-  return 1;
-}