2 * pthread_cond_destroy.c
5 * This translation unit implements condition variables and their primitives.
8 * --------------------------------------------------------------------------
10 * Pthreads-win32 - POSIX Threads Library for Win32
11 * Copyright(C) 1998 John E. Bossom
12 * Copyright(C) 1999,2005 Pthreads-win32 contributors
14 * Contact Email: rpj@callisto.canberra.edu.au
16 * The current list of contributors is contained
17 * in the file CONTRIBUTORS included with the source
18 * code distribution. The list can also be seen at the
19 * following World Wide Web location:
20 * http://sources.redhat.com/pthreads-win32/contributors.html
22 * This library is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU Lesser General Public
24 * License as published by the Free Software Foundation; either
25 * version 2 of the License, or (at your option) any later version.
27 * This library is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 * Lesser General Public License for more details.
32 * You should have received a copy of the GNU Lesser General Public
33 * License along with this library in the file COPYING.LIB;
34 * if not, write to the Free Software Foundation, Inc.,
35 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
39 #include "implement.h"
42 pthread_cond_destroy (pthread_cond_t
* cond
)
44 * ------------------------------------------------------
46 * This function destroys a condition variable
51 * pointer to an instance of pthread_cond_t
55 * This function destroys a condition variable.
58 * 1) A condition variable can be destroyed
59 * immediately after all the threads that
60 * are blocked on it are awakened. e.g.
70 * pthread_cond_t notbusy;
76 * list_find(struct list *lp, key k)
80 * pthread_mutex_lock(&lp->lm);
81 * while ((ep = find_elt(l,k) != NULL) && ep->busy)
82 * pthread_cond_wait(&ep->notbusy, &lp->lm);
85 * pthread_mutex_unlock(&lp->lm);
89 * delete_elt(struct list *lp, struct elt *ep)
91 * pthread_mutex_lock(&lp->lm);
93 * ... remove ep from list ...
95 * (A) pthread_cond_broadcast(&ep->notbusy);
96 * pthread_mutex_unlock(&lp->lm);
97 * (B) pthread_cond_destroy(&rp->notbusy);
101 * In this example, the condition variable
102 * and its list element may be freed (line B)
103 * immediately after all threads waiting for
104 * it are awakened (line A), since the mutex
105 * and the code ensure that no other thread
106 * can touch the element to be deleted.
109 * 0 successfully released condition variable,
110 * EINVAL 'cond' is invalid,
111 * EBUSY 'cond' is in use,
113 * ------------------------------------------------------
117 int result
= 0, result1
= 0, result2
= 0;
120 * Assuming any race condition here is harmless.
122 if (cond
== NULL
|| *cond
== NULL
)
127 if (*cond
!= PTHREAD_COND_INITIALIZER
)
129 ptw32_mcs_local_node_t node
;
130 ptw32_mcs_lock_acquire(&ptw32_cond_list_lock
, &node
);
135 * Close the gate; this will synchronize this thread with
136 * all already signaled waiters to let them retract their
137 * waiter status - SEE NOTE 1 ABOVE!!!
139 if (ptw32_semwait (&(cv
->semBlockLock
)) != 0) /* Non-cancelable */
146 * !TRY! lock mtxUnblockLock; try will detect busy condition
147 * and will not cause a deadlock with respect to concurrent
150 if ((result
= pthread_mutex_trylock (&(cv
->mtxUnblockLock
))) != 0)
152 (void) sem_post (&(cv
->semBlockLock
));
158 ptw32_mcs_lock_release(&node
);
163 * Check whether cv is still busy (still has waiters)
165 if (cv
->nWaitersBlocked
> cv
->nWaitersGone
)
167 if (sem_post (&(cv
->semBlockLock
)) != 0)
171 result1
= pthread_mutex_unlock (&(cv
->mtxUnblockLock
));
177 * Now it is safe to destroy
181 if (sem_destroy (&(cv
->semBlockLock
)) != 0)
185 if (sem_destroy (&(cv
->semBlockQueue
)) != 0)
189 if ((result2
= pthread_mutex_unlock (&(cv
->mtxUnblockLock
))) == 0)
191 result2
= pthread_mutex_destroy (&(cv
->mtxUnblockLock
));
194 /* Unlink the CV from the list */
196 if (ptw32_cond_list_head
== cv
)
198 ptw32_cond_list_head
= cv
->next
;
202 cv
->prev
->next
= cv
->next
;
205 if (ptw32_cond_list_tail
== cv
)
207 ptw32_cond_list_tail
= cv
->prev
;
211 cv
->next
->prev
= cv
->prev
;
217 ptw32_mcs_lock_release(&node
);
221 ptw32_mcs_local_node_t node
;
223 * See notes in ptw32_cond_check_need_init() above also.
225 ptw32_mcs_lock_acquire(&ptw32_cond_test_init_lock
, &node
);
230 if (*cond
== PTHREAD_COND_INITIALIZER
)
233 * This is all we need to do to destroy a statically
234 * initialised cond that has not yet been used (initialised).
235 * If we get to here, another thread waiting to initialise
236 * this cond will get an EINVAL. That's OK.
243 * The cv has been initialised while we were waiting
244 * so assume it's in use.
249 ptw32_mcs_lock_release(&node
);
252 return ((result
!= 0) ? result
: ((result1
!= 0) ? result1
: result2
));