GNU C Library master sources branch master updated. glibc-2.28.9000-390-gf21e8f8

schwab@sourceware.org schwab@sourceware.org
Thu Dec 13 11:24:00 GMT 2018


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

The branch, master has been updated
       via  f21e8f8ca466320fed38bdb71526c574dae98026 (commit)
       via  3d265911c2aac65d978f679101594f9071024874 (commit)
      from  bf8ae8c09ab7ae4c402f26fd1a2cff4b64e50eea (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

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

commit f21e8f8ca466320fed38bdb71526c574dae98026
Author: Andreas Schwab <schwab@suse.de>
Date:   Thu Nov 8 14:28:22 2018 +0100

    Fix rwlock stall with PREFER_WRITER_NONRECURSIVE_NP (bug 23861)
    
    In the read lock function (__pthread_rwlock_rdlock_full) there was a
    code path which would fail to reload __readers while waiting for
    PTHREAD_RWLOCK_RWAITING to change. This failure to reload __readers
    into a local value meant that various conditionals used the old value
    of __readers and with only two threads left it could result in an
    indefinite stall of one of the readers (waiting for PTHREAD_RWLOCK_RWAITING
    to go to zero, but it never would).

diff --git a/ChangeLog b/ChangeLog
index 787dab8..cd35115 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,11 @@
 2018-12-13  Andreas Schwab  <schwab@suse.de>
 
+	[BZ #23861]
 	* nptl/pthread_rwlock_common.c: Reindent.  Fix typos.
+	(__pthread_rwlock_rdlock_full): Update expected value for
+	__readers while waiting on PTHREAD_RWLOCK_RWAITING.
+	* nptl/tst-rwlock-pwn.c: New file.
+	* nptl/Makefile (tests): Add tst-rwlock-pwn.
 
 2018-12-12  Joseph Myers  <joseph@codesourcery.com>
 
diff --git a/nptl/Makefile b/nptl/Makefile
index 34ae830..b01f2b0 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -318,7 +318,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
 	tst-minstack-throw \
 	tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
 	tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \
-	tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock
+	tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \
+	tst-rwlock-pwn
 
 tests-internal := tst-rwlock19 tst-rwlock20 \
 		  tst-sem11 tst-sem12 tst-sem13 \
diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
index 5dd5342..85fc1bc 100644
--- a/nptl/pthread_rwlock_common.c
+++ b/nptl/pthread_rwlock_common.c
@@ -314,7 +314,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
 		 harmless because the flag is just about the state of
 		 __readers, and all threads set the flag under the same
 		 conditions.  */
-	      while ((atomic_load_relaxed (&rwlock->__data.__readers)
+	      while (((r = atomic_load_relaxed (&rwlock->__data.__readers))
 		      & PTHREAD_RWLOCK_RWAITING) != 0)
 		{
 		  int private = __pthread_rwlock_get_private (rwlock);
diff --git a/nptl/tst-rwlock-pwn.c b/nptl/tst-rwlock-pwn.c
new file mode 100644
index 0000000..c39dd70
--- /dev/null
+++ b/nptl/tst-rwlock-pwn.c
@@ -0,0 +1,87 @@
+/* Test rwlock with PREFER_WRITER_NONRECURSIVE_NP (bug 23861).
+   Copyright (C) 2018 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <support/xthread.h>
+
+/* We choose 10 iterations because this happens to be able to trigger the
+   stall on contemporary hardware.  */
+#define LOOPS 10
+/* We need 3 threads to trigger bug 23861.  One thread as a writer, and
+   two reader threads.  The test verifies that the second-to-last reader
+   is able to notify the *last* reader that it should be done waiting.
+   If the second-to-last reader fails to notify the last reader or does
+   so incorrectly then the last reader may stall indefinitely.  */
+#define NTHREADS 3
+
+_Atomic int do_exit;
+pthread_rwlockattr_t mylock_attr;
+pthread_rwlock_t mylock;
+
+void *
+run_loop (void *a)
+{
+  while (!do_exit)
+    {
+      if (random () & 1)
+	{
+	  xpthread_rwlock_wrlock (&mylock);
+	  xpthread_rwlock_unlock (&mylock);
+	}
+      else
+	{
+	  xpthread_rwlock_rdlock (&mylock);
+	  xpthread_rwlock_unlock (&mylock);
+	}
+    }
+  return NULL;
+}
+
+int
+do_test (void)
+{
+  xpthread_rwlockattr_init (&mylock_attr);
+  xpthread_rwlockattr_setkind_np (&mylock_attr,
+				  PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
+  xpthread_rwlock_init (&mylock, &mylock_attr);
+
+  for (int n = 0; n < LOOPS; n++)
+    {
+      pthread_t tids[NTHREADS];
+      do_exit = 0;
+      for (int i = 0; i < NTHREADS; i++)
+	tids[i] = xpthread_create (NULL, run_loop, NULL);
+      /* Let the threads run for some time.  */
+      sleep (1);
+      printf ("Exiting...");
+      fflush (stdout);
+      do_exit = 1;
+      for (int i = 0; i < NTHREADS; i++)
+	xpthread_join (tids[i]);
+      printf ("done.\n");
+    }
+  pthread_rwlock_destroy (&mylock);
+  pthread_rwlockattr_destroy (&mylock_attr);
+  return 0;
+}
+
+#define TIMEOUT (DEFAULT_TIMEOUT + 3 * LOOPS)
+#include <support/test-driver.c>

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

commit 3d265911c2aac65d978f679101594f9071024874
Author: Andreas Schwab <schwab@suse.de>
Date:   Mon Nov 12 11:11:40 2018 +0100

    Reindent nptl/pthread_rwlock_common.c

diff --git a/ChangeLog b/ChangeLog
index 92683cb..787dab8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2018-12-13  Andreas Schwab  <schwab@suse.de>
+
+	* nptl/pthread_rwlock_common.c: Reindent.  Fix typos.
+
 2018-12-12  Joseph Myers  <joseph@codesourcery.com>
 
 	* sysdeps/x86/fpu/bits/mathinline.h (hypot): Remove inline
diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
index a290d08..5dd5342 100644
--- a/nptl/pthread_rwlock_common.c
+++ b/nptl/pthread_rwlock_common.c
@@ -34,7 +34,7 @@
 
    A thread is allowed to acquire a read lock recursively (i.e., have rdlock
    critical sections that overlap in sequenced-before) unless the kind of the
-   rwlock is set to PTHREAD_RWLOCK_PREFER_WRITERS_NONRECURSIVE_NP.
+   rwlock is set to PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP.
 
    This lock is built so that workloads of mostly readers can be executed with
    low runtime overheads.  This matches that the default kind of the lock is
@@ -46,7 +46,7 @@
    An uncontended write lock acquisition is as fast as for a normal
    exclusive mutex but writer contention is somewhat more costly due to
    keeping track of the exact number of writers.  If the rwlock kind requests
-   writers to be preferred (i.e., PTHREAD_RWLOCK_PREFER_WRITERS_NP or the
+   writers to be preferred (i.e., PTHREAD_RWLOCK_PREFER_WRITER_NP or the
    no-recursive-readers variant of it), then writer--to--writer lock ownership
    hand-over is fairly fast and bypasses lock acquisition attempts by readers.
    The costs of lock ownership transfer between readers and writers vary.  If
@@ -251,7 +251,7 @@ __pthread_rwlock_rdunlock (pthread_rwlock_t *rwlock)
 	 the first reader's store to __wrphase_futex (or a later value) if
 	 the writer observes that a write phase has been started.  */
       if (atomic_compare_exchange_weak_release (&rwlock->__data.__readers,
-	  &r, rnew))
+						&r, rnew))
 	break;
       /* TODO Back-off.  */
     }
@@ -285,7 +285,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
   /* Make sure we are not holding the rwlock as a writer.  This is a deadlock
      situation we recognize and report.  */
   if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer)
-      == THREAD_GETMEM (THREAD_SELF, tid)))
+			== THREAD_GETMEM (THREAD_SELF, tid)))
     return EDEADLK;
 
   /* If we prefer writers, recursive rdlock is disallowed, we are in a read
@@ -299,9 +299,9 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
   if (rwlock->__data.__flags == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)
     {
       r = atomic_load_relaxed (&rwlock->__data.__readers);
-      while (((r & PTHREAD_RWLOCK_WRPHASE) == 0)
-	      && ((r & PTHREAD_RWLOCK_WRLOCKED) != 0)
-	      && ((r >> PTHREAD_RWLOCK_READER_SHIFT) > 0))
+      while ((r & PTHREAD_RWLOCK_WRPHASE) == 0
+	     && (r & PTHREAD_RWLOCK_WRLOCKED) != 0
+	     && (r >> PTHREAD_RWLOCK_READER_SHIFT) > 0)
 	{
 	  /* TODO Spin first.  */
 	  /* Try setting the flag signaling that we are waiting without having
@@ -315,11 +315,11 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
 		 __readers, and all threads set the flag under the same
 		 conditions.  */
 	      while ((atomic_load_relaxed (&rwlock->__data.__readers)
-		  & PTHREAD_RWLOCK_RWAITING) != 0)
+		      & PTHREAD_RWLOCK_RWAITING) != 0)
 		{
 		  int private = __pthread_rwlock_get_private (rwlock);
 		  int err = futex_abstimed_wait (&rwlock->__data.__readers,
-		      r, abstime, private);
+						 r, abstime, private);
 		  /* We ignore EAGAIN and EINTR.  On time-outs, we can just
 		     return because we don't need to clean up anything.  */
 		  if (err == ETIMEDOUT)
