Fix atomic.wait, get wasi_ctx exit code and thread mgr issues (#2024)
- Remove notify_stale_threads_on_exception and change atomic.wait to be interruptible by keep waiting and checking every one second, like the implementation of poll_oneoff in libc-wasi - Wait all other threads exit and then get wasi exit_code to avoid getting invalid value - Inherit suspend_flags of parent thread while creating new thread to avoid terminated flag isn't set for new thread - Fix wasi-threads test case update_shared_data_and_alloc_heap - Add "Lib wasi-threads enabled" prompt for cmake - Fix aot get exception, use aot_copy_exception instead
This commit is contained in:
@ -2331,12 +2331,6 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
|
||||
if (exec_env) {
|
||||
wasm_cluster_spread_exception(exec_env, exception ? false : true);
|
||||
}
|
||||
#if WASM_ENABLE_SHARED_MEMORY
|
||||
if (exception) {
|
||||
notify_stale_threads_on_exception(
|
||||
(WASMModuleInstanceCommon *)module_inst);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
(void)exec_env;
|
||||
#endif
|
||||
@ -3144,6 +3138,21 @@ uint32_t
|
||||
wasm_runtime_get_wasi_exit_code(WASMModuleInstanceCommon *module_inst)
|
||||
{
|
||||
WASIContext *wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
WASMCluster *cluster;
|
||||
WASMExecEnv *exec_env;
|
||||
|
||||
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
|
||||
if (exec_env && (cluster = wasm_exec_env_get_cluster(exec_env))) {
|
||||
/**
|
||||
* The main thread may exit earlier than other threads, and
|
||||
* the exit_code of wasi_ctx may be changed by other thread
|
||||
* when it runs into wasi_proc_exit, here we wait until all
|
||||
* other threads exit to avoid getting invalid exit_code.
|
||||
*/
|
||||
wasm_cluster_wait_for_all_except_self(cluster, exec_env);
|
||||
}
|
||||
#endif
|
||||
return wasi_ctx->exit_code;
|
||||
}
|
||||
|
||||
|
||||
@ -106,61 +106,6 @@ search_module(WASMModuleCommon *module)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
wait_map_address_count_callback(void *key, void *value,
|
||||
void *p_total_elem_count)
|
||||
{
|
||||
*(uint32 *)p_total_elem_count = *(uint32 *)p_total_elem_count + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
create_list_of_waiter_addresses(void *key, void *value, void *user_data)
|
||||
{
|
||||
AtomicWaitAddressArgs *data = (AtomicWaitAddressArgs *)user_data;
|
||||
data->addr[data->index++] = key;
|
||||
}
|
||||
|
||||
void
|
||||
notify_stale_threads_on_exception(WASMModuleInstanceCommon *module_inst)
|
||||
{
|
||||
AtomicWaitAddressArgs args = { 0 };
|
||||
uint32 i = 0, total_elem_count = 0;
|
||||
uint64 total_elem_count_size = 0;
|
||||
|
||||
os_mutex_lock(&wait_map_lock); /* Make the two traversals atomic */
|
||||
|
||||
/* count number of addresses in wait_map */
|
||||
bh_hash_map_traverse(wait_map, wait_map_address_count_callback,
|
||||
(void *)&total_elem_count);
|
||||
|
||||
if (!total_elem_count) {
|
||||
os_mutex_unlock(&wait_map_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate memory */
|
||||
total_elem_count_size = (uint64)sizeof(void *) * total_elem_count;
|
||||
if (total_elem_count_size >= UINT32_MAX
|
||||
|| !(args.addr = wasm_runtime_malloc((uint32)total_elem_count_size))) {
|
||||
LOG_ERROR(
|
||||
"failed to allocate memory for list of atomic wait addresses");
|
||||
os_mutex_unlock(&wait_map_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* set values in list of addresses */
|
||||
bh_hash_map_traverse(wait_map, create_list_of_waiter_addresses, &args);
|
||||
os_mutex_unlock(&wait_map_lock);
|
||||
|
||||
/* notify */
|
||||
for (i = 0; i < args.index; i++) {
|
||||
wasm_runtime_atomic_notify(module_inst, args.addr[i], UINT32_MAX);
|
||||
}
|
||||
|
||||
/* free memory allocated to args data */
|
||||
wasm_runtime_free(args.addr);
|
||||
}
|
||||
|
||||
WASMSharedMemNode *
|
||||
wasm_module_get_shared_memory(WASMModuleCommon *module)
|
||||
{
|
||||
@ -413,7 +358,9 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
AtomicWaitInfo *wait_info;
|
||||
AtomicWaitNode *wait_node;
|
||||
WASMSharedMemNode *node;
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
WASMExecEnv *exec_env;
|
||||
#endif
|
||||
bool check_ret, is_timeout, no_wait;
|
||||
|
||||
bh_assert(module->module_type == Wasm_Module_Bytecode
|
||||
@ -489,14 +436,47 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
/* condition wait start */
|
||||
os_mutex_lock(&wait_node->wait_lock);
|
||||
|
||||
if (!no_wait
|
||||
if (!no_wait) {
|
||||
/* unit of timeout is nsec, convert it to usec */
|
||||
uint64 timeout_left = (uint64)timeout / 1000, timeout_wait;
|
||||
uint64 timeout_1sec = 1e6;
|
||||
|
||||
while (1) {
|
||||
if (timeout < 0) {
|
||||
/* wait forever until it is notified or terminatied
|
||||
here we keep waiting and checking every second */
|
||||
os_cond_reltimedwait(&wait_node->wait_cond,
|
||||
&wait_node->wait_lock,
|
||||
(uint64)timeout_1sec);
|
||||
if (wait_node->status
|
||||
== S_NOTIFIED /* notified by atomic.notify */
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
&& !wasm_cluster_is_thread_terminated(exec_env)
|
||||
/* terminated by other thread */
|
||||
|| wasm_cluster_is_thread_terminated(exec_env)
|
||||
#endif
|
||||
) {
|
||||
os_cond_reltimedwait(&wait_node->wait_cond, &wait_node->wait_lock,
|
||||
timeout < 0 ? BHT_WAIT_FOREVER
|
||||
: (uint64)timeout / 1000);
|
||||
) {
|
||||
break;
|
||||
}
|
||||
/* continue to wait */
|
||||
}
|
||||
else {
|
||||
timeout_wait =
|
||||
timeout_left < timeout_1sec ? timeout_left : timeout_1sec;
|
||||
os_cond_reltimedwait(&wait_node->wait_cond,
|
||||
&wait_node->wait_lock, timeout_wait);
|
||||
if (wait_node->status
|
||||
== S_NOTIFIED /* notified by atomic.notify */
|
||||
|| timeout_left <= timeout_wait /* time out */
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
/* terminated by other thread */
|
||||
|| wasm_cluster_is_thread_terminated(exec_env)
|
||||
#endif
|
||||
) {
|
||||
break;
|
||||
}
|
||||
timeout_left -= timeout_wait;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is_timeout = wait_node->status == S_WAITING ? true : false;
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
#define _WASM_SHARED_MEMORY_H
|
||||
|
||||
#include "bh_common.h"
|
||||
#include "wasm_exec_env.h"
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
#include "wasm_runtime.h"
|
||||
#endif
|
||||
@ -40,9 +39,6 @@ wasm_shared_memory_init();
|
||||
void
|
||||
wasm_shared_memory_destroy();
|
||||
|
||||
void
|
||||
notify_stale_threads_on_exception(WASMModuleInstanceCommon *module);
|
||||
|
||||
WASMSharedMemNode *
|
||||
wasm_module_get_shared_memory(WASMModuleCommon *module);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user