public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: malteskarupke@fastmail.fm
To: libc-alpha@sourceware.org
Cc: Malte Skarupke <malteskarupke@fastmail.fm>
Subject: [PATCH 5/9] nptl: Remove g_refs from condition variables
Date: Fri, 27 Jan 2023 21:18:25 -0500	[thread overview]
Message-ID: <20230128021829.7990-6-malteskarupke@fastmail.fm> (raw)
In-Reply-To: <20230128021829.7990-1-malteskarupke@fastmail.fm>

From: Malte Skarupke <malteskarupke@fastmail.fm>

This variable used to be needed to wait in group switching until all sleepers
have confirmed that they have woken. This is no longer needed. Nothing waits
on this variable so there is no need to track how many threads are currently
asleep in each group.
---
 nptl/pthread_cond_wait.c                | 52 +------------------------
 nptl/tst-cond22.c                       | 12 +++---
 sysdeps/nptl/bits/thread-shared-types.h |  4 +-
 sysdeps/nptl/pthread.h                  |  2 +-
 4 files changed, 10 insertions(+), 60 deletions(-)

diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
index 47e834cade..8a9219e064 100644
--- a/nptl/pthread_cond_wait.c
+++ b/nptl/pthread_cond_wait.c
@@ -143,23 +143,6 @@ __condvar_cancel_waiting (pthread_cond_t *cond, uint64_t seq, unsigned int g,
     }
 }
 
-/* Wake up any signalers that might be waiting.  */
-static void
-__condvar_dec_grefs (pthread_cond_t *cond, unsigned int g, int private)
-{
-  /* Release MO to synchronize-with the acquire load in
-     __condvar_quiesce_and_switch_g1.  */
-  if (atomic_fetch_add_release (cond->__data.__g_refs + g, -2) == 3)
-    {
-      /* Clear the wake-up request flag before waking up.  We do not need more
-	 than relaxed MO and it doesn't matter if we apply this for an aliased
-	 group because we wake all futex waiters right after clearing the
-	 flag.  */
-      atomic_fetch_and_relaxed (cond->__data.__g_refs + g, ~(unsigned int) 1);
-      futex_wake (cond->__data.__g_refs + g, INT_MAX, private);
-    }
-}
-
 /* Clean-up for cancellation of waiters waiting for normal signals.  We cancel
    our registration as a waiter, confirm we have woken up, and re-acquire the
    mutex.  */
@@ -171,8 +154,6 @@ __condvar_cleanup_waiting (void *arg)
   pthread_cond_t *cond = cbuffer->cond;
   unsigned g = cbuffer->wseq & 1;
 
-  __condvar_dec_grefs (cond, g, cbuffer->private);
-
   __condvar_cancel_waiting (cond, cbuffer->wseq >> 1, g, cbuffer->private);
   /* FIXME With the current cancellation implementation, it is possible that
      a thread is cancelled after it has returned from a syscall.  This could
@@ -327,15 +308,6 @@ __condvar_cleanup_waiting (void *arg)
    sufficient because if a waiter can see a sufficiently large value, it could
    have also consume a signal in the waiters group.
 
-   It is essential that the last field in pthread_cond_t is __g_signals[1]:
-   The previous condvar used a pointer-sized field in pthread_cond_t, so a
-   PTHREAD_COND_INITIALIZER from that condvar implementation might only
-   initialize 4 bytes to zero instead of the 8 bytes we need (i.e., 44 bytes
-   in total instead of the 48 we need).  __g_signals[1] is not accessed before
-   the first group switch (G2 starts at index 0), which will set its value to
-   zero after a harmless fetch-or whose return value is ignored.  This
-   effectively completes initialization.
-
 
    Limitations:
    * This condvar isn't designed to allow for more than
@@ -440,21 +412,6 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
 	  if ((int)(signals - lowseq) >= 2)
 	    break;
 
-	  /* No signals available after spinning, so prepare to block.
-	     We first acquire a group reference and use acquire MO for that so
-	     that we synchronize with the dummy read-modify-write in
-	     __condvar_quiesce_and_switch_g1 if we read from that.  In turn,
-	     in this case this will make us see the advancement of __g_signals
-	     to the upcoming new g1_start that occurs with a concurrent
-	     attempt to reuse the group's slot.
-	     We use acquire MO for the __g_signals check to make the
-	     __g1_start check work (see spinning above).
-	     Note that the group reference acquisition will not mask the
-	     release MO when decrementing the reference count because we use
-	     an atomic read-modify-write operation and thus extend the release
-	     sequence.  */
-	  atomic_fetch_add_acquire (cond->__data.__g_refs + g, 2);
-
 	  // Now block.
 	  struct _pthread_cleanup_buffer buffer;
 	  struct _condvar_cleanup_buffer cbuffer;
@@ -471,18 +428,11 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
 
 	  if (__glibc_unlikely (err == ETIMEDOUT || err == EOVERFLOW))
 	    {
-	      __condvar_dec_grefs (cond, g, private);
-	      /* If we timed out, we effectively cancel waiting.  Note that
-		 we have decremented __g_refs before cancellation, so that a
-		 deadlock between waiting for quiescence of our group in
-		 __condvar_quiesce_and_switch_g1 and us trying to acquire
-		 the lock during cancellation is not possible.  */
+	      /* If we timed out, we effectively cancel waiting.  */
 	      __condvar_cancel_waiting (cond, seq, g, private);
 	      result = err;
 	      goto done;
 	    }