@@ -338,8 +338,9 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
      expected value for future operations.  Acquire MO so we synchronize with
      prior writers as well as the last reader of the previous read phase (see
      below).  */
-  r = atomic_fetch_add_acquire (&rwlock->__data.__readers,
-      (1 << PTHREAD_RWLOCK_READER_SHIFT)) + (1 << PTHREAD_RWLOCK_READER_SHIFT);
+  r = (atomic_fetch_add_acquire (&rwlock->__data.__readers,
+				 (1 << PTHREAD_RWLOCK_READER_SHIFT))
+       + (1 << PTHREAD_RWLOCK_READER_SHIFT));
 
   /* Check whether there is an overflow in the number of readers.  We assume
      that the total number of threads is less than half the maximum number
@@ -359,8 +360,9 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
       /* Relaxed MO is okay because we just want to undo our registration and
 	 cannot have changed the rwlock state substantially if the CAS
 	 succeeds.  */
-      if (atomic_compare_exchange_weak_relaxed (&rwlock->__data.__readers, &r,
-	  r - (1 << PTHREAD_RWLOCK_READER_SHIFT)))
+      if (atomic_compare_exchange_weak_relaxed
+	  (&rwlock->__data.__readers,
+	   &r, r - (1 << PTHREAD_RWLOCK_READER_SHIFT)))
 	return EAGAIN;
     }
 
