thread_manager.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "thread_manager.h"
  6. #if WASM_ENABLE_INTERP != 0
  7. #include "../interpreter/wasm_runtime.h"
  8. #endif
  9. #if WASM_ENABLE_AOT != 0
  10. #include "../aot/aot_runtime.h"
  11. #endif
  12. #if WASM_ENABLE_DEBUG_INTERP != 0
  13. #include "debug_engine.h"
  14. #endif
  15. typedef struct {
  16. bh_list_link l;
  17. void (*destroy_cb)(WASMCluster *);
  18. } DestroyCallBackNode;
  19. static bh_list destroy_callback_list_head;
  20. static bh_list *const destroy_callback_list = &destroy_callback_list_head;
  21. static bh_list cluster_list_head;
  22. static bh_list *const cluster_list = &cluster_list_head;
  23. static korp_mutex cluster_list_lock;
  24. typedef void (*list_visitor)(void *, void *);
  25. static uint32 cluster_max_thread_num = CLUSTER_MAX_THREAD_NUM;
  26. /* Set the maximum thread number, if this function is not called,
  27. the max thread num is defined by CLUSTER_MAX_THREAD_NUM */
  28. void
  29. wasm_cluster_set_max_thread_num(uint32 num)
  30. {
  31. if (num > 0)
  32. cluster_max_thread_num = num;
  33. }
  34. bool
  35. thread_manager_init()
  36. {
  37. if (bh_list_init(cluster_list) != 0)
  38. return false;
  39. if (os_mutex_init(&cluster_list_lock) != 0)
  40. return false;
  41. return true;
  42. }
  43. void
  44. thread_manager_destroy()
  45. {
  46. WASMCluster *cluster = bh_list_first_elem(cluster_list);
  47. WASMCluster *next;
  48. while (cluster) {
  49. next = bh_list_elem_next(cluster);
  50. wasm_cluster_destroy(cluster);
  51. cluster = next;
  52. }
  53. wasm_cluster_cancel_all_callbacks();
  54. os_mutex_destroy(&cluster_list_lock);
  55. }
  56. static void
  57. traverse_list(bh_list *l, list_visitor visitor, void *user_data)
  58. {
  59. void *next, *node = bh_list_first_elem(l);
  60. while (node) {
  61. next = bh_list_elem_next(node);
  62. visitor(node, user_data);
  63. node = next;
  64. }
  65. }
  66. static bool
  67. allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size)
  68. {
  69. WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
  70. #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0
  71. WASMModuleInstanceCommon *module_inst =
  72. wasm_exec_env_get_module_inst(exec_env);
  73. *start = wasm_runtime_module_malloc(module_inst, cluster->stack_size, NULL);
  74. *size = cluster->stack_size;
  75. return *start != 0;
  76. #else
  77. uint32 i;
  78. /* If the module doesn't have aux stack info,
  79. it can't create any threads */
  80. if (!cluster->stack_segment_occupied)
  81. return false;
  82. os_mutex_lock(&cluster->lock);
  83. for (i = 0; i < cluster_max_thread_num; i++) {
  84. if (!cluster->stack_segment_occupied[i]) {
  85. if (start)
  86. *start = cluster->stack_tops[i];
  87. if (size)
  88. *size = cluster->stack_size;
  89. cluster->stack_segment_occupied[i] = true;
  90. os_mutex_unlock(&cluster->lock);
  91. return true;
  92. }
  93. }
  94. os_mutex_unlock(&cluster->lock);
  95. return false;
  96. #endif
  97. }
  98. static bool
  99. free_aux_stack(WASMExecEnv *exec_env, uint32 start)
  100. {
  101. #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0
  102. WASMModuleInstanceCommon *module_inst =
  103. wasm_exec_env_get_module_inst(exec_env);
  104. wasm_runtime_module_free(module_inst, start);
  105. return true;
  106. #else
  107. WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
  108. uint32 i;
  109. for (i = 0; i < cluster_max_thread_num; i++) {
  110. if (start == cluster->stack_tops[i]) {
  111. os_mutex_lock(&cluster->lock);
  112. cluster->stack_segment_occupied[i] = false;
  113. os_mutex_unlock(&cluster->lock);
  114. return true;
  115. }
  116. }
  117. return false;
  118. #endif
  119. }
  120. WASMCluster *
  121. wasm_cluster_create(WASMExecEnv *exec_env)
  122. {
  123. WASMCluster *cluster;
  124. uint32 aux_stack_start, aux_stack_size;
  125. bh_assert(exec_env->cluster == NULL);
  126. if (!(cluster = wasm_runtime_malloc(sizeof(WASMCluster)))) {
  127. LOG_ERROR("thread manager error: failed to allocate memory");
  128. return NULL;
  129. }
  130. memset(cluster, 0, sizeof(WASMCluster));
  131. exec_env->cluster = cluster;
  132. bh_list_init(&cluster->exec_env_list);
  133. bh_list_insert(&cluster->exec_env_list, exec_env);
  134. if (os_mutex_init(&cluster->lock) != 0) {
  135. wasm_runtime_free(cluster);
  136. LOG_ERROR("thread manager error: failed to init mutex");
  137. return NULL;
  138. }
  139. /* Prepare the aux stack top and size for every thread */
  140. if (!wasm_exec_env_get_aux_stack(exec_env, &aux_stack_start,
  141. &aux_stack_size)) {
  142. LOG_VERBOSE("No aux stack info for this module, can't create thread");
  143. /* If the module don't have aux stack info, don't throw error here,
  144. but remain stack_tops and stack_segment_occupied as NULL */
  145. os_mutex_lock(&cluster_list_lock);
  146. if (bh_list_insert(cluster_list, cluster) != 0) {
  147. os_mutex_unlock(&cluster_list_lock);
  148. goto fail;
  149. }
  150. os_mutex_unlock(&cluster_list_lock);
  151. return cluster;
  152. }
  153. #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0
  154. cluster->stack_size = aux_stack_size;
  155. #else
  156. cluster->stack_size = aux_stack_size / (cluster_max_thread_num + 1);
  157. if (cluster->stack_size < WASM_THREAD_AUX_STACK_SIZE_MIN) {
  158. goto fail;
  159. }
  160. /* Make stack size 16-byte aligned */
  161. cluster->stack_size = cluster->stack_size & (~15);
  162. #endif
  163. /* Set initial aux stack top to the instance and
  164. aux stack boundary to the main exec_env */
  165. if (!wasm_exec_env_set_aux_stack(exec_env, aux_stack_start,
  166. cluster->stack_size))
  167. goto fail;
  168. #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
  169. if (cluster_max_thread_num != 0) {
  170. uint64 total_size = cluster_max_thread_num * sizeof(uint32);
  171. uint32 i;
  172. if (total_size >= UINT32_MAX
  173. || !(cluster->stack_tops =
  174. wasm_runtime_malloc((uint32)total_size))) {
  175. goto fail;
  176. }
  177. memset(cluster->stack_tops, 0, (uint32)total_size);
  178. if (!(cluster->stack_segment_occupied =
  179. wasm_runtime_malloc(cluster_max_thread_num * sizeof(bool)))) {
  180. goto fail;
  181. }
  182. memset(cluster->stack_segment_occupied, 0,
  183. cluster_max_thread_num * sizeof(bool));
  184. /* Reserve space for main instance */
  185. aux_stack_start -= cluster->stack_size;
  186. for (i = 0; i < cluster_max_thread_num; i++) {
  187. cluster->stack_tops[i] = aux_stack_start - cluster->stack_size * i;
  188. }
  189. }
  190. #endif
  191. os_mutex_lock(&cluster_list_lock);
  192. if (bh_list_insert(cluster_list, cluster) != 0) {
  193. os_mutex_unlock(&cluster_list_lock);
  194. goto fail;
  195. }
  196. os_mutex_unlock(&cluster_list_lock);
  197. return cluster;
  198. fail:
  199. if (cluster)
  200. wasm_cluster_destroy(cluster);
  201. return NULL;
  202. }
  203. static void
  204. destroy_cluster_visitor(void *node, void *user_data)
  205. {
  206. DestroyCallBackNode *destroy_node = (DestroyCallBackNode *)node;
  207. WASMCluster *cluster = (WASMCluster *)user_data;
  208. destroy_node->destroy_cb(cluster);
  209. }
  210. void
  211. wasm_cluster_destroy(WASMCluster *cluster)
  212. {
  213. traverse_list(destroy_callback_list, destroy_cluster_visitor,
  214. (void *)cluster);
  215. /* Remove the cluster from the cluster list */
  216. os_mutex_lock(&cluster_list_lock);
  217. bh_list_remove(cluster_list, cluster);
  218. os_mutex_unlock(&cluster_list_lock);
  219. os_mutex_destroy(&cluster->lock);
  220. #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
  221. if (cluster->stack_tops)
  222. wasm_runtime_free(cluster->stack_tops);
  223. if (cluster->stack_segment_occupied)
  224. wasm_runtime_free(cluster->stack_segment_occupied);
  225. #endif
  226. #if WASM_ENABLE_DEBUG_INTERP != 0
  227. wasm_debug_instance_destroy(cluster);
  228. #endif
  229. wasm_runtime_free(cluster);
  230. }
  231. static void
  232. free_node_visitor(void *node, void *user_data)
  233. {
  234. wasm_runtime_free(node);
  235. }
  236. void
  237. wasm_cluster_cancel_all_callbacks()
  238. {
  239. traverse_list(destroy_callback_list, free_node_visitor, NULL);
  240. bh_list_init(destroy_callback_list);
  241. }
  242. WASMCluster *
  243. wasm_exec_env_get_cluster(WASMExecEnv *exec_env)
  244. {
  245. return exec_env->cluster;
  246. }
  247. bool
  248. wasm_cluster_add_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env)
  249. {
  250. bool ret = true;
  251. exec_env->cluster = cluster;
  252. os_mutex_lock(&cluster->lock);
  253. if (cluster->exec_env_list.len == cluster_max_thread_num + 1) {
  254. LOG_ERROR("thread manager error: "
  255. "maximum number of threads exceeded");
  256. ret = false;
  257. }
  258. if (ret && bh_list_insert(&cluster->exec_env_list, exec_env) != 0)
  259. ret = false;
  260. os_mutex_unlock(&cluster->lock);
  261. return ret;
  262. }
  263. bool
  264. wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env)
  265. {
  266. bool ret = true;
  267. bh_assert(exec_env->cluster == cluster);
  268. #if WASM_ENABLE_DEBUG_INTERP != 0
  269. /* Wait for debugger control thread to process the
  270. stop event of this thread */
  271. if (cluster->debug_inst) {
  272. /* lock the debug_inst->wait_lock so
  273. other threads can't fire stop events */
  274. os_mutex_lock(&cluster->debug_inst->wait_lock);
  275. while (cluster->debug_inst->stopped_thread == exec_env) {
  276. /* either wakes up by signal or by 1-second timeout */
  277. os_cond_reltimedwait(&cluster->debug_inst->wait_cond,
  278. &cluster->debug_inst->wait_lock, 1000000);
  279. }
  280. os_mutex_unlock(&cluster->debug_inst->wait_lock);
  281. }
  282. #endif
  283. os_mutex_lock(&cluster->lock);
  284. if (bh_list_remove(&cluster->exec_env_list, exec_env) != 0)
  285. ret = false;
  286. os_mutex_unlock(&cluster->lock);
  287. if (cluster->exec_env_list.len == 0) {
  288. /* exec_env_list empty, destroy the cluster */
  289. wasm_cluster_destroy(cluster);
  290. }
  291. return ret;
  292. }
  293. static WASMExecEnv *
  294. wasm_cluster_search_exec_env(WASMCluster *cluster,
  295. WASMModuleInstanceCommon *module_inst)
  296. {
  297. WASMExecEnv *node = NULL;
  298. os_mutex_lock(&cluster->lock);
  299. node = bh_list_first_elem(&cluster->exec_env_list);
  300. while (node) {
  301. if (node->module_inst == module_inst) {
  302. os_mutex_unlock(&cluster->lock);
  303. return node;
  304. }
  305. node = bh_list_elem_next(node);
  306. }
  307. os_mutex_unlock(&cluster->lock);
  308. return NULL;
  309. }
  310. /* search the global cluster list to find if the given
  311. module instance have a corresponding exec_env */
  312. WASMExecEnv *
  313. wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst)
  314. {
  315. WASMCluster *cluster = NULL;
  316. WASMExecEnv *exec_env = NULL;
  317. os_mutex_lock(&cluster_list_lock);
  318. cluster = bh_list_first_elem(cluster_list);
  319. while (cluster) {
  320. exec_env = wasm_cluster_search_exec_env(cluster, module_inst);
  321. if (exec_env) {
  322. os_mutex_unlock(&cluster_list_lock);
  323. return exec_env;
  324. }
  325. cluster = bh_list_elem_next(cluster);
  326. }
  327. os_mutex_unlock(&cluster_list_lock);
  328. return NULL;
  329. }
  330. WASMExecEnv *
  331. wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
  332. {
  333. WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
  334. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  335. wasm_module_t module;
  336. wasm_module_inst_t new_module_inst;
  337. #if WASM_ENABLE_LIBC_WASI != 0
  338. WASIContext *wasi_ctx;
  339. #endif
  340. WASMExecEnv *new_exec_env;
  341. uint32 aux_stack_start, aux_stack_size;
  342. uint32 stack_size = 8192;
  343. if (!module_inst || !(module = wasm_exec_env_get_module(exec_env))) {
  344. return NULL;
  345. }
  346. #if WASM_ENABLE_INTERP != 0
  347. if (module_inst->module_type == Wasm_Module_Bytecode) {
  348. stack_size =
  349. ((WASMModuleInstance *)module_inst)->default_wasm_stack_size;
  350. }
  351. #endif
  352. #if WASM_ENABLE_AOT != 0
  353. if (module_inst->module_type == Wasm_Module_AoT) {
  354. stack_size =
  355. ((AOTModuleInstance *)module_inst)->default_wasm_stack_size;
  356. }
  357. #endif
  358. if (!(new_module_inst = wasm_runtime_instantiate_internal(
  359. module, true, stack_size, 0, NULL, 0))) {
  360. return NULL;
  361. }
  362. /* Set custom_data to new module instance */
  363. wasm_runtime_set_custom_data_internal(
  364. new_module_inst, wasm_runtime_get_custom_data(module_inst));
  365. #if WASM_ENABLE_LIBC_WASI != 0
  366. wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
  367. wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
  368. #endif
  369. new_exec_env = wasm_exec_env_create_internal(new_module_inst,
  370. exec_env->wasm_stack_size);
  371. if (!new_exec_env)
  372. goto fail1;
  373. if (!allocate_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) {
  374. LOG_ERROR("thread manager error: "
  375. "failed to allocate aux stack space for new thread");
  376. goto fail2;
  377. }
  378. /* Set aux stack for current thread */
  379. if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start,
  380. aux_stack_size)) {
  381. goto fail3;
  382. }
  383. if (!wasm_cluster_add_exec_env(cluster, new_exec_env))
  384. goto fail3;
  385. return new_exec_env;
  386. fail3:
  387. /* free the allocated aux stack space */
  388. free_aux_stack(exec_env, aux_stack_start);
  389. fail2:
  390. wasm_exec_env_destroy(new_exec_env);
  391. fail1:
  392. wasm_runtime_deinstantiate_internal(new_module_inst, true);
  393. return NULL;
  394. }
  395. void
  396. wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env)
  397. {
  398. WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
  399. wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env);
  400. bh_assert(cluster != NULL);
  401. /* Free aux stack space */
  402. free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom);
  403. wasm_cluster_del_exec_env(cluster, exec_env);
  404. wasm_exec_env_destroy_internal(exec_env);
  405. wasm_runtime_deinstantiate_internal(module_inst, true);
  406. }
  407. /* start routine of thread manager */
  408. static void *
  409. thread_manager_start_routine(void *arg)
  410. {
  411. void *ret;
  412. WASMExecEnv *exec_env = (WASMExecEnv *)arg;
  413. WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
  414. WASMModuleInstanceCommon *module_inst =
  415. wasm_exec_env_get_module_inst(exec_env);
  416. bh_assert(cluster != NULL);
  417. bh_assert(module_inst != NULL);
  418. exec_env->handle = os_self_thread();
  419. ret = exec_env->thread_start_routine(exec_env);
  420. #ifdef OS_ENABLE_HW_BOUND_CHECK
  421. if (exec_env->suspend_flags.flags & 0x08)
  422. ret = exec_env->thread_ret_value;
  423. #endif
  424. /* Routine exit */
  425. /* Free aux stack space */
  426. free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom);
  427. /* routine exit, destroy instance */
  428. wasm_runtime_deinstantiate_internal(module_inst, true);
  429. /* Detach the native thread here to ensure the resources are freed */
  430. wasm_cluster_detach_thread(exec_env);
  431. #if WASM_ENABLE_DEBUG_INTERP != 0
  432. wasm_cluster_thread_exited(exec_env);
  433. #endif
  434. /* Remove and destroy exec_env */
  435. wasm_cluster_del_exec_env(cluster, exec_env);
  436. wasm_exec_env_destroy_internal(exec_env);
  437. os_thread_exit(ret);
  438. return ret;
  439. }
  440. int32
  441. wasm_cluster_create_thread(WASMExecEnv *exec_env,
  442. wasm_module_inst_t module_inst,
  443. void *(*thread_routine)(void *), void *arg)
  444. {
  445. WASMCluster *cluster;
  446. WASMExecEnv *new_exec_env;
  447. uint32 aux_stack_start, aux_stack_size;
  448. korp_tid tid;
  449. cluster = wasm_exec_env_get_cluster(exec_env);
  450. bh_assert(cluster);
  451. new_exec_env =
  452. wasm_exec_env_create_internal(module_inst, exec_env->wasm_stack_size);
  453. if (!new_exec_env)
  454. return -1;
  455. if (!allocate_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) {
  456. LOG_ERROR("thread manager error: "
  457. "failed to allocate aux stack space for new thread");
  458. goto fail1;
  459. }
  460. /* Set aux stack for current thread */
  461. if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start,
  462. aux_stack_size)) {
  463. goto fail2;
  464. }
  465. if (!wasm_cluster_add_exec_env(cluster, new_exec_env))
  466. goto fail2;
  467. new_exec_env->thread_start_routine = thread_routine;
  468. new_exec_env->thread_arg = arg;
  469. if (0
  470. != os_thread_create(&tid, thread_manager_start_routine,
  471. (void *)new_exec_env,
  472. APP_THREAD_STACK_SIZE_DEFAULT)) {
  473. goto fail3;
  474. }
  475. return 0;
  476. fail3:
  477. wasm_cluster_del_exec_env(cluster, new_exec_env);
  478. fail2:
  479. /* free the allocated aux stack space */
  480. free_aux_stack(exec_env, aux_stack_start);
  481. fail1:
  482. wasm_exec_env_destroy(new_exec_env);
  483. return -1;
  484. }
  485. #if WASM_ENABLE_DEBUG_INTERP != 0
  486. WASMCurrentEnvStatus *
  487. wasm_cluster_create_exenv_status()
  488. {
  489. WASMCurrentEnvStatus *status;
  490. if (!(status = wasm_runtime_malloc(sizeof(WASMCurrentEnvStatus)))) {
  491. return NULL;
  492. }
  493. status->step_count = 0;
  494. status->signal_flag = 0;
  495. status->running_status = 0;
  496. return status;
  497. }
  498. void
  499. wasm_cluster_destroy_exenv_status(WASMCurrentEnvStatus *status)
  500. {
  501. wasm_runtime_free(status);
  502. }
  503. inline static bool
  504. wasm_cluster_thread_is_running(WASMExecEnv *exec_env)
  505. {
  506. return exec_env->current_status->running_status == STATUS_RUNNING
  507. || exec_env->current_status->running_status == STATUS_STEP;
  508. }
  509. void
  510. wasm_cluster_clear_thread_signal(WASMExecEnv *exec_env)
  511. {
  512. exec_env->current_status->signal_flag = 0;
  513. }
  514. void
  515. wasm_cluster_thread_send_signal(WASMExecEnv *exec_env, uint32 signo)
  516. {
  517. exec_env->current_status->signal_flag = signo;
  518. }
  519. static void
  520. notify_debug_instance(WASMExecEnv *exec_env)
  521. {
  522. WASMCluster *cluster;
  523. cluster = wasm_exec_env_get_cluster(exec_env);
  524. bh_assert(cluster);
  525. if (!cluster->debug_inst) {
  526. return;
  527. }
  528. on_thread_stop_event(cluster->debug_inst, exec_env);
  529. }
  530. static void
  531. notify_debug_instance_exit(WASMExecEnv *exec_env)
  532. {
  533. WASMCluster *cluster;
  534. cluster = wasm_exec_env_get_cluster(exec_env);
  535. bh_assert(cluster);
  536. if (!cluster->debug_inst) {
  537. return;
  538. }
  539. on_thread_exit_event(cluster->debug_inst, exec_env);
  540. }
  541. void
  542. wasm_cluster_thread_stopped(WASMExecEnv *exec_env)
  543. {
  544. exec_env->current_status->running_status = STATUS_STOP;
  545. notify_debug_instance(exec_env);
  546. }
  547. void
  548. wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env)
  549. {
  550. os_mutex_lock(&exec_env->wait_lock);
  551. while (!wasm_cluster_thread_is_running(exec_env)) {
  552. os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock);
  553. }
  554. os_mutex_unlock(&exec_env->wait_lock);
  555. }
  556. void
  557. wasm_cluster_send_signal_all(WASMCluster *cluster, uint32 signo)
  558. {
  559. WASMExecEnv *exec_env = bh_list_first_elem(&cluster->exec_env_list);
  560. while (exec_env) {
  561. wasm_cluster_thread_send_signal(exec_env, signo);
  562. exec_env = bh_list_elem_next(exec_env);
  563. }
  564. }
  565. void
  566. wasm_cluster_thread_exited(WASMExecEnv *exec_env)
  567. {
  568. exec_env->current_status->running_status = STATUS_EXIT;
  569. notify_debug_instance_exit(exec_env);
  570. }
  571. void
  572. wasm_cluster_thread_continue(WASMExecEnv *exec_env)
  573. {
  574. wasm_cluster_clear_thread_signal(exec_env);
  575. exec_env->current_status->running_status = STATUS_RUNNING;
  576. os_cond_signal(&exec_env->wait_cond);
  577. }
  578. void
  579. wasm_cluster_thread_step(WASMExecEnv *exec_env)
  580. {
  581. exec_env->current_status->running_status = STATUS_STEP;
  582. os_cond_signal(&exec_env->wait_cond);
  583. }
  584. void
  585. wasm_cluster_set_debug_inst(WASMCluster *cluster, WASMDebugInstance *inst)
  586. {
  587. cluster->debug_inst = inst;
  588. }
  589. #endif /* end of WASM_ENABLE_DEBUG_INTERP */
  590. /* Check whether the exec_env is in one of all clusters, the caller
  591. should add lock to the cluster list before calling us */
  592. static bool
  593. clusters_have_exec_env(WASMExecEnv *exec_env)
  594. {
  595. WASMCluster *cluster = bh_list_first_elem(cluster_list);
  596. WASMExecEnv *node;
  597. while (cluster) {
  598. node = bh_list_first_elem(&cluster->exec_env_list);
  599. while (node) {
  600. if (node == exec_env) {
  601. bh_assert(exec_env->cluster == cluster);
  602. return true;
  603. }
  604. node = bh_list_elem_next(node);
  605. }
  606. cluster = bh_list_elem_next(cluster);
  607. }
  608. return false;
  609. }
  610. int32
  611. wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val)
  612. {
  613. korp_tid handle;
  614. os_mutex_lock(&cluster_list_lock);
  615. if (!clusters_have_exec_env(exec_env) || exec_env->thread_is_detached) {
  616. /* Invalid thread, thread has exited or thread has been detached */
  617. if (ret_val)
  618. *ret_val = NULL;
  619. os_mutex_unlock(&cluster_list_lock);
  620. return 0;
  621. }
  622. exec_env->wait_count++;
  623. handle = exec_env->handle;
  624. os_mutex_unlock(&cluster_list_lock);
  625. return os_thread_join(handle, ret_val);
  626. }
  627. int32
  628. wasm_cluster_detach_thread(WASMExecEnv *exec_env)
  629. {
  630. int32 ret = 0;
  631. os_mutex_lock(&cluster_list_lock);
  632. if (!clusters_have_exec_env(exec_env)) {
  633. /* Invalid thread or the thread has exited */
  634. os_mutex_unlock(&cluster_list_lock);
  635. return 0;
  636. }
  637. if (exec_env->wait_count == 0 && !exec_env->thread_is_detached) {
  638. /* Only detach current thread when there is no other thread
  639. joining it, otherwise let the system resources for the
  640. thread be released after joining */
  641. ret = os_thread_detach(exec_env->handle);
  642. exec_env->thread_is_detached = true;
  643. }
  644. os_mutex_unlock(&cluster_list_lock);
  645. return ret;
  646. }
  647. void
  648. wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval)
  649. {
  650. WASMCluster *cluster;
  651. #ifdef OS_ENABLE_HW_BOUND_CHECK
  652. if (exec_env->jmpbuf_stack_top) {
  653. /* Store the return value in exec_env */
  654. exec_env->thread_ret_value = retval;
  655. exec_env->suspend_flags.flags |= 0x08;
  656. #ifndef BH_PLATFORM_WINDOWS
  657. /* Pop all jmpbuf_node except the last one */
  658. while (exec_env->jmpbuf_stack_top->prev) {
  659. wasm_exec_env_pop_jmpbuf(exec_env);
  660. }
  661. os_longjmp(exec_env->jmpbuf_stack_top->jmpbuf, 1);
  662. return;
  663. #endif
  664. }
  665. #endif
  666. cluster = wasm_exec_env_get_cluster(exec_env);
  667. bh_assert(cluster);
  668. #if WASM_ENABLE_DEBUG_INTERP != 0
  669. wasm_cluster_clear_thread_signal(exec_env);
  670. wasm_cluster_thread_exited(exec_env);
  671. #endif
  672. /* App exit the thread, free the resources before exit native thread */
  673. /* Free aux stack space */
  674. free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom);
  675. /* Detach the native thread here to ensure the resources are freed */
  676. wasm_cluster_detach_thread(exec_env);
  677. /* Remove and destroy exec_env */
  678. wasm_cluster_del_exec_env(cluster, exec_env);
  679. wasm_exec_env_destroy_internal(exec_env);
  680. os_thread_exit(retval);
  681. }
  682. int32
  683. wasm_cluster_cancel_thread(WASMExecEnv *exec_env)
  684. {
  685. os_mutex_lock(&cluster_list_lock);
  686. if (!clusters_have_exec_env(exec_env)) {
  687. /* Invalid thread or the thread has exited */
  688. os_mutex_unlock(&cluster_list_lock);
  689. return 0;
  690. }
  691. os_mutex_unlock(&cluster_list_lock);
  692. /* Set the termination flag */
  693. #if WASM_ENABLE_DEBUG_INTERP != 0
  694. wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM);
  695. #else
  696. exec_env->suspend_flags.flags |= 0x01;
  697. #endif
  698. return 0;
  699. }
  700. static void
  701. terminate_thread_visitor(void *node, void *user_data)
  702. {
  703. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  704. WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
  705. if (curr_exec_env == exec_env)
  706. return;
  707. wasm_cluster_cancel_thread(curr_exec_env);
  708. wasm_cluster_join_thread(curr_exec_env, NULL);
  709. }
  710. void
  711. wasm_cluster_terminate_all(WASMCluster *cluster)
  712. {
  713. traverse_list(&cluster->exec_env_list, terminate_thread_visitor, NULL);
  714. }
  715. void
  716. wasm_cluster_terminate_all_except_self(WASMCluster *cluster,
  717. WASMExecEnv *exec_env)
  718. {
  719. traverse_list(&cluster->exec_env_list, terminate_thread_visitor,
  720. (void *)exec_env);
  721. }
  722. static void
  723. wait_for_thread_visitor(void *node, void *user_data)
  724. {
  725. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  726. WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
  727. if (curr_exec_env == exec_env)
  728. return;
  729. wasm_cluster_join_thread(curr_exec_env, NULL);
  730. }
  731. void
  732. wams_cluster_wait_for_all(WASMCluster *cluster)
  733. {
  734. traverse_list(&cluster->exec_env_list, wait_for_thread_visitor, NULL);
  735. }
  736. void
  737. wasm_cluster_wait_for_all_except_self(WASMCluster *cluster,
  738. WASMExecEnv *exec_env)
  739. {
  740. traverse_list(&cluster->exec_env_list, wait_for_thread_visitor,
  741. (void *)exec_env);
  742. }
  743. bool
  744. wasm_cluster_register_destroy_callback(void (*callback)(WASMCluster *))
  745. {
  746. DestroyCallBackNode *node;
  747. if (!(node = wasm_runtime_malloc(sizeof(DestroyCallBackNode)))) {
  748. LOG_ERROR("thread manager error: failed to allocate memory");
  749. return false;
  750. }
  751. node->destroy_cb = callback;
  752. bh_list_insert(destroy_callback_list, node);
  753. return true;
  754. }
  755. void
  756. wasm_cluster_suspend_thread(WASMExecEnv *exec_env)
  757. {
  758. /* Set the suspend flag */
  759. exec_env->suspend_flags.flags |= 0x02;
  760. }
  761. static void
  762. suspend_thread_visitor(void *node, void *user_data)
  763. {
  764. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  765. WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
  766. if (curr_exec_env == exec_env)
  767. return;
  768. wasm_cluster_suspend_thread(curr_exec_env);
  769. }
  770. void
  771. wasm_cluster_suspend_all(WASMCluster *cluster)
  772. {
  773. traverse_list(&cluster->exec_env_list, suspend_thread_visitor, NULL);
  774. }
  775. void
  776. wasm_cluster_suspend_all_except_self(WASMCluster *cluster,
  777. WASMExecEnv *exec_env)
  778. {
  779. traverse_list(&cluster->exec_env_list, suspend_thread_visitor,
  780. (void *)exec_env);
  781. }
  782. void
  783. wasm_cluster_resume_thread(WASMExecEnv *exec_env)
  784. {
  785. exec_env->suspend_flags.flags &= ~0x02;
  786. os_cond_signal(&exec_env->wait_cond);
  787. }
  788. static void
  789. resume_thread_visitor(void *node, void *user_data)
  790. {
  791. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  792. wasm_cluster_resume_thread(curr_exec_env);
  793. }
  794. void
  795. wasm_cluster_resume_all(WASMCluster *cluster)
  796. {
  797. traverse_list(&cluster->exec_env_list, resume_thread_visitor, NULL);
  798. }
  799. static void
  800. set_exception_visitor(void *node, void *user_data)
  801. {
  802. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  803. WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
  804. WASMModuleInstanceCommon *module_inst = get_module_inst(exec_env);
  805. WASMModuleInstanceCommon *curr_module_inst = get_module_inst(curr_exec_env);
  806. const char *exception = wasm_runtime_get_exception(module_inst);
  807. /* skip "Exception: " */
  808. exception += 11;
  809. if (curr_exec_env != exec_env) {
  810. curr_module_inst = get_module_inst(curr_exec_env);
  811. wasm_runtime_set_exception(curr_module_inst, exception);
  812. }
  813. }
  814. void
  815. wasm_cluster_spread_exception(WASMExecEnv *exec_env)
  816. {
  817. WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
  818. bh_assert(cluster);
  819. traverse_list(&cluster->exec_env_list, set_exception_visitor, exec_env);
  820. }
  821. static void
  822. set_custom_data_visitor(void *node, void *user_data)
  823. {
  824. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  825. WASMModuleInstanceCommon *module_inst = get_module_inst(curr_exec_env);
  826. wasm_runtime_set_custom_data_internal(module_inst, user_data);
  827. }
  828. void
  829. wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
  830. void *custom_data)
  831. {
  832. WASMExecEnv *exec_env = wasm_clusters_search_exec_env(module_inst);
  833. if (exec_env == NULL) {
  834. /* Maybe threads have not been started yet. */
  835. wasm_runtime_set_custom_data_internal(module_inst, custom_data);
  836. }
  837. else {
  838. WASMCluster *cluster;
  839. cluster = wasm_exec_env_get_cluster(exec_env);
  840. bh_assert(cluster);
  841. traverse_list(&cluster->exec_env_list, set_custom_data_visitor,
  842. custom_data);
  843. }
  844. }