thread_manager.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294
  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. #if WASM_ENABLE_SHARED_MEMORY != 0
  16. #include "wasm_shared_memory.h"
  17. #endif
  18. typedef struct {
  19. bh_list_link l;
  20. void (*destroy_cb)(WASMCluster *);
  21. } DestroyCallBackNode;
  22. static bh_list destroy_callback_list_head;
  23. static bh_list *const destroy_callback_list = &destroy_callback_list_head;
  24. static bh_list cluster_list_head;
  25. static bh_list *const cluster_list = &cluster_list_head;
  26. static korp_mutex cluster_list_lock;
  27. typedef void (*list_visitor)(void *, void *);
  28. static uint32 cluster_max_thread_num = CLUSTER_MAX_THREAD_NUM;
  29. /* Set the maximum thread number, if this function is not called,
  30. the max thread num is defined by CLUSTER_MAX_THREAD_NUM */
  31. void
  32. wasm_cluster_set_max_thread_num(uint32 num)
  33. {
  34. if (num > 0)
  35. cluster_max_thread_num = num;
  36. }
  37. bool
  38. thread_manager_init()
  39. {
  40. if (bh_list_init(cluster_list) != 0)
  41. return false;
  42. if (os_mutex_init(&cluster_list_lock) != 0)
  43. return false;
  44. return true;
  45. }
  46. void
  47. thread_manager_destroy()
  48. {
  49. WASMCluster *cluster = bh_list_first_elem(cluster_list);
  50. WASMCluster *next;
  51. while (cluster) {
  52. next = bh_list_elem_next(cluster);
  53. wasm_cluster_destroy(cluster);
  54. cluster = next;
  55. }
  56. wasm_cluster_cancel_all_callbacks();
  57. os_mutex_destroy(&cluster_list_lock);
  58. }
  59. static void
  60. traverse_list(bh_list *l, list_visitor visitor, void *user_data)
  61. {
  62. void *next, *node = bh_list_first_elem(l);
  63. while (node) {
  64. next = bh_list_elem_next(node);
  65. visitor(node, user_data);
  66. node = next;
  67. }
  68. }
  69. /* Assumes cluster->lock is locked */
  70. static bool
  71. safe_traverse_exec_env_list(WASMCluster *cluster, list_visitor visitor,
  72. void *user_data)
  73. {
  74. Vector proc_nodes;
  75. void *node;
  76. bool ret = true;
  77. if (!bh_vector_init(&proc_nodes, cluster->exec_env_list.len, sizeof(void *),
  78. false)) {
  79. ret = false;
  80. goto final;
  81. }
  82. node = bh_list_first_elem(&cluster->exec_env_list);
  83. while (node) {
  84. bool already_processed = false;
  85. void *proc_node;
  86. uint32 i;
  87. for (i = 0; i < (uint32)bh_vector_size(&proc_nodes); i++) {
  88. if (!bh_vector_get(&proc_nodes, i, &proc_node)) {
  89. ret = false;
  90. goto final;
  91. }
  92. if (proc_node == node) {
  93. already_processed = true;
  94. break;
  95. }
  96. }
  97. if (already_processed) {
  98. node = bh_list_elem_next(node);
  99. continue;
  100. }
  101. os_mutex_unlock(&cluster->lock);
  102. visitor(node, user_data);
  103. os_mutex_lock(&cluster->lock);
  104. if (!bh_vector_append(&proc_nodes, &node)) {
  105. ret = false;
  106. goto final;
  107. }
  108. node = bh_list_first_elem(&cluster->exec_env_list);
  109. }
  110. final:
  111. bh_vector_destroy(&proc_nodes);
  112. return ret;
  113. }
  114. /* The caller must lock cluster->lock */
  115. static bool
  116. allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size)
  117. {
  118. WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
  119. #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0
  120. WASMModuleInstanceCommon *module_inst =
  121. wasm_exec_env_get_module_inst(exec_env);
  122. uint32 stack_end;
  123. stack_end =
  124. wasm_runtime_module_malloc(module_inst, cluster->stack_size, NULL);
  125. *start = stack_end + cluster->stack_size;
  126. *size = cluster->stack_size;
  127. return stack_end != 0;
  128. #else
  129. uint32 i;
  130. /* If the module doesn't have aux stack info,
  131. it can't create any threads */
  132. if (!cluster->stack_segment_occupied)
  133. return false;
  134. for (i = 0; i < cluster_max_thread_num; i++) {
  135. if (!cluster->stack_segment_occupied[i]) {
  136. if (start)
  137. *start = cluster->stack_tops[i];
  138. if (size)
  139. *size = cluster->stack_size;
  140. cluster->stack_segment_occupied[i] = true;
  141. return true;
  142. }
  143. }
  144. return false;
  145. #endif
  146. }
  147. /* The caller must lock cluster->lock */
  148. static bool
  149. free_aux_stack(WASMExecEnv *exec_env, uint32 start)
  150. {
  151. WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
  152. #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0
  153. WASMModuleInstanceCommon *module_inst =
  154. wasm_exec_env_get_module_inst(exec_env);
  155. if (!wasm_exec_env_is_aux_stack_managed_by_runtime(exec_env)) {
  156. return true;
  157. }
  158. bh_assert(start >= cluster->stack_size);
  159. wasm_runtime_module_free(module_inst, start - cluster->stack_size);
  160. return true;
  161. #else
  162. uint32 i;
  163. for (i = 0; i < cluster_max_thread_num; i++) {
  164. if (start == cluster->stack_tops[i]) {
  165. cluster->stack_segment_occupied[i] = false;
  166. return true;
  167. }
  168. }
  169. return false;
  170. #endif
  171. }
  172. WASMCluster *
  173. wasm_cluster_create(WASMExecEnv *exec_env)
  174. {
  175. WASMCluster *cluster;
  176. uint32 aux_stack_start, aux_stack_size;
  177. bh_assert(exec_env->cluster == NULL);
  178. if (!(cluster = wasm_runtime_malloc(sizeof(WASMCluster)))) {
  179. LOG_ERROR("thread manager error: failed to allocate memory");
  180. return NULL;
  181. }
  182. memset(cluster, 0, sizeof(WASMCluster));
  183. exec_env->cluster = cluster;
  184. bh_list_init(&cluster->exec_env_list);
  185. bh_list_insert(&cluster->exec_env_list, exec_env);
  186. if (os_mutex_init(&cluster->lock) != 0) {
  187. wasm_runtime_free(cluster);
  188. LOG_ERROR("thread manager error: failed to init mutex");
  189. return NULL;
  190. }
  191. /* Prepare the aux stack top and size for every thread */
  192. if (!wasm_exec_env_get_aux_stack(exec_env, &aux_stack_start,
  193. &aux_stack_size)) {
  194. #if WASM_ENABLE_LIB_WASI_THREADS == 0
  195. LOG_VERBOSE("No aux stack info for this module, can't create thread");
  196. #endif
  197. /* If the module don't have aux stack info, don't throw error here,
  198. but remain stack_tops and stack_segment_occupied as NULL */
  199. os_mutex_lock(&cluster_list_lock);
  200. if (bh_list_insert(cluster_list, cluster) != 0) {
  201. os_mutex_unlock(&cluster_list_lock);
  202. goto fail;
  203. }
  204. os_mutex_unlock(&cluster_list_lock);
  205. return cluster;
  206. }
  207. #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0
  208. cluster->stack_size = aux_stack_size;
  209. #else
  210. cluster->stack_size = aux_stack_size / (cluster_max_thread_num + 1);
  211. if (cluster->stack_size < WASM_THREAD_AUX_STACK_SIZE_MIN) {
  212. goto fail;
  213. }
  214. /* Make stack size 16-byte aligned */
  215. cluster->stack_size = cluster->stack_size & (~15);
  216. #endif
  217. /* Set initial aux stack top to the instance and
  218. aux stack boundary to the main exec_env */
  219. if (!wasm_exec_env_set_aux_stack(exec_env, aux_stack_start,
  220. cluster->stack_size))
  221. goto fail;
  222. #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
  223. if (cluster_max_thread_num != 0) {
  224. uint64 total_size = cluster_max_thread_num * sizeof(uint32);
  225. uint32 i;
  226. if (total_size >= UINT32_MAX
  227. || !(cluster->stack_tops =
  228. wasm_runtime_malloc((uint32)total_size))) {
  229. goto fail;
  230. }
  231. memset(cluster->stack_tops, 0, (uint32)total_size);
  232. if (!(cluster->stack_segment_occupied =
  233. wasm_runtime_malloc(cluster_max_thread_num * sizeof(bool)))) {
  234. goto fail;
  235. }
  236. memset(cluster->stack_segment_occupied, 0,
  237. cluster_max_thread_num * sizeof(bool));
  238. /* Reserve space for main instance */
  239. aux_stack_start -= cluster->stack_size;
  240. for (i = 0; i < cluster_max_thread_num; i++) {
  241. cluster->stack_tops[i] = aux_stack_start - cluster->stack_size * i;
  242. }
  243. }
  244. #endif
  245. os_mutex_lock(&cluster_list_lock);
  246. if (bh_list_insert(cluster_list, cluster) != 0) {
  247. os_mutex_unlock(&cluster_list_lock);
  248. goto fail;
  249. }
  250. os_mutex_unlock(&cluster_list_lock);
  251. return cluster;
  252. fail:
  253. if (cluster)
  254. wasm_cluster_destroy(cluster);
  255. return NULL;
  256. }
  257. static void
  258. destroy_cluster_visitor(void *node, void *user_data)
  259. {
  260. DestroyCallBackNode *destroy_node = (DestroyCallBackNode *)node;
  261. WASMCluster *cluster = (WASMCluster *)user_data;
  262. destroy_node->destroy_cb(cluster);
  263. }
  264. void
  265. wasm_cluster_destroy(WASMCluster *cluster)
  266. {
  267. traverse_list(destroy_callback_list, destroy_cluster_visitor,
  268. (void *)cluster);
  269. /* Remove the cluster from the cluster list */
  270. os_mutex_lock(&cluster_list_lock);
  271. bh_list_remove(cluster_list, cluster);
  272. os_mutex_unlock(&cluster_list_lock);
  273. os_mutex_destroy(&cluster->lock);
  274. #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
  275. if (cluster->stack_tops)
  276. wasm_runtime_free(cluster->stack_tops);
  277. if (cluster->stack_segment_occupied)
  278. wasm_runtime_free(cluster->stack_segment_occupied);
  279. #endif
  280. #if WASM_ENABLE_DEBUG_INTERP != 0
  281. wasm_debug_instance_destroy(cluster);
  282. #endif
  283. wasm_runtime_free(cluster);
  284. }
  285. static void
  286. free_node_visitor(void *node, void *user_data)
  287. {
  288. wasm_runtime_free(node);
  289. }
  290. void
  291. wasm_cluster_cancel_all_callbacks()
  292. {
  293. traverse_list(destroy_callback_list, free_node_visitor, NULL);
  294. bh_list_init(destroy_callback_list);
  295. }
  296. WASMCluster *
  297. wasm_exec_env_get_cluster(WASMExecEnv *exec_env)
  298. {
  299. return exec_env->cluster;
  300. }
  301. /* The caller must lock cluster->lock */
  302. static bool
  303. wasm_cluster_add_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env)
  304. {
  305. bool ret = true;
  306. exec_env->cluster = cluster;
  307. if (cluster->exec_env_list.len == cluster_max_thread_num + 1) {
  308. LOG_ERROR("thread manager error: "
  309. "maximum number of threads exceeded");
  310. ret = false;
  311. }
  312. if (ret && bh_list_insert(&cluster->exec_env_list, exec_env) != 0)
  313. ret = false;
  314. return ret;
  315. }
  316. /* The caller should lock cluster->lock for thread safety */
  317. bool
  318. wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env)
  319. {
  320. bool ret = true;
  321. bh_assert(exec_env->cluster == cluster);
  322. #if WASM_ENABLE_DEBUG_INTERP != 0
  323. /* Wait for debugger control thread to process the
  324. stop event of this thread */
  325. if (cluster->debug_inst) {
  326. /* lock the debug_inst->wait_lock so
  327. other threads can't fire stop events */
  328. os_mutex_lock(&cluster->debug_inst->wait_lock);
  329. while (cluster->debug_inst->stopped_thread == exec_env) {
  330. /* either wakes up by signal or by 1-second timeout */
  331. os_cond_reltimedwait(&cluster->debug_inst->wait_cond,
  332. &cluster->debug_inst->wait_lock, 1000000);
  333. }
  334. os_mutex_unlock(&cluster->debug_inst->wait_lock);
  335. }
  336. #endif
  337. if (bh_list_remove(&cluster->exec_env_list, exec_env) != 0)
  338. ret = false;
  339. if (cluster->exec_env_list.len == 0) {
  340. /* exec_env_list empty, destroy the cluster */
  341. wasm_cluster_destroy(cluster);
  342. }
  343. return ret;
  344. }
  345. static WASMExecEnv *
  346. wasm_cluster_search_exec_env(WASMCluster *cluster,
  347. WASMModuleInstanceCommon *module_inst)
  348. {
  349. WASMExecEnv *node = NULL;
  350. os_mutex_lock(&cluster->lock);
  351. node = bh_list_first_elem(&cluster->exec_env_list);
  352. while (node) {
  353. if (node->module_inst == module_inst) {
  354. os_mutex_unlock(&cluster->lock);
  355. return node;
  356. }
  357. node = bh_list_elem_next(node);
  358. }
  359. os_mutex_unlock(&cluster->lock);
  360. return NULL;
  361. }
  362. /* search the global cluster list to find if the given
  363. module instance have a corresponding exec_env */
  364. WASMExecEnv *
  365. wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst)
  366. {
  367. WASMCluster *cluster = NULL;
  368. WASMExecEnv *exec_env = NULL;
  369. os_mutex_lock(&cluster_list_lock);
  370. cluster = bh_list_first_elem(cluster_list);
  371. while (cluster) {
  372. exec_env = wasm_cluster_search_exec_env(cluster, module_inst);
  373. if (exec_env) {
  374. os_mutex_unlock(&cluster_list_lock);
  375. return exec_env;
  376. }
  377. cluster = bh_list_elem_next(cluster);
  378. }
  379. os_mutex_unlock(&cluster_list_lock);
  380. return NULL;
  381. }
  382. WASMExecEnv *
  383. wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
  384. {
  385. WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
  386. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  387. wasm_module_t module;
  388. wasm_module_inst_t new_module_inst;
  389. #if WASM_ENABLE_LIBC_WASI != 0
  390. WASIContext *wasi_ctx;
  391. #endif
  392. WASMExecEnv *new_exec_env;
  393. uint32 aux_stack_start, aux_stack_size;
  394. uint32 stack_size = 8192;
  395. if (!module_inst || !(module = wasm_exec_env_get_module(exec_env))) {
  396. return NULL;
  397. }
  398. os_mutex_lock(&cluster->lock);
  399. if (cluster->has_exception || cluster->processing) {
  400. goto fail1;
  401. }
  402. #if WASM_ENABLE_INTERP != 0
  403. if (module_inst->module_type == Wasm_Module_Bytecode) {
  404. stack_size =
  405. ((WASMModuleInstance *)module_inst)->default_wasm_stack_size;
  406. }
  407. #endif
  408. #if WASM_ENABLE_AOT != 0
  409. if (module_inst->module_type == Wasm_Module_AoT) {
  410. stack_size =
  411. ((AOTModuleInstance *)module_inst)->default_wasm_stack_size;
  412. }
  413. #endif
  414. if (!(new_module_inst = wasm_runtime_instantiate_internal(
  415. module, true, stack_size, 0, NULL, 0))) {
  416. goto fail1;
  417. }
  418. /* Set custom_data to new module instance */
  419. wasm_runtime_set_custom_data_internal(
  420. new_module_inst, wasm_runtime_get_custom_data(module_inst));
  421. #if WASM_ENABLE_LIBC_WASI != 0
  422. wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
  423. wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
  424. #endif
  425. new_exec_env = wasm_exec_env_create_internal(new_module_inst,
  426. exec_env->wasm_stack_size);
  427. if (!new_exec_env)
  428. goto fail2;
  429. if (!allocate_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) {
  430. LOG_ERROR("thread manager error: "
  431. "failed to allocate aux stack space for new thread");
  432. goto fail3;
  433. }
  434. /* Set aux stack for current thread */
  435. if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start,
  436. aux_stack_size)) {
  437. goto fail4;
  438. }
  439. /* Inherit suspend_flags of parent thread */
  440. new_exec_env->suspend_flags.flags = exec_env->suspend_flags.flags;
  441. if (!wasm_cluster_add_exec_env(cluster, new_exec_env))
  442. goto fail4;
  443. os_mutex_unlock(&cluster->lock);
  444. return new_exec_env;
  445. fail4:
  446. /* free the allocated aux stack space */
  447. free_aux_stack(exec_env, aux_stack_start);
  448. fail3:
  449. wasm_exec_env_destroy_internal(new_exec_env);
  450. fail2:
  451. wasm_runtime_deinstantiate_internal(new_module_inst, true);
  452. fail1:
  453. os_mutex_unlock(&cluster->lock);
  454. return NULL;
  455. }
  456. void
  457. wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env)
  458. {
  459. WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
  460. wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env);
  461. bh_assert(cluster != NULL);
  462. os_mutex_lock(&cluster->lock);
  463. /* Free aux stack space */
  464. free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom);
  465. /* Remove exec_env */
  466. wasm_cluster_del_exec_env(cluster, exec_env);
  467. /* Destroy exec_env */
  468. wasm_exec_env_destroy_internal(exec_env);
  469. /* Routine exit, destroy instance */
  470. wasm_runtime_deinstantiate_internal(module_inst, true);
  471. os_mutex_unlock(&cluster->lock);
  472. }
  473. /* start routine of thread manager */
  474. static void *
  475. thread_manager_start_routine(void *arg)
  476. {
  477. void *ret;
  478. WASMExecEnv *exec_env = (WASMExecEnv *)arg;
  479. WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
  480. WASMModuleInstanceCommon *module_inst =
  481. wasm_exec_env_get_module_inst(exec_env);
  482. bh_assert(cluster != NULL);
  483. bh_assert(module_inst != NULL);
  484. os_mutex_lock(&exec_env->wait_lock);
  485. exec_env->handle = os_self_thread();
  486. /* Notify the parent thread to continue running */
  487. os_cond_signal(&exec_env->wait_cond);
  488. os_mutex_unlock(&exec_env->wait_lock);
  489. ret = exec_env->thread_start_routine(exec_env);
  490. #ifdef OS_ENABLE_HW_BOUND_CHECK
  491. os_mutex_lock(&exec_env->wait_lock);
  492. if (exec_env->suspend_flags.flags & 0x08)
  493. ret = exec_env->thread_ret_value;
  494. os_mutex_unlock(&exec_env->wait_lock);
  495. #endif
  496. /* Routine exit */
  497. #if WASM_ENABLE_DEBUG_INTERP != 0
  498. wasm_cluster_thread_exited(exec_env);
  499. #endif
  500. os_mutex_lock(&cluster_list_lock);
  501. os_mutex_lock(&cluster->lock);
  502. /* Detach the native thread here to ensure the resources are freed */
  503. if (exec_env->wait_count == 0 && !exec_env->thread_is_detached) {
  504. /* Only detach current thread when there is no other thread
  505. joining it, otherwise let the system resources for the
  506. thread be released after joining */
  507. os_thread_detach(exec_env->handle);
  508. /* No need to set exec_env->thread_is_detached to true here
  509. since we will exit soon */
  510. }
  511. /* Free aux stack space */
  512. free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom);
  513. /* Remove exec_env */
  514. wasm_cluster_del_exec_env(cluster, exec_env);
  515. /* Destroy exec_env */
  516. wasm_exec_env_destroy_internal(exec_env);
  517. /* Routine exit, destroy instance */
  518. wasm_runtime_deinstantiate_internal(module_inst, true);
  519. os_mutex_unlock(&cluster->lock);
  520. os_mutex_unlock(&cluster_list_lock);
  521. os_thread_exit(ret);
  522. return ret;
  523. }
  524. int32
  525. wasm_cluster_create_thread(WASMExecEnv *exec_env,
  526. wasm_module_inst_t module_inst, bool alloc_aux_stack,
  527. void *(*thread_routine)(void *), void *arg)
  528. {
  529. WASMCluster *cluster;
  530. WASMExecEnv *new_exec_env;
  531. uint32 aux_stack_start = 0, aux_stack_size;
  532. korp_tid tid;
  533. cluster = wasm_exec_env_get_cluster(exec_env);
  534. bh_assert(cluster);
  535. os_mutex_lock(&cluster->lock);
  536. if (cluster->has_exception || cluster->processing) {
  537. goto fail1;
  538. }
  539. new_exec_env =
  540. wasm_exec_env_create_internal(module_inst, exec_env->wasm_stack_size);
  541. if (!new_exec_env)
  542. goto fail1;
  543. if (alloc_aux_stack) {
  544. if (!allocate_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) {
  545. LOG_ERROR("thread manager error: "
  546. "failed to allocate aux stack space for new thread");
  547. goto fail2;
  548. }
  549. /* Set aux stack for current thread */
  550. if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start,
  551. aux_stack_size)) {
  552. goto fail3;
  553. }
  554. }
  555. else {
  556. /* Disable aux stack */
  557. new_exec_env->aux_stack_boundary.boundary = 0;
  558. new_exec_env->aux_stack_bottom.bottom = UINT32_MAX;
  559. }
  560. /* Inherit suspend_flags of parent thread */
  561. new_exec_env->suspend_flags.flags = exec_env->suspend_flags.flags;
  562. if (!wasm_cluster_add_exec_env(cluster, new_exec_env))
  563. goto fail3;
  564. new_exec_env->thread_start_routine = thread_routine;
  565. new_exec_env->thread_arg = arg;
  566. os_mutex_lock(&new_exec_env->wait_lock);
  567. if (0
  568. != os_thread_create(&tid, thread_manager_start_routine,
  569. (void *)new_exec_env,
  570. APP_THREAD_STACK_SIZE_DEFAULT)) {
  571. os_mutex_unlock(&new_exec_env->wait_lock);
  572. goto fail4;
  573. }
  574. /* Wait until the new_exec_env->handle is set to avoid it is
  575. illegally accessed after unlocking cluster->lock */
  576. os_cond_wait(&new_exec_env->wait_cond, &new_exec_env->wait_lock);
  577. os_mutex_unlock(&new_exec_env->wait_lock);
  578. os_mutex_unlock(&cluster->lock);
  579. return 0;
  580. fail4:
  581. wasm_cluster_del_exec_env(cluster, new_exec_env);
  582. fail3:
  583. /* free the allocated aux stack space */
  584. if (alloc_aux_stack)
  585. free_aux_stack(exec_env, aux_stack_start);
  586. fail2:
  587. wasm_exec_env_destroy_internal(new_exec_env);
  588. fail1:
  589. os_mutex_unlock(&cluster->lock);
  590. return -1;
  591. }
  592. #if WASM_ENABLE_DEBUG_INTERP != 0
  593. WASMCurrentEnvStatus *
  594. wasm_cluster_create_exenv_status()
  595. {
  596. WASMCurrentEnvStatus *status;
  597. if (!(status = wasm_runtime_malloc(sizeof(WASMCurrentEnvStatus)))) {
  598. return NULL;
  599. }
  600. status->step_count = 0;
  601. status->signal_flag = 0;
  602. status->running_status = 0;
  603. return status;
  604. }
  605. void
  606. wasm_cluster_destroy_exenv_status(WASMCurrentEnvStatus *status)
  607. {
  608. wasm_runtime_free(status);
  609. }
  610. inline static bool
  611. wasm_cluster_thread_is_running(WASMExecEnv *exec_env)
  612. {
  613. return exec_env->current_status->running_status == STATUS_RUNNING
  614. || exec_env->current_status->running_status == STATUS_STEP;
  615. }
  616. void
  617. wasm_cluster_clear_thread_signal(WASMExecEnv *exec_env)
  618. {
  619. exec_env->current_status->signal_flag = 0;
  620. }
  621. void
  622. wasm_cluster_thread_send_signal(WASMExecEnv *exec_env, uint32 signo)
  623. {
  624. exec_env->current_status->signal_flag = signo;
  625. }
  626. static void
  627. notify_debug_instance(WASMExecEnv *exec_env)
  628. {
  629. WASMCluster *cluster;
  630. cluster = wasm_exec_env_get_cluster(exec_env);
  631. bh_assert(cluster);
  632. if (!cluster->debug_inst) {
  633. return;
  634. }
  635. on_thread_stop_event(cluster->debug_inst, exec_env);
  636. }
  637. static void
  638. notify_debug_instance_exit(WASMExecEnv *exec_env)
  639. {
  640. WASMCluster *cluster;
  641. cluster = wasm_exec_env_get_cluster(exec_env);
  642. bh_assert(cluster);
  643. if (!cluster->debug_inst) {
  644. return;
  645. }
  646. on_thread_exit_event(cluster->debug_inst, exec_env);
  647. }
  648. void
  649. wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env)
  650. {
  651. os_mutex_lock(&exec_env->wait_lock);
  652. /* Wake up debugger thread after we get the lock, otherwise we may miss the
  653. * signal from debugger thread, see
  654. * https://github.com/bytecodealliance/wasm-micro-runtime/issues/1860 */
  655. exec_env->current_status->running_status = STATUS_STOP;
  656. notify_debug_instance(exec_env);
  657. while (!wasm_cluster_thread_is_running(exec_env)) {
  658. os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock);
  659. }
  660. os_mutex_unlock(&exec_env->wait_lock);
  661. }
  662. void
  663. wasm_cluster_send_signal_all(WASMCluster *cluster, uint32 signo)
  664. {
  665. WASMExecEnv *exec_env = bh_list_first_elem(&cluster->exec_env_list);
  666. while (exec_env) {
  667. wasm_cluster_thread_send_signal(exec_env, signo);
  668. exec_env = bh_list_elem_next(exec_env);
  669. }
  670. }
  671. void
  672. wasm_cluster_thread_exited(WASMExecEnv *exec_env)
  673. {
  674. exec_env->current_status->running_status = STATUS_EXIT;
  675. notify_debug_instance_exit(exec_env);
  676. }
  677. void
  678. wasm_cluster_thread_continue(WASMExecEnv *exec_env)
  679. {
  680. os_mutex_lock(&exec_env->wait_lock);
  681. wasm_cluster_clear_thread_signal(exec_env);
  682. exec_env->current_status->running_status = STATUS_RUNNING;
  683. os_cond_signal(&exec_env->wait_cond);
  684. os_mutex_unlock(&exec_env->wait_lock);
  685. }
  686. void
  687. wasm_cluster_thread_step(WASMExecEnv *exec_env)
  688. {
  689. os_mutex_lock(&exec_env->wait_lock);
  690. exec_env->current_status->running_status = STATUS_STEP;
  691. os_cond_signal(&exec_env->wait_cond);
  692. os_mutex_unlock(&exec_env->wait_lock);
  693. }
  694. void
  695. wasm_cluster_set_debug_inst(WASMCluster *cluster, WASMDebugInstance *inst)
  696. {
  697. cluster->debug_inst = inst;
  698. }
  699. #endif /* end of WASM_ENABLE_DEBUG_INTERP */
  700. /* Check whether the exec_env is in one of all clusters, the caller
  701. should add lock to the cluster list before calling us */
  702. static bool
  703. clusters_have_exec_env(WASMExecEnv *exec_env)
  704. {
  705. WASMCluster *cluster = bh_list_first_elem(cluster_list);
  706. WASMExecEnv *node;
  707. while (cluster) {
  708. os_mutex_lock(&cluster->lock);
  709. node = bh_list_first_elem(&cluster->exec_env_list);
  710. while (node) {
  711. if (node == exec_env) {
  712. bh_assert(exec_env->cluster == cluster);
  713. os_mutex_unlock(&cluster->lock);
  714. return true;
  715. }
  716. node = bh_list_elem_next(node);
  717. }
  718. os_mutex_unlock(&cluster->lock);
  719. cluster = bh_list_elem_next(cluster);
  720. }
  721. return false;
  722. }
  723. int32
  724. wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val)
  725. {
  726. korp_tid handle;
  727. os_mutex_lock(&cluster_list_lock);
  728. if (!clusters_have_exec_env(exec_env) || exec_env->thread_is_detached) {
  729. /* Invalid thread, thread has exited or thread has been detached */
  730. if (ret_val)
  731. *ret_val = NULL;
  732. os_mutex_unlock(&cluster_list_lock);
  733. return 0;
  734. }
  735. os_mutex_lock(&exec_env->wait_lock);
  736. exec_env->wait_count++;
  737. handle = exec_env->handle;
  738. os_mutex_unlock(&exec_env->wait_lock);
  739. os_mutex_unlock(&cluster_list_lock);
  740. return os_thread_join(handle, ret_val);
  741. }
  742. int32
  743. wasm_cluster_detach_thread(WASMExecEnv *exec_env)
  744. {
  745. int32 ret = 0;
  746. os_mutex_lock(&cluster_list_lock);
  747. if (!clusters_have_exec_env(exec_env)) {
  748. /* Invalid thread or the thread has exited */
  749. os_mutex_unlock(&cluster_list_lock);
  750. return 0;
  751. }
  752. if (exec_env->wait_count == 0 && !exec_env->thread_is_detached) {
  753. /* Only detach current thread when there is no other thread
  754. joining it, otherwise let the system resources for the
  755. thread be released after joining */
  756. ret = os_thread_detach(exec_env->handle);
  757. exec_env->thread_is_detached = true;
  758. }
  759. os_mutex_unlock(&cluster_list_lock);
  760. return ret;
  761. }
  762. void
  763. wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval)
  764. {
  765. WASMCluster *cluster;
  766. WASMModuleInstanceCommon *module_inst;
  767. #ifdef OS_ENABLE_HW_BOUND_CHECK
  768. if (exec_env->jmpbuf_stack_top) {
  769. /* Store the return value in exec_env */
  770. exec_env->thread_ret_value = retval;
  771. exec_env->suspend_flags.flags |= 0x08;
  772. #ifndef BH_PLATFORM_WINDOWS
  773. /* Pop all jmpbuf_node except the last one */
  774. while (exec_env->jmpbuf_stack_top->prev) {
  775. wasm_exec_env_pop_jmpbuf(exec_env);
  776. }
  777. os_longjmp(exec_env->jmpbuf_stack_top->jmpbuf, 1);
  778. return;
  779. #endif
  780. }
  781. #endif
  782. cluster = wasm_exec_env_get_cluster(exec_env);
  783. bh_assert(cluster);
  784. #if WASM_ENABLE_DEBUG_INTERP != 0
  785. wasm_cluster_clear_thread_signal(exec_env);
  786. wasm_cluster_thread_exited(exec_env);
  787. #endif
  788. /* App exit the thread, free the resources before exit native thread */
  789. os_mutex_lock(&cluster_list_lock);
  790. os_mutex_lock(&cluster->lock);
  791. /* Detach the native thread here to ensure the resources are freed */
  792. if (exec_env->wait_count == 0 && !exec_env->thread_is_detached) {
  793. /* Only detach current thread when there is no other thread
  794. joining it, otherwise let the system resources for the
  795. thread be released after joining */
  796. os_thread_detach(exec_env->handle);
  797. /* No need to set exec_env->thread_is_detached to true here
  798. since we will exit soon */
  799. }
  800. module_inst = exec_env->module_inst;
  801. /* Free aux stack space */
  802. free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom);
  803. /* Remove exec_env */
  804. wasm_cluster_del_exec_env(cluster, exec_env);
  805. /* Destroy exec_env */
  806. wasm_exec_env_destroy_internal(exec_env);
  807. /* Routine exit, destroy instance */
  808. wasm_runtime_deinstantiate_internal(module_inst, true);
  809. os_mutex_unlock(&cluster->lock);
  810. os_mutex_unlock(&cluster_list_lock);
  811. os_thread_exit(retval);
  812. }
  813. static void
  814. set_thread_cancel_flags(WASMExecEnv *exec_env)
  815. {
  816. os_mutex_lock(&exec_env->wait_lock);
  817. /* Set the termination flag */
  818. #if WASM_ENABLE_DEBUG_INTERP != 0
  819. wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM);
  820. #else
  821. exec_env->suspend_flags.flags |= 0x01;
  822. #endif
  823. os_mutex_unlock(&exec_env->wait_lock);
  824. }
  825. int32
  826. wasm_cluster_cancel_thread(WASMExecEnv *exec_env)
  827. {
  828. os_mutex_lock(&cluster_list_lock);
  829. if (!exec_env->cluster) {
  830. os_mutex_unlock(&cluster_list_lock);
  831. return 0;
  832. }
  833. if (!clusters_have_exec_env(exec_env)) {
  834. /* Invalid thread or the thread has exited */
  835. goto final;
  836. }
  837. set_thread_cancel_flags(exec_env);
  838. final:
  839. os_mutex_unlock(&cluster_list_lock);
  840. return 0;
  841. }
  842. static void
  843. terminate_thread_visitor(void *node, void *user_data)
  844. {
  845. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  846. WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
  847. if (curr_exec_env == exec_env)
  848. return;
  849. wasm_cluster_cancel_thread(curr_exec_env);
  850. wasm_cluster_join_thread(curr_exec_env, NULL);
  851. }
  852. void
  853. wasm_cluster_terminate_all(WASMCluster *cluster)
  854. {
  855. os_mutex_lock(&cluster->lock);
  856. cluster->processing = true;
  857. safe_traverse_exec_env_list(cluster, terminate_thread_visitor, NULL);
  858. cluster->processing = false;
  859. os_mutex_unlock(&cluster->lock);
  860. }
  861. void
  862. wasm_cluster_terminate_all_except_self(WASMCluster *cluster,
  863. WASMExecEnv *exec_env)
  864. {
  865. os_mutex_lock(&cluster->lock);
  866. cluster->processing = true;
  867. safe_traverse_exec_env_list(cluster, terminate_thread_visitor,
  868. (void *)exec_env);
  869. cluster->processing = false;
  870. os_mutex_unlock(&cluster->lock);
  871. }
  872. static void
  873. wait_for_thread_visitor(void *node, void *user_data)
  874. {
  875. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  876. WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
  877. if (curr_exec_env == exec_env)
  878. return;
  879. wasm_cluster_join_thread(curr_exec_env, NULL);
  880. }
  881. void
  882. wams_cluster_wait_for_all(WASMCluster *cluster)
  883. {
  884. os_mutex_lock(&cluster->lock);
  885. cluster->processing = true;
  886. safe_traverse_exec_env_list(cluster, wait_for_thread_visitor, NULL);
  887. cluster->processing = false;
  888. os_mutex_unlock(&cluster->lock);
  889. }
  890. void
  891. wasm_cluster_wait_for_all_except_self(WASMCluster *cluster,
  892. WASMExecEnv *exec_env)
  893. {
  894. os_mutex_lock(&cluster->lock);
  895. cluster->processing = true;
  896. safe_traverse_exec_env_list(cluster, wait_for_thread_visitor,
  897. (void *)exec_env);
  898. cluster->processing = false;
  899. os_mutex_unlock(&cluster->lock);
  900. }
  901. bool
  902. wasm_cluster_register_destroy_callback(void (*callback)(WASMCluster *))
  903. {
  904. DestroyCallBackNode *node;
  905. if (!(node = wasm_runtime_malloc(sizeof(DestroyCallBackNode)))) {
  906. LOG_ERROR("thread manager error: failed to allocate memory");
  907. return false;
  908. }
  909. node->destroy_cb = callback;
  910. bh_list_insert(destroy_callback_list, node);
  911. return true;
  912. }
  913. void
  914. wasm_cluster_suspend_thread(WASMExecEnv *exec_env)
  915. {
  916. /* Set the suspend flag */
  917. exec_env->suspend_flags.flags |= 0x02;
  918. }
  919. static void
  920. suspend_thread_visitor(void *node, void *user_data)
  921. {
  922. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  923. WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
  924. if (curr_exec_env == exec_env)
  925. return;
  926. wasm_cluster_suspend_thread(curr_exec_env);
  927. }
  928. void
  929. wasm_cluster_suspend_all(WASMCluster *cluster)
  930. {
  931. os_mutex_lock(&cluster->lock);
  932. traverse_list(&cluster->exec_env_list, suspend_thread_visitor, NULL);
  933. os_mutex_unlock(&cluster->lock);
  934. }
  935. void
  936. wasm_cluster_suspend_all_except_self(WASMCluster *cluster,
  937. WASMExecEnv *exec_env)
  938. {
  939. os_mutex_lock(&cluster->lock);
  940. traverse_list(&cluster->exec_env_list, suspend_thread_visitor,
  941. (void *)exec_env);
  942. os_mutex_unlock(&cluster->lock);
  943. }
  944. void
  945. wasm_cluster_resume_thread(WASMExecEnv *exec_env)
  946. {
  947. exec_env->suspend_flags.flags &= ~0x02;
  948. os_cond_signal(&exec_env->wait_cond);
  949. }
  950. static void
  951. resume_thread_visitor(void *node, void *user_data)
  952. {
  953. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  954. wasm_cluster_resume_thread(curr_exec_env);
  955. }
  956. void
  957. wasm_cluster_resume_all(WASMCluster *cluster)
  958. {
  959. os_mutex_lock(&cluster->lock);
  960. traverse_list(&cluster->exec_env_list, resume_thread_visitor, NULL);
  961. os_mutex_unlock(&cluster->lock);
  962. }
  963. static void
  964. set_exception_visitor(void *node, void *user_data)
  965. {
  966. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  967. WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
  968. WASMModuleInstanceCommon *module_inst = get_module_inst(exec_env);
  969. WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst;
  970. if (curr_exec_env != exec_env) {
  971. WASMModuleInstance *curr_wasm_inst =
  972. (WASMModuleInstance *)get_module_inst(curr_exec_env);
  973. /* Only spread non "wasi proc exit" exception */
  974. #if WASM_ENABLE_SHARED_MEMORY != 0
  975. WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory(
  976. (WASMModuleCommon *)curr_wasm_inst->module);
  977. if (shared_mem_node)
  978. os_mutex_lock(&shared_mem_node->shared_mem_lock);
  979. #endif
  980. if (!strstr(wasm_inst->cur_exception, "wasi proc exit")) {
  981. bh_memcpy_s(curr_wasm_inst->cur_exception,
  982. sizeof(curr_wasm_inst->cur_exception),
  983. wasm_inst->cur_exception,
  984. sizeof(wasm_inst->cur_exception));
  985. }
  986. #if WASM_ENABLE_SHARED_MEMORY != 0
  987. if (shared_mem_node)
  988. os_mutex_unlock(&shared_mem_node->shared_mem_lock);
  989. #endif
  990. /* Terminate the thread so it can exit from dead loops */
  991. set_thread_cancel_flags(curr_exec_env);
  992. }
  993. }
  994. static void
  995. clear_exception_visitor(void *node, void *user_data)
  996. {
  997. WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
  998. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  999. if (curr_exec_env != exec_env) {
  1000. WASMModuleInstance *curr_wasm_inst =
  1001. (WASMModuleInstance *)get_module_inst(curr_exec_env);
  1002. #if WASM_ENABLE_SHARED_MEMORY != 0
  1003. WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory(
  1004. (WASMModuleCommon *)curr_wasm_inst->module);
  1005. if (shared_mem_node)
  1006. os_mutex_lock(&shared_mem_node->shared_mem_lock);
  1007. #endif
  1008. curr_wasm_inst->cur_exception[0] = '\0';
  1009. #if WASM_ENABLE_SHARED_MEMORY != 0
  1010. if (shared_mem_node)
  1011. os_mutex_unlock(&shared_mem_node->shared_mem_lock);
  1012. #endif
  1013. }
  1014. }
  1015. void
  1016. wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear)
  1017. {
  1018. WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
  1019. bh_assert(cluster);
  1020. os_mutex_lock(&cluster->lock);
  1021. cluster->has_exception = !clear;
  1022. traverse_list(&cluster->exec_env_list,
  1023. clear ? clear_exception_visitor : set_exception_visitor,
  1024. exec_env);
  1025. os_mutex_unlock(&cluster->lock);
  1026. }
  1027. static void
  1028. set_custom_data_visitor(void *node, void *user_data)
  1029. {
  1030. WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
  1031. WASMModuleInstanceCommon *module_inst = get_module_inst(curr_exec_env);
  1032. wasm_runtime_set_custom_data_internal(module_inst, user_data);
  1033. }
  1034. void
  1035. wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
  1036. void *custom_data)
  1037. {
  1038. WASMExecEnv *exec_env = wasm_clusters_search_exec_env(module_inst);
  1039. if (exec_env == NULL) {
  1040. /* Maybe threads have not been started yet. */
  1041. wasm_runtime_set_custom_data_internal(module_inst, custom_data);
  1042. }
  1043. else {
  1044. WASMCluster *cluster;
  1045. cluster = wasm_exec_env_get_cluster(exec_env);
  1046. bh_assert(cluster);
  1047. os_mutex_lock(&cluster->lock);
  1048. traverse_list(&cluster->exec_env_list, set_custom_data_visitor,
  1049. custom_data);
  1050. os_mutex_unlock(&cluster->lock);
  1051. }
  1052. }
  1053. bool
  1054. wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env)
  1055. {
  1056. os_mutex_lock(&exec_env->wait_lock);
  1057. bool is_thread_terminated =
  1058. (exec_env->suspend_flags.flags & 0x01) ? true : false;
  1059. os_mutex_unlock(&exec_env->wait_lock);
  1060. return is_thread_terminated;
  1061. }