pthread_cond_destroy.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * pthread_cond_destroy.c
  3. *
  4. * Description:
  5. * This translation unit implements condition variables and their primitives.
  6. *
  7. *
  8. * --------------------------------------------------------------------------
  9. *
  10. * Pthreads-win32 - POSIX Threads Library for Win32
  11. * Copyright(C) 1998 John E. Bossom
  12. * Copyright(C) 1999,2005 Pthreads-win32 contributors
  13. *
  14. * Contact Email: [email protected]
  15. *
  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
  21. *
  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.
  26. *
  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.
  31. *
  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
  36. */
  37. #include "pthread.h"
  38. #include "implement.h"
  39. int
  40. pthread_cond_destroy (pthread_cond_t * cond)
  41. /*
  42. * ------------------------------------------------------
  43. * DOCPUBLIC
  44. * This function destroys a condition variable
  45. *
  46. *
  47. * PARAMETERS
  48. * cond
  49. * pointer to an instance of pthread_cond_t
  50. *
  51. *
  52. * DESCRIPTION
  53. * This function destroys a condition variable.
  54. *
  55. * NOTES:
  56. * 1) A condition variable can be destroyed
  57. * immediately after all the threads that
  58. * are blocked on it are awakened. e.g.
  59. *
  60. * struct list {
  61. * pthread_mutex_t lm;
  62. * ...
  63. * }
  64. *
  65. * struct elt {
  66. * key k;
  67. * int busy;
  68. * pthread_cond_t notbusy;
  69. * ...
  70. * }
  71. *
  72. *
  73. * struct elt *
  74. * list_find(struct list *lp, key k)
  75. * {
  76. * struct elt *ep;
  77. *
  78. * pthread_mutex_lock(&lp->lm);
  79. * while ((ep = find_elt(l,k) != NULL) && ep->busy)
  80. * pthread_cond_wait(&ep->notbusy, &lp->lm);
  81. * if (ep != NULL)
  82. * ep->busy = 1;
  83. * pthread_mutex_unlock(&lp->lm);
  84. * return(ep);
  85. * }
  86. *
  87. * delete_elt(struct list *lp, struct elt *ep)
  88. * {
  89. * pthread_mutex_lock(&lp->lm);
  90. * assert(ep->busy);
  91. * ... remove ep from list ...
  92. * ep->busy = 0;
  93. * (A) pthread_cond_broadcast(&ep->notbusy);
  94. * pthread_mutex_unlock(&lp->lm);
  95. * (B) pthread_cond_destroy(&rp->notbusy);
  96. * free(ep);
  97. * }
  98. *
  99. * In this example, the condition variable
  100. * and its list element may be freed (line B)
  101. * immediately after all threads waiting for
  102. * it are awakened (line A), since the mutex
  103. * and the code ensure that no other thread
  104. * can touch the element to be deleted.
  105. *
  106. * RESULTS
  107. * 0 successfully released condition variable,
  108. * EINVAL 'cond' is invalid,
  109. * EBUSY 'cond' is in use,
  110. *
  111. * ------------------------------------------------------
  112. */
  113. {
  114. pthread_cond_t cv;
  115. int result = 0, result1 = 0, result2 = 0;
  116. /*
  117. * Assuming any race condition here is harmless.
  118. */
  119. if (cond == NULL || *cond == NULL)
  120. {
  121. return EINVAL;
  122. }
  123. if (*cond != PTHREAD_COND_INITIALIZER)
  124. {
  125. ptw32_mcs_local_node_t node;
  126. ptw32_mcs_lock_acquire(&ptw32_cond_list_lock, &node);
  127. cv = *cond;
  128. /*
  129. * Close the gate; this will synchronize this thread with
  130. * all already signaled waiters to let them retract their
  131. * waiter status - SEE NOTE 1 ABOVE!!!
  132. */
  133. if (ptw32_semwait (&(cv->semBlockLock)) != 0) /* Non-cancelable */
  134. {
  135. result = errno;
  136. }
  137. else
  138. {
  139. /*
  140. * !TRY! lock mtxUnblockLock; try will detect busy condition
  141. * and will not cause a deadlock with respect to concurrent
  142. * signal/broadcast.
  143. */
  144. if ((result = pthread_mutex_trylock (&(cv->mtxUnblockLock))) != 0)
  145. {
  146. (void) sem_post (&(cv->semBlockLock));
  147. }
  148. }
  149. if (result != 0)
  150. {
  151. ptw32_mcs_lock_release(&node);
  152. return result;
  153. }
  154. /*
  155. * Check whether cv is still busy (still has waiters)
  156. */
  157. if (cv->nWaitersBlocked > cv->nWaitersGone)
  158. {
  159. if (sem_post (&(cv->semBlockLock)) != 0)
  160. {
  161. result = errno;
  162. }
  163. result1 = pthread_mutex_unlock (&(cv->mtxUnblockLock));
  164. result2 = EBUSY;
  165. }
  166. else
  167. {
  168. /*
  169. * Now it is safe to destroy
  170. */
  171. *cond = NULL;
  172. if (sem_destroy (&(cv->semBlockLock)) != 0)
  173. {
  174. result = errno;
  175. }
  176. if (sem_destroy (&(cv->semBlockQueue)) != 0)
  177. {
  178. result1 = errno;
  179. }
  180. if ((result2 = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0)
  181. {
  182. result2 = pthread_mutex_destroy (&(cv->mtxUnblockLock));
  183. }
  184. /* Unlink the CV from the list */
  185. if (ptw32_cond_list_head == cv)
  186. {
  187. ptw32_cond_list_head = cv->next;
  188. }
  189. else
  190. {
  191. cv->prev->next = cv->next;
  192. }
  193. if (ptw32_cond_list_tail == cv)
  194. {
  195. ptw32_cond_list_tail = cv->prev;
  196. }
  197. else
  198. {
  199. cv->next->prev = cv->prev;
  200. }
  201. (void) free (cv);
  202. }
  203. ptw32_mcs_lock_release(&node);
  204. }
  205. else
  206. {
  207. ptw32_mcs_local_node_t node;
  208. /*
  209. * See notes in ptw32_cond_check_need_init() above also.
  210. */
  211. ptw32_mcs_lock_acquire(&ptw32_cond_test_init_lock, &node);
  212. /*
  213. * Check again.
  214. */
  215. if (*cond == PTHREAD_COND_INITIALIZER)
  216. {
  217. /*
  218. * This is all we need to do to destroy a statically
  219. * initialised cond that has not yet been used (initialised).
  220. * If we get to here, another thread waiting to initialise
  221. * this cond will get an EINVAL. That's OK.
  222. */
  223. *cond = NULL;
  224. }
  225. else
  226. {
  227. /*
  228. * The cv has been initialised while we were waiting
  229. * so assume it's in use.
  230. */
  231. result = EBUSY;
  232. }
  233. ptw32_mcs_lock_release(&node);
  234. }
  235. return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
  236. }