diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 0aa2d641..82676ae2 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -8,6 +8,10 @@ #include "bh_platform.h" #include "mem_alloc.h" +#if WASM_ENABLE_SHARED_MEMORY != 0 +#include "../common/wasm_shared_memory.h" +#endif + typedef enum Memory_Mode { MEMORY_MODE_UNKNOWN = 0, MEMORY_MODE_POOL, @@ -506,7 +510,7 @@ wasm_get_default_memory(WASMModuleInstance *module_inst) #ifndef OS_ENABLE_HW_BOUND_CHECK bool -wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) +wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) { WASMMemoryInstance *memory = wasm_get_default_memory(module); uint8 *memory_data_old, *memory_data_new, *heap_data_old; @@ -624,7 +628,7 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) } #else bool -wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) +wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) { WASMMemoryInstance *memory = wasm_get_default_memory(module); uint32 num_bytes_per_page, total_size_old; @@ -697,3 +701,59 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) return true; } #endif /* end of OS_ENABLE_HW_BOUND_CHECK */ + +bool +wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) +{ + bool ret = false; + +#if WASM_ENABLE_SHARED_MEMORY != 0 + WASMSharedMemNode *node = + wasm_module_get_shared_memory((WASMModuleCommon *)module->module); + if (node) + os_mutex_lock(&node->shared_mem_lock); +#endif + ret = wasm_enlarge_memory_internal(module, inc_page_count); +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (node) + os_mutex_unlock(&node->shared_mem_lock); +#endif + + return ret; +} + +#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ + || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ + || WASM_ENABLE_BULK_MEMORY != 0 +uint32 +wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node) +{ + uint32 num_bytes_per_page; +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (node) + os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock); +#endif + num_bytes_per_page = memory->num_bytes_per_page; +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (node) + os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock); +#endif + return num_bytes_per_page; +} + +uint32 +wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node) +{ + uint32 linear_mem_size; +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (node) + os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock); +#endif + linear_mem_size = memory->num_bytes_per_page * memory->cur_page_count; +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (node) + os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock); +#endif + return linear_mem_size; +} +#endif \ No newline at end of file diff --git a/core/iwasm/common/wasm_memory.h b/core/iwasm/common/wasm_memory.h index b5f3f78c..1324742f 100644 --- a/core/iwasm/common/wasm_memory.h +++ b/core/iwasm/common/wasm_memory.h @@ -8,6 +8,7 @@ #include "bh_common.h" #include "../include/wasm_export.h" +#include "../interpreter/wasm_runtime.h" #ifdef __cplusplus extern "C" { @@ -23,6 +24,16 @@ wasm_runtime_memory_destroy(); unsigned wasm_runtime_memory_pool_size(); +#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ + || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ + || WASM_ENABLE_BULK_MEMORY != 0 +uint32 +wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node); + +uint32 +wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node); +#endif + #ifdef __cplusplus } #endif diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 0b09a9db..e92370c7 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -194,7 +194,7 @@ runtime_signal_handler(void *sig_addr) else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr && (uint8 *)sig_addr < exec_env_tls->exce_check_guard_page + page_size) { - bh_assert(wasm_get_exception(module_inst)); + bh_assert(wasm_copy_exception(module_inst, NULL)); os_longjmp(jmpbuf_node->jmpbuf, 1); } } @@ -250,7 +250,7 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info) else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr && (uint8 *)sig_addr < exec_env_tls->exce_check_guard_page + page_size) { - bh_assert(wasm_get_exception(module_inst)); + bh_assert(wasm_copy_exception(module_inst, NULL)); if (module_inst->module_type == Wasm_Module_Bytecode) { return EXCEPTION_CONTINUE_SEARCH; } @@ -1870,14 +1870,15 @@ static bool clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm) { #if WASM_ENABLE_LIBC_WASI != 0 - const char *exception; + bool has_exception; + char exception[EXCEPTION_BUF_LEN]; WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); - exception = wasm_get_exception(module_inst); - if (exception && !strcmp(exception, "Exception: wasi proc exit")) { + has_exception = wasm_copy_exception(module_inst, exception); + if (has_exception && !strcmp(exception, "Exception: wasi proc exit")) { /* The "wasi proc exit" exception is thrown by native lib to let wasm app exit, which is a normal behavior, we clear the exception here. And just clear the exception of current @@ -2306,6 +2307,12 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) { WASMExecEnv *exec_env = NULL; +#if WASM_ENABLE_SHARED_MEMORY != 0 + WASMSharedMemNode *node = + wasm_module_get_shared_memory((WASMModuleCommon *)module_inst->module); + if (node) + os_mutex_lock(&node->shared_mem_lock); +#endif if (exception) { snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception), "Exception: %s", exception); @@ -2313,6 +2320,10 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) else { module_inst->cur_exception[0] = '\0'; } +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (node) + os_mutex_unlock(&node->shared_mem_lock); +#endif #if WASM_ENABLE_THREAD_MGR != 0 exec_env = @@ -2373,6 +2384,36 @@ wasm_get_exception(WASMModuleInstance *module_inst) return module_inst->cur_exception; } +bool +wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf) +{ + bool has_exception = false; + +#if WASM_ENABLE_SHARED_MEMORY != 0 + WASMSharedMemNode *node = + wasm_module_get_shared_memory((WASMModuleCommon *)module_inst->module); + if (node) + os_mutex_lock(&node->shared_mem_lock); +#endif + if (module_inst->cur_exception[0] != '\0') { + /* NULL is passed if the caller is not interested in getting the + * exception content, but only in knowing if an exception has been + * raised + */ + if (exception_buf != NULL) + bh_memcpy_s(exception_buf, sizeof(module_inst->cur_exception), + module_inst->cur_exception, + sizeof(module_inst->cur_exception)); + has_exception = true; + } +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (node) + os_mutex_unlock(&node->shared_mem_lock); +#endif + + return has_exception; +} + void wasm_runtime_set_exception(WASMModuleInstanceCommon *module_inst_comm, const char *exception) @@ -2394,6 +2435,17 @@ wasm_runtime_get_exception(WASMModuleInstanceCommon *module_inst_comm) return wasm_get_exception(module_inst); } +bool +wasm_runtime_copy_exception(WASMModuleInstanceCommon *module_inst_comm, + char *exception_buf) +{ + WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; + + bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode + || module_inst_comm->module_type == Wasm_Module_AoT); + return wasm_copy_exception(module_inst, exception_buf); +} + void wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst_comm) { @@ -3317,7 +3369,7 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, } } - ret = !wasm_runtime_get_exception(module) ? true : false; + ret = !wasm_runtime_copy_exception(module, NULL); fail: if (argv1 != argv_buf) @@ -3792,7 +3844,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, } exec_env->attachment = NULL; - ret = !wasm_runtime_get_exception(module) ? true : false; + ret = !wasm_runtime_copy_exception(module, NULL); fail: if (argv1 != argv_buf) @@ -4006,7 +4058,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, } exec_env->attachment = NULL; - ret = !wasm_runtime_get_exception(module) ? true : false; + ret = !wasm_runtime_copy_exception(module, NULL); fail: if (argv1 != argv_buf) @@ -4333,7 +4385,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, } exec_env->attachment = NULL; - ret = !wasm_runtime_get_exception(module) ? true : false; + ret = !wasm_runtime_copy_exception(module, NULL); fail: if (argv1 != argv_buf) wasm_runtime_free(argv1); diff --git a/core/iwasm/common/wasm_shared_memory.c b/core/iwasm/common/wasm_shared_memory.c index 6295de01..eb66f2f0 100644 --- a/core/iwasm/common/wasm_shared_memory.c +++ b/core/iwasm/common/wasm_shared_memory.c @@ -37,6 +37,7 @@ typedef struct AtomicWaitAddressArgs { /* Atomic wait map */ static HashMap *wait_map; +static korp_mutex wait_map_lock; static uint32 wait_address_hash(void *address); @@ -52,11 +53,18 @@ wasm_shared_memory_init() { if (os_mutex_init(&shared_memory_list_lock) != 0) return false; + + if (os_mutex_init(&wait_map_lock) != 0) { + os_mutex_destroy(&shared_memory_list_lock); + return false; + } + /* wait map not exists, create new map */ if (!(wait_map = bh_hash_map_create(32, true, (HashFunc)wait_address_hash, (KeyEqualFunc)wait_address_equal, NULL, destroy_wait_info))) { os_mutex_destroy(&shared_memory_list_lock); + os_mutex_destroy(&wait_map_lock); return false; } @@ -67,6 +75,7 @@ void wasm_shared_memory_destroy() { os_mutex_destroy(&shared_memory_list_lock); + os_mutex_destroy(&wait_map_lock); if (wait_map) { bh_hash_map_destroy(wait_map); } @@ -113,14 +122,14 @@ notify_stale_threads_on_exception(WASMModuleInstanceCommon *module_inst) uint32 i = 0, total_elem_count = 0; uint64 total_elem_count_size = 0; - os_mutex_lock(&shared_memory_list_lock); + 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(&shared_memory_list_lock); + os_mutex_unlock(&wait_map_lock); return; } @@ -130,13 +139,13 @@ notify_stale_threads_on_exception(WASMModuleInstanceCommon *module_inst) || !(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(&shared_memory_list_lock); + 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(&shared_memory_list_lock); + os_mutex_unlock(&wait_map_lock); /* notify */ for (i = 0; i < args.index; i++) { @@ -276,9 +285,11 @@ notify_wait_list(bh_list *wait_list, uint32 count) bh_assert(node); next = bh_list_elem_next(node); + os_mutex_lock(&node->wait_lock); node->status = S_NOTIFIED; /* wakeup */ os_cond_signal(&node->wait_cond); + os_mutex_unlock(&node->wait_lock); node = next; } @@ -292,13 +303,13 @@ acquire_wait_info(void *address, bool create) AtomicWaitInfo *wait_info = NULL; bh_list_status ret; - os_mutex_lock(&shared_memory_list_lock); + os_mutex_lock(&wait_map_lock); /* Make find + insert atomic */ if (address) wait_info = (AtomicWaitInfo *)bh_hash_map_find(wait_map, address); if (!create) { - os_mutex_unlock(&shared_memory_list_lock); + os_mutex_unlock(&wait_map_lock); return wait_info; } @@ -325,7 +336,7 @@ acquire_wait_info(void *address, bool create) } } - os_mutex_unlock(&shared_memory_list_lock); + os_mutex_unlock(&wait_map_lock); bh_assert(wait_info); (void)ret; @@ -338,7 +349,7 @@ fail2: wasm_runtime_free(wait_info); fail1: - os_mutex_unlock(&shared_memory_list_lock); + os_mutex_unlock(&wait_map_lock); return NULL; } @@ -365,17 +376,16 @@ destroy_wait_info(void *wait_info) } } -static void -release_wait_info(HashMap *wait_map_, AtomicWaitInfo *wait_info, void *address) +static bool +map_remove_wait_info(HashMap *wait_map_, AtomicWaitInfo *wait_info, + void *address) { - os_mutex_lock(&shared_memory_list_lock); - - if (wait_info->wait_list->len == 0) { - bh_hash_map_remove(wait_map_, address, NULL, NULL); - destroy_wait_info(wait_info); + if (wait_info->wait_list->len > 0) { + return false; } - os_mutex_unlock(&shared_memory_list_lock); + bh_hash_map_remove(wait_map_, address, NULL, NULL); + return true; } uint32 @@ -386,12 +396,12 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, AtomicWaitInfo *wait_info; AtomicWaitNode *wait_node; WASMSharedMemNode *node; - bool check_ret, is_timeout, no_wait; + bool check_ret, is_timeout, no_wait, removed_from_map; bh_assert(module->module_type == Wasm_Module_Bytecode || module->module_type == Wasm_Module_AoT); - if (wasm_get_exception(module_inst)) { + if (wasm_copy_exception(module_inst, NULL)) { return -1; } @@ -416,8 +426,6 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, return -1; } - os_mutex_lock(&wait_info->wait_list_lock); - node = search_module((WASMModuleCommon *)module_inst->module); os_mutex_lock(&node->shared_mem_lock); no_wait = (!wait64 && *(uint32 *)address != (uint32)expect) @@ -425,7 +433,6 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, os_mutex_unlock(&node->shared_mem_lock); if (no_wait) { - os_mutex_unlock(&wait_info->wait_list_lock); return 1; } else { @@ -433,33 +440,29 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) { wasm_runtime_set_exception(module, "failed to create wait node"); - os_mutex_unlock(&wait_info->wait_list_lock); return -1; } memset(wait_node, 0, sizeof(AtomicWaitNode)); if (0 != os_mutex_init(&wait_node->wait_lock)) { wasm_runtime_free(wait_node); - os_mutex_unlock(&wait_info->wait_list_lock); return -1; } if (0 != os_cond_init(&wait_node->wait_cond)) { os_mutex_destroy(&wait_node->wait_lock); wasm_runtime_free(wait_node); - os_mutex_unlock(&wait_info->wait_list_lock); return -1; } wait_node->status = S_WAITING; - + os_mutex_lock(&wait_info->wait_list_lock); ret = bh_list_insert(wait_info->wait_list, wait_node); + os_mutex_unlock(&wait_info->wait_list_lock); bh_assert(ret == BH_LIST_SUCCESS); (void)ret; } - os_mutex_unlock(&wait_info->wait_list_lock); - /* condition wait start */ os_mutex_lock(&wait_node->wait_lock); @@ -467,23 +470,26 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, timeout < 0 ? BHT_WAIT_FOREVER : (uint64)timeout / 1000); + is_timeout = wait_node->status == S_WAITING ? true : false; os_mutex_unlock(&wait_node->wait_lock); - /* Check the wait node status */ + os_mutex_lock(&node->shared_mem_lock); os_mutex_lock(&wait_info->wait_list_lock); + check_ret = is_wait_node_exists(wait_info->wait_list, wait_node); bh_assert(check_ret); - is_timeout = wait_node->status == S_WAITING ? true : false; - + /* Remove wait node */ bh_list_remove(wait_info->wait_list, wait_node); os_mutex_destroy(&wait_node->wait_lock); os_cond_destroy(&wait_node->wait_cond); wasm_runtime_free(wait_node); - os_mutex_unlock(&wait_info->wait_list_lock); - os_mutex_lock(&node->shared_mem_lock); - release_wait_info(wait_map, wait_info, address); + /* Release wait info if no wait nodes attached */ + removed_from_map = map_remove_wait_info(wait_map, wait_info, address); + os_mutex_unlock(&wait_info->wait_list_lock); + if (removed_from_map) + destroy_wait_info(wait_info); os_mutex_unlock(&node->shared_mem_lock); (void)check_ret; @@ -518,16 +524,20 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address, } wait_info = acquire_wait_info(address, false); - if (node) - os_mutex_unlock(&node->shared_mem_lock); /* Nobody wait on this address */ - if (!wait_info) + if (!wait_info) { + if (node) + os_mutex_unlock(&node->shared_mem_lock); return 0; + } os_mutex_lock(&wait_info->wait_list_lock); notify_result = notify_wait_list(wait_info->wait_list, count); os_mutex_unlock(&wait_info->wait_list_lock); + if (node) + os_mutex_unlock(&node->shared_mem_lock); + return notify_result; } diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 5f1072fa..9927d1b2 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -8,6 +8,7 @@ #include "wasm_runtime.h" #include "wasm_opcode.h" #include "wasm_loader.h" +#include "wasm_memory.h" #include "../common/wasm_exec_env.h" #if WASM_ENABLE_SHARED_MEMORY != 0 #include "../common/wasm_shared_memory.h" @@ -954,7 +955,7 @@ fast_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, WASMFunctionInstance *cur_func = module_inst->e->functions + func_idx; wasm_interp_call_func_native(module_inst, exec_env, cur_func, prev_frame); - return wasm_get_exception(module_inst) ? false : true; + return wasm_copy_exception(module_inst, NULL) ? false : true; } #endif @@ -1023,7 +1024,7 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst; /* transfer exception if it is thrown */ - if (wasm_get_exception(sub_module_inst)) { + if (wasm_copy_exception(sub_module_inst, NULL)) { bh_memcpy_s(module_inst->cur_exception, sizeof(module_inst->cur_exception), sub_module_inst->cur_exception, @@ -1126,14 +1127,22 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { +#if WASM_ENABLE_SHARED_MEMORY != 0 + WASMSharedMemNode *node = + wasm_module_get_shared_memory((WASMModuleCommon *)module->module); +#else + void *node = NULL; +#endif + WASMMemoryInstance *memory = wasm_get_default_memory(module); uint8 *global_data = module->global_data; #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ || WASM_ENABLE_BULK_MEMORY != 0 - uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0; + uint32 num_bytes_per_page = + memory ? wasm_get_num_bytes_per_page(memory, node) : 0; uint32 linear_mem_size = - memory ? num_bytes_per_page * memory->cur_page_count : 0; + memory ? wasm_get_linear_memory_size(memory, node) : 0; #endif WASMType **wasm_types = module->module->types; WASMGlobalInstance *globals = module->e->globals, *global; @@ -1157,11 +1166,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 cache_index, type_index, param_cell_num, cell_num; uint8 value_type; -#if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module->module); -#endif - #if WASM_ENABLE_DEBUG_INTERP != 0 uint8 *frame_ip_orig = NULL; WASMDebugInstance *debug_instance = wasm_exec_env_get_instance(exec_env); @@ -3859,7 +3863,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (memory) linear_mem_size = num_bytes_per_page * memory->cur_page_count; #endif - if (wasm_get_exception(module)) + if (wasm_copy_exception(module, NULL)) goto got_exception; } else { @@ -4002,7 +4006,7 @@ fast_jit_call_func_bytecode(WASMModuleInstance *module_inst, module_inst->fast_jit_func_ptrs[func_idx_non_import]); bh_assert(action == JIT_INTERP_ACTION_NORMAL || (action == JIT_INTERP_ACTION_THROWN - && wasm_runtime_get_exception(exec_env->module_inst))); + && wasm_runtime_copy_exception(exec_env->module_inst, NULL))); /* Get the return values form info.out.ret */ if (func_type->result_count) { @@ -4137,7 +4141,7 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL, argv, argc, argv); - return ret && !wasm_get_exception(module_inst) ? true : false; + return ret && !wasm_copy_exception(module_inst, NULL) ? true : false; } } #endif /* end of WASM_ENABLE_JIT != 0 */ @@ -4157,6 +4161,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num); unsigned i; bool copy_argv_from_frame = true; + char exception[EXCEPTION_BUF_LEN]; if (argc < function->param_cell_num) { char buf[128]; @@ -4267,7 +4272,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, } /* Output the return value to the caller */ - if (!wasm_get_exception(module_inst)) { + if (!wasm_copy_exception(module_inst, NULL)) { if (copy_argv_from_frame) { for (i = 0; i < function->ret_cell_num; i++) { argv[i] = *(frame->sp + i - function->ret_cell_num); @@ -4280,7 +4285,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, wasm_interp_dump_call_stack(exec_env, true, NULL, 0); } #endif - LOG_DEBUG("meet an exception %s", wasm_get_exception(module_inst)); + wasm_copy_exception(module_inst, exception); + LOG_DEBUG("meet an exception %s", exception); } wasm_exec_env_set_cur_frame(exec_env, prev_frame); diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 34cb45c8..bd347fcd 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -8,6 +8,7 @@ #include "wasm_runtime.h" #include "wasm_opcode.h" #include "wasm_loader.h" +#include "wasm_memory.h" #include "../common/wasm_exec_env.h" #if WASM_ENABLE_SHARED_MEMORY != 0 #include "../common/wasm_shared_memory.h" @@ -1042,7 +1043,7 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst; /* transfer exception if it is thrown */ - if (wasm_get_exception(sub_module_inst)) { + if (wasm_copy_exception(sub_module_inst, NULL)) { bh_memcpy_s(module_inst->cur_exception, sizeof(module_inst->cur_exception), sub_module_inst->cur_exception, @@ -1154,13 +1155,22 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { +#if WASM_ENABLE_SHARED_MEMORY != 0 + WASMSharedMemNode *node = + wasm_module_get_shared_memory((WASMModuleCommon *)module->module); +#else + void *node = NULL; +#endif + WASMMemoryInstance *memory = wasm_get_default_memory(module); + #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ || WASM_ENABLE_BULK_MEMORY != 0 - uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0; + uint32 num_bytes_per_page = + memory ? wasm_get_num_bytes_per_page(memory, node) : 0; uint32 linear_mem_size = - memory ? num_bytes_per_page * memory->cur_page_count : 0; + memory ? wasm_get_linear_memory_size(memory, node) : 0; #endif uint8 *global_data = module->global_data; WASMGlobalInstance *globals = module->e ? module->e->globals : NULL; @@ -1186,11 +1196,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 local_idx, local_offset, global_idx; uint8 opcode, local_type, *global_addr; -#if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module->module); -#endif - #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OPCODE(op) &&HANDLE_##op DEFINE_GOTO_TABLE(const void *, handle_table); @@ -3797,7 +3802,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (memory) linear_mem_size = num_bytes_per_page * memory->cur_page_count; #endif - if (wasm_get_exception(module)) + if (wasm_copy_exception(module, NULL)) goto got_exception; } else { @@ -3908,6 +3913,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, /* This frame won't be used by JITed code, so only allocate interp frame here. */ unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num); + char exception[EXCEPTION_BUF_LEN]; if (argc < function->param_cell_num) { char buf[128]; @@ -3973,7 +3979,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, } /* Output the return value to the caller */ - if (!wasm_get_exception(module_inst)) { + if (!wasm_copy_exception(module_inst, NULL)) { for (i = 0; i < function->ret_cell_num; i++) argv[i] = *(frame->lp + i); } @@ -3983,7 +3989,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, wasm_interp_dump_call_stack(exec_env, true, NULL, 0); } #endif - LOG_DEBUG("meet an exception %s", wasm_get_exception(module_inst)); + wasm_copy_exception(module_inst, exception); + LOG_DEBUG("meet an exception %s", exception); } wasm_exec_env_set_cur_frame(exec_env, prev_frame); diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 28de0017..6f55ff74 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2243,6 +2243,8 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst, #ifdef BH_PLATFORM_WINDOWS const char *exce; int result; + bool has_exception; + char exception[EXCEPTION_BUF_LEN]; #endif bool ret = true; @@ -2275,14 +2277,14 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst, #else __try { wasm_interp_call_wasm(module_inst, exec_env, function, argc, argv); - } __except (wasm_get_exception(module_inst) + } __except (wasm_copy_exception(module_inst, NULL) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { /* exception was thrown in wasm_exception_handler */ ret = false; } - if ((exce = wasm_get_exception(module_inst)) - && strstr(exce, "native stack overflow")) { + has_exception = wasm_copy_exception(module_inst, exception); + if (has_exception && strstr(exception, "native stack overflow")) { /* After a stack overflow, the stack was left in a damaged state, let the CRT repair it */ result = _resetstkoflw(); @@ -2336,7 +2338,7 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, wasm_exec_env_set_thread_info(exec_env); interp_call_wasm(module_inst, exec_env, function, argc, argv); - return !wasm_get_exception(module_inst) ? true : false; + return !wasm_copy_exception(module_inst, NULL); } bool @@ -2509,6 +2511,12 @@ wasm_module_free(WASMModuleInstance *module_inst, uint32 ptr) return; } +#if WASM_ENABLE_SHARED_MEMORY != 0 + WASMSharedMemNode *node = wasm_module_get_shared_memory( + (WASMModuleCommon *)module_inst->module); + if (node) + os_mutex_lock(&node->shared_mem_lock); +#endif addr = memory->memory_data + ptr; if (memory->heap_handle && memory->heap_data <= addr @@ -2521,6 +2529,10 @@ wasm_module_free(WASMModuleInstance *module_inst, uint32 ptr) execute_free_function(module_inst, module_inst->e->free_function, ptr); } +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (node) + os_mutex_unlock(&node->shared_mem_lock); +#endif } } @@ -2633,7 +2645,7 @@ call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, interp_call_wasm(module_inst, exec_env, func_inst, argc, argv); - return !wasm_get_exception(module_inst) ? true : false; + return !wasm_copy_exception(module_inst, NULL); got_exception: return false; diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index bf231ad6..1767c540 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -19,6 +19,8 @@ extern "C" { #endif +#define EXCEPTION_BUF_LEN 128 + typedef struct WASMModuleInstance WASMModuleInstance; typedef struct WASMFunctionInstance WASMFunctionInstance; typedef struct WASMMemoryInstance WASMMemoryInstance; @@ -282,7 +284,7 @@ struct WASMModuleInstance { DefPointer(WASMExportTabInstance *, export_tables); /* The exception buffer of wasm interpreter for current thread. */ - char cur_exception[128]; + char cur_exception[EXCEPTION_BUF_LEN]; /* The WASM module or AOT module, for AOTModuleInstance, it denotes `AOTModule *` */ @@ -444,6 +446,15 @@ wasm_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id); const char * wasm_get_exception(WASMModuleInstance *module); +/** + * @brief Copy exception in buffer passed as parameter. Thread-safe version of + * `wasm_get_exception()` + * @note Buffer size must be no smaller than EXCEPTION_BUF_LEN + * @return true if exception found + */ +bool +wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf); + uint32 wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size, void **p_native_addr); diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index c2021805..1fe3cde0 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -16,6 +16,10 @@ #include "debug_engine.h" #endif +#if WASM_ENABLE_SHARED_MEMORY != 0 +#include "wasm_shared_memory.h" +#endif + typedef struct { bh_list_link l; void (*destroy_cb)(WASMCluster *); @@ -826,15 +830,18 @@ clusters_have_exec_env(WASMExecEnv *exec_env) WASMExecEnv *node; while (cluster) { + os_mutex_lock(&cluster->lock); node = bh_list_first_elem(&cluster->exec_env_list); while (node) { if (node == exec_env) { bh_assert(exec_env->cluster == cluster); + os_mutex_unlock(&cluster->lock); return true; } node = bh_list_elem_next(node); } + os_mutex_unlock(&cluster->lock); cluster = bh_list_elem_next(cluster); } @@ -848,13 +855,11 @@ wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val) korp_tid handle; os_mutex_lock(&cluster_list_lock); - os_mutex_lock(&exec_env->cluster->lock); if (!clusters_have_exec_env(exec_env) || exec_env->thread_is_detached) { /* Invalid thread, thread has exited or thread has been detached */ if (ret_val) *ret_val = NULL; - os_mutex_unlock(&exec_env->cluster->lock); os_mutex_unlock(&cluster_list_lock); return 0; } @@ -864,7 +869,6 @@ wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val) handle = exec_env->handle; os_mutex_unlock(&exec_env->wait_lock); - os_mutex_unlock(&exec_env->cluster->lock); os_mutex_unlock(&cluster_list_lock); return os_thread_join(handle, ret_val); @@ -1146,12 +1150,22 @@ set_exception_visitor(void *node, void *user_data) (WASMModuleInstance *)get_module_inst(curr_exec_env); /* Only spread non "wasi proc exit" exception */ +#if WASM_ENABLE_SHARED_MEMORY != 0 + WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory( + (WASMModuleCommon *)curr_wasm_inst->module); + if (shared_mem_node) + os_mutex_lock(&shared_mem_node->shared_mem_lock); +#endif if (!strstr(wasm_inst->cur_exception, "wasi proc exit")) { bh_memcpy_s(curr_wasm_inst->cur_exception, sizeof(curr_wasm_inst->cur_exception), wasm_inst->cur_exception, sizeof(wasm_inst->cur_exception)); } +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (shared_mem_node) + os_mutex_unlock(&shared_mem_node->shared_mem_lock); +#endif /* Terminate the thread so it can exit from dead loops */ set_thread_cancel_flags(curr_exec_env); @@ -1168,7 +1182,17 @@ clear_exception_visitor(void *node, void *user_data) WASMModuleInstance *curr_wasm_inst = (WASMModuleInstance *)get_module_inst(curr_exec_env); +#if WASM_ENABLE_SHARED_MEMORY != 0 + WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory( + (WASMModuleCommon *)curr_wasm_inst->module); + if (shared_mem_node) + os_mutex_lock(&shared_mem_node->shared_mem_lock); +#endif curr_wasm_inst->cur_exception[0] = '\0'; +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (shared_mem_node) + os_mutex_unlock(&shared_mem_node->shared_mem_lock); +#endif } }