In case the rwlock is unlocked right before we time out, we will have been
given ownership, so we shouldn't time out.

Reported-by: Brent Baccala <[email protected]> 's Claude assistant
---
 sysdeps/htl/pt-rwlock-timedrdlock.c | 41 +++++++++++++----------------
 sysdeps/htl/pt-rwlock-timedwrlock.c | 35 +++++++++++-------------
 2 files changed, 35 insertions(+), 41 deletions(-)

diff --git a/sysdeps/htl/pt-rwlock-timedrdlock.c 
b/sysdeps/htl/pt-rwlock-timedrdlock.c
index 41671e40f9..25b761433a 100644
--- a/sysdeps/htl/pt-rwlock-timedrdlock.c
+++ b/sysdeps/htl/pt-rwlock-timedrdlock.c
@@ -31,7 +31,6 @@ __pthread_rwlock_timedrdlock_internal (struct 
__pthread_rwlock *rwlock,
                                       const struct timespec *abstime)
 {
   error_t err;
-  int drain;
   struct __pthread *self;
 
   __pthread_spin_wait (&rwlock->__lock);
@@ -85,35 +84,33 @@ __pthread_rwlock_timedrdlock_internal (struct 
__pthread_rwlock *rwlock,
 
   __pthread_spin_wait (&rwlock->__lock);
   if (self->prevp == NULL)
-    /* Another thread removed us from the queue, which means a wakeup message
-       has been sent.  It was either consumed while we were blocking, or
-       queued after we timed out and before we acquired the rwlock lock, in
-       which case the message queue must be drained.  */
-    drain = err ? 1 : 0;
+    {
+      /* Another thread removed us from the queue, which means it gave us
+        ownership and a wakeup message has been sent. It was either consumed
+        while we were blocking, or queued after we timed out and before we
+        acquired the rwlock lock, in which case the message queue must be
+        drained. */
+      __pthread_spin_unlock (&rwlock->__lock);
+      if (err)
+       /* We have not consumed the message, do it now.  */
+       __pthread_block (self);
+
+      /* The reader count has already been increment by whoever woke us
+        up.  */
+
+      assert (rwlock->__readers > 0);
+
+      return 0;
+    }
   else
     {
       /* We're still in the queue.  No one attempted to wake us up, i.e. we
          timed out.  */
       __pthread_dequeue (self);
-      drain = 0;
-    }
-  __pthread_spin_unlock (&rwlock->__lock);
-
-  if (drain)
-    __pthread_block (self);
-
-  if (err)
-    {
+      __pthread_spin_unlock (&rwlock->__lock);
       assert (err == ETIMEDOUT);
       return err;
     }
-
-  /* The reader count has already been increment by whoever woke us
-     up.  */
-
-  assert (rwlock->__readers > 0);
-
-  return 0;
 }
 
 int
diff --git a/sysdeps/htl/pt-rwlock-timedwrlock.c 
b/sysdeps/htl/pt-rwlock-timedwrlock.c
index 6b202a25dd..841d1f9101 100644
--- a/sysdeps/htl/pt-rwlock-timedwrlock.c
+++ b/sysdeps/htl/pt-rwlock-timedwrlock.c
@@ -31,7 +31,6 @@ __pthread_rwlock_timedwrlock_internal (struct 
__pthread_rwlock *rwlock,
                                       const struct timespec *abstime)
 {
   error_t err;
-  int drain;
   struct __pthread *self;
 
   __pthread_spin_wait (&rwlock->__lock);
@@ -71,32 +70,30 @@ __pthread_rwlock_timedwrlock_internal (struct 
__pthread_rwlock *rwlock,
 
   __pthread_spin_wait (&rwlock->__lock);
   if (self->prevp == NULL)
-    /* Another thread removed us from the queue, which means a wakeup message
-       has been sent.  It was either consumed while we were blocking, or
-       queued after we timed out and before we acquired the rwlock lock, in
-       which case the message queue must be drained.  */
-    drain = err ? 1 : 0;
+    {
+      /* Another thread removed us from the queue, which means it gave us
+        ownership and a wakeup message has been sent. It was either consumed
+        while we were blocking, or queued after we timed out and before we
+        acquired the rwlock lock, in which case the message queue must be
+        drained. */
+      __pthread_spin_unlock (&rwlock->__lock);
+      if (err)
+       /* We have not consumed the message, do it now.  */
+       __pthread_block (self);
+
+      assert (rwlock->__readers == 0);
+
+      return 0;
+    }
   else
     {
       /* We're still in the queue.  No one attempted to wake us up, i.e. we
          timed out.  */
       __pthread_dequeue (self);
-      drain = 0;
-    }
-  __pthread_spin_unlock (&rwlock->__lock);
-
-  if (drain)
-    __pthread_block (self);
-
-  if (err)
-    {
+      __pthread_spin_unlock (&rwlock->__lock);
       assert (err == ETIMEDOUT);
       return err;
     }
-
-  assert (rwlock->__readers == 0);
-
-  return 0;
 }
 
 int
-- 
2.51.0


Reply via email to