diff options
Diffstat (limited to 'sysdeps/generic/pt-mutex-timedlock.c')
-rw-r--r-- | sysdeps/generic/pt-mutex-timedlock.c | 47 |
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) |