Author: sthibault
Date: 2013-02-24 18:17:19 +0000 (Sun, 24 Feb 2013)
New Revision: 5498

Added:
   
glibc-package/branches/eglibc-2.17/debian/patches/hurd-i386/libpthread_cancellation.diff
   
glibc-package/branches/eglibc-2.17/debian/patches/hurd-i386/libpthread_hurd_cond_timedwait.diff
Modified:
   glibc-package/branches/eglibc-2.17/debian/changelog
   glibc-package/branches/eglibc-2.17/debian/libc0.3.symbols.hurd-i386
   glibc-package/branches/eglibc-2.17/debian/patches/series
Log:
Forward 5497 from trunk.

* patches/hurd-i386/libpthread_cancellation.diff: New patch, fixes
  cancellations.
* patches/hurd-i386/libpthread_hurd_cond_timedwait.diff: New patch, introduces
  pthread_hurd_cond_timedwait_np needed to fix select with zero timeout in
  Hurd servers.


Modified: glibc-package/branches/eglibc-2.17/debian/changelog
===================================================================
--- glibc-package/branches/eglibc-2.17/debian/changelog 2013-02-24 18:16:00 UTC 
(rev 5497)
+++ glibc-package/branches/eglibc-2.17/debian/changelog 2013-02-24 18:17:19 UTC 
(rev 5498)
@@ -615,6 +615,11 @@
     version to fix stdio thread-safety.
   * patches/hurd-i386/tg-pie-sbrk.diff: Fix sbrk() use in PIE binaries (e.g.
     libgc, perl).
+  * patches/hurd-i386/libpthread_cancellation.diff: New patch, fixes
+    cancellations.
+  * patches/hurd-i386/libpthread_hurd_cond_timedwait.diff: New patch, 
introduces
+    pthread_hurd_cond_timedwait_np needed to fix select with zero timeout in
+    Hurd servers.
 
   [ Adam Conrad ]
   * debian/testsuite-checking/compare.sh: Disable failing the build on test

Modified: glibc-package/branches/eglibc-2.17/debian/libc0.3.symbols.hurd-i386
===================================================================
--- glibc-package/branches/eglibc-2.17/debian/libc0.3.symbols.hurd-i386 
2013-02-24 18:16:00 UTC (rev 5497)
+++ glibc-package/branches/eglibc-2.17/debian/libc0.3.symbols.hurd-i386 
2013-02-24 18:17:19 UTC (rev 5498)
@@ -944,4 +944,5 @@
 libpthread.so.0.3 #PACKAGE# #MINVER#
 #include "symbols.wildcards"
  *@GLIBC_2.13_DEBIAN_38 2.13-38~
+ *@GLIBC_2.13_DEBIAN_39 2.13-39~
  *@GLIBC_2.2.6 2.13-38~

Copied: 
glibc-package/branches/eglibc-2.17/debian/patches/hurd-i386/libpthread_cancellation.diff
 (from rev 5497, 
glibc-package/trunk/debian/patches/hurd-i386/libpthread_cancellation.diff)
===================================================================
--- 
glibc-package/branches/eglibc-2.17/debian/patches/hurd-i386/libpthread_cancellation.diff
                            (rev 0)
+++ 
glibc-package/branches/eglibc-2.17/debian/patches/hurd-i386/libpthread_cancellation.diff
    2013-02-24 18:17:19 UTC (rev 5498)