@@ -378,15 +380,15 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
   /* Otherwise, if we were in a write phase (states #6 or #8), we must wait
      for explicit hand-over of the read phase; the only exception is if we
      can start a read phase if there is no primary writer currently.  */
-  while (((r & PTHREAD_RWLOCK_WRPHASE) != 0)
-      && ((r & PTHREAD_RWLOCK_WRLOCKED) == 0))
+  while ((r & PTHREAD_RWLOCK_WRPHASE) != 0
+	 && (r & PTHREAD_RWLOCK_WRLOCKED) == 0)
     {
-       /* Try to enter a read phase: If the CAS below succeeds, we have
+      /* Try to enter a read phase: If the CAS below succeeds, we have
 	 ownership; if it fails, we will simply retry and reassess the
 	 situation.
 	 Acquire MO so we synchronize with prior writers.  */
       if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r,
-	  r ^ PTHREAD_RWLOCK_WRPHASE))
+						r ^ PTHREAD_RWLOCK_WRPHASE))
 	{
 	  /* We started the read phase, so we are also responsible for
 	     updating the write-phase futex.  Relaxed MO is sufficient.
@@ -397,7 +399,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
 	     (but we can pretend to do the setting and unsetting of WRLOCKED
 	     atomically, and thus can skip this step).  */
 	  if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
-	      & PTHREAD_RWLOCK_FUTEX_USED) != 0)
+	       & PTHREAD_RWLOCK_FUTEX_USED) != 0)
 	    {
 	      int private = __pthread_rwlock_get_private (rwlock);
 	      futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
@@ -435,16 +437,17 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
   for (;;)
     {
       while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
-	  | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
+	      | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
 	{
 	  int private = __pthread_rwlock_get_private (rwlock);
 	  if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
-	      && !atomic_compare_exchange_weak_relaxed
+	      && (!atomic_compare_exchange_weak_relaxed
 		  (&rwlock->__data.__wrphase_futex,
-		   &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED))
+		   &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED)))
 	    continue;
 	  int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
