mu-threads.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. // Copyright (C) 2004-2021 Artifex Software, Inc.
  2. //
  3. // This file is part of MuPDF.
  4. //
  5. // MuPDF is free software: you can redistribute it and/or modify it under the
  6. // terms of the GNU Affero General Public License as published by the Free
  7. // Software Foundation, either version 3 of the License, or (at your option)
  8. // any later version.
  9. //
  10. // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
  11. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. // details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
  17. //
  18. // Alternative licensing terms are available from the licensor.
  19. // For commercial licensing, see <https://www.artifex.com/> or contact
  20. // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  21. // CA 94129, USA, for further information.
  22. #include "mupdf/helpers/mu-threads.h"
  23. #ifdef DISABLE_MUTHREADS
  24. #include <stdlib.h>
  25. /* Null implementation. Just error out. */
  26. int mu_create_semaphore(mu_semaphore *sem)
  27. {
  28. return 1; /* Just Error */
  29. }
  30. void mu_destroy_semaphore(mu_semaphore *sem)
  31. {
  32. }
  33. int mu_trigger_semaphore(mu_semaphore *sem)
  34. {
  35. abort();
  36. return 1;
  37. }
  38. int mu_wait_semaphore(mu_semaphore *sem)
  39. {
  40. abort();
  41. return 1;
  42. }
  43. int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg)
  44. {
  45. return 1;
  46. }
  47. void mu_destroy_thread(mu_thread *th)
  48. {
  49. }
  50. int mu_create_mutex(mu_mutex *mutex)
  51. {
  52. return 1;
  53. }
  54. void mu_destroy_mutex(mu_mutex *mutex)
  55. {
  56. }
  57. void mu_lock_mutex(mu_mutex *mutex)
  58. {
  59. abort();
  60. }
  61. void mu_unlock_mutex(mu_mutex *mutex)
  62. {
  63. abort();
  64. }
  65. #elif MU_THREAD_IMPL_TYPE == 1
  66. /* Windows threads */
  67. int mu_create_semaphore(mu_semaphore *sem)
  68. {
  69. sem->handle = CreateSemaphore(NULL, 0, 1, NULL);
  70. return (sem->handle == NULL);
  71. }
  72. void mu_destroy_semaphore(mu_semaphore *sem)
  73. {
  74. if (sem->handle == NULL)
  75. return;
  76. /* We can't sensibly handle this failing */
  77. (void)CloseHandle(sem->handle);
  78. }
  79. int mu_trigger_semaphore(mu_semaphore *sem)
  80. {
  81. if (sem->handle == NULL)
  82. return 0;
  83. /* We can't sensibly handle this failing */
  84. return !ReleaseSemaphore(sem->handle, 1, NULL);
  85. }
  86. int mu_wait_semaphore(mu_semaphore *sem)
  87. {
  88. if (sem->handle == NULL)
  89. return 0;
  90. /* We can't sensibly handle this failing */
  91. return !WaitForSingleObject(sem->handle, INFINITE);
  92. }
  93. static DWORD WINAPI thread_starter(LPVOID arg)
  94. {
  95. mu_thread *th = (mu_thread *)arg;
  96. th->fn(th->arg);
  97. return 0;
  98. }
  99. int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg)
  100. {
  101. th->fn = fn;
  102. th->arg = arg;
  103. th->handle = CreateThread(NULL, 0, thread_starter, th, 0, NULL);
  104. return (th->handle == NULL);
  105. }
  106. void mu_destroy_thread(mu_thread *th)
  107. {
  108. if (th->handle == NULL)
  109. return;
  110. /* We can't sensibly handle this failing */
  111. (void)WaitForSingleObject(th->handle, INFINITE);
  112. (void)CloseHandle(th->handle);
  113. th->handle = NULL;
  114. }
  115. int mu_create_mutex(mu_mutex *mutex)
  116. {
  117. InitializeCriticalSection(&mutex->mutex);
  118. return 0; /* Magic function, never fails */
  119. }
  120. void mu_destroy_mutex(mu_mutex *mutex)
  121. {
  122. const static CRITICAL_SECTION empty = { 0 };
  123. if (memcmp(&mutex->mutex, &empty, sizeof(empty)) == 0)
  124. return;
  125. DeleteCriticalSection(&mutex->mutex);
  126. mutex->mutex = empty;
  127. }
  128. void mu_lock_mutex(mu_mutex *mutex)
  129. {
  130. EnterCriticalSection(&mutex->mutex);
  131. }
  132. void mu_unlock_mutex(mu_mutex *mutex)
  133. {
  134. LeaveCriticalSection(&mutex->mutex);
  135. }
  136. #elif MU_THREAD_IMPL_TYPE == 2
  137. /*
  138. PThreads - without working unnamed semaphores.
  139. Neither ios nor OSX supports unnamed semaphores.
  140. Named semaphores are a pain to use, so we implement
  141. our own semaphores using condition variables and
  142. mutexes.
  143. */
  144. #include <string.h>
  145. int
  146. mu_create_semaphore(mu_semaphore *sem)
  147. {
  148. int scode;
  149. sem->count = 0;
  150. scode = pthread_mutex_init(&sem->mutex, NULL);
  151. if (scode == 0)
  152. {
  153. scode = pthread_cond_init(&sem->cond, NULL);
  154. if (scode)
  155. pthread_mutex_destroy(&sem->mutex);
  156. }
  157. if (scode)
  158. memset(sem, 0, sizeof(*sem));
  159. return scode;
  160. }
  161. void
  162. mu_destroy_semaphore(mu_semaphore *sem)
  163. {
  164. const static mu_semaphore empty = { 0 };
  165. if (memcmp(sem, &empty, sizeof(empty)) == 0)
  166. return;
  167. (void)pthread_cond_destroy(&sem->cond);
  168. (void)pthread_mutex_destroy(&sem->mutex);
  169. *sem = empty;
  170. }
  171. int
  172. mu_wait_semaphore(mu_semaphore *sem)
  173. {
  174. int scode, scode2;
  175. scode = pthread_mutex_lock(&sem->mutex);
  176. if (scode)
  177. return scode;
  178. while (sem->count == 0) {
  179. scode = pthread_cond_wait(&sem->cond, &sem->mutex);
  180. if (scode)
  181. break;
  182. }
  183. if (scode == 0)
  184. --sem->count;
  185. scode2 = pthread_mutex_unlock(&sem->mutex);
  186. if (scode == 0)
  187. scode = scode2;
  188. return scode;
  189. }
  190. int
  191. mu_trigger_semaphore(mu_semaphore * sem)
  192. {
  193. int scode, scode2;
  194. scode = pthread_mutex_lock(&sem->mutex);
  195. if (scode)
  196. return scode;
  197. if (sem->count++ == 0)
  198. scode = pthread_cond_signal(&sem->cond);
  199. scode2 = pthread_mutex_unlock(&sem->mutex);
  200. if (scode == 0)
  201. scode = scode2;
  202. return scode;
  203. }
  204. static void *thread_starter(void *arg)
  205. {
  206. mu_thread *th = (mu_thread *)arg;
  207. th->fn(th->arg);
  208. return NULL;
  209. }
  210. int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg)
  211. {
  212. th->fn = fn;
  213. th->arg = arg;
  214. return pthread_create(&th->thread, NULL, thread_starter, th);
  215. }
  216. void mu_destroy_thread(mu_thread *th)
  217. {
  218. const static mu_thread empty; /* static objects are always initialized to zero */
  219. if (memcmp(th, &empty, sizeof(empty)) == 0)
  220. return;
  221. (void)pthread_join(th->thread, NULL);
  222. *th = empty;
  223. }
  224. int mu_create_mutex(mu_mutex *mutex)
  225. {
  226. return pthread_mutex_init(&mutex->mutex, NULL);
  227. }
  228. void mu_destroy_mutex(mu_mutex *mutex)
  229. {
  230. const static mu_mutex empty; /* static objects are always initialized to zero */
  231. if (memcmp(mutex, &empty, sizeof(empty)) == 0)
  232. return;
  233. (void)pthread_mutex_destroy(&mutex->mutex);
  234. *mutex = empty;
  235. }
  236. void mu_lock_mutex(mu_mutex *mutex)
  237. {
  238. (void)pthread_mutex_lock(&mutex->mutex);
  239. }
  240. void mu_unlock_mutex(mu_mutex *mutex)
  241. {
  242. (void)pthread_mutex_unlock(&mutex->mutex);
  243. }
  244. #else
  245. #error Unknown MU_THREAD_IMPL_TYPE setting
  246. #endif