@@ -0,0 +1,863 @@
+commit 5ab516af0779a7fd74ad893c7c67960df6ede065
+Author: Richard Braun <rbr...@sceen.net>
+Date:   Sun Feb 3 16:06:51 2013 +0100
+
+    Fix pthread timeout handling and cancellation issues
+    
+    This patch solves two issues. The first one is cancellation handling
+    when a cancellation request is sent before reaching a cancellation
+    point (namely, pthread_cond_{timed,}wait). Cancellation is implemented
+    by pushing an appropriate cleanup handler and switching to
+    PTHREAD_CANCEL_ASYNCHRONOUS type. The main problem is that it doesn't
+    handle pending requests, only a cancellation that occurs while blocking.
+    Other problems occur when trying to correctly handle a timeout and a
+    cancellation request through the cleanup routine.
+    
+    The other issue is correctly handling timeouts. This problem was already
+    well known, as explained by the following comment :
+    
+    "FIXME: What do we do if we get a wakeup message before we disconnect
+    ourself?  It may remain until the next time we block."
+    
+    In addition, the prevp thread member is inconsistently used. It is
+    sometimes accessed while protected by the appropriate queue lock to
+    determine whether a thread is still queued, while at times, threads
+    are unqueued without holding a lock, as in pthread_cond_broadcast :
+    
+      /* We can safely walk the list of waiting threads without holding
+         the lock since it is now decoupled from the condition.  */
+      __pthread_dequeuing_iterate (wakeup, wakeup)
+        __pthread_wakeup (wakeup);
+    
+    This is the root cause that triggers some assertion failures.
+    
+    The solution brought by this patch is to consistently use the prevp link
+    to determine if both a thread has been unqueued and if a wakeup message
+    has been sent (both are needed to wake up a thread). A thread unblocked
+    because of a timeout can now accurately determine if it needs to drain
+    its message queue. A direct improvement is that the message queue size
+    can be limited to one message, and wakeups are guaranteed to be
+    non-blocking, which allows safely calling __pthread_wakeup from critical
+    sections.
+    
+    As it now affects the cleanup cancellation routine of
+    __pthread_cond_timedwait_internal, cancellation is reworked as well.
+    Cancellation type is forced to PTHREAD_CANCEL_DEFERRED during the call,
+    and actually checked on both entry and return. A hook is set by the
+    blocking thread so that the waker doesn't need to know about the call
+    implementation. Cancellation members are now protected with a mutex for
+    truely safe access.
+    
+    * pthread/pt-alloc.c (initialize_pthread): Initialize the new 
`cancel_lock',
+    `cancel_hook' and `cancel_hook_args' fields.
+    * pthread/pt-cancel.c (pthread_cancel): Rework cancellation handling.
+    * pthread/pt-internal.h (struct __pthread): Add `cancel_lock', 
`cancel_hook'
+    and `cancel_hook_args' fields.
+    (__pthread_dequeue): Assert thread->prevp isn't NULL.
+    * pthread/pt-join.c (pthread_join): Describe how the cancellation point is
+    implemented.
+    * pthread/pt-setcancelstate.c (__pthread_setcancelstate): Lock the given
+    thread cancellation lock when switching state.
+    * pthread/pt-setcanceltype.c (__pthread_setcanceltype): Likewise for
+    cancellation type.
+    * pthread/pt-testcancel.c (pthread_testcancel): Likewise for pending
+    cancellations.
+    * sysdeps/generic/pt-cond-brdcast.c (__pthread_cond_broadcast): Dequeue
+    and wake up threads with condition locked.
+    * sysdeps/generic/pt-cond-signal.c (cond_signal): Remove function, move
+    implementation to ...
+    (__pthread_cond_signal): ... this function. Remove unused `unblocked'
+    variable.
+    * sysdeps/generic/pt-cond-timedwait.c (struct cancel_ctx): New structure.
+    (cancel_hook): New static function.
+    (__pthread_cond_timedwait_internal): Fix cancellation and timeout handling.
+    * sysdeps/generic/pt-mutex-timedlock.c
+    (__pthread_mutex_timedlock_internal): Fix timeout handling.
+    * sysdeps/generic/pt-rwlock-timedrdlock.c
+    (__pthread_rwlock_timedrdlock_internal): Likewise.
+    * sysdeps/generic/pt-rwlock-timedwrlock.c
+    (__pthread_rwlock_timedwrlock_internal): Likewise.
+    * sysdeps/generic/pt-rwlock-unlock.c (pthread_rwlock_unlock): Dequeue and
+    wake up threads with rwlock internal lock held.
+    * sysdeps/generic/sem-timedwait.c (__sem_timedwait_internal): Fix timeout
+    handling.
+    * sysdeps/mach/hurd/pt-docancel.c (__pthread_do_cancel): Unlock the given
+    thread cancellation lock.
+    * sysdeps/mach/pt-thread-alloc.c (create_wakeupmsg): Limit the message
+    queue size of the wakeup port to 1.
+     * sysdeps/mach/pt-wakeup.c (__pthread_wakeup): Call __mach_msg in a
+    non-blocking way.
+
+diff --git a/libpthread/pthread/pt-alloc.c b/libpthread/pthread/pt-alloc.c
+index 6af2da9..89fca8a 100644
+--- a/libpthread/pthread/pt-alloc.c
++++ b/libpthread/pthread/pt-alloc.c
+@@ -55,6 +55,9 @@ initialize_pthread (struct __pthread *new, int recycling)
+   if (err)
+     return err;
+ 
++  new->cancel_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
++  new->cancel_hook = NULL;
++  new->cancel_hook_arg = NULL;
+   new->cancel_state = PTHREAD_CANCEL_ENABLE;
+   new->cancel_type = PTHREAD_CANCEL_DEFERRED;
+   new->cancel_pending = 0;
+diff --git a/libpthread/pthread/pt-cancel.c b/libpthread/pthread/pt-cancel.c
+index d19c557..96c77f7 100644
+--- a/libpthread/pthread/pt-cancel.c
++++ b/libpthread/pthread/pt-cancel.c
+@@ -31,10 +31,33 @@ pthread_cancel (pthread_t t)
+   if (! p)
+     return ESRCH;
+ 
++  __pthread_mutex_lock (&p->cancel_lock);
++  if (p->cancel_pending)
++    {
++      __pthread_mutex_unlock (&p->cancel_lock);
++      return 0;
++    }
++
+   p->cancel_pending = 1;
+-  if (p->cancel_state == PTHREAD_CANCEL_ENABLE
+-      && p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS)
++
++  if (p->cancel_state != PTHREAD_CANCEL_ENABLE)
++    {
++      __pthread_mutex_unlock (&p->cancel_lock);
++      return 0;
++    }
++
++  if (p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS)
++    /* CANCEL_LOCK is unlocked by this call.  */
+     err = __pthread_do_cancel (p);
++  else
++    {
++      if (p->cancel_hook != NULL)
++      /* Thread blocking on a cancellation point.  Invoke hook to unblock.
++         See __pthread_cond_timedwait_internal.  */
++      p->cancel_hook (p->cancel_hook_arg);
++
++      __pthread_mutex_unlock (&p->cancel_lock);
++    }
+ 
+   return err;
+ }
+diff --git a/libpthread/pthread/pt-internal.h 
b/libpthread/pthread/pt-internal.h
+index 291baf5..aeac009 100644
+--- a/libpthread/pthread/pt-internal.h
++++ b/libpthread/pthread/pt-internal.h
+@@ -73,6 +73,11 @@ struct __pthread
+   pthread_t thread;
+ 
+   /* Cancellation.  */
++  pthread_mutex_t cancel_lock;  /* Protect cancel_xxx members.  */
++  void (*cancel_hook)(void *);        /* Called to unblock a thread blocking
++                                 in a cancellation point (namely,
++                                 __pthread_cond_timedwait_internal).  */
++  void *cancel_hook_arg;
+   int cancel_state;
+   int cancel_type;
+   int cancel_pending;
+@@ -107,6 +112,8 @@ struct __pthread
+   tcbhead_t *tcb;
+ #endif /* ENABLE_TLS */
+ 
++  /* Queue links.  Since PREVP is used to determine if a thread has been
++     awaken, it must be protected by the queue lock.  */
+   struct __pthread *next, **prevp;
+ };
+ 
+@@ -128,6 +135,7 @@ static inline void
+ __pthread_dequeue (struct __pthread *thread)
+ {
+   assert (thread);
++  assert (thread->prevp);
+ 
+   if (thread->next)
+     thread->next->prevp = thread->prevp;
+@@ -264,7 +272,8 @@ extern error_t __pthread_timedblock (struct __pthread 
*__restrict thread,
+ extern void __pthread_wakeup (struct __pthread *thread);
+ 
+ 
+-/* Perform a cancelation.  */
++/* Perform a cancelation.  The CANCEL_LOCK member of the given thread must
++   be locked before calling this function, which must unlock it.  */
+ extern int __pthread_do_cancel (struct __pthread *thread);
+ 
+ 
+diff --git a/libpthread/pthread/pt-join.c b/libpthread/pthread/pt-join.c
+index 153058b..8bd2c6c 100644
+--- a/libpthread/pthread/pt-join.c
++++ b/libpthread/pthread/pt-join.c
+@@ -40,6 +40,8 @@ pthread_join (pthread_t thread, void **status)
+   pthread_cleanup_push ((void (*)(void *)) __pthread_mutex_unlock,
+                       &pthread->state_lock);
+ 
++  /* Rely on pthread_cond_wait being a cancellation point to make
++     pthread_join one too.  */
+   while (pthread->state == PTHREAD_JOINABLE)
+     pthread_cond_wait (&pthread->state_cond, &pthread->state_lock);
+ 
+diff --git a/libpthread/pthread/pt-setcancelstate.c 
b/libpthread/pthread/pt-setcancelstate.c
+index 38550ee..7b60015 100644
+--- a/libpthread/pthread/pt-setcancelstate.c
++++ b/libpthread/pthread/pt-setcancelstate.c
+@@ -35,9 +35,11 @@ __pthread_setcancelstate (int state, int *oldstate)
+       break;
+     }
+ 
++  __pthread_mutex_lock (&p->cancel_lock);
+   if (oldstate)
+     *oldstate = p->cancel_state;
+   p->cancel_state = state;
++  __pthread_mutex_unlock (&p->cancel_lock);
+ 
+   return 0;
+ }
+diff --git a/libpthread/pthread/pt-setcanceltype.c 
b/libpthread/pthread/pt-setcanceltype.c
+index 7226a3a..3cfbe9c 100644
+--- a/libpthread/pthread/pt-setcanceltype.c
++++ b/libpthread/pthread/pt-setcanceltype.c
+@@ -35,9 +35,11 @@ __pthread_setcanceltype (int type, int *oldtype)
+       break;
+     }
+ 
++  __pthread_mutex_lock (&p->cancel_lock);
+   if (oldtype)
+     *oldtype = p->cancel_type;
+   p->cancel_type = type;
++  __pthread_mutex_unlock (&p->cancel_lock);
+ 
+   return 0;
+ }
+diff --git a/libpthread/pthread/pt-testcancel.c 
b/libpthread/pthread/pt-testcancel.c
+index 01f1ac9..3ba07b6 100644
+--- a/libpthread/pthread/pt-testcancel.c
++++ b/libpthread/pthread/pt-testcancel.c
+@@ -25,7 +25,12 @@ void
+ pthread_testcancel (void)
+ {
+   struct __pthread *p = _pthread_self ();
++  int cancelled;
+ 
+-  if (p->cancel_state == PTHREAD_CANCEL_ENABLE && p->cancel_pending)
++  __pthread_mutex_lock (&p->cancel_lock);
++  cancelled = (p->cancel_state == PTHREAD_CANCEL_ENABLE) && p->cancel_pending;
++  __pthread_mutex_unlock (&p->cancel_lock);
++
++  if (cancelled)
+     pthread_exit (PTHREAD_CANCELED);
+ }
+diff --git a/libpthread/sysdeps/generic/pt-cond-brdcast.c 
b/libpthread/sysdeps/generic/pt-cond-brdcast.c
+index 999cc2d..ad44f83 100644
+--- a/libpthread/sysdeps/generic/pt-cond-brdcast.c
++++ b/libpthread/sysdeps/generic/pt-cond-brdcast.c
+@@ -28,16 +28,12 @@ __pthread_cond_broadcast (pthread_cond_t *cond)
+   struct __pthread *wakeup;
+ 
+   __pthread_spin_lock (&cond->__lock);
++  __pthread_dequeuing_iterate (cond->__queue, wakeup)
++    __pthread_wakeup (wakeup);
+ 
+-  wakeup = cond->__queue;
+   cond->__queue = NULL;
+   __pthread_spin_unlock (&cond->__lock);
+ 
+-  /* We can safely walk the list of waiting threads without holding
+-     the lock since it is now decoupled from the condition.  */
+-  __pthread_dequeuing_iterate (wakeup, wakeup)
+-    __pthread_wakeup (wakeup);
+-
+   return 0;
+ }
+ 
+diff --git a/libpthread/sysdeps/generic/pt-cond-signal.c 
b/libpthread/sysdeps/generic/pt-cond-signal.c
+index d7c91e6..4b5450c 100644
+--- a/libpthread/sysdeps/generic/pt-cond-signal.c
++++ b/libpthread/sysdeps/generic/pt-cond-signal.c
+@@ -21,8 +21,10 @@
+ 
+ #include <pt-internal.h>
+ 
+-static int
+-cond_signal (struct __pthread_cond *cond, int *unblocked)
++/* Unblock at least one of the threads that are blocked on condition
++   variable COND.  */
++int
++__pthread_cond_signal (pthread_cond_t *cond)
+ {
+   struct __pthread *wakeup;
+   
+@@ -33,24 +35,9 @@ cond_signal (struct __pthread_cond *cond, int *unblocked)
+   __pthread_spin_unlock (&cond->__lock);
+ 
+   if (wakeup)
+-    {
+-      /* We found a thread waiting for the condition to be signalled.
+-         Wake it up!  */
+-      __pthread_wakeup (wakeup);
+-      *unblocked = 1;
+-    }
++    __pthread_wakeup (wakeup);
+ 
+   return 0;
+ }
+ 
+-/* Unblock at least one of the threads that are blocked on condition
+-   variable COND.  */
+-int
+-__pthread_cond_signal (pthread_cond_t *cond)
+-{
+-  int unblocked = 0;
+-
+-  return cond_signal (cond, &unblocked);
+-}
+-
+ strong_alias (__pthread_cond_signal, pthread_cond_signal);
+diff --git a/libpthread/sysdeps/generic/pt-cond-timedwait.c 
b/libpthread/sysdeps/generic/pt-cond-timedwait.c
+index 56eb1ec..978b0f4 100644
+--- a/libpthread/sysdeps/generic/pt-cond-timedwait.c
++++ b/libpthread/sysdeps/generic/pt-cond-timedwait.c
+@@ -35,6 +35,32 @@ __pthread_cond_timedwait (pthread_cond_t *cond,
+ 
+ strong_alias (__pthread_cond_timedwait, pthread_cond_timedwait);
+ 
++struct cancel_ctx
++  {
++    struct __pthread *wakeup;
++    pthread_cond_t *cond;
++  };
++
++static void
++cancel_hook (void *arg)
++{
++  struct cancel_ctx *ctx = arg;
++  struct __pthread *wakeup = ctx->wakeup;
++  pthread_cond_t *cond = ctx->cond;
++  int unblock;
++
++  __pthread_spin_lock (&cond->__lock);
++  /* The thread only needs to be awaken if it's blocking or about to block.
++     If it was already unblocked, it's not queued any more.  */
++  unblock = wakeup->prevp != NULL;
++  if (unblock)
++    __pthread_dequeue (wakeup);
++  __pthread_spin_unlock (&cond->__lock);
++
++  if (unblock)
++    __pthread_wakeup (wakeup);
++}
++
+ /* Block on condition variable COND until ABSTIME.  As a GNU
+    extension, if ABSTIME is NULL, then wait forever.  MUTEX should be
+    held by the calling thread.  On return, MUTEX will be held by the
+@@ -45,67 +71,108 @@ __pthread_cond_timedwait_internal (pthread_cond_t *cond,
+                                  const struct timespec *abstime)
+ {
+   error_t err;
+-  int canceltype;
++  int cancelled, oldtype, drain;
+   clockid_t clock_id = __pthread_default_condattr.clock;
+ 
+-  void cleanup (void *arg)
++  if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000))
++    return EINVAL;
++
++  struct __pthread *self = _pthread_self ();
++  struct cancel_ctx ctx;
++  ctx.wakeup= self;
++  ctx.cond = cond;
++
++  /* Test for a pending cancellation request, switch to deferred mode for
++     safer resource handling, and prepare the hook to call in case we're
++     cancelled while blocking.  Once CANCEL_LOCK is released, the cancellation
++     hook can be called by another thread at any time.  Whatever happens,
++     this function must exit with MUTEX locked.
++
++     This function contains inline implementations of pthread_testcancel and
++     pthread_setcanceltype to reduce locking overhead.  */
++  __pthread_mutex_lock (&self->cancel_lock);
++  cancelled = (self->cancel_state == PTHREAD_CANCEL_ENABLE)
++            && self->cancel_pending;
++
++  if (! cancelled)
+     {
+-      struct __pthread *self = _pthread_self ();
++      self->cancel_hook = cancel_hook;
++      self->cancel_hook_arg = &ctx;
++      oldtype = self->cancel_type;
++
++      if (oldtype != PTHREAD_CANCEL_DEFERRED)
++      self->cancel_type = PTHREAD_CANCEL_DEFERRED;
+ 
++      /* Add ourselves to the list of waiters.  This is done while setting
++       the cancellation hook to simplify the cancellation procedure, i.e.
++       if the thread is queued, it can be cancelled, otherwise it is
++       already unblocked, progressing on the return path.  */
+       __pthread_spin_lock (&cond->__lock);
+-      if (self->prevp)
+-      __pthread_dequeue (self);
++      __pthread_enqueue (&cond->__queue, self);
++      if (cond->__attr)
++      clock_id = cond->__attr->clock;
+       __pthread_spin_unlock (&cond->__lock);
+-
+-      pthread_setcanceltype (canceltype, &canceltype);
+-      __pthread_mutex_lock (mutex);
+     }
++  __pthread_mutex_unlock (&self->cancel_lock);
+ 
+-  if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000))
+-    return EINVAL;
+-
+-  struct __pthread *self = _pthread_self ();
+-
+-  /* Add ourselves to the list of waiters.  */
+-  __pthread_spin_lock (&cond->__lock);
+-  __pthread_enqueue (&cond->__queue, self);
+-  if (cond->__attr)
+-    clock_id = cond->__attr->clock;
+-  __pthread_spin_unlock (&cond->__lock);
++  if (cancelled)
++    pthread_exit (PTHREAD_CANCELED);
+ 
++  /* Release MUTEX before blocking.  */
+   __pthread_mutex_unlock (mutex);
+ 
+-  /* Enter async cancelation mode.  If cancelation is disabled, then
+-     this does not change anything which is exactly what we want.  */
+-  pthread_cleanup_push (cleanup, 0);
+-  pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &canceltype);
+-
++  /* Block the thread.  */
+   if (abstime)
++    err = __pthread_timedblock (self, abstime, clock_id);
++  else
+     {
+-      err = __pthread_timedblock (self, abstime, clock_id);
+-      if (err)
+-      /* We timed out.  We may need to disconnect ourself from the
+-         waiter queue.
+-
+-         FIXME: What do we do if we get a wakeup message before we
+-         disconnect ourself?  It may remain until the next time we
+-         block.  */
++      err = 0;
++      __pthread_block (self);
++    }
++
++  __pthread_spin_lock (&cond->__lock);
++  if (! self->prevp)
++    {
++      /* Another thread removed us from the list of waiters, 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
++       condition lock, in which case the message queue must be drained.  */
++      if (! err)
++      drain = 0;
++      else
+       {
+         assert (err == ETIMEDOUT);
+-
+-        __pthread_spin_lock (&mutex->__lock);
+-        if (self->prevp)
+-          __pthread_dequeue (self);
+-        __pthread_spin_unlock (&mutex->__lock);
++        drain = 1;
+       }
+     }
+   else
+     {
+-      err = 0;
+-      __pthread_block (self);
++      /* We're still in the list of waiters.  Noone attempted to wake us up,
++       i.e. we timed out.  */
++      assert (err == ETIMEDOUT);
++      __pthread_dequeue (self);
++      drain = 0;
+     }
++  __pthread_spin_unlock (&cond->__lock);
++
++  if (drain)
++    __pthread_block (self);
++
++  /* We're almost done.  Remove the unblock hook, restore the previous
++     cancellation type, and check for a pending cancellation request.  */
++  __pthread_mutex_lock (&self->cancel_lock);
++  self->cancel_hook = NULL;
++  self->cancel_hook_arg = NULL;
++  self->cancel_type = oldtype;
++  cancelled = (self->cancel_state == PTHREAD_CANCEL_ENABLE)
++            && self->cancel_pending;
++  __pthread_mutex_unlock (&self->cancel_lock);
++
++  /* Reacquire MUTEX before returning/cancelling.  */
++  __pthread_mutex_lock (mutex);
+ 
+-  pthread_cleanup_pop (1);
++  if (cancelled)
++    pthread_exit (PTHREAD_CANCELED);
+ 
+   return err;
+ }
+diff --git a/libpthread/sysdeps/generic/pt-mutex-timedlock.c 
b/libpthread/sysdeps/generic/pt-mutex-timedlock.c
+index 48bffaf..43e0eda 100644
+--- a/libpthread/sysdeps/generic/pt-mutex-timedlock.c
++++ b/libpthread/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)
+diff --git a/libpthread/sysdeps/generic/pt-rwlock-timedrdlock.c 
b/libpthread/sysdeps/generic/pt-rwlock-timedrdlock.c
+index a110213..a81ca71 100644
+--- a/libpthread/sysdeps/generic/pt-rwlock-timedrdlock.c
++++ b/libpthread/sysdeps/generic/pt-rwlock-timedrdlock.c
+@@ -29,6 +29,8 @@ int
+ __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock,
+                                      const struct timespec *abstime)
+ {
++  error_t err;
++  int drain;
+   struct __pthread *self;
+ 
+   __pthread_spin_lock (&rwlock->__lock);
+@@ -70,32 +72,37 @@ __pthread_rwlock_timedrdlock_internal (struct 
__pthread_rwlock *rwlock,
+ 
+   /* 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.
+-
+-         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 (&rwlock->__lock);
+-        if (self->prevp)
+-          /* Disconnect ourself.  */
+-          __pthread_dequeue (self);
+-        __pthread_spin_unlock (&rwlock->__lock);
+-
+-        return err;
+-      }
++      err = 0;
++      __pthread_block (self);
+     }
++
++  __pthread_spin_lock (&rwlock->__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 rwlock 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 (&rwlock->__lock);
++
++  if (drain)
+     __pthread_block (self);
+ 
++  if (err)
++    {
++      assert (err == ETIMEDOUT);
++      return err;
++    }
+ 
+   /* The reader count has already been increment by whoever woke us
+      up.  */
+diff --git a/libpthread/sysdeps/generic/pt-rwlock-timedwrlock.c 
b/libpthread/sysdeps/generic/pt-rwlock-timedwrlock.c
+index a5cc579..e47e936 100644
+--- a/libpthread/sysdeps/generic/pt-rwlock-timedwrlock.c
++++ b/libpthread/sysdeps/generic/pt-rwlock-timedwrlock.c
+@@ -29,6 +29,8 @@ int
+ __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock,
+                                      const struct timespec *abstime)
+ {
++  error_t err;
++  int drain;
+   struct __pthread *self;
+ 
+   __pthread_spin_lock (&rwlock->__lock);
+@@ -56,32 +58,38 @@ __pthread_rwlock_timedwrlock_internal (struct 
__pthread_rwlock *rwlock,
+ 
+   /* 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.
+-
+-         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 (&rwlock->__lock);
+-        if (self->prevp)
+-          /* Disconnect ourself.  */
+-          __pthread_dequeue (self);
+-        __pthread_spin_unlock (&rwlock->__lock);
+-
+-        return err;
+-      }
++      err = 0;
++      __pthread_block (self);
+     }
++
++  __pthread_spin_lock (&rwlock->__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 rwlock 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 (&rwlock->__lock);
++
++  if (drain)
+     __pthread_block (self);
+ 
++  if (err)
++    {
++      assert (err == ETIMEDOUT);
++      return err;
++    }
++
+   assert (rwlock->readers == 0);
+ 
+   return 0;
+diff --git a/libpthread/sysdeps/generic/pt-rwlock-unlock.c 
b/libpthread/sysdeps/generic/pt-rwlock-unlock.c
+index fb23a0b..212cca5 100644
+--- a/libpthread/sysdeps/generic/pt-rwlock-unlock.c
++++ b/libpthread/sysdeps/generic/pt-rwlock-unlock.c
+@@ -65,19 +65,16 @@ pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
+ 
+   if (rwlock->readerqueue)
+     {
+-      __pthread_queue_iterate (rwlock->readerqueue, wakeup)
+-      rwlock->readers ++;
++      __pthread_dequeuing_iterate (rwlock->readerqueue, wakeup)
++      {
++        rwlock->readers ++;
++        __pthread_wakeup (wakeup);
++      }
+ 
+-      wakeup = rwlock->readerqueue;
+       rwlock->readerqueue = 0;
+ 
+       __pthread_spin_unlock (&rwlock->__lock);
+ 
+-      /* We can safely walk the list of waiting threads without holding
+-       the lock since it is now decoupled from the rwlock.  */
+-      __pthread_dequeuing_iterate (wakeup, wakeup)
+-      __pthread_wakeup (wakeup);
+-
+       return 0;
+     }
+ 
+diff --git a/libpthread/sysdeps/generic/sem-timedwait.c 
b/libpthread/sysdeps/generic/sem-timedwait.c
+index 94e6dee..7ab1583 100644
+--- a/libpthread/sysdeps/generic/sem-timedwait.c
++++ b/libpthread/sysdeps/generic/sem-timedwait.c
+@@ -27,6 +27,8 @@ int
+ __sem_timedwait_internal (sem_t *restrict sem,
+                         const struct timespec *restrict timeout)
+ {
++  error_t err;
++  int drain;
+   struct __pthread *self;
+ 
+   __pthread_spin_lock (&sem->__lock);
+@@ -52,32 +54,39 @@ __sem_timedwait_internal (sem_t *restrict sem,
+ 
+   /* Block the thread.  */
+   if (timeout)
++    err = __pthread_timedblock (self, timeout, CLOCK_REALTIME);
++  else
+     {
+-      error_t err;
+-
+-      err = __pthread_timedblock (self, timeout, CLOCK_REALTIME);
+-      if (err)
+-      /* We timed out.  We may need to disconnect ourself from the
+-         waiter queue.
+-
+-         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 (&sem->__lock);
+-        if (self->prevp)
+-          __pthread_dequeue (self);
+-        __pthread_spin_unlock (&sem->__lock);
+-
+-        errno = err;
+-        return -1;
+-      }
++      err = 0;
++      __pthread_block (self);
+     }
++
++  __pthread_spin_lock (&sem->__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 semaphore 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 (&sem->__lock);
++
++  if (drain)
+     __pthread_block (self);
+ 
++  if (err)
++    {
++      assert (err == ETIMEDOUT);
++      errno = err;
++      return -1;
++    }
++
+   return 0;
+ }
+ 
+diff --git a/libpthread/sysdeps/mach/hurd/pt-docancel.c 
b/libpthread/sysdeps/mach/hurd/pt-docancel.c
+index 105c6fd..b3a5507 100644
+--- a/libpthread/sysdeps/mach/hurd/pt-docancel.c
++++ b/libpthread/sysdeps/mach/hurd/pt-docancel.c
+@@ -36,6 +36,8 @@ __pthread_do_cancel (struct __pthread *p)
+   assert (p->cancel_pending == 1);
+   assert (p->cancel_state == PTHREAD_CANCEL_ENABLE);
+ 
++  __pthread_mutex_unlock (&p->cancel_lock);
++
+   ktid = __mach_thread_self ();
+   me = p->kernel_thread == ktid;
+   __mach_port_deallocate (__mach_task_self (), ktid);
+diff --git a/libpthread/sysdeps/mach/pt-thread-alloc.c 
b/libpthread/sysdeps/mach/pt-thread-alloc.c
+index 3d7c046..794f63e 100644
+--- a/libpthread/sysdeps/mach/pt-thread-alloc.c
++++ b/libpthread/sysdeps/mach/pt-thread-alloc.c
+@@ -55,6 +55,10 @@ create_wakeupmsg (struct __pthread *thread)
+       return EAGAIN;
+     }
+ 
++  /* No need to queue more than one wakeup message on this port.  */
++  mach_port_set_qlimit (__mach_task_self (),
++                      thread->wakeupmsg.msgh_remote_port, 1);
++
+   return 0;
+ }
+ 
+diff --git a/libpthread/sysdeps/mach/pt-wakeup.c 
b/libpthread/sysdeps/mach/pt-wakeup.c
+index 4920d10..95fdbf9 100644
+--- a/libpthread/sysdeps/mach/pt-wakeup.c
++++ b/libpthread/sysdeps/mach/pt-wakeup.c
+@@ -31,8 +31,8 @@ __pthread_wakeup (struct __pthread *thread)
+ {
+   error_t err;
+   
+-  err = __mach_msg (&thread->wakeupmsg, MACH_SEND_MSG,
++  err = __mach_msg (&thread->wakeupmsg, MACH_SEND_MSG | MACH_SEND_TIMEOUT,
+                   sizeof (thread->wakeupmsg), 0, MACH_PORT_NULL,
+-                  MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
++                  0 , MACH_PORT_NULL);
+   assert_perror (err);
+ }

Copied: 
glibc-package/branches/eglibc-2.17/debian/patches/hurd-i386/libpthread_hurd_cond_timedwait.diff
 (from rev 5497, 
glibc-package/trunk/debian/patches/hurd-i386/libpthread_hurd_cond_timedwait.diff)
===================================================================
--- 
glibc-package/branches/eglibc-2.17/debian/patches/hurd-i386/libpthread_hurd_cond_timedwait.diff
                             (rev 0)
+++ 
glibc-package/branches/eglibc-2.17/debian/patches/hurd-i386/libpthread_hurd_cond_timedwait.diff
     2013-02-24 18:17:19 UTC (rev 5498)
@@ -0,0 +1,331 @@
+commit 87e9dfeae82e35cff3d7690e3e8e631d408cf665
+Author: Richard Braun <rbr...@sceen.net>
+Date:   Sun Feb 10 19:59:24 2013 +0100
+
+    Add pthread_hurd_cond_timedwait_np
+    
+    This new Hurd-specific function is meant to allow Hurd servers to wait
+    for events during a bounded period of time.
+    
+    * Makefile (libpthread-routines): Add pt-hurd-cond-timedwait.
+    * Versions: Include pthread_hurd_cond_timedwait_np in version GLIBC_2.17
+    of libpthread.
+    * sysdeps/mach/hurd/bits/pthread-np.h (pthread_hurd_cond_timedwait_np): New
+    declaration.
+    * sysdeps/mach/hurd/pt-hurd-cond-timedwait.c: New file that provides
+    __pthread_hurd_cond_timedwait_internal and 
__pthread_hurd_cond_timedwait_np.
+    * sysdeps/mach/hurd/pt-hurd-cond-wait.c (__pthread_hurd_cond_wait_np):
+    Rewrite as a call to __pthread_hurd_cond_timedwait_internal with no 
timeout.
+
+diff --git a/libpthread/Makefile b/libpthread/Makefile
+index 2c7645d..c57f1a0 100644
+--- a/libpthread/Makefile
++++ b/libpthread/Makefile
+@@ -115,6 +115,7 @@ libpthread-routines := pt-attr pt-attr-destroy 
pt-attr-getdetachstate          \
+       pt-cond-wait                                                        \
+       pt-cond-timedwait                                                   \
+       pt-hurd-cond-wait                                                   \
++      pt-hurd-cond-timedwait                                              \
+                                                                           \
+       pt-stack-alloc                                                      \
+       pt-thread-alloc                                                     \
+--- a/Versions.def
++++ b/Versions.def
+@@ -98,6 +98,7 @@ libpthread {
+   GLIBC_2.11
+   GLIBC_2.12
+   GLIBC_2.13_DEBIAN_38
++  GLIBC_2.13_DEBIAN_39
+   GLIBC_PRIVATE
+ }
+ libresolv {
+diff --git a/libpthread/Versions b/libpthread/Versions
+index 8573637..3d151cf 100644
+--- a/libpthread/Versions
++++ b/libpthread/Versions
+@@ -132,4 +132,7 @@ libpthread {
+   GLIBC_2.13_DEBIAN_38 {
+     pthread_hurd_cond_wait_np;
+   }
++  GLIBC_2.13_DEBIAN_39 {
++    pthread_hurd_cond_timedwait_np;
++  }
+ }
+diff --git a/libpthread/sysdeps/mach/hurd/bits/pthread-np.h 
b/libpthread/sysdeps/mach/hurd/bits/pthread-np.h
+index 9817a06..5f75e06 100644
+--- a/libpthread/sysdeps/mach/hurd/bits/pthread-np.h
++++ b/libpthread/sysdeps/mach/hurd/bits/pthread-np.h
+@@ -29,4 +29,10 @@
+ extern int pthread_hurd_cond_wait_np (pthread_cond_t *__restrict __cond,
+                                     pthread_mutex_t *__restrict __mutex);
+ 
++/* Same as pthread_cond_timedwait, but for Hurd-specific cancellation.
++   See hurd_thread_cancel.  */
++extern int pthread_hurd_cond_timedwait_np (pthread_cond_t *__restrict __cond,
++                                         pthread_mutex_t *__restrict __mutex,
++                                         const struct timespec *abstime);
++
+ #endif /* bits/pthread-np.h */
+diff --git a/libpthread/sysdeps/mach/hurd/pt-hurd-cond-timedwait.c 
b/libpthread/sysdeps/mach/hurd/pt-hurd-cond-timedwait.c
+new file mode 100644
+index 0000000..7491e0e
+--- /dev/null
++++ b/libpthread/sysdeps/mach/hurd/pt-hurd-cond-timedwait.c
+@@ -0,0 +1,169 @@
++/* pthread_hurd_cond_timedwait_np.  Hurd-specific wait on a condition.
++   Copyright (C) 2012 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Library General Public License as
++   published by the Free Software Foundation; either version 2 of the
++   License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Library General Public License for more details.
++
++   You should have received a copy of the GNU Library General Public
++   License along with the GNU C Library; see the file COPYING.LIB.  If not,
++   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++   Boston, MA 02111-1307, USA.  */
++
++#include <pthread.h>
++#include <assert.h>
++#include <hurd/signal.h>
++
++#include <pt-internal.h>
++
++extern int __pthread_hurd_cond_timedwait_internal (pthread_cond_t *cond,
++                                                 pthread_mutex_t *mutex,
++                                                 const struct timespec 
*abstime);
++
++int
++__pthread_hurd_cond_timedwait_np (pthread_cond_t *cond,
++                                pthread_mutex_t *mutex,
++                                const struct timespec *abstime)
++{
++  return __pthread_hurd_cond_timedwait_internal (cond, mutex, abstime);
++}
++
++strong_alias (__pthread_hurd_cond_timedwait_np, 
pthread_hurd_cond_timedwait_np);
++
++int
++__pthread_hurd_cond_timedwait_internal (pthread_cond_t *cond,
++                                      pthread_mutex_t *mutex,
++                                      const struct timespec *abstime)
++{
++  struct hurd_sigstate *ss = _hurd_self_sigstate ();
++  struct __pthread *self = _pthread_self ();
++  error_t err;
++  int cancel, drain;
++  clockid_t clock_id = __pthread_default_condattr.clock;
++
++  /* This function will be called by hurd_thread_cancel while we are blocked
++     We wake up our thread if it's still blocking or about to block, so it 
will
++     progress and notice the cancellation flag.  */
++  void cancel_me (void)
++    {
++      int unblock;
++
++      __pthread_spin_lock (&cond->__lock);
++      /* The thread only needs to be awaken if it's blocking or about to 
block.
++       If it was already unblocked, it's not queued any more.  */
++      unblock = self->prevp != NULL;
++      if (unblock)
++      __pthread_dequeue (self);
++      __pthread_spin_unlock (&cond->__lock);
++
++      if (unblock)
++      __pthread_wakeup (self);
++    }
++
++  assert (ss->intr_port == MACH_PORT_NULL); /* Sanity check for signal bugs. 
*/
++
++  if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000))
++    return EINVAL;
++
++  /* Atomically enqueue our thread on the condition variable's queue of
++     waiters, and mark our sigstate to indicate that `cancel_me' must be
++     called to wake us up.  We must hold the sigstate lock while acquiring
++     the condition variable's lock and tweaking it, so that
++     hurd_thread_cancel can never suspend us and then deadlock waiting for
++     the condition variable's lock.  */
++
++  __spin_lock (&ss->lock);
++  __pthread_spin_lock (&cond->__lock);
++  cancel = ss->cancel;
++  if (cancel)
++    /* We were cancelled before doing anything.  Don't block at all.  */
++    ss->cancel = 0;
++  else
++    {
++      /* Put us on the queue so that pthread_cond_broadcast will know to wake
++         us up.  */
++      __pthread_enqueue (&cond->__queue, self);
++      if (cond->__attr)
++      clock_id = cond->__attr->clock;
++      /* Tell hurd_thread_cancel how to unblock us.  */
++      ss->cancel_hook = &cancel_me;
++    }
++  __pthread_spin_unlock (&cond->__lock);
++  __spin_unlock (&ss->lock);
++
++  if (cancel)
++    {
++      /* Cancelled on entry.  Just leave the mutex locked.  */
++      mutex = NULL;
++
++      __spin_lock (&ss->lock);
++    }
++  else
++    {
++      /* Release MUTEX before blocking.  */
++      __pthread_mutex_unlock (mutex);
++
++      /* Block the thread.  */
++      if (abstime)
++      err = __pthread_timedblock (self, abstime, clock_id);
++      else
++      {
++        err = 0;
++        __pthread_block (self);
++      }
++
++      /* As it was done when enqueueing, prevent hurd_thread_cancel from
++       suspending us while the condition lock is held.  */
++      __spin_lock (&ss->lock);
++      __pthread_spin_lock (&cond->__lock);
++      if (! self->prevp)
++      /* Another thread removed us from the list of waiters, 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 condition lock, in which case the message queue
++         must be drained.  */
++      drain = err ? 1 : 0;
++      else
++      {
++        /* We're still in the list of waiters.  Noone attempted to wake us
++           up, i.e. we timed out.  */
++        __pthread_dequeue (self);
++        drain = 0;
++      }
++      __pthread_spin_unlock (&cond->__lock);
++
++      if (drain)
++      __pthread_block (self);
++    }
++
++  /* Clear the hook, now that we are done blocking.  */
++  ss->cancel_hook = NULL;
++  /* Check the cancellation flag; we might have unblocked due to
++     cancellation rather than a normal pthread_cond_signal or
++     pthread_cond_broadcast (or we might have just happened to get cancelled
++     right after waking up).  */
++  cancel |= ss->cancel;
++  ss->cancel = 0;
++  __spin_unlock (&ss->lock);
++
++  if (mutex)
++    /* Reacquire the mutex and return.  */
++    __pthread_mutex_lock (mutex);
++
++  if (cancel)
++    return EINTR;
++  else if (err)
++    {
++      assert (err == ETIMEDOUT);
++      return err;
++    }
++
++  return 0;
++}
+diff --git a/libpthread/sysdeps/mach/hurd/pt-hurd-cond-wait.c 
b/libpthread/sysdeps/mach/hurd/pt-hurd-cond-wait.c
+index d2b5847..5e7c007 100644
+--- a/libpthread/sysdeps/mach/hurd/pt-hurd-cond-wait.c
++++ b/libpthread/sysdeps/mach/hurd/pt-hurd-cond-wait.c
+@@ -23,71 +23,19 @@
+ 
+ #include <pt-internal.h>
+ 
++/* Implemented in pt-hurd-cond-timedwait.c.  */
++extern int __pthread_hurd_cond_timedwait_internal (pthread_cond_t *cond,
++                                                 pthread_mutex_t *mutex,
++                                                 const struct timespec 
*abstime);
++
+ int
+-pthread_hurd_cond_wait_np (pthread_cond_t *cond, pthread_mutex_t *mutex)
++__pthread_hurd_cond_wait_np (pthread_cond_t *cond,
++                           pthread_mutex_t *mutex)
+ {
+-  /* This function will be called by hurd_thread_cancel while we are blocked
+-     We wake up all threads blocked on COND, so our thread will wake up and
+-     notice the cancellation flag.  */
+-  void cancel_me (void)
+-    {
+-      pthread_cond_broadcast (cond);
+-    }
+-  struct hurd_sigstate *ss = _hurd_self_sigstate ();
+-  struct __pthread *self = _pthread_self ();
+-  int cancel;
+-
+-  assert (ss->intr_port == MACH_PORT_NULL); /* Sanity check for signal bugs. 
*/
+-
+-  /* Atomically enqueue our thread on the condition variable's queue of
+-     waiters, and mark our sigstate to indicate that `cancel_me' must be
+-     called to wake us up.  We must hold the sigstate lock while acquiring
+-     the condition variable's lock and tweaking it, so that
+-     hurd_thread_cancel can never suspend us and then deadlock in
+-     pthread_cond_broadcast waiting for the condition variable's lock.  */
+-
+-  __spin_lock (&ss->lock);
+-  __pthread_spin_lock (&cond->__lock);
+-  cancel = ss->cancel;
+-  if (cancel)
+-    /* We were cancelled before doing anything.  Don't block at all.  */
+-    ss->cancel = 0;
+-  else
+-    {
+-      /* Put us on the queue so that pthread_cond_broadcast will know to wake
+-         us up.  */
+-      __pthread_enqueue (&cond->__queue, self);
+-      /* Tell hurd_thread_cancel how to unblock us.  */
+-      ss->cancel_hook = &cancel_me;
+-    }
+-  __pthread_spin_unlock (&cond->__lock);
+-  __spin_unlock (&ss->lock);
+-
++  error_t err;
+ 
+-  if (cancel)
+-    /* Cancelled on entry.  Just leave the mutex locked.  */
+-    mutex = NULL;
+-  else
+-    {
+-      /* Now unlock the mutex and block until woken.  */
+-      __pthread_mutex_unlock (mutex);
+-      __pthread_block (self);
+-    }
+-
+-  __spin_lock (&ss->lock);
+-  /* Clear the hook, now that we are done blocking.  */
+-  ss->cancel_hook = NULL;
+-  /* Check the cancellation flag; we might have unblocked due to
+-     cancellation rather than a normal pthread_cond_signal or
+-     pthread_cond_broadcast (or we might have just happened to get cancelled
+-     right after waking up).  */
+-  cancel |= ss->cancel;
+-  ss->cancel = 0;
+-  __spin_unlock (&ss->lock);
+-
+-  if (mutex)
+-    /* Reacquire the mutex and return.  */
+-    __pthread_mutex_lock (mutex);
+-
+-  return cancel;
++  err = __pthread_hurd_cond_timedwait_internal (cond, mutex, NULL);
++  return (err == EINTR);
+ }
++
++strong_alias (__pthread_hurd_cond_wait_np, pthread_hurd_cond_wait_np);

Modified: glibc-package/branches/eglibc-2.17/debian/patches/series
===================================================================
--- glibc-package/branches/eglibc-2.17/debian/patches/series    2013-02-24 
18:16:00 UTC (rev 5497)
+++ glibc-package/branches/eglibc-2.17/debian/patches/series    2013-02-24 
18:17:19 UTC (rev 5498)
@@ -113,6 +113,8 @@
 hurd-i386/tg-select-EINTR.diff
 hurd-i386/cvs-libpthread_lock.diff
 hurd-i386/tg-pie-sbrk.diff
+hurd-i386/libpthread_cancellation.diff
+hurd-i386/libpthread_hurd_cond_timedwait.diff
 hurd-i386/tg-ifaddrs_v6.diff
 hurd-i386/unsubmitted-subhurd.diff
 



-- 
To UNSUBSCRIBE, email to debian-glibc-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: http://lists.debian.org/e1u9g8v-0003dl...@vasks.debian.org

Reply via email to