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
