pthread_cond_destroy.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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-embedded (PTE) - POSIX Threads Library for embedded systems
  11. * Copyright(C) 2008 Jason Schmidlapp
  12. *
  13. * Contact Email: jschmidlapp@users.sourceforge.net
  14. *
  15. *
  16. * Based upon Pthreads-win32 - POSIX Threads Library for Win32
  17. * Copyright(C) 1998 John E. Bossom
  18. * Copyright(C) 1999,2005 Pthreads-win32 contributors
  19. *
  20. * Contact Email: rpj@callisto.canberra.edu.au
  21. *
  22. * The original list of contributors to the Pthreads-win32 project
  23. * is contained in the file CONTRIBUTORS.ptw32 included with the
  24. * source code distribution. The list can also be seen at the
  25. * following World Wide Web location:
  26. * http://sources.redhat.com/pthreads-win32/contributors.html
  27. *
  28. * This library is free software; you can redistribute it and/or
  29. * modify it under the terms of the GNU Lesser General Public
  30. * License as published by the Free Software Foundation; either
  31. * version 2 of the License, or (at your option) any later version.
  32. *
  33. * This library is distributed in the hope that it will be useful,
  34. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  35. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  36. * Lesser General Public License for more details.
  37. *
  38. * You should have received a copy of the GNU Lesser General Public
  39. * License along with this library in the file COPYING.LIB;
  40. * if not, write to the Free Software Foundation, Inc.,
  41. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  42. */
  43. #include <stdlib.h>
  44. #include "pthread.h"
  45. #include "implement.h"
  46. int
  47. pthread_cond_destroy (pthread_cond_t * cond)
  48. /*
  49. * ------------------------------------------------------
  50. * DOCPUBLIC
  51. * This function destroys a condition variable
  52. *
  53. *
  54. * PARAMETERS
  55. * cond
  56. * pointer to an instance of pthread_cond_t
  57. *
  58. *
  59. * DESCRIPTION
  60. * This function destroys a condition variable.
  61. *
  62. * NOTES:
  63. * 1) A condition variable can be destroyed
  64. * immediately after all the threads that
  65. * are blocked on it are awakened. e.g.
  66. *
  67. * struct list {
  68. * pthread_mutex_t lm;
  69. * ...
  70. * }
  71. *
  72. * struct elt {
  73. * key k;
  74. * int busy;
  75. * pthread_cond_t notbusy;
  76. * ...
  77. * }
  78. *
  79. *
  80. * struct elt *
  81. * list_find(struct list *lp, key k)
  82. * {
  83. * struct elt *ep;
  84. *
  85. * pthread_mutex_lock(&lp->lm);
  86. * while ((ep = find_elt(l,k) != NULL) && ep->busy)
  87. * pthread_cond_wait(&ep->notbusy, &lp->lm);
  88. * if (ep != NULL)
  89. * ep->busy = 1;
  90. * pthread_mutex_unlock(&lp->lm);
  91. * return(ep);
  92. * }
  93. *
  94. * delete_elt(struct list *lp, struct elt *ep)
  95. * {
  96. * pthread_mutex_lock(&lp->lm);
  97. * assert(ep->busy);
  98. * ... remove ep from list ...
  99. * ep->busy = 0;
  100. * (A) pthread_cond_broadcast(&ep->notbusy);
  101. * pthread_mutex_unlock(&lp->lm);
  102. * (B) pthread_cond_destroy(&rp->notbusy);
  103. * free(ep);
  104. * }
  105. *
  106. * In this example, the condition variable
  107. * and its list element may be freed (line B)
  108. * immediately after all threads waiting for
  109. * it are awakened (line A), since the mutex
  110. * and the code ensure that no other thread
  111. * can touch the element to be deleted.
  112. *
  113. * RESULTS
  114. * 0 successfully released condition variable,
  115. * EINVAL 'cond' is invalid,
  116. * EBUSY 'cond' is in use,
  117. *
  118. * ------------------------------------------------------
  119. */
  120. {
  121. pthread_cond_t cv;
  122. int result = 0, result1 = 0, result2 = 0;
  123. /*
  124. * Assuming any race condition here is harmless.
  125. */
  126. if (cond == NULL || *cond == NULL)
  127. {
  128. return EINVAL;
  129. }
  130. if (*cond != PTHREAD_COND_INITIALIZER)
  131. {
  132. pte_osMutexLock (pte_cond_list_lock);
  133. cv = *cond;
  134. /*
  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!!!
  138. */
  139. if (sem_wait (&(cv->semBlockLock)) != 0)
  140. {
  141. return errno;
  142. }
  143. /*
  144. * !TRY! lock mtxUnblockLock; try will detect busy condition
  145. * and will not cause a deadlock with respect to concurrent
  146. * signal/broadcast.
  147. */
  148. if ((result = pthread_mutex_trylock (&(cv->mtxUnblockLock))) != 0)
  149. {
  150. (void) sem_post (&(cv->semBlockLock));
  151. return result;
  152. }
  153. /*
  154. * Check whether cv is still busy (still has waiters)
  155. */
  156. if (cv->nWaitersBlocked > cv->nWaitersGone)
  157. {
  158. if (sem_post (&(cv->semBlockLock)) != 0)
  159. {
  160. result = errno;
  161. }
  162. result1 = pthread_mutex_unlock (&(cv->mtxUnblockLock));
  163. result2 = EBUSY;
  164. }
  165. else
  166. {
  167. /*
  168. * Now it is safe to destroy
  169. */
  170. *cond = NULL;
  171. if (sem_destroy (&(cv->semBlockLock)) != 0)
  172. {
  173. result = errno;
  174. }
  175. if (sem_destroy (&(cv->semBlockQueue)) != 0)
  176. {
  177. result1 = errno;
  178. }
  179. if ((result2 = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0)
  180. {
  181. result2 = pthread_mutex_destroy (&(cv->mtxUnblockLock));
  182. }
  183. /* Unlink the CV from the list */
  184. if (pte_cond_list_head == cv)
  185. {
  186. pte_cond_list_head = cv->next;
  187. }
  188. else
  189. {
  190. cv->prev->next = cv->next;
  191. }
  192. if (pte_cond_list_tail == cv)
  193. {
  194. pte_cond_list_tail = cv->prev;
  195. }
  196. else
  197. {
  198. cv->next->prev = cv->prev;
  199. }
  200. (void) free (cv);
  201. }
  202. pte_osMutexUnlock(pte_cond_list_lock);
  203. }
  204. else
  205. {
  206. /*
  207. * See notes in pte_cond_check_need_init() above also.
  208. */
  209. pte_osMutexLock (pte_cond_test_init_lock);
  210. /*
  211. * Check again.
  212. */
  213. if (*cond == PTHREAD_COND_INITIALIZER)
  214. {
  215. /*
  216. * This is all we need to do to destroy a statically
  217. * initialised cond that has not yet been used (initialised).
  218. * If we get to here, another thread waiting to initialise
  219. * this cond will get an EINVAL. That's OK.
  220. */
  221. *cond = NULL;
  222. }
  223. else
  224. {
  225. /*
  226. * The cv has been initialised while we were waiting
  227. * so assume it's in use.
  228. */
  229. result = EBUSY;
  230. }
  231. pte_osMutexUnlock(pte_cond_test_init_lock);
  232. }
  233. return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
  234. }