Add/reorganize locks for thread synchronization (#1995)

Attempt to fix data races when using threads.
- Protect access (from multiple threads) to exception and memory
- Fix shared memory lock usage
This commit is contained in:
Enrico Loparco
2023-03-04 01:15:26 +01:00
committed by GitHub
parent 1c44411a97
commit e8d718096d
9 changed files with 274 additions and 81 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);