bh_thread.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "bh_thread.h"
  17. #include "bh_assert.h"
  18. #include "bh_log.h"
  19. #include "bh_memory.h"
  20. #include <windows.h>
  21. #include <process.h>
  22. #ifdef _DEBUG
  23. #define THREAD_STACK_ADJUSTMENT (32 * 1024)
  24. #else
  25. #define THREAD_STACK_ADJUSTMENT 0
  26. #endif
  27. static korp_mutex thread_list_lock;
  28. static DWORD tls_indexes[BH_MAX_TLS_NUM];
  29. typedef struct {
  30. int zero_padding;
  31. thread_start_routine_t start;
  32. void* stack;
  33. void* args;
  34. int stack_size;
  35. } vm_thread_block;
  36. static DWORD tb_index;
  37. int _vm_thread_sys_init()
  38. {
  39. unsigned int i;
  40. for (i = 0; i < BH_MAX_TLS_NUM; i++) {
  41. tls_indexes[i] = TlsAlloc();
  42. if (tls_indexes[i] == TLS_OUT_OF_INDEXES)
  43. return BHT_ERROR;
  44. }
  45. tb_index = TlsAlloc();
  46. if (tb_index == TLS_OUT_OF_INDEXES)
  47. return BHT_ERROR;
  48. return vm_mutex_init(&thread_list_lock);
  49. }
  50. static unsigned int BH_ROUTINE_MODIFIER beihai_starter(void* arg)
  51. {
  52. vm_thread_block* tb = (vm_thread_block*) arg;
  53. TlsSetValue(tb_index, tb);
  54. tb->stack = (void *) &arg;
  55. tb->start(tb->args);
  56. return 0;
  57. }
  58. int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
  59. unsigned int stack_size)
  60. {
  61. unsigned int default_stack_size = 20 * 1024;
  62. vm_thread_block* tb;
  63. bh_assert(tid);
  64. bh_assert(start);
  65. if (stack_size == 0)
  66. stack_size = default_stack_size;
  67. #ifdef _DEBUG
  68. stack_size = THREAD_STACK_ADJUSTMENT + stack_size*3;
  69. #endif
  70. tb = (vm_thread_block*) bh_malloc(sizeof(*tb));
  71. if (tb == NULL)
  72. return BHT_ERROR;
  73. memset(tb, 0, sizeof(*tb));
  74. tb->start = start;
  75. tb->stack_size = stack_size;
  76. tb->args = arg;
  77. *tid = (korp_tid) _beginthreadex(NULL, stack_size, beihai_starter,
  78. (void*) tb, 0, NULL);
  79. /* TODO: to deal with the handle; how to close it? */
  80. return (*tid == INVALID_THREAD_ID) ? BHT_ERROR : BHT_OK;
  81. }
  82. korp_tid _vm_self_thread()
  83. {
  84. return (korp_tid) GetCurrentThread();
  85. }
  86. void vm_thread_exit(void *code)
  87. {
  88. vm_thread_block *tb = (vm_thread_block*) TlsGetValue(tb_index);
  89. bh_free(tb);
  90. _endthreadex((unsigned int) code);
  91. }
  92. void* vm_get_stackaddr()
  93. {
  94. vm_thread_block *tb = (vm_thread_block*) TlsGetValue(tb_index);
  95. return (char *) tb->stack + THREAD_STACK_ADJUSTMENT - tb->stack_size;
  96. }
  97. void *_vm_tls_get(unsigned idx)
  98. {
  99. bh_assert(idx < BH_MAX_TLS_NUM);
  100. return TlsGetValue(tls_indexes[idx]);
  101. }
  102. int _vm_tls_put(unsigned idx, void *tls)
  103. {
  104. BOOL r;
  105. bh_assert(idx < BH_MAX_TLS_NUM);
  106. r = TlsSetValue(tls_indexes[idx], tls);
  107. return (r == FALSE) ? BHT_ERROR : BHT_OK;
  108. }
  109. int _vm_mutex_init(korp_mutex *mutex)
  110. {
  111. bh_assert(mutex);
  112. *mutex = CreateMutex(NULL, FALSE, NULL);
  113. return (*mutex == 0) ? BHT_ERROR : BHT_OK;
  114. }
  115. int _vm_mutex_destroy(korp_mutex *mutex)
  116. {
  117. return BHT_OK;
  118. }
  119. /* Returned error (e.g. ERROR_INVALID_HANDLE) from
  120. locking the mutex indicates some logic error present in
  121. the program somewhere.
  122. Don't try to recover error for an existing unknown error.*/
  123. void vm_mutex_lock(korp_mutex *mutex)
  124. {
  125. DWORD ret;
  126. bh_assert(mutex);
  127. ret = WaitForSingleObject(*mutex, INFINITE);
  128. if (WAIT_FAILED == ret) {
  129. LOG_FATAL("vm mutex lock failed (ret=%d)!\n", GetLastError());
  130. exit(-1);
  131. }
  132. }
  133. int vm_mutex_trylock(korp_mutex *mutex)
  134. {
  135. DWORD ret;
  136. bh_assert(mutex);
  137. ret = WaitForSingleObject(*mutex, 0);
  138. if (WAIT_FAILED == ret) {
  139. LOG_FATAL("vm mutex lock failed (ret=%d)!\n", GetLastError());
  140. exit(-1);
  141. }
  142. return ret == WAIT_OBJECT_0 ? BHT_OK : BHT_ERROR;
  143. }
  144. /* Returned error (e.g. ERROR_INVALID_HANDLE) from
  145. unlocking the mutex indicates some logic error present
  146. in the program somewhere.
  147. Don't try to recover error for an existing unknown error.*/
  148. void vm_mutex_unlock(korp_mutex *mutex)
  149. {
  150. BOOL ret;
  151. bh_assert(mutex);
  152. ret = ReleaseMutex(*mutex);
  153. if (FALSE == ret) {
  154. LOG_FATAL("vm mutex unlock failed (ret=%d)!\n", GetLastError());
  155. exit(-1);
  156. }
  157. }
  158. #define BH_SEM_COUNT_MAX 0xFFFF
  159. int _vm_sem_init(korp_sem *sem, unsigned int count)
  160. {
  161. bh_assert(sem);
  162. bh_assert(count <= BH_SEM_COUNT_MAX);
  163. *sem = CreateSemaphore(NULL, count, BH_SEM_COUNT_MAX, NULL);
  164. return (*sem == NULL) ? BHT_ERROR : BHT_OK;
  165. }
  166. int _vm_sem_destroy(korp_sem *sem)
  167. {
  168. return BHT_OK;
  169. }
  170. int _vm_sem_P(korp_sem *sem)
  171. {
  172. DWORD r;
  173. bh_assert(sem);
  174. r = WaitForSingleObject(*sem, INFINITE);
  175. return (r == WAIT_FAILED) ? BHT_ERROR : BHT_OK;
  176. }
  177. int _vm_sem_reltimedP(korp_sem *sem, int mills)
  178. {
  179. DWORD r;
  180. bh_assert(sem);
  181. if (mills == BHT_WAIT_FOREVER)
  182. mills = INFINITE;
  183. r = WaitForSingleObject(*sem, (unsigned int) mills);
  184. switch (r) {
  185. case WAIT_OBJECT_0:
  186. return BHT_OK;
  187. case WAIT_TIMEOUT:
  188. return BHT_TIMEDOUT;
  189. default:
  190. return BHT_ERROR;
  191. }
  192. }
  193. int _vm_sem_V(korp_sem *sem)
  194. {
  195. BOOL r;
  196. bh_assert(sem);
  197. r = ReleaseSemaphore(*sem, 1, NULL);
  198. return (r == FALSE) ? BHT_ERROR : BHT_OK;
  199. }
  200. int _vm_cond_init(korp_cond *cond)
  201. {
  202. bh_assert(cond);
  203. cond->waiting_count = 0;
  204. return vm_sem_init(&cond->s, 0);
  205. }
  206. int _vm_cond_destroy(korp_cond *cond)
  207. {
  208. bh_assert(cond);
  209. return vm_sem_destroy(&cond->s);
  210. }
  211. int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex)
  212. {
  213. bh_assert(cond);
  214. bh_assert(mutex);
  215. cond->waiting_count++;
  216. vm_mutex_unlock(mutex);
  217. if (vm_sem_P(&cond->s) != BHT_OK)
  218. return BHT_ERROR;
  219. vm_mutex_lock(mutex);
  220. cond->waiting_count--;
  221. return BHT_OK;
  222. }
  223. int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills)
  224. {
  225. int r;
  226. bh_assert(cond);
  227. bh_assert(mutex);
  228. cond->waiting_count++;
  229. vm_mutex_unlock(mutex);
  230. r = vm_sem_reltimedP(&cond->s, mills);
  231. if ((r != BHT_OK) && (r != BHT_TIMEDOUT))
  232. return BHT_ERROR;
  233. vm_mutex_lock(mutex);
  234. cond->waiting_count--;
  235. return r;
  236. }
  237. int _vm_cond_signal(korp_cond *cond)
  238. {
  239. bh_assert(cond);
  240. if (cond->waiting_count == 0)
  241. return BHT_OK;
  242. if (vm_sem_V(&cond->s) != BHT_OK)
  243. return BHT_ERROR;
  244. return BHT_OK;
  245. }
  246. int _vm_cond_broadcast(korp_cond *cond)
  247. {
  248. /* FIXME: use pthread's API to implement this and above
  249. functions. */
  250. unsigned count = cond->waiting_count;
  251. for (; count > 0; count--)
  252. vm_sem_V(&cond->s);
  253. return BHT_OK;
  254. }
  255. int _vm_thread_cancel(korp_tid thread)
  256. {
  257. /* FIXME: implement this with Windows API. */
  258. return 0;
  259. }
  260. int _vm_thread_join(korp_tid thread, void **value_ptr)
  261. {
  262. /* FIXME: implement this with Windows API. */
  263. return 0;
  264. }
  265. int _vm_thread_detach(korp_tid thread)
  266. {
  267. /* FIXME: implement this with Windows API. */
  268. return 0;
  269. }