-	      1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
+					 1 | PTHREAD_RWLOCK_FUTEX_USED,
+					 abstime, private);
 	  if (err == ETIMEDOUT)
 	    {
 	      /* If we timed out, we need to unregister.  If no read phase
@@ -477,8 +480,8 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
 		 in this case and thus make the spin-waiting we need
 		 unnecessarily expensive.  */
 	      while ((atomic_load_relaxed (&rwlock->__data.__wrphase_futex)
-		  | PTHREAD_RWLOCK_FUTEX_USED)
-		  == (1 | PTHREAD_RWLOCK_FUTEX_USED))
+		      | PTHREAD_RWLOCK_FUTEX_USED)
+		     == (1 | PTHREAD_RWLOCK_FUTEX_USED))
 		{
 		  /* TODO Back-off?  */
 		}
@@ -495,7 +498,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
 	 release of the writer, and so that we observe a recent value of
 	 __wrphase_futex (see below).  */
       if ((atomic_load_acquire (&rwlock->__data.__readers)
-	  & PTHREAD_RWLOCK_WRPHASE) == 0)
+	   & PTHREAD_RWLOCK_WRPHASE) == 0)
 	/* We are in a read phase now, so the least recent modification of
 	   __wrphase_futex we can read from is the store by the writer
 	   with value 1.  Thus, only now we can assume that if we observe
@@ -516,8 +519,9 @@ __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock)
   atomic_store_relaxed (&rwlock->__data.__cur_writer, 0);
   /* Disable waiting by writers.  We will wake up after we decided how to
      proceed.  */
-  bool wake_writers = ((atomic_exchange_relaxed
-      (&rwlock->__data.__writers_futex, 0) & PTHREAD_RWLOCK_FUTEX_USED) != 0);
+  bool wake_writers
+    = ((atomic_exchange_relaxed (&rwlock->__data.__writers_futex, 0)
+	& PTHREAD_RWLOCK_FUTEX_USED) != 0);
 
   if (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP)
     {
@@ -529,8 +533,8 @@ __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock)
 	     synchronize with us and thus can take over our view of
 	     __readers (including, for example, whether we are in a write
 	     phase or not).  */
-	  if (atomic_compare_exchange_weak_release (&rwlock->__data.__writers,
-	      &w, w | PTHREAD_RWLOCK_WRHANDOVER))
+	  if (atomic_compare_exchange_weak_release
+	      (&rwlock->__data.__writers, &w, w | PTHREAD_RWLOCK_WRHANDOVER))
 	    /* Another writer will take over.  */
 	    goto done;
 	  /* TODO Back-off.  */
