summary refs log tree commit diff
path: root/nptl/pthread_cond_destroy.c
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/pthread_cond_destroy.c')
-rw-r--r--nptl/pthread_cond_destroy.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/nptl/pthread_cond_destroy.c b/nptl/pthread_cond_destroy.c
index 5ade3e63db..0208d18ce4 100644
--- a/nptl/pthread_cond_destroy.c
+++ b/nptl/pthread_cond_destroy.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -17,6 +17,7 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <errno.h>
 #include <shlib-compat.h>
 #include "pthreadP.h"
 
@@ -25,6 +26,35 @@ int
 __pthread_cond_destroy (cond)
      pthread_cond_t *cond;
 {
+  /* Make sure we are alone.  */
+  lll_mutex_lock (cond->__data.__lock);
+
+  if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
+    {
+      /* If there are still some waiters which have not been
+	 woken up, this is an application bug.  */
+      lll_mutex_unlock (cond->__data.__lock);
+      return EBUSY;
+    }
+
+  /* Tell pthread_cond_*wait that this condvar is being destroyed.  */
+  cond->__data.__total_seq = -1ULL;
+
+  /* If there are waiters which have been already signalled or
+     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))
+    {
+      lll_mutex_unlock (cond->__data.__lock);
+
+      lll_futex_wait (&cond->__data.__nwaiters, nwaiters);
+
+      lll_mutex_lock (cond->__data.__lock);
+
+      nwaiters = cond->__data.__nwaiters;
+    }
+
   return 0;
 }
 versioned_symbol (libpthread, __pthread_cond_destroy,