threading-posix.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * Copyright (c) 2014 Hugh Bailey <[email protected]>
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifdef __APPLE__
  17. #include <sys/time.h>
  18. #include <mach/semaphore.h>
  19. #include <mach/task.h>
  20. #include <mach/mach_init.h>
  21. #else
  22. #include <semaphore.h>
  23. #endif
  24. #include "bmem.h"
  25. #include "threading.h"
  26. struct os_event_data {
  27. pthread_mutex_t mutex;
  28. pthread_cond_t cond;
  29. volatile bool signalled;
  30. bool manual;
  31. };
  32. int os_event_init(os_event_t *event, enum os_event_type type)
  33. {
  34. int code = 0;
  35. struct os_event_data *data = bzalloc(sizeof(struct os_event_data));
  36. if ((code = pthread_mutex_init(&data->mutex, NULL)) < 0) {
  37. bfree(data);
  38. return code;
  39. }
  40. if ((code = pthread_cond_init(&data->cond, NULL)) < 0) {
  41. pthread_mutex_destroy(&data->mutex);
  42. bfree(data);
  43. return code;
  44. }
  45. data->manual = (type == OS_EVENT_TYPE_MANUAL);
  46. data->signalled = false;
  47. *event = data;
  48. return 0;
  49. }
  50. void os_event_destroy(os_event_t event)
  51. {
  52. if (event) {
  53. pthread_mutex_destroy(&event->mutex);
  54. pthread_cond_destroy(&event->cond);
  55. bfree(event);
  56. }
  57. }
  58. int os_event_wait(os_event_t event)
  59. {
  60. int code = 0;
  61. pthread_mutex_lock(&event->mutex);
  62. if (!event->signalled)
  63. code = pthread_cond_wait(&event->cond, &event->mutex);
  64. if (code == 0) {
  65. if (!event->manual)
  66. event->signalled = false;
  67. pthread_mutex_unlock(&event->mutex);
  68. }
  69. return code;
  70. }
  71. static inline void add_ms_to_ts(struct timespec *ts,
  72. unsigned long milliseconds)
  73. {
  74. ts->tv_sec += milliseconds/1000;
  75. ts->tv_nsec += (milliseconds%1000)*1000000;
  76. if (ts->tv_nsec > 1000000000) {
  77. ts->tv_sec += 1;
  78. ts->tv_nsec -= 1000000000;
  79. }
  80. }
  81. int os_event_timedwait(os_event_t event, unsigned long milliseconds)
  82. {
  83. int code = 0;
  84. pthread_mutex_lock(&event->mutex);
  85. if (!event->signalled) {
  86. struct timespec ts;
  87. #ifdef __APPLE__
  88. struct timeval tv;
  89. gettimeofday(&tv, NULL);
  90. ts.tv_sec = tv.tv_sec;
  91. ts.tv_nsec = tv.tv_usec * 1000;
  92. #else
  93. clock_gettime(CLOCK_REALTIME, &ts);
  94. #endif
  95. add_ms_to_ts(&ts, milliseconds);
  96. code = pthread_cond_timedwait(&event->cond, &event->mutex, &ts);
  97. }
  98. if (code == 0) {
  99. if (!event->manual)
  100. event->signalled = false;
  101. }
  102. pthread_mutex_unlock(&event->mutex);
  103. return code;
  104. }
  105. int os_event_try(os_event_t event)
  106. {
  107. int ret = EAGAIN;
  108. pthread_mutex_lock(&event->mutex);
  109. if (event->signalled) {
  110. if (!event->manual)
  111. event->signalled = false;
  112. ret = 0;
  113. }
  114. pthread_mutex_unlock(&event->mutex);
  115. return ret;
  116. }
  117. int os_event_signal(os_event_t event)
  118. {
  119. int code = 0;
  120. pthread_mutex_lock(&event->mutex);
  121. code = pthread_cond_signal(&event->cond);
  122. event->signalled = true;
  123. pthread_mutex_unlock(&event->mutex);
  124. return code;
  125. }
  126. void os_event_reset(os_event_t event)
  127. {
  128. pthread_mutex_lock(&event->mutex);
  129. event->signalled = false;
  130. pthread_mutex_unlock(&event->mutex);
  131. }
  132. #ifdef __APPLE__
  133. struct os_sem_data {
  134. semaphore_t sem;
  135. task_t task;
  136. };
  137. int os_sem_init(os_sem_t *sem, int value)
  138. {
  139. semaphore_t new_sem;
  140. task_t task = mach_task_self();
  141. if (semaphore_create(task, &new_sem, 0, value) != KERN_SUCCESS)
  142. return -1;
  143. *sem = bzalloc(sizeof(struct os_sem_data));
  144. (*sem)->sem = new_sem;
  145. (*sem)->task = task;
  146. return 0;
  147. }
  148. void os_sem_destroy(os_sem_t sem)
  149. {
  150. if (sem) {
  151. semaphore_destroy(sem->task, sem->sem);
  152. bfree(sem);
  153. }
  154. }
  155. int os_sem_post(os_sem_t sem)
  156. {
  157. if (!sem) return -1;
  158. return (semaphore_signal(sem->sem) == KERN_SUCCESS) ? 0 : -1;
  159. }
  160. int os_sem_wait(os_sem_t sem)
  161. {
  162. if (!sem) return -1;
  163. return (semaphore_wait(sem->sem) == KERN_SUCCESS) ? 0 : -1;
  164. }
  165. #else
  166. struct os_sem_data {
  167. sem_t sem;
  168. };
  169. int os_sem_init(os_sem_t *sem, int value)
  170. {
  171. sem_t new_sem;
  172. int ret = sem_init(&new_sem, 0, value);
  173. if (ret != 0)
  174. return ret;
  175. *sem = bzalloc(sizeof(struct os_sem_data));
  176. (*sem)->sem = new_sem;
  177. return 0;
  178. }
  179. void os_sem_destroy(os_sem_t sem)
  180. {
  181. if (sem) {
  182. sem_destroy(&sem->sem);
  183. bfree(sem);
  184. }
  185. }
  186. int os_sem_post(os_sem_t sem)
  187. {
  188. if (!sem) return -1;
  189. return sem_post(&sem->sem);
  190. }
  191. int os_sem_wait(os_sem_t sem)
  192. {
  193. if (!sem) return -1;
  194. return sem_wait(&sem->sem);
  195. }
  196. #endif
  197. long os_atomic_inc_long(volatile long *val)
  198. {
  199. return __sync_fetch_and_add(val, 1);
  200. }
  201. long os_atomic_dec_long(volatile long *val)
  202. {
  203. return __sync_fetch_and_sub(val, 1);
  204. }