@@ -543,9 +547,10 @@ __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock)
   unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
   /* Release MO so that subsequent readers or writers synchronize with us.  */
   while (!atomic_compare_exchange_weak_release
-      (&rwlock->__data.__readers, &r, (r ^ PTHREAD_RWLOCK_WRLOCKED)
-	  ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
-	      : PTHREAD_RWLOCK_WRPHASE)))
+	 (&rwlock->__data.__readers, &r,
+	  ((r ^ PTHREAD_RWLOCK_WRLOCKED)
+	   ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
+	      : PTHREAD_RWLOCK_WRPHASE))))
     {
       /* TODO Back-off.  */
     }
@@ -574,7 +579,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
   /* Make sure we are not holding the rwlock as a writer.  This is a deadlock
      situation we recognize and report.  */
   if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer)
-      == THREAD_GETMEM (THREAD_SELF, tid)))
+			== THREAD_GETMEM (THREAD_SELF, tid)))
     return EDEADLK;
 
   /* First we try to acquire the role of primary writer by setting WRLOCKED;
@@ -593,12 +598,12 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
      this could be less scalable if readers arrive and leave frequently.  */
   bool may_share_futex_used_flag = false;
   unsigned int r = atomic_fetch_or_acquire (&rwlock->__data.__readers,
-      PTHREAD_RWLOCK_WRLOCKED);
+					    PTHREAD_RWLOCK_WRLOCKED);
   if (__glibc_unlikely ((r & PTHREAD_RWLOCK_WRLOCKED) != 0))
     {
       /* There is another primary writer.  */
-      bool prefer_writer =
-	  (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP);
+      bool prefer_writer
+	= (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP);
       if (prefer_writer)
 	{
 	  /* We register as a waiting writer, so that we can make use of
@@ -617,8 +622,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 	      /* Try to become the primary writer or retry.  Acquire MO as in
 		 the fetch_or above.  */
 	      if (atomic_compare_exchange_weak_acquire
-		  (&rwlock->__data.__readers, &r,
-		      r | PTHREAD_RWLOCK_WRLOCKED))
+		  (&rwlock->__data.__readers, &r, r | PTHREAD_RWLOCK_WRLOCKED))
 		{
 		  if (prefer_writer)
 		    {
@@ -633,8 +637,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 			 __writers).
 			 ??? Perhaps this is not strictly necessary for
 			 reasons we do not yet know of.  */
-		      atomic_fetch_add_relaxed (&rwlock->__data.__writers,
-			  -1);
+		      atomic_fetch_add_relaxed (&rwlock->__data.__writers, -1);
 		    }
 		  break;
 		}
