1 /* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18 
19 #include <errno.h>
20 #include "pthreadP.h"
21 
22 
23 int
24 attribute_protected
__pthread_cond_destroy(pthread_cond_t * cond)25 __pthread_cond_destroy (
26      pthread_cond_t *cond)
27 {
28   int pshared = (cond->__data.__mutex == (void *) ~0l)
29 		? LLL_SHARED : LLL_PRIVATE;
30 
31   /* Make sure we are alone.  */
32   lll_lock (cond->__data.__lock, pshared);
33 
34   if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
35     {
36       /* If there are still some waiters which have not been
37 	 woken up, this is an application bug.  */
38       lll_unlock (cond->__data.__lock, pshared);
39       return EBUSY;
40     }
41 
42   /* Tell pthread_cond_*wait that this condvar is being destroyed.  */
43   cond->__data.__total_seq = -1ULL;
44 
45   /* If there are waiters which have been already signalled or
46      broadcasted, but still are using the pthread_cond_t structure,
47      pthread_cond_destroy needs to wait for them.  */
48   unsigned int nwaiters = cond->__data.__nwaiters;
49 
50   if (nwaiters >= (1 << COND_NWAITERS_SHIFT))
51     {
52       /* Wake everybody on the associated mutex in case there are
53          threads that have been requeued to it.
54          Without this, pthread_cond_destroy could block potentially
55          for a long time or forever, as it would depend on other
56          thread's using the mutex.
57          When all threads waiting on the mutex are woken up, pthread_cond_wait
58          only waits for threads to acquire and release the internal
59          condvar lock.  */
60       if (cond->__data.__mutex != NULL
61 	  && cond->__data.__mutex != (void *) ~0l)
62 	{
63 	  pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
64 	  lll_futex_wake (&mut->__data.__lock, INT_MAX,
65 			  PTHREAD_MUTEX_PSHARED (mut));
66 	}
67 
68       do
69 	{
70 	  lll_unlock (cond->__data.__lock, pshared);
71 
72 	  lll_futex_wait (&cond->__data.__nwaiters, nwaiters, pshared);
73 
74 	  lll_lock (cond->__data.__lock, pshared);
75 
76 	  nwaiters = cond->__data.__nwaiters;
77 	}
78       while (nwaiters >= (1 << COND_NWAITERS_SHIFT));
79     }
80 
81   return 0;
82 }
83 weak_alias(__pthread_cond_destroy, pthread_cond_destroy)
84