sem_wait.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * -------------------------------------------------------------
  3. *
  4. * Module: sem_wait.c
  5. *
  6. * Purpose:
  7. * Semaphores aren't actually part of the PThreads standard.
  8. * They are defined by the POSIX Standard:
  9. *
  10. * POSIX 1003.1b-1993 (POSIX.1b)
  11. *
  12. * -------------------------------------------------------------
  13. *
  14. * --------------------------------------------------------------------------
  15. *
  16. * Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
  17. * Copyright(C) 2008 Jason Schmidlapp
  18. *
  19. * Contact Email: [email protected]
  20. *
  21. *
  22. * Based upon Pthreads-win32 - POSIX Threads Library for Win32
  23. * Copyright(C) 1998 John E. Bossom
  24. * Copyright(C) 1999,2005 Pthreads-win32 contributors
  25. *
  26. * Contact Email: [email protected]
  27. *
  28. * The original list of contributors to the Pthreads-win32 project
  29. * is contained in the file CONTRIBUTORS.ptw32 included with the
  30. * source code distribution. The list can also be seen at the
  31. * following World Wide Web location:
  32. * http://sources.redhat.com/pthreads-win32/contributors.html
  33. *
  34. * This library is free software; you can redistribute it and/or
  35. * modify it under the terms of the GNU Lesser General Public
  36. * License as published by the Free Software Foundation; either
  37. * version 2 of the License, or (at your option) any later version.
  38. *
  39. * This library is distributed in the hope that it will be useful,
  40. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  41. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  42. * Lesser General Public License for more details.
  43. *
  44. * You should have received a copy of the GNU Lesser General Public
  45. * License along with this library in the file COPYING.LIB;
  46. * if not, write to the Free Software Foundation, Inc.,
  47. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  48. */
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include "pthread.h"
  52. #include "semaphore.h"
  53. #include "implement.h"
  54. static void
  55. pte_sem_wait_cleanup(void * sem)
  56. {
  57. sem_t s = (sem_t) sem;
  58. unsigned int timeout;
  59. if (pthread_mutex_lock (&s->lock) == 0)
  60. {
  61. /*
  62. * If sema is destroyed do nothing, otherwise:-
  63. * If the sema is posted between us being cancelled and us locking
  64. * the sema again above then we need to consume that post but cancel
  65. * anyway. If we don't get the semaphore we indicate that we're no
  66. * longer waiting.
  67. */
  68. timeout = 0;
  69. if (pte_osSemaphorePend(s->sem, &timeout) != PTE_OS_OK)
  70. {
  71. ++s->value;
  72. /*
  73. * Don't release the W32 sema, it doesn't need adjustment
  74. * because it doesn't record the number of waiters.
  75. */
  76. }
  77. (void) pthread_mutex_unlock (&s->lock);
  78. }
  79. }
  80. int
  81. sem_wait (sem_t * sem)
  82. /*
  83. * ------------------------------------------------------
  84. * DOCPUBLIC
  85. * This function waits on a semaphore.
  86. *
  87. * PARAMETERS
  88. * sem
  89. * pointer to an instance of sem_t
  90. *
  91. * DESCRIPTION
  92. * This function waits on a semaphore. If the
  93. * semaphore value is greater than zero, it decreases
  94. * its value by one. If the semaphore value is zero, then
  95. * the calling thread (or process) is blocked until it can
  96. * successfully decrease the value or until interrupted by
  97. * a signal.
  98. *
  99. * RESULTS
  100. * 0 successfully decreased semaphore,
  101. * -1 failed, error in errno
  102. * ERRNO
  103. * EINVAL 'sem' is not a valid semaphore,
  104. * ENOSYS semaphores are not supported,
  105. * EINTR the function was interrupted by a signal,
  106. * EDEADLK a deadlock condition was detected.
  107. *
  108. * ------------------------------------------------------
  109. */
  110. {
  111. int result = 0;
  112. sem_t s = *sem;
  113. pthread_testcancel();
  114. if (s == NULL)
  115. {
  116. result = EINVAL;
  117. }
  118. else
  119. {
  120. if ((result = pthread_mutex_lock (&s->lock)) == 0)
  121. {
  122. int v;
  123. /* See sem_destroy.c
  124. */
  125. if (*sem == NULL)
  126. {
  127. (void) pthread_mutex_unlock (&s->lock);
  128. errno = EINVAL;
  129. return -1;
  130. }
  131. v = --s->value;
  132. (void) pthread_mutex_unlock (&s->lock);
  133. if (v < 0)
  134. {
  135. /* Must wait */
  136. pthread_cleanup_push(pte_sem_wait_cleanup, (void *) s);
  137. result = pte_cancellable_wait(s->sem,NULL);
  138. /* Cleanup if we're canceled or on any other error */
  139. pthread_cleanup_pop(result);
  140. // Wait was cancelled, indicate that we're no longer waiting on this semaphore.
  141. /*
  142. if (result == PTE_OS_INTERRUPTED)
  143. {
  144. result = EINTR;
  145. ++s->value;
  146. }
  147. */
  148. }
  149. }
  150. }
  151. if (result != 0)
  152. {
  153. errno = result;
  154. return -1;
  155. }
  156. return 0;
  157. } /* sem_wait */
  158. int
  159. sem_wait_nocancel (sem_t * sem)
  160. /*
  161. * ------------------------------------------------------
  162. * DOCPUBLIC
  163. * This function waits on a semaphore, and doesn't
  164. * allow cancellation.
  165. *
  166. * PARAMETERS
  167. * sem
  168. * pointer to an instance of sem_t
  169. *
  170. * DESCRIPTION
  171. * This function waits on a semaphore. If the
  172. * semaphore value is greater than zero, it decreases
  173. * its value by one. If the semaphore value is zero, then
  174. * the calling thread (or process) is blocked until it can
  175. * successfully decrease the value or until interrupted by
  176. * a signal.
  177. *
  178. * RESULTS
  179. * 0 successfully decreased semaphore,
  180. * -1 failed, error in errno
  181. * ERRNO
  182. * EINVAL 'sem' is not a valid semaphore,
  183. * ENOSYS semaphores are not supported,
  184. * EINTR the function was interrupted by a signal,
  185. * EDEADLK a deadlock condition was detected.
  186. *
  187. * ------------------------------------------------------
  188. */
  189. {
  190. int result = 0;
  191. sem_t s = *sem;
  192. pthread_testcancel();
  193. if (s == NULL)
  194. {
  195. result = EINVAL;
  196. }
  197. else
  198. {
  199. if ((result = pthread_mutex_lock (&s->lock)) == 0)
  200. {
  201. int v;
  202. /* See sem_destroy.c
  203. */
  204. if (*sem == NULL)
  205. {
  206. (void) pthread_mutex_unlock (&s->lock);
  207. errno = EINVAL;
  208. return -1;
  209. }
  210. v = --s->value;
  211. (void) pthread_mutex_unlock (&s->lock);
  212. if (v < 0)
  213. {
  214. pte_osSemaphorePend(s->sem, NULL);
  215. }
  216. }
  217. }
  218. if (result != 0)
  219. {
  220. errno = result;
  221. return -1;
  222. }
  223. return 0;
  224. } /* sem_wait_nocancel */