@@ -646,8 +649,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 	     succeed, we own WRLOCKED.  */
 	  if (prefer_writer)
 	    {
-	      unsigned int w = atomic_load_relaxed
-		  (&rwlock->__data.__writers);
+	      unsigned int w = atomic_load_relaxed (&rwlock->__data.__writers);
 	      if ((w & PTHREAD_RWLOCK_WRHANDOVER) != 0)
 		{
 		  /* Acquire MO is required here so that we synchronize with
@@ -677,13 +679,13 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 	  /* We did not acquire WRLOCKED nor were able to use writer--writer
 	     hand-over, so we block on __writers_futex.  */
 	  int private = __pthread_rwlock_get_private (rwlock);
-	  unsigned int wf = atomic_load_relaxed
-	      (&rwlock->__data.__writers_futex);
+	  unsigned int wf
+	    = atomic_load_relaxed (&rwlock->__data.__writers_futex);
 	  if (((wf & ~(unsigned int) PTHREAD_RWLOCK_FUTEX_USED) != 1)
 	      || ((wf != (1 | PTHREAD_RWLOCK_FUTEX_USED))
-		  && !atomic_compare_exchange_weak_relaxed
+		  && (!atomic_compare_exchange_weak_relaxed
 		      (&rwlock->__data.__writers_futex, &wf,
-		       1 | PTHREAD_RWLOCK_FUTEX_USED)))
+		       1 | PTHREAD_RWLOCK_FUTEX_USED))))
 	    {
 	      /* If we cannot block on __writers_futex because there is no
 		 primary writer, or we cannot set PTHREAD_RWLOCK_FUTEX_USED,
@@ -704,7 +706,8 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 	     in this group.  */
 	  may_share_futex_used_flag = true;
 	  int err = futex_abstimed_wait (&rwlock->__data.__writers_futex,
-	      1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
+					 1 | PTHREAD_RWLOCK_FUTEX_USED,
+					 abstime, private);
 	  if (err == ETIMEDOUT)
 	    {
 	      if (prefer_writer)
@@ -716,10 +719,10 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 		     that this happened before the timeout; see
 		     pthread_rwlock_rdlock_full for the full reasoning.)
 		     Also see the similar code above.  */
-		  unsigned int w = atomic_load_relaxed
-		      (&rwlock->__data.__writers);
+		  unsigned int w
+		    = atomic_load_relaxed (&rwlock->__data.__writers);
 		  while (!atomic_compare_exchange_weak_acquire
-		      (&rwlock->__data.__writers, &w,
+			 (&rwlock->__data.__writers, &w,
 			  (w == PTHREAD_RWLOCK_WRHANDOVER + 1 ? 0 : w - 1)))
 		    {
 		      /* TODO Back-off.  */
@@ -751,7 +754,8 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
      modifications of __readers ensures that this store happens after the
      store of value 0 by the previous primary writer.  */
   atomic_store_relaxed (&rwlock->__data.__writers_futex,
-      1 | (may_share_futex_used_flag ? PTHREAD_RWLOCK_FUTEX_USED : 0));
+			1 | (may_share_futex_used_flag
+			     ? PTHREAD_RWLOCK_FUTEX_USED : 0));
 
   /* If we are in a write phase, we have acquired the lock.  */
   if ((r & PTHREAD_RWLOCK_WRPHASE) != 0)
@@ -759,15 +763,15 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 
   /* If we are in a read phase and there are no readers, try to start a write
      phase.  */
-  while (((r & PTHREAD_RWLOCK_WRPHASE) == 0)
-      && ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0))
+  while ((r & PTHREAD_RWLOCK_WRPHASE) == 0
+	 && (r >> PTHREAD_RWLOCK_READER_SHIFT) == 0)
     {
       /* Acquire MO so that we synchronize with prior writers and do
 	 not interfere with their updates to __writers_futex, as well
 	 as regarding prior readers and their updates to __wrphase_futex,
 	 respectively.  */
       if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers,
-	  &r, r | PTHREAD_RWLOCK_WRPHASE))
+						&r, r | PTHREAD_RWLOCK_WRPHASE))
 	{
 	  /* We have started a write phase, so need to enable readers to wait.
 	     See the similar case in __pthread_rwlock_rdlock_full.  Unlike in
@@ -792,24 +796,24 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
   for (;;)
     {
       while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
-	  | PTHREAD_RWLOCK_FUTEX_USED) == PTHREAD_RWLOCK_FUTEX_USED)
+	      | PTHREAD_RWLOCK_FUTEX_USED) == PTHREAD_RWLOCK_FUTEX_USED)
 	{
 	  int private = __pthread_rwlock_get_private (rwlock);
-	  if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
-	      && !atomic_compare_exchange_weak_relaxed
+	  if ((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0
+	      && (!atomic_compare_exchange_weak_relaxed
 		  (&rwlock->__data.__wrphase_futex, &wpf,
-		   PTHREAD_RWLOCK_FUTEX_USED))
+		   PTHREAD_RWLOCK_FUTEX_USED)))
 	    continue;
 	  int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
-	      PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
+					 PTHREAD_RWLOCK_FUTEX_USED,
+					 abstime, private);
 	  if (err == ETIMEDOUT)
 	    {
-	      if (rwlock->__data.__flags
-		  != PTHREAD_RWLOCK_PREFER_READER_NP)
+	      if (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP)
 		{
 		  /* We try writer--writer hand-over.  */
-		  unsigned int w = atomic_load_relaxed
-		      (&rwlock->__data.__writers);
+		  unsigned int w
+		    = atomic_load_relaxed (&rwlock->__data.__writers);
 		  if (w != 0)
 		    {
 		      /* We are about to hand over WRLOCKED, so we must
@@ -823,13 +827,13 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 			 Release MO so that another writer that gets
 			 WRLOCKED from us can take over our view of
 			 __readers.  */
-		      unsigned int wf = atomic_exchange_relaxed
-			  (&rwlock->__data.__writers_futex, 0);
+		      unsigned int wf
+			= atomic_exchange_relaxed (&rwlock->__data.__writers_futex, 0);
 		      while (w != 0)
 			{
 			  if (atomic_compare_exchange_weak_release
 			      (&rwlock->__data.__writers, &w,
-				  w | PTHREAD_RWLOCK_WRHANDOVER))
+			       w | PTHREAD_RWLOCK_WRHANDOVER))
 			    {
 			      /* Wake other writers.  */
 			      if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0)
@@ -844,8 +848,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 			 again.  Make sure we don't loose the flag that
 			 signals whether there are threads waiting on
 			 this futex.  */
-		      atomic_store_relaxed
-			  (&rwlock->__data.__writers_futex, wf);
+		      atomic_store_relaxed (&rwlock->__data.__writers_futex, wf);
 		    }
 		}
 	      /* If we timed out and we are not in a write phase, we can
@@ -857,8 +860,8 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 		  /* We are about to release WRLOCKED, so we must release
 		     __writers_futex too; see the handling of
 		     writer--writer hand-over above.  */
