summaryrefslogtreecommitdiff
path: root/sysdeps/generic/pt-mutex-timedlock.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/generic/pt-mutex-timedlock.c')
-rw-r--r--sysdeps/generic/pt-mutex-timedlock.c47
1 files changed, 28 insertions, 19 deletions
diff --git a/sysdeps/generic/pt-mutex-timedlock.c b/sysdeps/generic/pt-mutex-timedlock.c
index 48bffaf..43e0eda 100644
--- a/sysdeps/generic/pt-mutex-timedlock.c
+++ b/sysdeps/generic/pt-mutex-timedlock.c
@@ -30,6 +30,8 @@ int
__pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex,
const struct timespec *abstime)
{
+ error_t err;
+ int drain;
struct __pthread *self;
const struct __pthread_mutexattr *attr = mutex->attr;
@@ -127,30 +129,37 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex,
/* Block the thread. */
if (abstime)
+ err = __pthread_timedblock (self, abstime, CLOCK_REALTIME);
+ else
{
- error_t err;
-
- err = __pthread_timedblock (self, abstime, CLOCK_REALTIME);
- if (err)
- /* We timed out. We may need to disconnect ourself from the
- waiter queue.
+ err = 0;
+ __pthread_block (self);
+ }
- FIXME: What do we do if we get a wakeup message before we
- disconnect ourself? It may remain until the next time we
- block. */
- {
- assert (err == ETIMEDOUT);
+ __pthread_spin_lock (&mutex->__lock);
+ if (! self->prevp)
+ /* 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 mutex lock, in
+ which case the message queue must be drained. */
+ drain = err ? 1 : 0;
+ else
+ {
+ /* We're still in the queue. Noone attempted to wake us up, i.e. we
+ timed out. */
+ __pthread_dequeue (self);
+ drain = 0;
+ }
+ __pthread_spin_unlock (&mutex->__lock);
- __pthread_spin_lock (&mutex->__lock);
- if (self->prevp)
- __pthread_dequeue (self);
- __pthread_spin_unlock (&mutex->__lock);
+ if (drain)
+ __pthread_block (self);
- return err;
- }
+ if (err)
+ {
+ assert (err == ETIMEDOUT);
+ return err;
}
- else
- __pthread_block (self);
#if !defined(ALWAYS_TRACK_MUTEX_OWNER)
if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL)