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 4/9] nptl: Remove unnecessary quadruple check in pthread_cond_wait
Date: Fri, 27 Jan 2023 21:18:24 -0500	[thread overview]
Message-ID: <20230128021829.7990-5-malteskarupke@fastmail.fm> (raw)
In-Reply-To: <20230128021829.7990-1-malteskarupke@fastmail.fm>

From: Malte Skarupke <malteskarupke@fastmail.fm>

pthread_cond_wait was checking whether it was in a closed group no less than
four times. Checking once is enough. Here are the four checks:

1. While spin-waiting. This was dead code: maxspin is set to 0 and has been
   for years.
2. Before deciding to go to sleep, and before incrementing grefs: I kept this
3. After incrementing grefs. There is no reason to think that the group would
   close while we do an atomic increment. Obviously it could close at any
   point, but that doesn't mean we have to recheck after every step. This
   check was equally good as check 2, except it has to do more work.
4. When we find ourselves in a group that has a signal. We only get here after
   we check that we're not in a closed group. There is no need to check again.
   The check would only have helped in cases where the compare_exchange in the
   next line would also have failed. Relying on the compare_exchange is fine.

Removing the duplicate checks clarifies the code.
---
 nptl/pthread_cond_wait.c | 49 ----------------------------------------
 1 file changed, 49 deletions(-)

diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
index cee1968756..47e834cade 100644
--- a/nptl/pthread_cond_wait.c
+++ b/nptl/pthread_cond_wait.c
@@ -366,7 +366,6 @@ static __always_inline int
 __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
     clockid_t clockid, const struct __timespec64 *abstime)
 {
-  const int maxspin = 0;
   int err;
   int result = 0;
 
@@ -425,33 +424,6 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
 	  uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
 	  unsigned int lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
 
-	  /* Spin-wait first.
-	     Note that spinning first without checking whether a timeout
-	     passed might lead to what looks like a spurious wake-up even
-	     though we should return ETIMEDOUT (e.g., if the caller provides
-	     an absolute timeout that is clearly in the past).  However,
-	     (1) spurious wake-ups are allowed, (2) it seems unlikely that a
-	     user will (ab)use pthread_cond_wait as a check for whether a
-	     point in time is in the past, and (3) spinning first without
-	     having to compare against the current time seems to be the right
-	     choice from a performance perspective for most use cases.  */
-	  unsigned int spin = maxspin;
-	  while (spin > 0 && ((int)(signals - lowseq) < 2))
-	    {
-	      /* Check that we are not spinning on a group that's already
-		 closed.  */
-	      if (seq < (g1_start >> 1))
-		break;
-
-	      /* TODO Back off.  */
-
-	      /* Reload signals.  See above for MO.  */
-	      signals = atomic_load_acquire (cond->__data.__g_signals + g);
-	      g1_start = __condvar_load_g1_start_relaxed (cond);
-	      lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
-	      spin--;
-	    }
-
 	  if (seq < (g1_start >> 1))
 	    {
 	      /* If the group is closed already,
@@ -482,24 +454,6 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
 	     an atomic read-modify-write operation and thus extend the release
 	     sequence.  */
 	  atomic_fetch_add_acquire (cond->__data.__g_refs + g, 2);
-	  signals = atomic_load_acquire (cond->__data.__g_signals + g);
-	  g1_start = __condvar_load_g1_start_relaxed (cond);
-	  lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
-
-	  if (seq < (g1_start >> 1))
-	    {
-	      /* group is closed already, so don't block */
-	      __condvar_dec_grefs (cond, g, private);
-	      goto done;
-	    }
-
-	  if ((int)(signals - lowseq) >= 2)
-	    {
-	      /* a signal showed up or G1/G2 switched after we grabbed the
-	         refcount */
-	      __condvar_dec_grefs (cond, g, private);
-	      break;
-	    }
 
 	  // Now block.
 	  struct _pthread_cleanup_buffer buffer;
@@ -533,9 +487,6 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
 	  /* Reload signals.  See above for MO.  */
 	  signals = atomic_load_acquire (cond->__data.__g_signals + g);
 	}
-
-       if (seq < (__condvar_load_g1_start_relaxed (cond) >> 1))
-	 goto done;
     }
   /* Try to grab a signal.  See above for MO.  (if we do another loop
      iteration we need to see the correct value of g1_start)  */
-- 
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 ` malteskarupke [this message]
2023-01-28  2:18 ` [PATCH 5/9] nptl: Remove g_refs from condition variables malteskarupke
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-5-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).