You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

std_thread.c 4.4 kB

3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #ifdef _WIN32
  2. /* windows.h needs to be the top-most header usually */
  3. # include <windows.h>
  4. #endif
  5. #include "std_testcase.h"
  6. #ifdef _WIN32
  7. # include <process.h>
  8. #else
  9. # include <pthread.h>
  10. #endif
  11. #include "std_thread.h"
  12. struct _stdThread {
  13. #ifdef _WIN32
  14. uintptr_t handle;
  15. #else
  16. pthread_t handle;
  17. #endif
  18. stdThreadRoutine start;
  19. void *args;
  20. };
  21. #ifdef __cplusplus
  22. extern "C" {
  23. #endif
  24. #ifdef _WIN32
  25. static unsigned __stdcall internal_start(void *args)
  26. #else
  27. static void *internal_start(void *args)
  28. #endif
  29. {
  30. stdThread thread = (stdThread)args;
  31. thread->start(thread->args);
  32. #ifdef _WIN32
  33. _endthreadex(0);
  34. /* dead code, but return to avoid warnings */
  35. return 0;
  36. #else
  37. pthread_exit(NULL);
  38. /* dead code, but return to avoid warnings */
  39. return NULL;
  40. #endif
  41. }
  42. int stdThreadCreate(stdThreadRoutine start, void *args, stdThread *thread)
  43. {
  44. #ifdef _WIN32
  45. uintptr_t handle;
  46. #else
  47. pthread_t handle;
  48. #endif
  49. stdThread my_thread;
  50. *thread = NULL;
  51. my_thread = (stdThread)malloc(sizeof(*my_thread));
  52. if (my_thread == NULL) {
  53. return 0;
  54. }
  55. my_thread->start = start;
  56. my_thread->args = args;
  57. #ifdef _WIN32
  58. handle = _beginthreadex(NULL, 0, internal_start, my_thread, 0, NULL);
  59. if (handle == 0) {
  60. free(my_thread);
  61. return 0;
  62. }
  63. #else
  64. if (0 != pthread_create(&handle, NULL, internal_start, my_thread)) {
  65. free(my_thread);
  66. return 0;
  67. }
  68. #endif
  69. /* clearly, you cannot access _stdThread.handle from within the thread
  70. * itself, because initialization of this field is not synchronized w.r.t.
  71. * multiple threads
  72. */
  73. my_thread->handle = handle;
  74. *thread = my_thread;
  75. return 1;
  76. }
  77. int stdThreadJoin(stdThread thread)
  78. {
  79. #ifdef _WIN32
  80. DWORD value;
  81. value = WaitForSingleObject((HANDLE)thread->handle, INFINITE);
  82. if (value != WAIT_OBJECT_0) return 0;
  83. #else
  84. void *dummy;
  85. if (0 != pthread_join(thread->handle, &dummy)) return 0;
  86. #endif
  87. return 1;
  88. }
  89. int stdThreadDestroy(stdThread thread)
  90. {
  91. #ifdef _WIN32
  92. CloseHandle((HANDLE)thread->handle);
  93. #else
  94. #endif
  95. free(thread);
  96. return 1;
  97. }
  98. #ifdef __cplusplus
  99. } /* end extern "C" */
  100. #endif
  101. struct _stdThreadLock {
  102. #ifdef _WIN32
  103. CRITICAL_SECTION CriticalSection;
  104. #else
  105. pthread_mutex_t mutex;
  106. #endif
  107. };
  108. #ifdef __cplusplus
  109. extern "C" {
  110. #endif
  111. int stdThreadLockCreate(stdThreadLock *lock)
  112. {
  113. stdThreadLock my_lock = NULL;
  114. *lock = NULL;
  115. my_lock = (stdThreadLock)malloc(sizeof(*my_lock));
  116. if (my_lock == NULL) return 0;
  117. #ifdef _WIN32
  118. __try {
  119. InitializeCriticalSection(&my_lock->CriticalSection);
  120. } __except (GetExceptionCode() == STATUS_NO_MEMORY) {
  121. free(my_lock);
  122. return 0;
  123. }
  124. #else
  125. if (0 != pthread_mutex_init(&my_lock->mutex, NULL)) {
  126. free(lock);
  127. return 0;
  128. }
  129. #endif
  130. *lock = my_lock;
  131. return 1;
  132. }
  133. void stdThreadLockAcquire(stdThreadLock lock)
  134. {
  135. /* pthread_mutex's and CRITICAL_SECTIONS differ
  136. *
  137. * CRITICAL_SECTION's are recursive, meaning a thread can acquire a
  138. * CRITICAL_SECTION multiple times, so long as it then releases it
  139. * the same number of times.
  140. *
  141. * pthread_mutex's seem to be undefined with regards to recursion,
  142. * meaning that acquiring the same mutex twice leads to undefined
  143. * behavior (it could deadlock, crash, act recursively, who knows)
  144. *
  145. * Therefore, we will define multiple acquisitions of a lock in a
  146. * single thread as "undefined" behavior, thereby allowing us to
  147. * ignore the platform compatibility issues here.
  148. */
  149. #ifdef _WIN32
  150. /* may throw an exception in Windows 2000 but documentation says to let
  151. * it terminate the process (i.e., don't handle it)
  152. */
  153. EnterCriticalSection(&lock->CriticalSection);
  154. #else
  155. pthread_mutex_lock(&lock->mutex);
  156. #endif
  157. }
  158. void stdThreadLockRelease(stdThreadLock lock)
  159. {
  160. /* see comments in stdThreadLockAcquire with regards to lock
  161. * recursion */
  162. #ifdef _WIN32
  163. LeaveCriticalSection(&lock->CriticalSection);
  164. #else
  165. pthread_mutex_unlock(&lock->mutex);
  166. #endif
  167. }
  168. void stdThreadLockDestroy(stdThreadLock lock)\
  169. {
  170. #ifdef _WIN32
  171. DeleteCriticalSection(&lock->CriticalSection);
  172. #else
  173. pthread_mutex_destroy(&lock->mutex);
  174. #endif
  175. free(lock);
  176. }
  177. #ifdef __cplusplus
  178. } /* end extern "C" */
  179. #endif

No Description

Contributors (1)