pthread_cond_signal.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * pthread_cond_signal.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. * -------------------------------------------------------------
  38. * Algorithm:
  39. * See the comments at the top of pthread_cond_wait.c.
  40. */
  41. #include "pthread.h"
  42. #include "implement.h"
  43. static INLINE int
  44. ptw32_cond_unblock (pthread_cond_t * cond, int unblockAll)
  45. /*
  46. * Notes.
  47. *
  48. * Does not use the external mutex for synchronisation,
  49. * therefore semBlockLock is needed.
  50. * mtxUnblockLock is for LEVEL-2 synch. LEVEL-2 is the
  51. * state where the external mutex is not necessarily locked by
  52. * any thread, ie. between cond_wait unlocking and re-acquiring
  53. * the lock after having been signaled or a timeout or
  54. * cancellation.
  55. *
  56. * Uses the following CV elements:
  57. * nWaitersBlocked
  58. * nWaitersToUnblock
  59. * nWaitersGone
  60. * mtxUnblockLock
  61. * semBlockLock
  62. * semBlockQueue
  63. */
  64. {
  65. int result;
  66. pthread_cond_t cv;
  67. int nSignalsToIssue;
  68. if (cond == NULL || *cond == NULL)
  69. {
  70. return EINVAL;
  71. }
  72. cv = *cond;
  73. /*
  74. * No-op if the CV is static and hasn't been initialised yet.
  75. * Assuming that any race condition is harmless.
  76. */
  77. if (cv == PTHREAD_COND_INITIALIZER)
  78. {
  79. return 0;
  80. }
  81. if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0)
  82. {
  83. return result;
  84. }
  85. if (0 != cv->nWaitersToUnblock)
  86. {
  87. if (0 == cv->nWaitersBlocked)
  88. {
  89. return pthread_mutex_unlock (&(cv->mtxUnblockLock));
  90. }
  91. if (unblockAll)
  92. {
  93. cv->nWaitersToUnblock += (nSignalsToIssue = cv->nWaitersBlocked);
  94. cv->nWaitersBlocked = 0;
  95. }
  96. else
  97. {
  98. nSignalsToIssue = 1;
  99. cv->nWaitersToUnblock++;
  100. cv->nWaitersBlocked--;
  101. }
  102. }
  103. else if (cv->nWaitersBlocked > cv->nWaitersGone)
  104. {
  105. /* Use the non-cancellable version of sem_wait() */
  106. if (ptw32_semwait (&(cv->semBlockLock)) != 0)
  107. {
  108. result = errno;
  109. (void) pthread_mutex_unlock (&(cv->mtxUnblockLock));
  110. return result;
  111. }
  112. if (0 != cv->nWaitersGone)
  113. {
  114. cv->nWaitersBlocked -= cv->nWaitersGone;
  115. cv->nWaitersGone = 0;
  116. }
  117. if (unblockAll)
  118. {
  119. nSignalsToIssue = cv->nWaitersToUnblock = cv->nWaitersBlocked;
  120. cv->nWaitersBlocked = 0;
  121. }
  122. else
  123. {
  124. nSignalsToIssue = cv->nWaitersToUnblock = 1;
  125. cv->nWaitersBlocked--;
  126. }
  127. }
  128. else
  129. {
  130. return pthread_mutex_unlock (&(cv->mtxUnblockLock));
  131. }
  132. if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0)
  133. {
  134. if (sem_post_multiple (&(cv->semBlockQueue), nSignalsToIssue) != 0)
  135. {
  136. result = errno;
  137. }
  138. }
  139. return result;
  140. } /* ptw32_cond_unblock */
  141. int
  142. pthread_cond_signal (pthread_cond_t * cond)
  143. /*
  144. * ------------------------------------------------------
  145. * DOCPUBLIC
  146. * This function signals a condition variable, waking
  147. * one waiting thread.
  148. * If SCHED_FIFO or SCHED_RR policy threads are waiting
  149. * the highest priority waiter is awakened; otherwise,
  150. * an unspecified waiter is awakened.
  151. *
  152. * PARAMETERS
  153. * cond
  154. * pointer to an instance of pthread_cond_t
  155. *
  156. *
  157. * DESCRIPTION
  158. * This function signals a condition variable, waking
  159. * one waiting thread.
  160. * If SCHED_FIFO or SCHED_RR policy threads are waiting
  161. * the highest priority waiter is awakened; otherwise,
  162. * an unspecified waiter is awakened.
  163. *
  164. * NOTES:
  165. *
  166. * 1) Use when any waiter can respond and only one need
  167. * respond (all waiters being equal).
  168. *
  169. * RESULTS
  170. * 0 successfully signaled condition,
  171. * EINVAL 'cond' is invalid,
  172. *
  173. * ------------------------------------------------------
  174. */
  175. {
  176. /*
  177. * The '0'(FALSE) unblockAll arg means unblock ONE waiter.
  178. */
  179. return (ptw32_cond_unblock (cond, 0));
  180. } /* pthread_cond_signal */
  181. int
  182. pthread_cond_broadcast (pthread_cond_t * cond)
  183. /*
  184. * ------------------------------------------------------
  185. * DOCPUBLIC
  186. * This function broadcasts the condition variable,
  187. * waking all current waiters.
  188. *
  189. * PARAMETERS
  190. * cond
  191. * pointer to an instance of pthread_cond_t
  192. *
  193. *
  194. * DESCRIPTION
  195. * This function signals a condition variable, waking
  196. * all waiting threads.
  197. *
  198. * NOTES:
  199. *
  200. * 1) Use when more than one waiter may respond to
  201. * predicate change or if any waiting thread may
  202. * not be able to respond
  203. *
  204. * RESULTS
  205. * 0 successfully signalled condition to all
  206. * waiting threads,
  207. * EINVAL 'cond' is invalid
  208. * ENOSPC a required resource has been exhausted,
  209. *
  210. * ------------------------------------------------------
  211. */
  212. {
  213. /*
  214. * The TRUE unblockAll arg means unblock ALL waiters.
  215. */
  216. return (ptw32_cond_unblock (cond, PTW32_TRUE));
  217. } /* pthread_cond_broadcast */