threads.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #ifndef AL_THREADS_H
  2. #define AL_THREADS_H
  3. #include <time.h>
  4. #if defined(__GNUC__) && defined(__i386__)
  5. /* force_align_arg_pointer is required for proper function arguments aligning
  6. * when SSE code is used. Some systems (Windows, QNX) do not guarantee our
  7. * thread functions will be properly aligned on the stack, even though GCC may
  8. * generate code with the assumption that it is. */
  9. #define FORCE_ALIGN __attribute__((force_align_arg_pointer))
  10. #else
  11. #define FORCE_ALIGN
  12. #endif
  13. #ifdef __cplusplus
  14. extern "C" {
  15. #endif
  16. enum {
  17. althrd_success = 0,
  18. althrd_error,
  19. althrd_nomem,
  20. althrd_timedout,
  21. althrd_busy
  22. };
  23. enum {
  24. almtx_plain = 0,
  25. almtx_recursive = 1,
  26. };
  27. typedef int (*althrd_start_t)(void*);
  28. typedef void (*altss_dtor_t)(void*);
  29. #define AL_TIME_UTC 1
  30. #ifdef _WIN32
  31. #define WIN32_LEAN_AND_MEAN
  32. #include <windows.h>
  33. #ifndef HAVE_STRUCT_TIMESPEC
  34. struct timespec {
  35. time_t tv_sec;
  36. long tv_nsec;
  37. };
  38. #endif
  39. typedef DWORD althrd_t;
  40. typedef CRITICAL_SECTION almtx_t;
  41. #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600
  42. typedef CONDITION_VARIABLE alcnd_t;
  43. #else
  44. typedef struct { void *Ptr; } alcnd_t;
  45. #endif
  46. typedef HANDLE alsem_t;
  47. typedef DWORD altss_t;
  48. typedef LONG alonce_flag;
  49. #define AL_ONCE_FLAG_INIT 0
  50. int althrd_sleep(const struct timespec *ts, struct timespec *rem);
  51. void alcall_once(alonce_flag *once, void (*callback)(void));
  52. void althrd_deinit(void);
  53. void althrd_thread_detach(void);
  54. inline althrd_t althrd_current(void)
  55. {
  56. return GetCurrentThreadId();
  57. }
  58. inline int althrd_equal(althrd_t thr0, althrd_t thr1)
  59. {
  60. return thr0 == thr1;
  61. }
  62. inline void althrd_exit(int res)
  63. {
  64. ExitThread(res);
  65. }
  66. inline void althrd_yield(void)
  67. {
  68. SwitchToThread();
  69. }
  70. inline int almtx_lock(almtx_t *mtx)
  71. {
  72. if(!mtx) return althrd_error;
  73. EnterCriticalSection(mtx);
  74. return althrd_success;
  75. }
  76. inline int almtx_unlock(almtx_t *mtx)
  77. {
  78. if(!mtx) return althrd_error;
  79. LeaveCriticalSection(mtx);
  80. return althrd_success;
  81. }
  82. inline int almtx_trylock(almtx_t *mtx)
  83. {
  84. if(!mtx) return althrd_error;
  85. if(!TryEnterCriticalSection(mtx))
  86. return althrd_busy;
  87. return althrd_success;
  88. }
  89. inline void *altss_get(altss_t tss_id)
  90. {
  91. return TlsGetValue(tss_id);
  92. }
  93. inline int altss_set(altss_t tss_id, void *val)
  94. {
  95. if(TlsSetValue(tss_id, val) == 0)
  96. return althrd_error;
  97. return althrd_success;
  98. }
  99. #else
  100. #include <stdint.h>
  101. #include <errno.h>
  102. #include <pthread.h>
  103. #include <semaphore.h>
  104. typedef pthread_t althrd_t;
  105. typedef pthread_mutex_t almtx_t;
  106. typedef pthread_cond_t alcnd_t;
  107. typedef sem_t alsem_t;
  108. typedef pthread_key_t altss_t;
  109. typedef pthread_once_t alonce_flag;
  110. #define AL_ONCE_FLAG_INIT PTHREAD_ONCE_INIT
  111. inline althrd_t althrd_current(void)
  112. {
  113. return pthread_self();
  114. }
  115. inline int althrd_equal(althrd_t thr0, althrd_t thr1)
  116. {
  117. return pthread_equal(thr0, thr1);
  118. }
  119. inline void althrd_exit(int res)
  120. {
  121. pthread_exit((void*)(intptr_t)res);
  122. }
  123. inline void althrd_yield(void)
  124. {
  125. sched_yield();
  126. }
  127. inline int althrd_sleep(const struct timespec *ts, struct timespec *rem)
  128. {
  129. int ret = nanosleep(ts, rem);
  130. if(ret != 0)
  131. {
  132. ret = ((errno==EINTR) ? -1 : -2);
  133. errno = 0;
  134. }
  135. return ret;
  136. }
  137. inline int almtx_lock(almtx_t *mtx)
  138. {
  139. if(pthread_mutex_lock(mtx) != 0)
  140. return althrd_error;
  141. return althrd_success;
  142. }
  143. inline int almtx_unlock(almtx_t *mtx)
  144. {
  145. if(pthread_mutex_unlock(mtx) != 0)
  146. return althrd_error;
  147. return althrd_success;
  148. }
  149. inline int almtx_trylock(almtx_t *mtx)
  150. {
  151. int ret = pthread_mutex_trylock(mtx);
  152. switch(ret)
  153. {
  154. case 0: return althrd_success;
  155. case EBUSY: return althrd_busy;
  156. }
  157. return althrd_error;
  158. }
  159. inline void *altss_get(altss_t tss_id)
  160. {
  161. return pthread_getspecific(tss_id);
  162. }
  163. inline int altss_set(altss_t tss_id, void *val)
  164. {
  165. if(pthread_setspecific(tss_id, val) != 0)
  166. return althrd_error;
  167. return althrd_success;
  168. }
  169. inline void alcall_once(alonce_flag *once, void (*callback)(void))
  170. {
  171. pthread_once(once, callback);
  172. }
  173. inline void althrd_deinit(void) { }
  174. inline void althrd_thread_detach(void) { }
  175. #endif
  176. int althrd_create(althrd_t *thr, althrd_start_t func, void *arg);
  177. int althrd_detach(althrd_t thr);
  178. int althrd_join(althrd_t thr, int *res);
  179. void althrd_setname(althrd_t thr, const char *name);
  180. int almtx_init(almtx_t *mtx, int type);
  181. void almtx_destroy(almtx_t *mtx);
  182. int alcnd_init(alcnd_t *cond);
  183. int alcnd_signal(alcnd_t *cond);
  184. int alcnd_broadcast(alcnd_t *cond);
  185. int alcnd_wait(alcnd_t *cond, almtx_t *mtx);
  186. void alcnd_destroy(alcnd_t *cond);
  187. int alsem_init(alsem_t *sem, unsigned int initial);
  188. void alsem_destroy(alsem_t *sem);
  189. int alsem_post(alsem_t *sem);
  190. int alsem_wait(alsem_t *sem);
  191. int alsem_trywait(alsem_t *sem);
  192. int altss_create(altss_t *tss_id, altss_dtor_t callback);
  193. void altss_delete(altss_t tss_id);
  194. int altimespec_get(struct timespec *ts, int base);
  195. void al_nssleep(unsigned long nsec);
  196. #ifdef __cplusplus
  197. }
  198. #endif
  199. #endif /* AL_THREADS_H */