about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2005-09-25 23:58:51 +0000
committerUlrich Drepper <drepper@redhat.com>2005-09-25 23:58:51 +0000
commit560b47093fedfc210e2020d93c20fcfe3e620312 (patch)
tree67299737972434af7a2a89d8c64a520dc612dff8
parent9c5a79048766f0ac89aa84ad0c9a2f6e6dffec17 (diff)
downloadglibc-560b47093fedfc210e2020d93c20fcfe3e620312.tar.gz
glibc-560b47093fedfc210e2020d93c20fcfe3e620312.tar.xz
glibc-560b47093fedfc210e2020d93c20fcfe3e620312.zip
* pthread_cond_destroy.c (__pthread_cond_destroy): If there are
	waiters, awake all waiters on the associated mutex.
-rw-r--r--nptl/ChangeLog5
-rw-r--r--nptl/pthread_cond_destroy.c30
2 files changed, 30 insertions, 5 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 4884cc2d12..8e48cfde66 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,8 @@
+2004-09-02  Jakub Jelinek  <jakub@redhat.com>
+
+	* pthread_cond_destroy.c (__pthread_cond_destroy): If there are
+	waiters, awake all waiters on the associated mutex.
+
 2005-09-22  Roland McGrath  <roland@redhat.com>
 
 	* perf.c [__x86_64__] (HP_TIMING_NOW): New macro (copied from
diff --git a/nptl/pthread_cond_destroy.c b/nptl/pthread_cond_destroy.c
index 0208d18ce4..3e4ec8d0e4 100644
--- a/nptl/pthread_cond_destroy.c
+++ b/nptl/pthread_cond_destroy.c
@@ -44,15 +44,35 @@ __pthread_cond_destroy (cond)
      broadcasted, but still are using the pthread_cond_t structure,
      pthread_cond_destroy needs to wait for them.  */
   unsigned int nwaiters = cond->__data.__nwaiters;
-  while (nwaiters >= (1 << COND_CLOCK_BITS))
+
+  if (nwaiters >= (1 << COND_CLOCK_BITS))
     {
-      lll_mutex_unlock (cond->__data.__lock);
+      /* Wake everybody on the associated mutex in case there are
+         threads that have been requeued to it.
+         Without this, pthread_cond_destroy could block potentially
+         for a long time or forever, as it would depend on other
+         thread's using the mutex.
+         When all threads waiting on the mutex are woken up, pthread_cond_wait
+         only waits for threads to acquire and release the internal
+         condvar lock.  */
+      if (cond->__data.__mutex != NULL
+	  && cond->__data.__mutex != (void *) ~0l)
+	{
+	  pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
+	  lll_futex_wake (&mut->__data.__lock, INT_MAX);
+	}
+
+      do
+	{
+	  lll_mutex_unlock (cond->__data.__lock);
 
-      lll_futex_wait (&cond->__data.__nwaiters, nwaiters);
+	  lll_futex_wait (&cond->__data.__nwaiters, nwaiters);
 
-      lll_mutex_lock (cond->__data.__lock);
+	  lll_mutex_lock (cond->__data.__lock);
 
-      nwaiters = cond->__data.__nwaiters;
+	  nwaiters = cond->__data.__nwaiters;
+	}
+      while (nwaiters >= (1 << COND_CLOCK_BITS));
     }
 
   return 0;