-		  unsigned int wf = atomic_exchange_relaxed
-		      (&rwlock->__data.__writers_futex, 0);
+		  unsigned int wf
+		    = atomic_exchange_relaxed (&rwlock->__data.__writers_futex, 0);
 		  while ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
 		    {
 		      /* While we don't need to make anything from a
@@ -877,11 +880,11 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 			  /* Wake other writers.  */
 			  if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0)
 			    futex_wake (&rwlock->__data.__writers_futex,
-				1, private);
+					1, private);
 			  /* Wake waiting readers.  */
 			  if ((r & PTHREAD_RWLOCK_RWAITING) != 0)
 			    futex_wake (&rwlock->__data.__readers,
-				INT_MAX, private);
+					INT_MAX, private);
 			  return ETIMEDOUT;
 			}
 		    }
@@ -898,10 +901,9 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 	      atomic_thread_fence_acquire ();
 	      /* We still need to wait for explicit hand-over, but we must
 		 not use futex_wait anymore.  */
-	      while ((atomic_load_relaxed
-		  (&rwlock->__data.__wrphase_futex)
-		   | PTHREAD_RWLOCK_FUTEX_USED)
-		  == PTHREAD_RWLOCK_FUTEX_USED)
+	      while ((atomic_load_relaxed (&rwlock->__data.__wrphase_futex)
+		      | PTHREAD_RWLOCK_FUTEX_USED)
+		     == PTHREAD_RWLOCK_FUTEX_USED)
 		{
 		  /* TODO Back-off.  */
 		}
@@ -915,12 +917,12 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
       if (ready)
 	break;
       if ((atomic_load_acquire (&rwlock->__data.__readers)
-	  & PTHREAD_RWLOCK_WRPHASE) != 0)
+	   & PTHREAD_RWLOCK_WRPHASE) != 0)
 	ready = true;
     }
 
  done:
   atomic_store_relaxed (&rwlock->__data.__cur_writer,
-      THREAD_GETMEM (THREAD_SELF, tid));
+			THREAD_GETMEM (THREAD_SELF, tid));
   return 0;
 }

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

Summary of changes:
 ChangeLog                    |    9 +++
 nptl/Makefile                |    3 +-
 nptl/pthread_rwlock_common.c |  160 +++++++++++++++++++++---------------------
 nptl/tst-rwlock-pwn.c        |   87 +++++++++++++++++++++++
 4 files changed, 179 insertions(+), 80 deletions(-)
 create mode 100644 nptl/tst-rwlock-pwn.c


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



More information about the Glibc-cvs mailing list