bh_thread.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "bh_thread.h"
  6. #include "bh_assert.h"
  7. #include "bh_log.h"
  8. #include "bh_memory.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. struct bh_thread_data;
  12. typedef struct bh_thread_wait_node {
  13. aos_sem_t sem;
  14. bh_thread_wait_list next;
  15. } bh_thread_wait_node;
  16. typedef struct bh_thread_data {
  17. /* Thread body */
  18. aos_task_t thread;
  19. /* Thread start routine */
  20. thread_start_routine_t start_routine;
  21. /* Thread start routine argument */
  22. void *arg;
  23. /* Thread local root */
  24. void *tlr;
  25. /* Wait node of current thread */
  26. bh_thread_wait_node wait_node;
  27. /* Lock for waiting list */
  28. aos_mutex_t wait_list_lock;
  29. /* Waiting list of other threads who are joining this thread */
  30. bh_thread_wait_list thread_wait_list;
  31. } bh_thread_data;
  32. static bool is_thread_sys_inited = false;
  33. /* Thread data of supervisor thread */
  34. static bh_thread_data supervisor_thread_data;
  35. /* Thread data key */
  36. static aos_task_key_t thread_data_key;
  37. /* Thread name index */
  38. static int thread_name_index;
  39. int
  40. _vm_thread_sys_init()
  41. {
  42. if (is_thread_sys_inited)
  43. return BHT_OK;
  44. if (aos_task_key_create(&thread_data_key) != 0)
  45. return BHT_ERROR;
  46. /* Initialize supervisor thread data */
  47. memset(&supervisor_thread_data, 0, sizeof(supervisor_thread_data));
  48. if (aos_sem_new(&supervisor_thread_data.wait_node.sem, 1) != 0) {
  49. aos_task_key_delete(thread_data_key);
  50. return BHT_ERROR;
  51. }
  52. if (aos_task_setspecific(thread_data_key, &supervisor_thread_data)) {
  53. aos_sem_free(&supervisor_thread_data.wait_node.sem);
  54. aos_task_key_delete(thread_data_key);
  55. return BHT_ERROR;
  56. }
  57. is_thread_sys_inited = true;
  58. return BHT_OK;
  59. }
  60. void
  61. vm_thread_sys_destroy()
  62. {
  63. if (is_thread_sys_inited) {
  64. aos_task_key_delete(thread_data_key);
  65. aos_sem_free(&supervisor_thread_data.wait_node.sem);
  66. is_thread_sys_inited = false;
  67. }
  68. }
  69. static bh_thread_data *
  70. thread_data_current()
  71. {
  72. return aos_task_getspecific(thread_data_key);
  73. }
  74. static void
  75. vm_thread_cleanup(void)
  76. {
  77. bh_thread_data *thread_data = thread_data_current();
  78. bh_thread_wait_list thread_wait_list;
  79. aos_mutex_t *wait_list_lock;
  80. aos_sem_t *wait_node_sem;
  81. bh_assert(thread_data != NULL);
  82. wait_list_lock = &thread_data->wait_list_lock;
  83. thread_wait_list = thread_data->thread_wait_list;
  84. wait_node_sem = &thread_data->wait_node.sem;
  85. /* Free thread data firstly */
  86. bh_free(thread_data);
  87. aos_mutex_lock(wait_list_lock, AOS_WAIT_FOREVER);
  88. if (thread_wait_list) {
  89. /* Signal each joining thread */
  90. bh_thread_wait_list head = thread_wait_list;
  91. while (head) {
  92. bh_thread_wait_list next = head->next;
  93. aos_sem_signal(&head->sem);
  94. head = next;
  95. }
  96. }
  97. aos_mutex_unlock(wait_list_lock);
  98. /* Free sem and lock */
  99. aos_sem_free(wait_node_sem);
  100. aos_mutex_free(wait_list_lock);
  101. }
  102. static void
  103. vm_thread_wrapper(void *arg)
  104. {
  105. bh_thread_data *thread_data = arg;
  106. /* Set thread custom data */
  107. if (!aos_task_setspecific(thread_data_key, thread_data))
  108. thread_data->start_routine(thread_data->arg);
  109. vm_thread_cleanup();
  110. }
  111. int
  112. _vm_thread_create(korp_tid *p_tid, thread_start_routine_t start,
  113. void *arg, unsigned int stack_size)
  114. {
  115. return _vm_thread_create_with_prio(p_tid, start, arg, stack_size,
  116. BH_THREAD_DEFAULT_PRIORITY);
  117. }
  118. int
  119. _vm_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start,
  120. void *arg, unsigned int stack_size, int prio)
  121. {
  122. bh_thread_data *thread_data;
  123. char thread_name[32];
  124. if (!p_tid || !stack_size)
  125. return BHT_ERROR;
  126. /* Create and initialize thread data */
  127. if (!(thread_data = bh_malloc(sizeof(bh_thread_data))))
  128. return BHT_ERROR;
  129. memset(thread_data, 0, sizeof(bh_thread_data));
  130. thread_data->start_routine = start;
  131. thread_data->arg = arg;
  132. if (aos_sem_new(&thread_data->wait_node.sem, 1) != 0)
  133. goto fail1;
  134. if (aos_mutex_new(&thread_data->wait_list_lock))
  135. goto fail2;
  136. snprintf(thread_name, sizeof(thread_name), "%s%d",
  137. "wasm-thread-", ++thread_name_index);
  138. /* Create the thread */
  139. if (aos_task_new_ext((aos_task_t*)thread_data, thread_name,
  140. vm_thread_wrapper, thread_data,
  141. stack_size, prio))
  142. goto fail3;
  143. aos_msleep(10);
  144. *p_tid = (korp_tid)thread_data;
  145. return BHT_OK;
  146. fail3:
  147. aos_mutex_free(&thread_data->wait_list_lock);
  148. fail2:
  149. aos_sem_free(&thread_data->wait_node.sem);
  150. fail1:
  151. bh_free(thread_data);
  152. return BHT_ERROR;
  153. }
  154. korp_tid
  155. _vm_self_thread()
  156. {
  157. return (korp_tid)aos_task_getspecific(thread_data_key);
  158. }
  159. void
  160. vm_thread_exit(void * code)
  161. {
  162. vm_thread_cleanup();
  163. aos_task_exit((int)(intptr_t)code);
  164. }
  165. int
  166. _vm_thread_cancel (korp_tid thread)
  167. {
  168. /* TODO */
  169. return 0;
  170. }
  171. int
  172. _vm_thread_join (korp_tid thread, void **value_ptr, int mills)
  173. {
  174. (void)value_ptr;
  175. bh_thread_data *thread_data, *curr_thread_data;
  176. /* Get thread data of current thread */
  177. curr_thread_data = thread_data_current();
  178. curr_thread_data->wait_node.next = NULL;
  179. /* Get thread data */
  180. thread_data = (bh_thread_data*)thread;
  181. aos_mutex_lock(&thread_data->wait_list_lock, AOS_WAIT_FOREVER);
  182. if (!thread_data->thread_wait_list)
  183. thread_data->thread_wait_list = &curr_thread_data->wait_node;
  184. else {
  185. /* Add to end of waiting list */
  186. bh_thread_wait_node *p = thread_data->thread_wait_list;
  187. while (p->next)
  188. p = p->next;
  189. p->next = &curr_thread_data->wait_node;
  190. }
  191. aos_mutex_unlock(&thread_data->wait_list_lock);
  192. /* Wait the sem */
  193. aos_sem_wait(&curr_thread_data->wait_node.sem, mills);
  194. return BHT_OK;
  195. }
  196. int
  197. _vm_thread_detach (korp_tid thread)
  198. {
  199. (void)thread;
  200. return BHT_OK;
  201. }
  202. void *
  203. _vm_tls_get(unsigned idx)
  204. {
  205. (void)idx;
  206. bh_thread_data *thread_data;
  207. bh_assert (idx == 0);
  208. thread_data = thread_data_current();
  209. return thread_data ? thread_data->tlr : NULL;
  210. }
  211. int
  212. _vm_tls_put(unsigned idx, void * tls)
  213. {
  214. bh_thread_data *thread_data;
  215. (void)idx;
  216. bh_assert (idx == 0);
  217. thread_data = thread_data_current();
  218. bh_assert (thread_data != NULL);
  219. thread_data->tlr = tls;
  220. return BHT_OK;
  221. }
  222. int
  223. _vm_mutex_init(korp_mutex *mutex)
  224. {
  225. return aos_mutex_new(mutex) == 0 ? BHT_OK : BHT_ERROR;
  226. }
  227. int
  228. _vm_recursive_mutex_init(korp_mutex *mutex)
  229. {
  230. return aos_mutex_new(mutex) == 0 ? BHT_OK : BHT_ERROR;
  231. }
  232. int
  233. _vm_mutex_destroy(korp_mutex *mutex)
  234. {
  235. aos_mutex_free(mutex);
  236. return BHT_OK;
  237. }
  238. void
  239. vm_mutex_lock(korp_mutex *mutex)
  240. {
  241. aos_mutex_lock(mutex, AOS_WAIT_FOREVER);
  242. }
  243. int
  244. vm_mutex_trylock(korp_mutex *mutex)
  245. {
  246. return aos_mutex_lock(mutex, AOS_NO_WAIT);
  247. }
  248. void vm_mutex_unlock(korp_mutex *mutex)
  249. {
  250. aos_mutex_unlock(mutex);
  251. }
  252. int _vm_sem_init(korp_sem* sem, unsigned int c)
  253. {
  254. return aos_sem_new(sem, c) == 0 ? BHT_OK : BHT_ERROR;
  255. }
  256. int _vm_sem_destroy(korp_sem *sem)
  257. {
  258. aos_sem_free(sem);
  259. return BHT_OK;
  260. }
  261. int _vm_sem_wait(korp_sem *sem)
  262. {
  263. return aos_sem_wait(sem, AOS_WAIT_FOREVER);
  264. }
  265. int _vm_sem_reltimedwait(korp_sem *sem, int mills)
  266. {
  267. return aos_sem_wait(sem, mills);
  268. }
  269. int _vm_sem_post(korp_sem *sem)
  270. {
  271. aos_sem_signal(sem);
  272. return BHT_OK;
  273. }
  274. int
  275. _vm_cond_init(korp_cond *cond)
  276. {
  277. if (aos_mutex_new(&cond->wait_list_lock) != 0)
  278. return BHT_ERROR;
  279. cond->thread_wait_list = NULL;
  280. return BHT_OK;
  281. }
  282. int
  283. _vm_cond_destroy(korp_cond *cond)
  284. {
  285. aos_mutex_free(&cond->wait_list_lock);
  286. return BHT_OK;
  287. }
  288. static int
  289. vm_cond_wait_internal(korp_cond *cond, korp_mutex *mutex,
  290. bool timed, int mills)
  291. {
  292. bh_thread_wait_node *node = &thread_data_current()->wait_node;
  293. node->next = NULL;
  294. aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
  295. if (!cond->thread_wait_list)
  296. cond->thread_wait_list = node;
  297. else {
  298. /* Add to end of wait list */
  299. bh_thread_wait_node *p = cond->thread_wait_list;
  300. while (p->next)
  301. p = p->next;
  302. p->next = node;
  303. }
  304. aos_mutex_unlock(&cond->wait_list_lock);
  305. /* Unlock mutex, wait sem and lock mutex again */
  306. aos_mutex_unlock(mutex);
  307. aos_sem_wait(&node->sem, timed ? mills : AOS_WAIT_FOREVER);
  308. aos_mutex_lock(mutex, AOS_WAIT_FOREVER);
  309. /* Remove wait node from wait list */
  310. aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
  311. if (cond->thread_wait_list == node)
  312. cond->thread_wait_list = node->next;
  313. else {
  314. /* Remove from the wait list */
  315. bh_thread_wait_node *p = cond->thread_wait_list;
  316. while (p->next != node)
  317. p = p->next;
  318. p->next = node->next;
  319. }
  320. aos_mutex_unlock(&cond->wait_list_lock);
  321. return BHT_OK;
  322. }
  323. int
  324. _vm_cond_wait(korp_cond *cond, korp_mutex *mutex)
  325. {
  326. return vm_cond_wait_internal(cond, mutex, false, 0);
  327. }
  328. int
  329. _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills)
  330. {
  331. return vm_cond_wait_internal(cond, mutex, true, mills);
  332. }
  333. int
  334. _vm_cond_signal(korp_cond *cond)
  335. {
  336. /* Signal the head wait node of wait list */
  337. aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
  338. if (cond->thread_wait_list)
  339. aos_sem_signal(&cond->thread_wait_list->sem);
  340. aos_mutex_unlock(&cond->wait_list_lock);
  341. return BHT_OK;
  342. }
  343. int
  344. _vm_cond_broadcast (korp_cond *cond)
  345. {
  346. /* Signal each wait node of wait list */
  347. aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
  348. if (cond->thread_wait_list) {
  349. bh_thread_wait_node *p = cond->thread_wait_list;
  350. while (p) {
  351. aos_sem_signal(&p->sem);
  352. p = p->next;
  353. }
  354. }
  355. aos_mutex_unlock(&cond->wait_list_lock);
  356. return BHT_OK;
  357. }