-	  else
-	    __condvar_dec_grefs (cond, g, private);
 
 	  /* Reload signals.  See above for MO.  */
 	  signals = atomic_load_acquire (cond->__data.__g_signals + g);
diff --git a/nptl/tst-cond22.c b/nptl/tst-cond22.c
index 1336e9c79d..bdcb45c536 100644
--- a/nptl/tst-cond22.c
+++ b/nptl/tst-cond22.c
@@ -106,13 +106,13 @@ do_test (void)
       status = 1;
     }
 
-  printf ("cond = { 0x%x:%x, 0x%x:%x, %u/%u/%u, %u/%u/%u, %u, %u }\n",
+  printf ("cond = { 0x%x:%x, 0x%x:%x, %u/%u, %u/%u, %u, %u }\n",
 	  c.__data.__wseq.__value32.__high,
 	  c.__data.__wseq.__value32.__low,
 	  c.__data.__g1_start.__value32.__high,
 	  c.__data.__g1_start.__value32.__low,
-	  c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
-	  c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
+	  c.__data.__g_signals[0], c.__data.__g_size[0],
+	  c.__data.__g_signals[1], c.__data.__g_size[1],
 	  c.__data.__g1_orig_size, c.__data.__wrefs);
 
   if (pthread_create (&th, NULL, tf, (void *) 1l) != 0)
@@ -152,13 +152,13 @@ do_test (void)
       status = 1;
     }
 
-  printf ("cond = { 0x%x:%x, 0x%x:%x, %u/%u/%u, %u/%u/%u, %u, %u }\n",
+  printf ("cond = { 0x%x:%x, 0x%x:%x, %u/%u, %u/%u, %u, %u }\n",
 	  c.__data.__wseq.__value32.__high,
 	  c.__data.__wseq.__value32.__low,
 	  c.__data.__g1_start.__value32.__high,
 	  c.__data.__g1_start.__value32.__low,
-	  c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
-	  c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
+	  c.__data.__g_signals[0], c.__data.__g_size[0],
+	  c.__data.__g_signals[1], c.__data.__g_size[1],
 	  c.__data.__g1_orig_size, c.__data.__wrefs);
 
   return status;
diff --git a/sysdeps/nptl/bits/thread-shared-types.h b/sysdeps/nptl/bits/thread-shared-types.h
index 5653507e55..d1af98b215 100644
--- a/sysdeps/nptl/bits/thread-shared-types.h
+++ b/sysdeps/nptl/bits/thread-shared-types.h
@@ -95,11 +95,11 @@ struct __pthread_cond_s
 {
   __atomic_wide_counter __wseq;
   __atomic_wide_counter __g1_start;
-  unsigned int __g_refs[2] __LOCK_ALIGNMENT;
-  unsigned int __g_size[2];
+  unsigned int __g_size[2] __LOCK_ALIGNMENT;
   unsigned int __g1_orig_size;
   unsigned int __wrefs;
   unsigned int __g_signals[2];
+  unsigned int __unused;
 };
 
 typedef unsigned int __tss_t;
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
index dedad4ec86..10e7f35e9a 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -152,7 +152,7 @@ enum
 
 
 /* Conditional variable handling.  */
-#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } }
+#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, 0, 0, {0, 0}, 0 } }
 
 
 /* Cleanup buffers */
-- 
2.25.1


  parent reply	other threads:[~2023-01-28  2:18 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-28  2:18 [PATCH 0/9] Patch to fix glibc condition variable bug (BZ 25847) malteskarupke
2023-01-28  2:18 ` [PATCH 1/9] pthreads NPTL: lost wakeup fix 2 malteskarupke
2023-01-28  2:18 ` [PATCH 2/9] nptl: Update comments and indentation for new condvar implementation malteskarupke
2023-01-28  2:18 ` [PATCH 3/9] nptl: Remove unnecessary catch-all-wake in condvar group switch malteskarupke
2023-01-28  2:18 ` [PATCH 4/9] nptl: Remove unnecessary quadruple check in pthread_cond_wait malteskarupke
2023-01-28  2:18 ` malteskarupke [this message]
2023-01-28  2:18 ` [PATCH 6/9] nptl: Use a single loop in pthread_cond_wait instaed of a nested loop malteskarupke
2023-01-28  2:18 ` [PATCH 7/9] nptl: Fix indentation malteskarupke
2023-01-28  2:18 ` [PATCH 8/9] nptl: rename __condvar_quiesce_and_switch_g1 malteskarupke
2023-01-28  2:18 ` [PATCH 9/9] nptl: Use all of g1_start and g_signals malteskarupke
2023-02-08  2:48 ` [PATCH 0/9] Patch to fix glibc condition variable bug (BZ 25847) Malte Skarupke
2023-02-08  2:51   ` Sam James
2023-03-18 12:08     ` Malte Skarupke

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230128021829.7990-6-malteskarupke@fastmail.fm \
    --to=malteskarupke@fastmail.fm \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).