Merge pull request #2426 from bytecodealliance/main
Merge branch main into dev/wasi-libc-windows
This commit is contained in:
@ -461,4 +461,15 @@
|
||||
#define WASM_CONFIGURABLE_BOUNDS_CHECKS 0
|
||||
#endif
|
||||
|
||||
/* Some chip cannot support external ram with rwx attr at the same time,
|
||||
it has to map it into 2 spaces of idbus and dbus, code in dbus can be
|
||||
read/written and read/executed in ibus. so there are 2 steps to execute
|
||||
the code, first, copy&do relocaiton in dbus space, and second execute
|
||||
it in ibus space, since in the 2 spaces the contents are the same,
|
||||
so we call it bus mirror.
|
||||
*/
|
||||
#ifndef WASM_MEM_DUAL_BUS_MIRROR
|
||||
#define WASM_MEM_DUAL_BUS_MIRROR 0
|
||||
#endif
|
||||
|
||||
#endif /* end of _CONFIG_H_ */
|
||||
|
||||
@ -3013,6 +3013,9 @@ create_sections(AOTModule *module, const uint8 *buf, uint32 size,
|
||||
uint32 section_size;
|
||||
uint64 total_size;
|
||||
uint8 *aot_text;
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
uint8 *mirrored_text;
|
||||
#endif
|
||||
|
||||
if (!resolve_execute_mode(buf, size, &is_indirect_mode, error_buf,
|
||||
error_buf_size)) {
|
||||
@ -3071,8 +3074,17 @@ create_sections(AOTModule *module, const uint8 *buf, uint32 size,
|
||||
bh_assert((uintptr_t)aot_text < INT32_MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
mirrored_text = os_get_dbus_mirror(aot_text);
|
||||
bh_assert(mirrored_text != NULL);
|
||||
bh_memcpy_s(mirrored_text, (uint32)total_size,
|
||||
section->section_body, (uint32)section_size);
|
||||
os_dcache_flush();
|
||||
#else
|
||||
bh_memcpy_s(aot_text, (uint32)total_size,
|
||||
section->section_body, (uint32)section_size);
|
||||
#endif
|
||||
section->section_body = aot_text;
|
||||
destroy_aot_text = true;
|
||||
|
||||
|
||||
@ -339,11 +339,8 @@ memories_deinstantiate(AOTModuleInstance *module_inst)
|
||||
memory_inst = module_inst->memories[i];
|
||||
if (memory_inst) {
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (memory_inst->is_shared) {
|
||||
int32 ref_count = shared_memory_dec_reference(
|
||||
(WASMModuleCommon *)module_inst->module);
|
||||
bh_assert(ref_count >= 0);
|
||||
|
||||
if (shared_memory_is_shared(memory_inst)) {
|
||||
uint32 ref_count = shared_memory_dec_reference(memory_inst);
|
||||
/* if the reference count is not zero,
|
||||
don't free the memory */
|
||||
if (ref_count > 0)
|
||||
@ -373,9 +370,10 @@ memories_deinstantiate(AOTModuleInstance *module_inst)
|
||||
}
|
||||
|
||||
static AOTMemoryInstance *
|
||||
memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
AOTMemoryInstance *memory_inst, AOTMemory *memory,
|
||||
uint32 heap_size, char *error_buf, uint32 error_buf_size)
|
||||
memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
|
||||
AOTModule *module, AOTMemoryInstance *memory_inst,
|
||||
AOTMemory *memory, uint32 memory_idx, uint32 heap_size,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
void *heap_handle;
|
||||
uint32 num_bytes_per_page = memory->num_bytes_per_page;
|
||||
@ -396,23 +394,13 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
bool is_shared_memory = memory->memory_flags & 0x02 ? true : false;
|
||||
|
||||
/* Shared memory */
|
||||
if (is_shared_memory) {
|
||||
if (is_shared_memory && parent != NULL) {
|
||||
AOTMemoryInstance *shared_memory_instance;
|
||||
WASMSharedMemNode *node =
|
||||
wasm_module_get_shared_memory((WASMModuleCommon *)module);
|
||||
/* If the memory of this module has been instantiated,
|
||||
return the memory instance directly */
|
||||
if (node) {
|
||||
uint32 ref_count;
|
||||
ref_count = shared_memory_inc_reference((WASMModuleCommon *)module);
|
||||
bh_assert(ref_count > 0);
|
||||
shared_memory_instance =
|
||||
(AOTMemoryInstance *)shared_memory_get_memory_inst(node);
|
||||
bh_assert(shared_memory_instance);
|
||||
|
||||
(void)ref_count;
|
||||
return shared_memory_instance;
|
||||
}
|
||||
bh_assert(memory_idx == 0);
|
||||
bh_assert(parent->memory_count > memory_idx);
|
||||
shared_memory_instance = parent->memories[memory_idx];
|
||||
shared_memory_inc_reference(shared_memory_instance);
|
||||
return shared_memory_instance;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -609,23 +597,12 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (is_shared_memory) {
|
||||
memory_inst->is_shared = true;
|
||||
if (!shared_memory_set_memory_inst(
|
||||
(WASMModuleCommon *)module,
|
||||
(WASMMemoryInstanceCommon *)memory_inst)) {
|
||||
set_error_buf(error_buf, error_buf_size, "allocate memory failed");
|
||||
goto fail3;
|
||||
}
|
||||
memory_inst->ref_count = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return memory_inst;
|
||||
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
fail3:
|
||||
if (heap_size > 0)
|
||||
mem_allocator_destroy(memory_inst->heap_handle);
|
||||
#endif
|
||||
fail2:
|
||||
if (heap_size > 0)
|
||||
wasm_runtime_free(memory_inst->heap_handle);
|
||||
@ -654,8 +631,9 @@ aot_get_default_memory(AOTModuleInstance *module_inst)
|
||||
}
|
||||
|
||||
static bool
|
||||
memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
uint32 heap_size, char *error_buf, uint32 error_buf_size)
|
||||
memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
|
||||
AOTModule *module, uint32 heap_size, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
uint32 global_index, global_data_offset, base_offset, length;
|
||||
uint32 i, memory_count = module->memory_count;
|
||||
@ -672,8 +650,8 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
|
||||
memories = module_inst->global_table_data.memory_instances;
|
||||
for (i = 0; i < memory_count; i++, memories++) {
|
||||
memory_inst = memory_instantiate(module_inst, module, memories,
|
||||
&module->memories[i], heap_size,
|
||||
memory_inst = memory_instantiate(module_inst, parent, module, memories,
|
||||
&module->memories[i], i, heap_size,
|
||||
error_buf, error_buf_size);
|
||||
if (!memory_inst) {
|
||||
return false;
|
||||
@ -1100,9 +1078,9 @@ check_linked_symbol(AOTModule *module, char *error_buf, uint32 error_buf_size)
|
||||
}
|
||||
|
||||
AOTModuleInstance *
|
||||
aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main,
|
||||
uint32 stack_size, uint32 heap_size, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
|
||||
WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
AOTModuleInstance *module_inst;
|
||||
const uint32 module_inst_struct_size =
|
||||
@ -1112,6 +1090,7 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main,
|
||||
uint64 total_size, table_size = 0;
|
||||
uint8 *p;
|
||||
uint32 i, extra_info_offset;
|
||||
const bool is_sub_inst = parent != NULL;
|
||||
|
||||
/* Check heap size */
|
||||
heap_size = align_uint(heap_size, 8);
|
||||
@ -1171,7 +1150,7 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main,
|
||||
goto fail;
|
||||
|
||||
/* Initialize memory space */
|
||||
if (!memories_instantiate(module_inst, module, heap_size, error_buf,
|
||||
if (!memories_instantiate(module_inst, parent, module, heap_size, error_buf,
|
||||
error_buf_size))
|
||||
goto fail;
|
||||
|
||||
@ -1264,16 +1243,6 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
|
||||
wasm_exec_env_destroy((WASMExecEnv *)module_inst->exec_env_singleton);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
/* Destroy wasi resource before freeing app heap, since some fields of
|
||||
wasi contex are allocated from app heap, and if app heap is freed,
|
||||
these fields will be set to NULL, we cannot free their internal data
|
||||
which may allocated from global heap. */
|
||||
/* Only destroy wasi ctx in the main module instance */
|
||||
if (!is_sub_inst)
|
||||
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_PERF_PROFILING != 0
|
||||
if (module_inst->func_perf_profilings)
|
||||
wasm_runtime_free(module_inst->func_perf_profilings);
|
||||
@ -1306,10 +1275,14 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
|
||||
wasm_runtime_free(
|
||||
((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports);
|
||||
|
||||
if (!is_sub_inst) {
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst);
|
||||
#endif
|
||||
#if WASM_ENABLE_WASI_NN != 0
|
||||
if (!is_sub_inst)
|
||||
wasi_nn_destroy(module_inst);
|
||||
#endif
|
||||
}
|
||||
|
||||
wasm_runtime_free(module_inst);
|
||||
}
|
||||
@ -2489,13 +2462,13 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
|
||||
tbl_seg = module->table_init_data_list[tbl_seg_idx];
|
||||
bh_assert(tbl_seg);
|
||||
|
||||
if (!length) {
|
||||
if (offset_len_out_of_bounds(src_offset, length, tbl_seg->func_index_count)
|
||||
|| offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) {
|
||||
aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (length + src_offset > tbl_seg->func_index_count
|
||||
|| dst_offset + length > tbl_inst->cur_size) {
|
||||
aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
|
||||
if (!length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2528,8 +2501,9 @@ aot_table_copy(AOTModuleInstance *module_inst, uint32 src_tbl_idx,
|
||||
dst_tbl_inst = module_inst->tables[dst_tbl_idx];
|
||||
bh_assert(dst_tbl_inst);
|
||||
|
||||
if ((uint64)dst_offset + length > dst_tbl_inst->cur_size
|
||||
|| (uint64)src_offset + length > src_tbl_inst->cur_size) {
|
||||
if (offset_len_out_of_bounds(dst_offset, length, dst_tbl_inst->cur_size)
|
||||
|| offset_len_out_of_bounds(src_offset, length,
|
||||
src_tbl_inst->cur_size)) {
|
||||
aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
|
||||
return;
|
||||
}
|
||||
@ -2554,7 +2528,7 @@ aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length,
|
||||
tbl_inst = module_inst->tables[tbl_idx];
|
||||
bh_assert(tbl_inst);
|
||||
|
||||
if (data_offset + length > tbl_inst->cur_size) {
|
||||
if (offset_len_out_of_bounds(data_offset, length, tbl_inst->cur_size)) {
|
||||
aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -406,7 +406,7 @@ aot_unload(AOTModule *module);
|
||||
* Instantiate a AOT module.
|
||||
*
|
||||
* @param module the AOT module to instantiate
|
||||
* @param is_sub_inst the flag of sub instance
|
||||
* @param parent the parent module instance
|
||||
* @param heap_size the default heap size of the module instance, a heap will
|
||||
* be created besides the app memory space. Both wasm app and native
|
||||
* function can allocate memory from the heap. If heap_size is 0, the
|
||||
@ -417,9 +417,9 @@ aot_unload(AOTModule *module);
|
||||
* @return return the instantiated AOT module instance, NULL if failed
|
||||
*/
|
||||
AOTModuleInstance *
|
||||
aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main,
|
||||
uint32 stack_size, uint32 heap_size, char *error_buf,
|
||||
uint32 error_buf_size);
|
||||
aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
|
||||
WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
/**
|
||||
* Deinstantiate a AOT module instance, destroy the resources.
|
||||
|
||||
@ -78,6 +78,13 @@ static SymbolMap target_sym_map[] = {
|
||||
REG_SYM(__addsf3),
|
||||
REG_SYM(__divdf3),
|
||||
REG_SYM(__divsf3),
|
||||
REG_SYM(__eqdf2),
|
||||
REG_SYM(__eqsf2),
|
||||
REG_SYM(__extendsfdf2),
|
||||
REG_SYM(__fixunsdfdi),
|
||||
REG_SYM(__fixunsdfsi),
|
||||
REG_SYM(__fixunssfdi),
|
||||
REG_SYM(__fixunssfsi),
|
||||
REG_SYM(__gedf2),
|
||||
REG_SYM(__gesf2),
|
||||
REG_SYM(__gtdf2),
|
||||
@ -89,44 +96,33 @@ static SymbolMap target_sym_map[] = {
|
||||
REG_SYM(__muldf3),
|
||||
REG_SYM(__nedf2),
|
||||
REG_SYM(__nesf2),
|
||||
REG_SYM(__eqsf2),
|
||||
REG_SYM(__eqdf2),
|
||||
REG_SYM(__extendsfdf2),
|
||||
REG_SYM(__fixunsdfdi),
|
||||
REG_SYM(__fixunsdfsi),
|
||||
REG_SYM(__fixunssfsi),
|
||||
REG_SYM(__subdf3),
|
||||
REG_SYM(__subsf3),
|
||||
REG_SYM(__truncdfsf2),
|
||||
REG_SYM(__unorddf2),
|
||||
REG_SYM(__unordsf2),
|
||||
#endif
|
||||
REG_SYM(__divdi3),
|
||||
REG_SYM(__divsi3),
|
||||
#if __riscv_xlen == 32
|
||||
REG_SYM(__fixdfdi),
|
||||
REG_SYM(__fixdfsi),
|
||||
REG_SYM(__fixsfdi),
|
||||
REG_SYM(__fixsfsi),
|
||||
#endif
|
||||
REG_SYM(__fixunssfdi),
|
||||
#if __riscv_xlen == 32
|
||||
REG_SYM(__floatdidf),
|
||||
REG_SYM(__floatdisf),
|
||||
REG_SYM(__floatsisf),
|
||||
REG_SYM(__floatsidf),
|
||||
REG_SYM(__floatsisf),
|
||||
REG_SYM(__floatundidf),
|
||||
REG_SYM(__floatundisf),
|
||||
REG_SYM(__floatunsisf),
|
||||
REG_SYM(__floatunsidf),
|
||||
#endif
|
||||
REG_SYM(__moddi3),
|
||||
REG_SYM(__modsi3),
|
||||
REG_SYM(__muldi3),
|
||||
#if __riscv_xlen == 32
|
||||
REG_SYM(__floatunsisf),
|
||||
REG_SYM(__mulsf3),
|
||||
REG_SYM(__mulsi3),
|
||||
#endif
|
||||
#endif
|
||||
REG_SYM(__divdi3),
|
||||
REG_SYM(__divsi3),
|
||||
REG_SYM(__moddi3),
|
||||
REG_SYM(__modsi3),
|
||||
REG_SYM(__muldi3),
|
||||
REG_SYM(__udivdi3),
|
||||
REG_SYM(__udivsi3),
|
||||
REG_SYM(__umoddi3),
|
||||
|
||||
@ -43,6 +43,11 @@ void __floatdidf();
|
||||
void __divsf3();
|
||||
void __fixdfdi();
|
||||
void __floatundidf();
|
||||
void __fixsfdi();
|
||||
void __fixunssfdi();
|
||||
void __fixunsdfdi();
|
||||
void __floatdisf();
|
||||
void __floatundisf();
|
||||
|
||||
|
||||
static SymbolMap target_sym_map[] = {
|
||||
@ -85,6 +90,11 @@ static SymbolMap target_sym_map[] = {
|
||||
REG_SYM(__divsf3),
|
||||
REG_SYM(__fixdfdi),
|
||||
REG_SYM(__floatundidf),
|
||||
REG_SYM(__fixsfdi),
|
||||
REG_SYM(__fixunssfdi),
|
||||
REG_SYM(__fixunsdfdi),
|
||||
REG_SYM(__floatdisf),
|
||||
REG_SYM(__floatundisf),
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
@ -207,6 +217,10 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
|
||||
case R_XTENSA_32:
|
||||
{
|
||||
uint8 *insn_addr = target_section_addr + reloc_offset;
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
insn_addr = os_get_dbus_mirror((void *)insn_addr);
|
||||
bh_assert(insn_addr != NULL);
|
||||
#endif
|
||||
int32 initial_addend;
|
||||
/* (S + A) */
|
||||
if ((intptr_t)insn_addr & 3) {
|
||||
@ -265,6 +279,11 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
|
||||
return false;
|
||||
}
|
||||
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
insn_addr = os_get_dbus_mirror((void *)insn_addr);
|
||||
bh_assert(insn_addr != NULL);
|
||||
l32r_insn = (l32r_insn_t *)insn_addr;
|
||||
#endif
|
||||
imm16 = (int16)(relative_offset >> 2);
|
||||
|
||||
/* write back the imm16 to the l32r instruction */
|
||||
@ -285,7 +304,6 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
|
||||
#if __GNUC__ >= 9
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#define _WASM_EXEC_ENV_H
|
||||
|
||||
#include "bh_assert.h"
|
||||
#include "wasm_suspend_flags.h"
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
#include "../interpreter/wasm.h"
|
||||
#endif
|
||||
@ -57,15 +58,8 @@ typedef struct WASMExecEnv {
|
||||
exception. */
|
||||
uint8 *native_stack_boundary;
|
||||
|
||||
/* Used to terminate or suspend current thread
|
||||
bit 0: need to terminate
|
||||
bit 1: need to suspend
|
||||
bit 2: need to go into breakpoint
|
||||
bit 3: return from pthread_exit */
|
||||
union {
|
||||
uint32 flags;
|
||||
uintptr_t __padding__;
|
||||
} suspend_flags;
|
||||
/* Used to terminate or suspend current thread */
|
||||
WASMSuspendFlags suspend_flags;
|
||||
|
||||
/* Auxiliary stack boundary */
|
||||
union {
|
||||
|
||||
@ -608,7 +608,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (memory->is_shared) {
|
||||
if (shared_memory_is_shared(memory)) {
|
||||
memory->num_bytes_per_page = num_bytes_per_page;
|
||||
memory->cur_page_count = total_page_count;
|
||||
memory->max_page_count = max_page_count;
|
||||
@ -769,52 +769,14 @@ 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);
|
||||
if (module->memory_count > 0)
|
||||
shared_memory_lock(module->memories[0]);
|
||||
#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);
|
||||
if (module->memory_count > 0)
|
||||
shared_memory_unlock(module->memories[0]);
|
||||
#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
|
||||
|
||||
@ -24,16 +24,6 @@ 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
|
||||
|
||||
@ -1196,7 +1196,8 @@ wasm_runtime_unload(WASMModuleCommon *module)
|
||||
}
|
||||
|
||||
WASMModuleInstanceCommon *
|
||||
wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst,
|
||||
wasm_runtime_instantiate_internal(WASMModuleCommon *module,
|
||||
WASMModuleInstanceCommon *parent,
|
||||
WASMExecEnv *exec_env_main, uint32 stack_size,
|
||||
uint32 heap_size, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
@ -1204,14 +1205,14 @@ wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst,
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module->module_type == Wasm_Module_Bytecode)
|
||||
return (WASMModuleInstanceCommon *)wasm_instantiate(
|
||||
(WASMModule *)module, is_sub_inst, exec_env_main, stack_size,
|
||||
heap_size, error_buf, error_buf_size);
|
||||
(WASMModule *)module, (WASMModuleInstance *)parent, exec_env_main,
|
||||
stack_size, heap_size, error_buf, error_buf_size);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module->module_type == Wasm_Module_AoT)
|
||||
return (WASMModuleInstanceCommon *)aot_instantiate(
|
||||
(AOTModule *)module, is_sub_inst, exec_env_main, stack_size,
|
||||
heap_size, error_buf, error_buf_size);
|
||||
(AOTModule *)module, (AOTModuleInstance *)parent, exec_env_main,
|
||||
stack_size, heap_size, error_buf, error_buf_size);
|
||||
#endif
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"Instantiate module failed, invalid module type");
|
||||
@ -1224,7 +1225,7 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
return wasm_runtime_instantiate_internal(
|
||||
module, false, NULL, stack_size, heap_size, error_buf, error_buf_size);
|
||||
module, NULL, NULL, stack_size, heap_size, error_buf, error_buf_size);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2310,10 +2311,8 @@ 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);
|
||||
if (module_inst->memory_count > 0)
|
||||
shared_memory_lock(module_inst->memories[0]);
|
||||
#endif
|
||||
if (exception) {
|
||||
snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception),
|
||||
@ -2323,8 +2322,8 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
|
||||
module_inst->cur_exception[0] = '\0';
|
||||
}
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (node)
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
if (module_inst->memory_count > 0)
|
||||
shared_memory_unlock(module_inst->memories[0]);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
@ -2386,10 +2385,8 @@ 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);
|
||||
if (module_inst->memory_count > 0)
|
||||
shared_memory_lock(module_inst->memories[0]);
|
||||
#endif
|
||||
if (module_inst->cur_exception[0] != '\0') {
|
||||
/* NULL is passed if the caller is not interested in getting the
|
||||
@ -2403,8 +2400,8 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf)
|
||||
has_exception = true;
|
||||
}
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (node)
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
if (module_inst->memory_count > 0)
|
||||
shared_memory_unlock(module_inst->memories[0]);
|
||||
#endif
|
||||
|
||||
return has_exception;
|
||||
|
||||
@ -498,7 +498,8 @@ wasm_runtime_unload(WASMModuleCommon *module);
|
||||
|
||||
/* Internal API */
|
||||
WASMModuleInstanceCommon *
|
||||
wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst,
|
||||
wasm_runtime_instantiate_internal(WASMModuleCommon *module,
|
||||
WASMModuleInstanceCommon *parent,
|
||||
WASMExecEnv *exec_env_main, uint32 stack_size,
|
||||
uint32 heap_size, char *error_buf,
|
||||
uint32 error_buf_size);
|
||||
|
||||
@ -9,9 +9,16 @@
|
||||
#include "../libraries/thread-mgr/thread_manager.h"
|
||||
#endif
|
||||
|
||||
static bh_list shared_memory_list_head;
|
||||
static bh_list *const shared_memory_list = &shared_memory_list_head;
|
||||
static korp_mutex shared_memory_list_lock;
|
||||
/*
|
||||
* Note: this lock can be per memory.
|
||||
*
|
||||
* For now, just use a global because:
|
||||
* - it's a bit cumbersome to extend WASMMemoryInstance w/o breaking
|
||||
* the AOT ABI.
|
||||
* - If you care performance, it's better to make the interpreters
|
||||
* use atomic ops.
|
||||
*/
|
||||
static korp_mutex _shared_memory_lock;
|
||||
|
||||
/* clang-format off */
|
||||
enum {
|
||||
@ -48,17 +55,15 @@ destroy_wait_info(void *wait_info);
|
||||
bool
|
||||
wasm_shared_memory_init()
|
||||
{
|
||||
if (os_mutex_init(&shared_memory_list_lock) != 0)
|
||||
if (os_mutex_init(&_shared_memory_lock) != 0)
|
||||
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(&_shared_memory_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -66,110 +71,79 @@ void
|
||||
wasm_shared_memory_destroy()
|
||||
{
|
||||
bh_hash_map_destroy(wait_map);
|
||||
os_mutex_destroy(&shared_memory_list_lock);
|
||||
os_mutex_destroy(&_shared_memory_lock);
|
||||
}
|
||||
|
||||
static WASMSharedMemNode *
|
||||
search_module(WASMModuleCommon *module)
|
||||
uint32
|
||||
shared_memory_inc_reference(WASMMemoryInstance *memory)
|
||||
{
|
||||
WASMSharedMemNode *node;
|
||||
|
||||
os_mutex_lock(&shared_memory_list_lock);
|
||||
node = bh_list_first_elem(shared_memory_list);
|
||||
|
||||
while (node) {
|
||||
if (module == node->module) {
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
return node;
|
||||
}
|
||||
node = bh_list_elem_next(node);
|
||||
}
|
||||
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
return NULL;
|
||||
bh_assert(shared_memory_is_shared(memory));
|
||||
uint32 old;
|
||||
#if BH_ATOMIC_32_IS_ATOMIC == 0
|
||||
os_mutex_lock(&_shared_memory_lock);
|
||||
#endif
|
||||
old = BH_ATOMIC_32_FETCH_ADD(memory->ref_count, 1);
|
||||
#if BH_ATOMIC_32_IS_ATOMIC == 0
|
||||
os_mutex_unlock(&_shared_memory_lock);
|
||||
#endif
|
||||
bh_assert(old >= 1);
|
||||
bh_assert(old < UINT32_MAX);
|
||||
return old + 1;
|
||||
}
|
||||
|
||||
WASMSharedMemNode *
|
||||
wasm_module_get_shared_memory(WASMModuleCommon *module)
|
||||
uint32
|
||||
shared_memory_dec_reference(WASMMemoryInstance *memory)
|
||||
{
|
||||
return search_module(module);
|
||||
bh_assert(shared_memory_is_shared(memory));
|
||||
uint32 old;
|
||||
#if BH_ATOMIC_32_IS_ATOMIC == 0
|
||||
os_mutex_lock(&_shared_memory_lock);
|
||||
#endif
|
||||
old = BH_ATOMIC_32_FETCH_SUB(memory->ref_count, 1);
|
||||
#if BH_ATOMIC_32_IS_ATOMIC == 0
|
||||
os_mutex_unlock(&_shared_memory_lock);
|
||||
#endif
|
||||
bh_assert(old > 0);
|
||||
return old - 1;
|
||||
}
|
||||
|
||||
int32
|
||||
shared_memory_inc_reference(WASMModuleCommon *module)
|
||||
bool
|
||||
shared_memory_is_shared(WASMMemoryInstance *memory)
|
||||
{
|
||||
WASMSharedMemNode *node = search_module(module);
|
||||
uint32 ref_count = -1;
|
||||
if (node) {
|
||||
os_mutex_lock(&node->lock);
|
||||
ref_count = ++node->ref_count;
|
||||
os_mutex_unlock(&node->lock);
|
||||
}
|
||||
return ref_count;
|
||||
uint32 old;
|
||||
#if BH_ATOMIC_32_IS_ATOMIC == 0
|
||||
os_mutex_lock(&_shared_memory_lock);
|
||||
#endif
|
||||
old = BH_ATOMIC_32_LOAD(memory->ref_count);
|
||||
#if BH_ATOMIC_32_IS_ATOMIC == 0
|
||||
os_mutex_unlock(&_shared_memory_lock);
|
||||
#endif
|
||||
return old > 0;
|
||||
}
|
||||
|
||||
int32
|
||||
shared_memory_dec_reference(WASMModuleCommon *module)
|
||||
static korp_mutex *
|
||||
shared_memory_get_lock_pointer(WASMMemoryInstance *memory)
|
||||
{
|
||||
WASMSharedMemNode *node = search_module(module);
|
||||
uint32 ref_count = 0;
|
||||
if (node) {
|
||||
os_mutex_lock(&node->lock);
|
||||
ref_count = --node->ref_count;
|
||||
os_mutex_unlock(&node->lock);
|
||||
if (ref_count == 0) {
|
||||
os_mutex_lock(&shared_memory_list_lock);
|
||||
bh_list_remove(shared_memory_list, node);
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
|
||||
os_mutex_destroy(&node->shared_mem_lock);
|
||||
os_mutex_destroy(&node->lock);
|
||||
wasm_runtime_free(node);
|
||||
}
|
||||
return ref_count;
|
||||
}
|
||||
|
||||
return -1;
|
||||
bh_assert(memory != NULL);
|
||||
return &_shared_memory_lock;
|
||||
}
|
||||
|
||||
WASMMemoryInstanceCommon *
|
||||
shared_memory_get_memory_inst(WASMSharedMemNode *node)
|
||||
void
|
||||
shared_memory_lock(WASMMemoryInstance *memory)
|
||||
{
|
||||
return node->memory_inst;
|
||||
/*
|
||||
* Note: exception logic is currently abusing this lock.
|
||||
* cf. https://github.com/bytecodealliance/wasm-micro-runtime/issues/2407
|
||||
*/
|
||||
bh_assert(memory != NULL);
|
||||
os_mutex_lock(&_shared_memory_lock);
|
||||
}
|
||||
|
||||
WASMSharedMemNode *
|
||||
shared_memory_set_memory_inst(WASMModuleCommon *module,
|
||||
WASMMemoryInstanceCommon *memory)
|
||||
void
|
||||
shared_memory_unlock(WASMMemoryInstance *memory)
|
||||
{
|
||||
WASMSharedMemNode *node;
|
||||
bh_list_status ret;
|
||||
|
||||
if (!(node = wasm_runtime_malloc(sizeof(WASMSharedMemNode))))
|
||||
return NULL;
|
||||
|
||||
node->module = module;
|
||||
node->memory_inst = memory;
|
||||
node->ref_count = 1;
|
||||
|
||||
if (os_mutex_init(&node->shared_mem_lock) != 0) {
|
||||
wasm_runtime_free(node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (os_mutex_init(&node->lock) != 0) {
|
||||
os_mutex_destroy(&node->shared_mem_lock);
|
||||
wasm_runtime_free(node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_mutex_lock(&shared_memory_list_lock);
|
||||
ret = bh_list_insert(shared_memory_list, node);
|
||||
bh_assert(ret == BH_LIST_SUCCESS);
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
|
||||
(void)ret;
|
||||
return node;
|
||||
bh_assert(memory != NULL);
|
||||
os_mutex_unlock(&_shared_memory_lock);
|
||||
}
|
||||
|
||||
/* Atomics wait && notify APIs */
|
||||
@ -307,7 +281,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
|
||||
AtomicWaitInfo *wait_info;
|
||||
AtomicWaitNode *wait_node;
|
||||
WASMSharedMemNode *node;
|
||||
korp_mutex *lock;
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
WASMExecEnv *exec_env;
|
||||
#endif
|
||||
@ -322,7 +296,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
}
|
||||
|
||||
/* Currently we have only one memory instance */
|
||||
if (!module_inst->memories[0]->is_shared) {
|
||||
if (!shared_memory_is_shared(module_inst->memories[0])) {
|
||||
wasm_runtime_set_exception(module, "expected shared memory");
|
||||
return -1;
|
||||
}
|
||||
@ -340,30 +314,29 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
bh_assert(exec_env);
|
||||
#endif
|
||||
|
||||
node = search_module((WASMModuleCommon *)module_inst->module);
|
||||
bh_assert(node);
|
||||
lock = shared_memory_get_lock_pointer(module_inst->memories[0]);
|
||||
|
||||
/* Lock the shared_mem_lock for the whole atomic wait process,
|
||||
and use it to os_cond_reltimedwait */
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
os_mutex_lock(lock);
|
||||
|
||||
no_wait = (!wait64 && *(uint32 *)address != (uint32)expect)
|
||||
|| (wait64 && *(uint64 *)address != expect);
|
||||
|
||||
if (no_wait) {
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
os_mutex_unlock(lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) {
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
os_mutex_unlock(lock);
|
||||
wasm_runtime_set_exception(module, "failed to create wait node");
|
||||
return -1;
|
||||
}
|
||||
memset(wait_node, 0, sizeof(AtomicWaitNode));
|
||||
|
||||
if (0 != os_cond_init(&wait_node->wait_cond)) {
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
os_mutex_unlock(lock);
|
||||
wasm_runtime_free(wait_node);
|
||||
wasm_runtime_set_exception(module, "failed to init wait cond");
|
||||
return -1;
|
||||
@ -375,7 +348,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
wait_info = acquire_wait_info(address, wait_node);
|
||||
|
||||
if (!wait_info) {
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
os_mutex_unlock(lock);
|
||||
os_cond_destroy(&wait_node->wait_cond);
|
||||
wasm_runtime_free(wait_node);
|
||||
wasm_runtime_set_exception(module, "failed to acquire wait_info");
|
||||
@ -390,7 +363,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
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, &node->shared_mem_lock,
|
||||
os_cond_reltimedwait(&wait_node->wait_cond, lock,
|
||||
(uint64)timeout_1sec);
|
||||
if (wait_node->status == S_NOTIFIED /* notified by atomic.notify */
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
@ -404,8 +377,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
else {
|
||||
timeout_wait =
|
||||
timeout_left < timeout_1sec ? timeout_left : timeout_1sec;
|
||||
os_cond_reltimedwait(&wait_node->wait_cond, &node->shared_mem_lock,
|
||||
timeout_wait);
|
||||
os_cond_reltimedwait(&wait_node->wait_cond, 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
|
||||
@ -433,7 +405,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
/* Release wait info if no wait nodes are attached */
|
||||
map_try_release_wait_info(wait_map, wait_info, address);
|
||||
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
os_mutex_unlock(lock);
|
||||
|
||||
return is_timeout ? 2 : 0;
|
||||
}
|
||||
@ -445,7 +417,7 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
|
||||
uint32 notify_result;
|
||||
AtomicWaitInfo *wait_info;
|
||||
WASMSharedMemNode *node;
|
||||
korp_mutex *lock;
|
||||
bool out_of_bounds;
|
||||
|
||||
bh_assert(module->module_type == Wasm_Module_Bytecode
|
||||
@ -461,31 +433,30 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
|
||||
}
|
||||
|
||||
/* Currently we have only one memory instance */
|
||||
if (!module_inst->memories[0]->is_shared) {
|
||||
if (!shared_memory_is_shared(module_inst->memories[0])) {
|
||||
/* Always return 0 for ushared linear memory since there is
|
||||
no way to create a waiter on it */
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = search_module((WASMModuleCommon *)module_inst->module);
|
||||
bh_assert(node);
|
||||
lock = shared_memory_get_lock_pointer(module_inst->memories[0]);
|
||||
|
||||
/* Lock the shared_mem_lock for the whole atomic notify process,
|
||||
and use it to os_cond_signal */
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
os_mutex_lock(lock);
|
||||
|
||||
wait_info = acquire_wait_info(address, NULL);
|
||||
|
||||
/* Nobody wait on this address */
|
||||
if (!wait_info) {
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
os_mutex_unlock(lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Notify each wait node in the wait list */
|
||||
notify_result = notify_wait_list(wait_info->wait_list, count);
|
||||
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
os_mutex_unlock(lock);
|
||||
|
||||
return notify_result;
|
||||
}
|
||||
|
||||
@ -7,53 +7,33 @@
|
||||
#define _WASM_SHARED_MEMORY_H
|
||||
|
||||
#include "bh_common.h"
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
#include "wasm_runtime.h"
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
#include "aot_runtime.h"
|
||||
#endif
|
||||
#include "../interpreter/wasm_runtime.h"
|
||||
#include "wasm_runtime_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct WASMSharedMemNode {
|
||||
bh_list_link l;
|
||||
/* Lock */
|
||||
korp_mutex lock;
|
||||
/* The module reference */
|
||||
WASMModuleCommon *module;
|
||||
/* The memory information */
|
||||
WASMMemoryInstanceCommon *memory_inst;
|
||||
/* Lock used for atomic operations */
|
||||
korp_mutex shared_mem_lock;
|
||||
|
||||
/* reference count */
|
||||
uint32 ref_count;
|
||||
} WASMSharedMemNode;
|
||||
|
||||
bool
|
||||
wasm_shared_memory_init();
|
||||
|
||||
void
|
||||
wasm_shared_memory_destroy();
|
||||
|
||||
WASMSharedMemNode *
|
||||
wasm_module_get_shared_memory(WASMModuleCommon *module);
|
||||
uint32
|
||||
shared_memory_inc_reference(WASMMemoryInstance *memory);
|
||||
|
||||
int32
|
||||
shared_memory_inc_reference(WASMModuleCommon *module);
|
||||
uint32
|
||||
shared_memory_dec_reference(WASMMemoryInstance *memory);
|
||||
|
||||
int32
|
||||
shared_memory_dec_reference(WASMModuleCommon *module);
|
||||
bool
|
||||
shared_memory_is_shared(WASMMemoryInstance *memory);
|
||||
|
||||
WASMMemoryInstanceCommon *
|
||||
shared_memory_get_memory_inst(WASMSharedMemNode *node);
|
||||
void
|
||||
shared_memory_lock(WASMMemoryInstance *memory);
|
||||
|
||||
WASMSharedMemNode *
|
||||
shared_memory_set_memory_inst(WASMModuleCommon *module,
|
||||
WASMMemoryInstanceCommon *memory);
|
||||
void
|
||||
shared_memory_unlock(WASMMemoryInstance *memory);
|
||||
|
||||
uint32
|
||||
wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
|
||||
48
core/iwasm/common/wasm_suspend_flags.h
Normal file
48
core/iwasm/common/wasm_suspend_flags.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Amazon Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _WASM_SUSPEND_FLAGS_H
|
||||
#define _WASM_SUSPEND_FLAGS_H
|
||||
|
||||
#include "bh_atomic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Need to terminate */
|
||||
#define WASM_SUSPEND_FLAG_TERMINATE 0x1
|
||||
/* Need to suspend */
|
||||
#define WASM_SUSPEND_FLAG_SUSPEND 0x2
|
||||
/* Need to go into breakpoint */
|
||||
#define WASM_SUSPEND_FLAG_BREAKPOINT 0x4
|
||||
/* Return from pthread_exit */
|
||||
#define WASM_SUSPEND_FLAG_EXIT 0x8
|
||||
|
||||
typedef union WASMSuspendFlags {
|
||||
bh_atomic_32_t flags;
|
||||
uintptr_t __padding__;
|
||||
} WASMSuspendFlags;
|
||||
|
||||
#define WASM_SUSPEND_FLAGS_IS_ATOMIC BH_ATOMIC_32_IS_ATOMIC
|
||||
#define WASM_SUSPEND_FLAGS_GET(s_flags) BH_ATOMIC_32_LOAD(s_flags.flags)
|
||||
#define WASM_SUSPEND_FLAGS_FETCH_OR(s_flags, val) \
|
||||
BH_ATOMIC_32_FETCH_OR(s_flags.flags, val)
|
||||
#define WASM_SUSPEND_FLAGS_FETCH_AND(s_flags, val) \
|
||||
BH_ATOMIC_32_FETCH_AND(s_flags.flags, val)
|
||||
|
||||
#if WASM_SUSPEND_FLAGS_IS_ATOMIC != 0
|
||||
#define WASM_SUSPEND_FLAGS_LOCK(lock) (void)0
|
||||
#define WASM_SUSPEND_FLAGS_UNLOCK(lock) (void)0
|
||||
#else /* else of WASM_SUSPEND_FLAGS_IS_ATOMIC */
|
||||
#define WASM_SUSPEND_FLAGS_LOCK(lock) os_mutex_lock(&lock)
|
||||
#define WASM_SUSPEND_FLAGS_UNLOCK(lock) os_mutex_unlock(&lock);
|
||||
#endif /* WASM_SUSPEND_FLAGS_IS_ATOMIC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of _WASM_SUSPEND_FLAGS_H */
|
||||
@ -43,7 +43,7 @@ typedef WASMType AOTFuncType;
|
||||
typedef WASMExport AOTExport;
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
typedef void *dwar_extractor_handle_t;
|
||||
typedef void *dwarf_extractor_handle_t;
|
||||
#endif
|
||||
|
||||
typedef enum AOTIntCond {
|
||||
@ -285,7 +285,7 @@ typedef struct AOTCompData {
|
||||
|
||||
WASMModule *wasm_module;
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
dwar_extractor_handle_t extractor;
|
||||
dwarf_extractor_handle_t extractor;
|
||||
#endif
|
||||
} AOTCompData;
|
||||
|
||||
|
||||
@ -2696,7 +2696,7 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
|
||||
if (comp_ctx->stack_sizes != NULL) {
|
||||
LLVMOrcJITTargetAddress addr;
|
||||
if ((err = LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &addr,
|
||||
aot_stack_sizes_name))) {
|
||||
aot_stack_sizes_alias_name))) {
|
||||
aot_handle_llvm_errmsg("failed to look up stack_sizes", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -82,43 +82,40 @@ class ExpandMemoryOpPass : public PassInfoMixin<ExpandMemoryOpPass>
|
||||
PreservedAnalyses
|
||||
ExpandMemoryOpPass::run(Function &F, FunctionAnalysisManager &AM)
|
||||
{
|
||||
Intrinsic::ID ID = F.getIntrinsicID();
|
||||
bool Changed = false;
|
||||
SmallVector<MemIntrinsic *, 16> MemCalls;
|
||||
|
||||
for (auto I = F.user_begin(), E = F.user_end(); I != E;) {
|
||||
Instruction *Inst = cast<Instruction>(*I);
|
||||
++I;
|
||||
/* Iterate over all instructions in the function, looking for memcpy,
|
||||
* memmove, and memset. When we find one, expand it into a loop. */
|
||||
|
||||
switch (ID) {
|
||||
case Intrinsic::memcpy:
|
||||
{
|
||||
auto *Memcpy = cast<MemCpyInst>(Inst);
|
||||
Function *ParentFunc = Memcpy->getParent()->getParent();
|
||||
const TargetTransformInfo &TTI =
|
||||
AM.getResult<TargetIRAnalysis>(*ParentFunc);
|
||||
expandMemCpyAsLoop(Memcpy, TTI);
|
||||
Memcpy->eraseFromParent();
|
||||
Changed = true;
|
||||
break;
|
||||
for (auto &BB : F) {
|
||||
for (auto &Inst : BB) {
|
||||
if (auto *Memcpy = dyn_cast_or_null<MemCpyInst>(&Inst)) {
|
||||
MemCalls.push_back(Memcpy);
|
||||
}
|
||||
case Intrinsic::memmove:
|
||||
{
|
||||
auto *Memmove = cast<MemMoveInst>(Inst);
|
||||
expandMemMoveAsLoop(Memmove);
|
||||
Memmove->eraseFromParent();
|
||||
Changed = true;
|
||||
break;
|
||||
else if (auto *Memmove = dyn_cast_or_null<MemMoveInst>(&Inst)) {
|
||||
MemCalls.push_back(Memmove);
|
||||
}
|
||||
case Intrinsic::memset:
|
||||
{
|
||||
auto *Memset = cast<MemSetInst>(Inst);
|
||||
expandMemSetAsLoop(Memset);
|
||||
Memset->eraseFromParent();
|
||||
Changed = true;
|
||||
break;
|
||||
else if (auto *Memset = dyn_cast_or_null<MemSetInst>(&Inst)) {
|
||||
MemCalls.push_back(Memset);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (MemIntrinsic *MemCall : MemCalls) {
|
||||
if (MemCpyInst *Memcpy = dyn_cast<MemCpyInst>(MemCall)) {
|
||||
Function *ParentFunc = Memcpy->getParent()->getParent();
|
||||
const TargetTransformInfo &TTI =
|
||||
AM.getResult<TargetIRAnalysis>(*ParentFunc);
|
||||
expandMemCpyAsLoop(Memcpy, TTI);
|
||||
Memcpy->eraseFromParent();
|
||||
}
|
||||
else if (MemMoveInst *Memmove = dyn_cast<MemMoveInst>(MemCall)) {
|
||||
expandMemMoveAsLoop(Memmove);
|
||||
Memmove->eraseFromParent();
|
||||
}
|
||||
else if (MemSetInst *Memset = dyn_cast<MemSetInst>(MemCall)) {
|
||||
expandMemSetAsLoop(Memset);
|
||||
Memset->eraseFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,13 +294,6 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module)
|
||||
FPM.addPass(SLPVectorizerPass());
|
||||
FPM.addPass(LoadStoreVectorizerPass());
|
||||
|
||||
/* Run specific passes for AOT indirect mode in last since general
|
||||
optimization may create some intrinsic function calls like
|
||||
llvm.memset, so let's remove these function calls here. */
|
||||
if (comp_ctx->is_indirect_mode) {
|
||||
FPM.addPass(ExpandMemoryOpPass());
|
||||
}
|
||||
|
||||
if (comp_ctx->enable_llvm_pgo || comp_ctx->use_prof_file) {
|
||||
/* LICM pass: loop invariant code motion, attempting to remove
|
||||
as much code from the body of a loop as possible. Experiments
|
||||
@ -341,6 +331,15 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module)
|
||||
else {
|
||||
MPM.addPass(PB.buildPerModuleDefaultPipeline(OL));
|
||||
}
|
||||
|
||||
/* Run specific passes for AOT indirect mode in last since general
|
||||
optimization may create some intrinsic function calls like
|
||||
llvm.memset, so let's remove these function calls here. */
|
||||
if (comp_ctx->is_indirect_mode) {
|
||||
FunctionPassManager FPM1;
|
||||
FPM1.addPass(ExpandMemoryOpPass());
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM1)));
|
||||
}
|
||||
}
|
||||
|
||||
MPM.run(*M, MAM);
|
||||
|
||||
@ -28,25 +28,25 @@
|
||||
|
||||
using namespace lldb;
|
||||
|
||||
typedef struct dwar_extractor {
|
||||
typedef struct dwarf_extractor {
|
||||
SBDebugger debugger;
|
||||
SBTarget target;
|
||||
SBModule module;
|
||||
|
||||
} dwar_extractor;
|
||||
} dwarf_extractor;
|
||||
|
||||
#define TO_HANDLE(extractor) (dwar_extractor_handle_t)(extractor)
|
||||
#define TO_HANDLE(extractor) (dwarf_extractor_handle_t)(extractor)
|
||||
|
||||
#define TO_EXTACTOR(handle) (dwar_extractor *)(handle)
|
||||
#define TO_EXTACTOR(handle) (dwarf_extractor *)(handle)
|
||||
|
||||
static bool is_debugger_initialized;
|
||||
|
||||
dwar_extractor_handle_t
|
||||
dwarf_extractor_handle_t
|
||||
create_dwarf_extractor(AOTCompData *comp_data, char *file_name)
|
||||
{
|
||||
char *arch = NULL;
|
||||
char *platform = NULL;
|
||||
dwar_extractor *extractor = NULL;
|
||||
dwarf_extractor *extractor = NULL;
|
||||
|
||||
//__attribute__((constructor)) may be better?
|
||||
if (!is_debugger_initialized) {
|
||||
@ -61,7 +61,7 @@ create_dwarf_extractor(AOTCompData *comp_data, char *file_name)
|
||||
SBError error;
|
||||
SBFileSpec exe_file_spec(file_name, true);
|
||||
|
||||
if (!(extractor = new dwar_extractor())) {
|
||||
if (!(extractor = new dwarf_extractor())) {
|
||||
LOG_ERROR("Create Dwarf Extractor error: failed to allocate memory");
|
||||
goto fail3;
|
||||
}
|
||||
@ -101,9 +101,9 @@ fail3:
|
||||
}
|
||||
|
||||
void
|
||||
destroy_dwarf_extractor(dwar_extractor_handle_t handle)
|
||||
destroy_dwarf_extractor(dwarf_extractor_handle_t handle)
|
||||
{
|
||||
dwar_extractor *extractor = TO_EXTACTOR(handle);
|
||||
dwarf_extractor *extractor = TO_EXTACTOR(handle);
|
||||
if (!extractor)
|
||||
return;
|
||||
extractor->debugger.DeleteTarget(extractor->target);
|
||||
@ -116,7 +116,7 @@ destroy_dwarf_extractor(dwar_extractor_handle_t handle)
|
||||
LLVMMetadataRef
|
||||
dwarf_gen_file_info(const AOTCompContext *comp_ctx)
|
||||
{
|
||||
dwar_extractor *extractor;
|
||||
dwarf_extractor *extractor;
|
||||
int units_number;
|
||||
LLVMMetadataRef file_info = NULL;
|
||||
const char *file_name;
|
||||
@ -193,7 +193,7 @@ dwarf_gen_mock_vm_info(AOTCompContext *comp_ctx)
|
||||
LLVMMetadataRef
|
||||
dwarf_gen_comp_unit_info(const AOTCompContext *comp_ctx)
|
||||
{
|
||||
dwar_extractor *extractor;
|
||||
dwarf_extractor *extractor;
|
||||
int units_number;
|
||||
LLVMMetadataRef comp_unit = NULL;
|
||||
|
||||
@ -292,7 +292,7 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx,
|
||||
SBTypeList function_args = function.GetType().GetFunctionArgumentTypes();
|
||||
SBType return_type = function.GetType().GetFunctionReturnType();
|
||||
const size_t num_function_args = function_args.GetSize();
|
||||
dwar_extractor *extractor;
|
||||
dwarf_extractor *extractor;
|
||||
|
||||
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
|
||||
return NULL;
|
||||
@ -393,7 +393,7 @@ dwarf_gen_func_info(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMMetadataRef func_info = NULL;
|
||||
dwar_extractor *extractor;
|
||||
dwarf_extractor *extractor;
|
||||
uint64_t vm_offset;
|
||||
AOTFunc *func = func_ctx->aot_func;
|
||||
|
||||
@ -423,7 +423,7 @@ dwarf_get_func_name(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx, char *name, int len)
|
||||
{
|
||||
LLVMMetadataRef func_info = NULL;
|
||||
dwar_extractor *extractor;
|
||||
dwarf_extractor *extractor;
|
||||
uint64_t vm_offset;
|
||||
AOTFunc *func = func_ctx->aot_func;
|
||||
|
||||
@ -454,7 +454,7 @@ dwarf_gen_location(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx, uint64_t vm_offset)
|
||||
{
|
||||
LLVMMetadataRef location_info = NULL;
|
||||
dwar_extractor *extractor;
|
||||
dwarf_extractor *extractor;
|
||||
AOTFunc *func = func_ctx->aot_func;
|
||||
|
||||
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
|
||||
@ -493,7 +493,7 @@ dwarf_gen_func_ret_location(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMMetadataRef func_info = NULL;
|
||||
dwar_extractor *extractor;
|
||||
dwarf_extractor *extractor;
|
||||
uint64_t vm_offset;
|
||||
AOTFunc *func = func_ctx->aot_func;
|
||||
LLVMMetadataRef location_info = NULL;
|
||||
|
||||
@ -18,7 +18,7 @@ typedef unsigned int LLDBLangType;
|
||||
|
||||
struct AOTCompData;
|
||||
typedef struct AOTCompData *aot_comp_data_t;
|
||||
typedef void *dwar_extractor_handle_t;
|
||||
typedef void *dwarf_extractor_handle_t;
|
||||
|
||||
struct AOTCompContext;
|
||||
typedef struct AOTCompContext AOTCompContext;
|
||||
@ -26,7 +26,7 @@ typedef struct AOTCompContext AOTCompContext;
|
||||
struct AOTFuncContext;
|
||||
|
||||
typedef struct AOTFuncContext AOTFuncContext;
|
||||
dwar_extractor_handle_t
|
||||
dwarf_extractor_handle_t
|
||||
create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name);
|
||||
|
||||
LLVMMetadataRef
|
||||
|
||||
@ -88,27 +88,28 @@ fail:
|
||||
|
||||
static int
|
||||
wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx,
|
||||
uint32 dst, uint32 len, uint32 src)
|
||||
uint32 dst_offset, uint32 len, uint32 src_offset)
|
||||
{
|
||||
WASMTableInstance *tbl;
|
||||
uint32 tbl_sz;
|
||||
WASMTableSeg *elem;
|
||||
uint32 elem_len;
|
||||
|
||||
tbl = inst->tables[tbl_idx];
|
||||
tbl_sz = tbl->cur_size;
|
||||
if (dst > tbl_sz || tbl_sz - dst < len)
|
||||
goto out_of_bounds;
|
||||
|
||||
elem = inst->module->table_segments + elem_idx;
|
||||
elem_len = elem->function_count;
|
||||
if (src > elem_len || elem_len - src < len)
|
||||
if (offset_len_out_of_bounds(src_offset, len, elem_len))
|
||||
goto out_of_bounds;
|
||||
|
||||
tbl = inst->tables[tbl_idx];
|
||||
tbl_sz = tbl->cur_size;
|
||||
if (offset_len_out_of_bounds(dst_offset, len, tbl_sz))
|
||||
goto out_of_bounds;
|
||||
|
||||
bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems)
|
||||
+ dst * sizeof(uint32),
|
||||
(uint32)((tbl_sz - dst) * sizeof(uint32)),
|
||||
elem->func_indexes + src, (uint32)(len * sizeof(uint32)));
|
||||
+ dst_offset * sizeof(uint32),
|
||||
(uint32)((tbl_sz - dst_offset) * sizeof(uint32)),
|
||||
elem->func_indexes + src_offset,
|
||||
(uint32)(len * sizeof(uint32)));
|
||||
|
||||
return 0;
|
||||
out_of_bounds:
|
||||
@ -157,14 +158,14 @@ wasm_copy_table(WASMModuleInstance *inst, uint32 src_tbl_idx,
|
||||
WASMTableInstance *src_tbl, *dst_tbl;
|
||||
uint32 src_tbl_sz, dst_tbl_sz;
|
||||
|
||||
src_tbl = inst->tables[src_tbl_idx];
|
||||
src_tbl_sz = src_tbl->cur_size;
|
||||
if (src_offset > src_tbl_sz || src_tbl_sz - src_offset < len)
|
||||
goto out_of_bounds;
|
||||
|
||||
dst_tbl = inst->tables[dst_tbl_idx];
|
||||
dst_tbl_sz = dst_tbl->cur_size;
|
||||
if (dst_offset > dst_tbl_sz || dst_tbl_sz - dst_offset < len)
|
||||
if (offset_len_out_of_bounds(dst_offset, len, dst_tbl_sz))
|
||||
goto out_of_bounds;
|
||||
|
||||
src_tbl = inst->tables[src_tbl_idx];
|
||||
src_tbl_sz = src_tbl->cur_size;
|
||||
if (offset_len_out_of_bounds(src_offset, len, src_tbl_sz))
|
||||
goto out_of_bounds;
|
||||
|
||||
bh_memmove_s((uint8 *)dst_tbl + offsetof(WASMTableInstance, elems)
|
||||
@ -263,7 +264,7 @@ fail:
|
||||
}
|
||||
|
||||
static int
|
||||
wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst,
|
||||
wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst_offset,
|
||||
uint32 val, uint32 len)
|
||||
{
|
||||
WASMTableInstance *tbl;
|
||||
@ -272,11 +273,11 @@ wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst,
|
||||
tbl = inst->tables[tbl_idx];
|
||||
tbl_sz = tbl->cur_size;
|
||||
|
||||
if (dst > tbl_sz || tbl_sz - dst < len)
|
||||
if (offset_len_out_of_bounds(dst_offset, len, tbl_sz))
|
||||
goto out_of_bounds;
|
||||
|
||||
for (; len != 0; dst++, len--) {
|
||||
tbl->elems[dst] = val;
|
||||
for (; len != 0; dst_offset++, len--) {
|
||||
tbl->elems[dst_offset] = val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -26,8 +26,8 @@ void
|
||||
aot_destroy_comp_data(aot_comp_data_t comp_data);
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
typedef void *dwar_extractor_handle_t;
|
||||
dwar_extractor_handle_t
|
||||
typedef void *dwarf_extractor_handle_t;
|
||||
dwarf_extractor_handle_t
|
||||
create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name);
|
||||
#endif
|
||||
|
||||
|
||||
@ -627,7 +627,6 @@ typedef struct WASMBranchBlock {
|
||||
uint32 cell_num;
|
||||
} WASMBranchBlock;
|
||||
|
||||
/* Execution environment, e.g. stack info */
|
||||
/**
|
||||
* Align an unsigned value on a alignment boundary.
|
||||
*
|
||||
@ -643,6 +642,24 @@ align_uint(unsigned v, unsigned b)
|
||||
return (v + m) & ~m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a piece of data is out of range
|
||||
*
|
||||
* @param offset the offset that the data starts
|
||||
* @param len the length of the data
|
||||
* @param max_size the maximum size of the data range
|
||||
*
|
||||
* @return true if out of range, false otherwise
|
||||
*/
|
||||
inline static bool
|
||||
offset_len_out_of_bounds(uint32 offset, uint32 len, uint32 max_size)
|
||||
{
|
||||
if (offset + len < offset /* integer overflow */
|
||||
|| offset + len > max_size)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hash value of c string.
|
||||
*/
|
||||
|
||||
@ -710,28 +710,28 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = (uint32)(*(uint8 *)maddr); \
|
||||
*(uint8 *)maddr = (uint8)(readv op sval); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = (uint32)LOAD_U16(maddr); \
|
||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
else { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = LOAD_I32(maddr); \
|
||||
STORE_U32(maddr, readv op sval); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
PUSH_I32(readv); \
|
||||
break; \
|
||||
@ -750,39 +750,39 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = (uint64)(*(uint8 *)maddr); \
|
||||
*(uint8 *)maddr = (uint8)(readv op sval); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = (uint64)LOAD_U16(maddr); \
|
||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = (uint64)LOAD_U32(maddr); \
|
||||
STORE_U32(maddr, (uint32)(readv op sval)); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
else { \
|
||||
uint64 op_result; \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = (uint64)LOAD_I64(maddr); \
|
||||
op_result = readv op sval; \
|
||||
STORE_I64(maddr, op_result); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
PUSH_I64(readv); \
|
||||
break; \
|
||||
@ -1062,21 +1062,33 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
|
||||
os_mutex_unlock(&exec_env->wait_lock); \
|
||||
} while (0)
|
||||
#else
|
||||
#define CHECK_SUSPEND_FLAGS() \
|
||||
do { \
|
||||
os_mutex_lock(&exec_env->wait_lock); \
|
||||
if (exec_env->suspend_flags.flags != 0) { \
|
||||
if (exec_env->suspend_flags.flags & 0x01) { \
|
||||
/* terminate current thread */ \
|
||||
os_mutex_unlock(&exec_env->wait_lock); \
|
||||
return; \
|
||||
} \
|
||||
while (exec_env->suspend_flags.flags & 0x02) { \
|
||||
/* suspend current thread */ \
|
||||
os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \
|
||||
} \
|
||||
} \
|
||||
os_mutex_unlock(&exec_env->wait_lock); \
|
||||
#if WASM_SUSPEND_FLAGS_IS_ATOMIC != 0
|
||||
/* The lock is only needed when the suspend_flags is atomic; otherwise
|
||||
the lock is already taken at the time when SUSPENSION_LOCK() is called. */
|
||||
#define SUSPENSION_LOCK() os_mutex_lock(&exec_env->wait_lock);
|
||||
#define SUSPENSION_UNLOCK() os_mutex_unlock(&exec_env->wait_lock);
|
||||
#else
|
||||
#define SUSPENSION_LOCK()
|
||||
#define SUSPENSION_UNLOCK()
|
||||
#endif
|
||||
|
||||
#define CHECK_SUSPEND_FLAGS() \
|
||||
do { \
|
||||
WASM_SUSPEND_FLAGS_LOCK(exec_env->wait_lock); \
|
||||
if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) \
|
||||
& WASM_SUSPEND_FLAG_TERMINATE) { \
|
||||
/* terminate current thread */ \
|
||||
WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \
|
||||
return; \
|
||||
} \
|
||||
while (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) \
|
||||
& WASM_SUSPEND_FLAG_SUSPEND) { \
|
||||
/* suspend current thread */ \
|
||||
SUSPENSION_LOCK() \
|
||||
os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \
|
||||
SUSPENSION_UNLOCK() \
|
||||
} \
|
||||
WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \
|
||||
} while (0)
|
||||
#endif /* WASM_ENABLE_DEBUG_INTERP */
|
||||
#endif /* WASM_ENABLE_THREAD_MGR */
|
||||
@ -1144,10 +1156,6 @@ 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);
|
||||
#endif
|
||||
WASMMemoryInstance *memory = wasm_get_default_memory(module);
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|
||||
@ -3235,7 +3243,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
case WASM_OP_TABLE_INIT:
|
||||
{
|
||||
uint32 tbl_idx, elem_idx;
|
||||
uint64 n, s, d;
|
||||
uint32 n, s, d;
|
||||
WASMTableInstance *tbl_inst;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, elem_idx);
|
||||
@ -3250,20 +3258,21 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
s = (uint32)POP_I32();
|
||||
d = (uint32)POP_I32();
|
||||
|
||||
/* TODO: what if the element is not passive? */
|
||||
|
||||
if (!n) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (n + s > module->module->table_segments[elem_idx]
|
||||
.function_count
|
||||
|| d + n > tbl_inst->cur_size) {
|
||||
if (offset_len_out_of_bounds(
|
||||
s, n,
|
||||
module->module->table_segments[elem_idx]
|
||||
.function_count)
|
||||
|| offset_len_out_of_bounds(d, n,
|
||||
tbl_inst->cur_size)) {
|
||||
wasm_set_exception(module,
|
||||
"out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
if (!n) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (module->module->table_segments[elem_idx]
|
||||
.is_dropped) {
|
||||
wasm_set_exception(module,
|
||||
@ -3304,7 +3313,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
case WASM_OP_TABLE_COPY:
|
||||
{
|
||||
uint32 src_tbl_idx, dst_tbl_idx;
|
||||
uint64 n, s, d;
|
||||
uint32 n, s, d;
|
||||
WASMTableInstance *src_tbl_inst, *dst_tbl_inst;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx);
|
||||
@ -3321,8 +3330,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
s = (uint32)POP_I32();
|
||||
d = (uint32)POP_I32();
|
||||
|
||||
if (d + n > dst_tbl_inst->cur_size
|
||||
|| s + n > src_tbl_inst->cur_size) {
|
||||
if (offset_len_out_of_bounds(d, n,
|
||||
dst_tbl_inst->cur_size)
|
||||
|| offset_len_out_of_bounds(
|
||||
s, n, src_tbl_inst->cur_size)) {
|
||||
wasm_set_exception(module,
|
||||
"out of bounds table access");
|
||||
goto got_exception;
|
||||
@ -3392,11 +3403,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
fill_val = POP_I32();
|
||||
i = POP_I32();
|
||||
|
||||
/* TODO: what if the element is not passive? */
|
||||
/* TODO: what if the element is dropped? */
|
||||
|
||||
if (i + n > tbl_inst->cur_size) {
|
||||
/* TODO: verify warning content */
|
||||
if (offset_len_out_of_bounds(i, n,
|
||||
tbl_inst->cur_size)) {
|
||||
wasm_set_exception(module,
|
||||
"out of bounds table access");
|
||||
goto got_exception;
|
||||
@ -3514,23 +3522,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint32)(*(uint8 *)maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint32)LOAD_U16(maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = LOAD_I32(maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
|
||||
PUSH_I32(readv);
|
||||
@ -3549,30 +3557,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)(*(uint8 *)maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)LOAD_U16(maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)LOAD_U32(maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = LOAD_I64(maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
|
||||
PUSH_I64(readv);
|
||||
@ -3591,23 +3599,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
*(uint8 *)maddr = (uint8)sval;
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
STORE_U16(maddr, (uint16)sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
STORE_U32(maddr, sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3625,30 +3633,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
*(uint8 *)maddr = (uint8)sval;
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
STORE_U16(maddr, (uint16)sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
STORE_U32(maddr, (uint32)sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
PUT_I64_TO_ADDR((uint32 *)maddr, sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3668,32 +3676,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint8)expect;
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint32)(*(uint8 *)maddr);
|
||||
if (readv == expect)
|
||||
*(uint8 *)maddr = (uint8)(sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint16)expect;
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint32)LOAD_U16(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U16(maddr, (uint16)(sval));
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = LOAD_I32(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U32(maddr, sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
PUSH_I32(readv);
|
||||
break;
|
||||
@ -3714,43 +3722,43 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint8)expect;
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)(*(uint8 *)maddr);
|
||||
if (readv == expect)
|
||||
*(uint8 *)maddr = (uint8)(sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint16)expect;
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)LOAD_U16(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U16(maddr, (uint16)(sval));
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint32)expect;
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)LOAD_U32(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U32(maddr, (uint32)(sval));
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)LOAD_I64(maddr);
|
||||
if (readv == expect)
|
||||
STORE_I64(maddr, sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
PUSH_I64(readv);
|
||||
break;
|
||||
@ -3783,7 +3791,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
HANDLE_OP(DEBUG_OP_BREAK)
|
||||
{
|
||||
wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP);
|
||||
exec_env->suspend_flags.flags |= 2;
|
||||
WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags,
|
||||
WASM_SUSPEND_FLAG_SUSPEND);
|
||||
frame_ip--;
|
||||
SYNC_ALL_TO_FRAME();
|
||||
CHECK_SUSPEND_FLAGS();
|
||||
|
||||
@ -482,28 +482,28 @@ LOAD_PTR(void *addr)
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = (uint32)(*(uint8 *)maddr); \
|
||||
*(uint8 *)maddr = (uint8)(readv op sval); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = (uint32)LOAD_U16(maddr); \
|
||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
else { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = LOAD_I32(maddr); \
|
||||
STORE_U32(maddr, readv op sval); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
PUSH_I32(readv); \
|
||||
break; \
|
||||
@ -522,39 +522,39 @@ LOAD_PTR(void *addr)
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = (uint64)(*(uint8 *)maddr); \
|
||||
*(uint8 *)maddr = (uint8)(readv op sval); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = (uint64)LOAD_U16(maddr); \
|
||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = (uint64)LOAD_U32(maddr); \
|
||||
STORE_U32(maddr, (uint32)(readv op sval)); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
else { \
|
||||
uint64 op_result; \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(8); \
|
||||
\
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
shared_memory_lock(memory); \
|
||||
readv = (uint64)LOAD_I64(maddr); \
|
||||
op_result = readv op sval; \
|
||||
STORE_I64(maddr, op_result); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
shared_memory_unlock(memory); \
|
||||
} \
|
||||
PUSH_I64(readv); \
|
||||
break; \
|
||||
@ -1065,18 +1065,17 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
#define CHECK_SUSPEND_FLAGS() \
|
||||
do { \
|
||||
os_mutex_lock(&exec_env->wait_lock); \
|
||||
if (exec_env->suspend_flags.flags != 0) { \
|
||||
if (exec_env->suspend_flags.flags & 0x01) { \
|
||||
/* terminate current thread */ \
|
||||
os_mutex_unlock(&exec_env->wait_lock); \
|
||||
return; \
|
||||
} \
|
||||
/* TODO: support suspend and breakpoint */ \
|
||||
} \
|
||||
os_mutex_unlock(&exec_env->wait_lock); \
|
||||
#define CHECK_SUSPEND_FLAGS() \
|
||||
do { \
|
||||
WASM_SUSPEND_FLAGS_LOCK(exec_env->wait_lock); \
|
||||
if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) \
|
||||
& WASM_SUSPEND_FLAG_TERMINATE) { \
|
||||
/* terminate current thread */ \
|
||||
WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \
|
||||
return; \
|
||||
} \
|
||||
/* TODO: support suspend and breakpoint */ \
|
||||
WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
@ -1167,10 +1166,6 @@ 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);
|
||||
#endif
|
||||
WASMMemoryInstance *memory = wasm_get_default_memory(module);
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|
||||
@ -3079,7 +3074,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
case WASM_OP_TABLE_INIT:
|
||||
{
|
||||
uint32 tbl_idx, elem_idx;
|
||||
uint64 n, s, d;
|
||||
uint32 n, s, d;
|
||||
WASMTableInstance *tbl_inst;
|
||||
|
||||
elem_idx = read_uint32(frame_ip);
|
||||
@ -3094,18 +3089,21 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
s = (uint32)POP_I32();
|
||||
d = (uint32)POP_I32();
|
||||
|
||||
if (!n) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (n + s > module->module->table_segments[elem_idx]
|
||||
.function_count
|
||||
|| d + n > tbl_inst->cur_size) {
|
||||
if (offset_len_out_of_bounds(
|
||||
s, n,
|
||||
module->module->table_segments[elem_idx]
|
||||
.function_count)
|
||||
|| offset_len_out_of_bounds(d, n,
|
||||
tbl_inst->cur_size)) {
|
||||
wasm_set_exception(module,
|
||||
"out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
if (!n) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (module->module->table_segments[elem_idx]
|
||||
.is_dropped) {
|
||||
wasm_set_exception(module,
|
||||
@ -3144,7 +3142,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
case WASM_OP_TABLE_COPY:
|
||||
{
|
||||
uint32 src_tbl_idx, dst_tbl_idx;
|
||||
uint64 n, s, d;
|
||||
uint32 n, s, d;
|
||||
WASMTableInstance *src_tbl_inst, *dst_tbl_inst;
|
||||
|
||||
dst_tbl_idx = read_uint32(frame_ip);
|
||||
@ -3161,8 +3159,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
s = (uint32)POP_I32();
|
||||
d = (uint32)POP_I32();
|
||||
|
||||
if (d + n > dst_tbl_inst->cur_size
|
||||
|| s + n > src_tbl_inst->cur_size) {
|
||||
if (offset_len_out_of_bounds(d, n,
|
||||
dst_tbl_inst->cur_size)
|
||||
|| offset_len_out_of_bounds(
|
||||
s, n, src_tbl_inst->cur_size)) {
|
||||
wasm_set_exception(module,
|
||||
"out of bounds table access");
|
||||
goto got_exception;
|
||||
@ -3233,7 +3233,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
fill_val = POP_I32();
|
||||
i = POP_I32();
|
||||
|
||||
if (i + n > tbl_inst->cur_size) {
|
||||
if (offset_len_out_of_bounds(i, n,
|
||||
tbl_inst->cur_size)) {
|
||||
wasm_set_exception(module,
|
||||
"out of bounds table access");
|
||||
goto got_exception;
|
||||
@ -3348,23 +3349,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint32)(*(uint8 *)maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint32)LOAD_U16(maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = LOAD_I32(maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
|
||||
PUSH_I32(readv);
|
||||
@ -3383,30 +3384,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)(*(uint8 *)maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)LOAD_U16(maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)LOAD_U32(maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = LOAD_I64(maddr);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
|
||||
PUSH_I64(readv);
|
||||
@ -3424,23 +3425,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
*(uint8 *)maddr = (uint8)sval;
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
STORE_U16(maddr, (uint16)sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
STORE_U32(maddr, sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3458,30 +3459,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
*(uint8 *)maddr = (uint8)sval;
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
STORE_U16(maddr, (uint16)sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
STORE_U32(maddr, (uint32)sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
STORE_I64(maddr, sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3501,32 +3502,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
|
||||
expect = (uint8)expect;
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint32)(*(uint8 *)maddr);
|
||||
if (readv == expect)
|
||||
*(uint8 *)maddr = (uint8)(sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
|
||||
expect = (uint16)expect;
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint32)LOAD_U16(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U16(maddr, (uint16)(sval));
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = LOAD_I32(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U32(maddr, sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
PUSH_I32(readv);
|
||||
break;
|
||||
@ -3547,43 +3548,43 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
|
||||
expect = (uint8)expect;
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)(*(uint8 *)maddr);
|
||||
if (readv == expect)
|
||||
*(uint8 *)maddr = (uint8)(sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
|
||||
expect = (uint16)expect;
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)LOAD_U16(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U16(maddr, (uint16)(sval));
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
|
||||
expect = (uint32)expect;
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)LOAD_U32(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U32(maddr, (uint32)(sval));
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
||||
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
shared_memory_lock(memory);
|
||||
readv = (uint64)LOAD_I64(maddr);
|
||||
if (readv == expect)
|
||||
STORE_I64(maddr, sval);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
shared_memory_unlock(memory);
|
||||
}
|
||||
PUSH_I64(readv);
|
||||
break;
|
||||
|
||||
@ -7014,6 +7014,7 @@ static bool
|
||||
copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
bool ret = false;
|
||||
int16 *frame_offset = NULL;
|
||||
uint8 *cells = NULL, cell;
|
||||
int16 *src_offsets = NULL;
|
||||
@ -7084,13 +7085,13 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
|
||||
if (is_if_block)
|
||||
PUSH_OFFSET_TYPE(VALUE_TYPE_I32);
|
||||
|
||||
ret = true;
|
||||
|
||||
fail:
|
||||
/* Free the emit data */
|
||||
wasm_runtime_free(emit_data);
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -8065,7 +8066,8 @@ re_scan:
|
||||
uint8 vec_len, ref_type;
|
||||
|
||||
read_leb_uint32(p, p_end, vec_len);
|
||||
if (!vec_len) {
|
||||
if (vec_len != 1) {
|
||||
/* typed select must have exactly one result */
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"invalid result arity");
|
||||
goto fail;
|
||||
|
||||
@ -6235,7 +6235,8 @@ re_scan:
|
||||
uint8 vec_len, ref_type;
|
||||
|
||||
read_leb_uint32(p, p_end, vec_len);
|
||||
if (!vec_len) {
|
||||
if (vec_len != 1) {
|
||||
/* typed select must have exactly one result */
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"invalid result arity");
|
||||
goto fail;
|
||||
|
||||
@ -122,11 +122,8 @@ memories_deinstantiate(WASMModuleInstance *module_inst,
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (memories[i]->is_shared) {
|
||||
int32 ref_count = shared_memory_dec_reference(
|
||||
(WASMModuleCommon *)module_inst->module);
|
||||
bh_assert(ref_count >= 0);
|
||||
|
||||
if (shared_memory_is_shared(memories[i])) {
|
||||
uint32 ref_count = shared_memory_dec_reference(memories[i]);
|
||||
/* if the reference count is not zero,
|
||||
don't free the memory */
|
||||
if (ref_count > 0)
|
||||
@ -159,7 +156,8 @@ memories_deinstantiate(WASMModuleInstance *module_inst,
|
||||
}
|
||||
|
||||
static WASMMemoryInstance *
|
||||
memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory,
|
||||
memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
|
||||
WASMMemoryInstance *memory, uint32 memory_idx,
|
||||
uint32 num_bytes_per_page, uint32 init_page_count,
|
||||
uint32 max_page_count, uint32 heap_size, uint32 flags,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
@ -180,22 +178,11 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory,
|
||||
bool is_shared_memory = flags & 0x02 ? true : false;
|
||||
|
||||
/* shared memory */
|
||||
if (is_shared_memory) {
|
||||
WASMSharedMemNode *node = wasm_module_get_shared_memory(
|
||||
(WASMModuleCommon *)module_inst->module);
|
||||
/* If the memory of this module has been instantiated,
|
||||
return the memory instance directly */
|
||||
if (node) {
|
||||
uint32 ref_count;
|
||||
ref_count = shared_memory_inc_reference(
|
||||
(WASMModuleCommon *)module_inst->module);
|
||||
bh_assert(ref_count > 0);
|
||||
memory = (WASMMemoryInstance *)shared_memory_get_memory_inst(node);
|
||||
bh_assert(memory);
|
||||
|
||||
(void)ref_count;
|
||||
return memory;
|
||||
}
|
||||
if (is_shared_memory && parent != NULL) {
|
||||
bh_assert(parent->memory_count > memory_idx);
|
||||
memory = parent->memories[memory_idx];
|
||||
shared_memory_inc_reference(memory);
|
||||
return memory;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_SHARED_MEMORY */
|
||||
|
||||
@ -388,24 +375,13 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory,
|
||||
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (is_shared_memory) {
|
||||
memory->is_shared = true;
|
||||
if (!shared_memory_set_memory_inst(
|
||||
(WASMModuleCommon *)module_inst->module,
|
||||
(WASMMemoryInstanceCommon *)memory)) {
|
||||
set_error_buf(error_buf, error_buf_size, "allocate memory failed");
|
||||
goto fail4;
|
||||
}
|
||||
memory->ref_count = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
LOG_VERBOSE("Memory instantiate success.");
|
||||
return memory;
|
||||
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
fail4:
|
||||
if (heap_size > 0)
|
||||
mem_allocator_destroy(memory->heap_handle);
|
||||
#endif
|
||||
fail3:
|
||||
if (heap_size > 0)
|
||||
wasm_runtime_free(memory->heap_handle);
|
||||
@ -428,7 +404,8 @@ fail1:
|
||||
*/
|
||||
static WASMMemoryInstance **
|
||||
memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
|
||||
uint32 heap_size, char *error_buf, uint32 error_buf_size)
|
||||
WASMModuleInstance *parent, uint32 heap_size,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
WASMImport *import;
|
||||
uint32 mem_index = 0, i,
|
||||
@ -474,26 +451,29 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (!(memories[mem_index++] = memory_instantiate(
|
||||
module_inst, memory, num_bytes_per_page, init_page_count,
|
||||
max_page_count, actual_heap_size, flags, error_buf,
|
||||
error_buf_size))) {
|
||||
if (!(memories[mem_index] = memory_instantiate(
|
||||
module_inst, parent, memory, mem_index,
|
||||
num_bytes_per_page, init_page_count, max_page_count,
|
||||
actual_heap_size, flags, error_buf, error_buf_size))) {
|
||||
memories_deinstantiate(module_inst, memories, memory_count);
|
||||
return NULL;
|
||||
}
|
||||
mem_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/* instantiate memories from memory section */
|
||||
for (i = 0; i < module->memory_count; i++, memory++) {
|
||||
if (!(memories[mem_index++] = memory_instantiate(
|
||||
module_inst, memory, module->memories[i].num_bytes_per_page,
|
||||
if (!(memories[mem_index] = memory_instantiate(
|
||||
module_inst, parent, memory, mem_index,
|
||||
module->memories[i].num_bytes_per_page,
|
||||
module->memories[i].init_page_count,
|
||||
module->memories[i].max_page_count, heap_size,
|
||||
module->memories[i].flags, error_buf, error_buf_size))) {
|
||||
memories_deinstantiate(module_inst, memories, memory_count);
|
||||
return NULL;
|
||||
}
|
||||
mem_index++;
|
||||
}
|
||||
|
||||
bh_assert(mem_index == memory_count);
|
||||
@ -1104,10 +1084,14 @@ execute_post_instantiate_functions(WASMModuleInstance *module_inst,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
if (initialize_func
|
||||
&& !wasm_call_function(exec_env, initialize_func, 0, NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
(void)initialize_func;
|
||||
#endif
|
||||
|
||||
if (post_inst_func
|
||||
&& !wasm_call_function(exec_env, post_inst_func, 0, NULL)) {
|
||||
@ -1297,7 +1281,7 @@ sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
|
||||
WASMModuleInstance *sub_module_inst = NULL;
|
||||
|
||||
sub_module_inst =
|
||||
wasm_instantiate(sub_module, false, NULL, stack_size, heap_size,
|
||||
wasm_instantiate(sub_module, NULL, NULL, stack_size, heap_size,
|
||||
error_buf, error_buf_size);
|
||||
if (!sub_module_inst) {
|
||||
LOG_DEBUG("instantiate %s failed",
|
||||
@ -1642,7 +1626,7 @@ wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode)
|
||||
* Instantiate module
|
||||
*/
|
||||
WASMModuleInstance *
|
||||
wasm_instantiate(WASMModule *module, bool is_sub_inst,
|
||||
wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
||||
WASMExecEnv *exec_env_main, uint32 stack_size,
|
||||
uint32 heap_size, char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
@ -1659,6 +1643,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
bool ret = false;
|
||||
#endif
|
||||
const bool is_sub_inst = parent != NULL;
|
||||
|
||||
if (!module)
|
||||
return NULL;
|
||||
@ -1777,8 +1762,9 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
|
||||
|
||||
/* Instantiate memories/tables/functions */
|
||||
if ((module_inst->memory_count > 0
|
||||
&& !(module_inst->memories = memories_instantiate(
|
||||
module, module_inst, heap_size, error_buf, error_buf_size)))
|
||||
&& !(module_inst->memories =
|
||||
memories_instantiate(module, module_inst, parent, heap_size,
|
||||
error_buf, error_buf_size)))
|
||||
|| (module_inst->table_count > 0
|
||||
&& !(module_inst->tables =
|
||||
tables_instantiate(module, module_inst, first_table,
|
||||
@ -2212,16 +2198,6 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
|
||||
sub_module_deinstantiate(module_inst);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
/* Destroy wasi resource before freeing app heap, since some fields of
|
||||
wasi contex are allocated from app heap, and if app heap is freed,
|
||||
these fields will be set to NULL, we cannot free their internal data
|
||||
which may allocated from global heap. */
|
||||
/* Only destroy wasi ctx in the main module instance */
|
||||
if (!is_sub_inst)
|
||||
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst);
|
||||
#endif
|
||||
|
||||
if (module_inst->memory_count > 0)
|
||||
memories_deinstantiate(module_inst, module_inst->memories,
|
||||
module_inst->memory_count);
|
||||
@ -2254,10 +2230,14 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
|
||||
if (module_inst->e->c_api_func_imports)
|
||||
wasm_runtime_free(module_inst->e->c_api_func_imports);
|
||||
|
||||
if (!is_sub_inst) {
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst);
|
||||
#endif
|
||||
#if WASM_ENABLE_WASI_NN != 0
|
||||
if (!is_sub_inst)
|
||||
wasi_nn_destroy(module_inst);
|
||||
#endif
|
||||
}
|
||||
|
||||
wasm_runtime_free(module_inst);
|
||||
}
|
||||
@ -3297,13 +3277,13 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
|
||||
bh_assert(tbl_inst);
|
||||
bh_assert(tbl_seg);
|
||||
|
||||
if (!length) {
|
||||
if (offset_len_out_of_bounds(src_offset, length, tbl_seg->function_count)
|
||||
|| offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) {
|
||||
jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (length + src_offset > tbl_seg->function_count
|
||||
|| dst_offset + length > tbl_inst->cur_size) {
|
||||
jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
|
||||
if (!length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3345,8 +3325,9 @@ llvm_jit_table_copy(WASMModuleInstance *module_inst, uint32 src_tbl_idx,
|
||||
bh_assert(src_tbl_inst);
|
||||
bh_assert(dst_tbl_inst);
|
||||
|
||||
if ((uint64)dst_offset + length > dst_tbl_inst->cur_size
|
||||
|| (uint64)src_offset + length > src_tbl_inst->cur_size) {
|
||||
if (offset_len_out_of_bounds(dst_offset, length, dst_tbl_inst->cur_size)
|
||||
|| offset_len_out_of_bounds(src_offset, length,
|
||||
src_tbl_inst->cur_size)) {
|
||||
jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
|
||||
return;
|
||||
}
|
||||
@ -3378,7 +3359,7 @@ llvm_jit_table_fill(WASMModuleInstance *module_inst, uint32 tbl_idx,
|
||||
tbl_inst = wasm_get_table_inst(module_inst, tbl_idx);
|
||||
bh_assert(tbl_inst);
|
||||
|
||||
if (data_offset + length > tbl_inst->cur_size) {
|
||||
if (offset_len_out_of_bounds(data_offset, length, tbl_inst->cur_size)) {
|
||||
jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#define _WASM_RUNTIME_H
|
||||
|
||||
#include "wasm.h"
|
||||
#include "bh_atomic.h"
|
||||
#include "bh_hashmap.h"
|
||||
#include "../common/wasm_runtime_common.h"
|
||||
#include "../common/wasm_exec_env.h"
|
||||
@ -79,7 +80,7 @@ struct WASMMemoryInstance {
|
||||
/* Module type */
|
||||
uint32 module_type;
|
||||
/* Shared memory flag */
|
||||
bool is_shared;
|
||||
bh_atomic_32_t ref_count; /* 0: non-shared, > 0: reference count */
|
||||
|
||||
/* Number bytes per page */
|
||||
uint32 num_bytes_per_page;
|
||||
@ -400,7 +401,7 @@ void
|
||||
wasm_unload(WASMModule *module);
|
||||
|
||||
WASMModuleInstance *
|
||||
wasm_instantiate(WASMModule *module, bool is_sub_inst,
|
||||
wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
||||
WASMExecEnv *exec_env_main, uint32 stack_size,
|
||||
uint32 heap_size, char *error_buf, uint32 error_buf_size);
|
||||
|
||||
|
||||
@ -531,7 +531,8 @@ pthread_start_routine(void *arg)
|
||||
else {
|
||||
info_node->u.ret = (void *)(uintptr_t)argv[0];
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
if (exec_env->suspend_flags.flags & 0x08)
|
||||
if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags)
|
||||
& WASM_SUSPEND_FLAG_EXIT)
|
||||
/* argv[0] isn't set after longjmp(1) to
|
||||
invoke_native_with_hw_bound_check */
|
||||
info_node->u.ret = exec_env->thread_ret_value;
|
||||
@ -580,7 +581,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
|
||||
#endif
|
||||
|
||||
if (!(new_module_inst = wasm_runtime_instantiate_internal(
|
||||
module, true, exec_env, stack_size, 0, NULL, 0)))
|
||||
module, module_inst, exec_env, stack_size, 0, NULL, 0)))
|
||||
return -1;
|
||||
|
||||
/* Set custom_data to new module instance */
|
||||
@ -690,6 +691,14 @@ pthread_join_wrapper(wasm_exec_env_t exec_env, uint32 thread,
|
||||
bh_assert(node->joinable);
|
||||
join_ret = 0;
|
||||
ret = node->u.ret;
|
||||
|
||||
/* The target thread changes the node's status before calling
|
||||
wasm_cluster_exit_thread to exit, so here its resources may
|
||||
haven't been destroyed yet, we wait enough time to ensure that
|
||||
they are actually destroyed to avoid unexpected behavior. */
|
||||
os_mutex_lock(&exec_env->wait_lock);
|
||||
os_cond_reltimedwait(&exec_env->wait_cond, &exec_env->wait_lock, 1000);
|
||||
os_mutex_unlock(&exec_env->wait_lock);
|
||||
}
|
||||
|
||||
if (retval_offset != 0)
|
||||
@ -757,7 +766,6 @@ __pthread_self_wrapper(wasm_exec_env_t exec_env)
|
||||
static void
|
||||
pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
ThreadRoutineArgs *args = get_thread_arg(exec_env);
|
||||
/* Currently exit main thread is not allowed */
|
||||
if (!args)
|
||||
@ -775,9 +783,6 @@ pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset)
|
||||
/* destroy pthread key values */
|
||||
call_key_destructor(exec_env);
|
||||
|
||||
/* routine exit, destroy instance */
|
||||
wasm_runtime_deinstantiate_internal(module_inst, true);
|
||||
|
||||
if (!args->info_node->joinable) {
|
||||
delete_thread_info_node(args->info_node);
|
||||
}
|
||||
@ -789,6 +794,8 @@ pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset)
|
||||
|
||||
wasm_runtime_free(args);
|
||||
|
||||
/* Don't destroy exec_env->module_inst in this functuntion since
|
||||
it will be destroyed in wasm_cluster_exit_thread */
|
||||
wasm_cluster_exit_thread(exec_env, (void *)(uintptr_t)retval_offset);
|
||||
}
|
||||
|
||||
|
||||
@ -46,6 +46,7 @@ test_nslookup_mt(void *params)
|
||||
{
|
||||
int *af = (int *)params;
|
||||
test_nslookup(*af);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#ifdef __wasi__
|
||||
#include <wasi/api.h>
|
||||
#include <sys/socket.h>
|
||||
@ -12,105 +14,123 @@
|
||||
#endif
|
||||
#include <arpa/inet.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define SERVER_MSG "Message from server."
|
||||
#define PORT 8989
|
||||
pthread_mutex_t mut;
|
||||
pthread_cond_t cond;
|
||||
|
||||
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
int server_init_complete = 0;
|
||||
char buffer[sizeof(SERVER_MSG) + 1];
|
||||
|
||||
struct socket_info {
|
||||
union {
|
||||
struct sockaddr_in addr_ipv4;
|
||||
struct sockaddr_in6 addr_ipv6;
|
||||
} addr;
|
||||
typedef struct {
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addr_len;
|
||||
int sock;
|
||||
};
|
||||
|
||||
struct thread_args {
|
||||
int family;
|
||||
int protocol;
|
||||
};
|
||||
} socket_info_t;
|
||||
|
||||
struct socket_info
|
||||
init_socket_addr(int family, int protocol)
|
||||
void
|
||||
wait_for_server(int wait_time_seconds)
|
||||
{
|
||||
int sock = socket(family, protocol, 0);
|
||||
assert(sock != -1);
|
||||
int res = 0;
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ts.tv_sec += wait_time_seconds;
|
||||
|
||||
struct socket_info info;
|
||||
if (family == AF_INET) {
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(PORT);
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
info.addr.addr_ipv4 = addr;
|
||||
pthread_mutex_lock(&mut);
|
||||
while (server_init_complete == 0) {
|
||||
res = pthread_cond_timedwait(&cond, &mut, &ts);
|
||||
if (res == ETIMEDOUT)
|
||||
break;
|
||||
}
|
||||
else if (family == AF_INET6) {
|
||||
struct sockaddr_in6 addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin6_family = AF_INET6;
|
||||
addr.sin6_port = htons(PORT);
|
||||
addr.sin6_addr = in6addr_loopback;
|
||||
info.addr.addr_ipv6 = addr;
|
||||
}
|
||||
info.sock = sock;
|
||||
return info;
|
||||
pthread_mutex_unlock(&mut);
|
||||
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void
|
||||
assert_thread_args(struct thread_args *args)
|
||||
notify_server_started()
|
||||
{
|
||||
assert(args->family == AF_INET || args->family == AF_INET6);
|
||||
assert(args->protocol == SOCK_STREAM || args->protocol == SOCK_DGRAM);
|
||||
pthread_mutex_lock(&mut);
|
||||
server_init_complete = 1;
|
||||
pthread_cond_signal(&cond);
|
||||
pthread_mutex_unlock(&mut);
|
||||
}
|
||||
|
||||
socket_info_t
|
||||
init_socket_addr(int family, int protocol)
|
||||
{
|
||||
socket_info_t info;
|
||||
|
||||
info.sock = socket(family, protocol, 0);
|
||||
assert(info.sock != -1);
|
||||
info.protocol = protocol;
|
||||
|
||||
memset(&info.addr, 0, sizeof(info.addr));
|
||||
|
||||
if (family == AF_INET) {
|
||||
struct sockaddr_in *addr = (struct sockaddr_in *)&info.addr;
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_port = htons(PORT);
|
||||
addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
info.addr_len = sizeof(struct sockaddr_in);
|
||||
}
|
||||
else if (family == AF_INET6) {
|
||||
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&info.addr;
|
||||
addr->sin6_family = AF_INET6;
|
||||
addr->sin6_port = htons(PORT);
|
||||
addr->sin6_addr = in6addr_loopback;
|
||||
info.addr_len = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void *
|
||||
server(void *arg)
|
||||
{
|
||||
server_init_complete = 0;
|
||||
struct thread_args *args = (struct thread_args *)arg;
|
||||
assert_thread_args(args);
|
||||
|
||||
struct socket_info init_server_sock =
|
||||
init_socket_addr(args->family, args->protocol);
|
||||
|
||||
int server_sock = init_server_sock.sock;
|
||||
socklen_t addr_size;
|
||||
char buffer[sizeof(SERVER_MSG) + 1] = { 0 };
|
||||
struct sockaddr_storage client_addr;
|
||||
strcpy(buffer, SERVER_MSG);
|
||||
socket_info_t *info = (socket_info_t *)arg;
|
||||
struct sockaddr *server_addr = (struct sockaddr *)&info->addr;
|
||||
int server_sock = info->sock;
|
||||
|
||||
struct sockaddr *server_addr = (struct sockaddr *)&init_server_sock.addr;
|
||||
int ret = bind(server_sock, server_addr,
|
||||
args->family == AF_INET ? sizeof(struct sockaddr_in)
|
||||
: sizeof(struct sockaddr_in6));
|
||||
assert(ret == 0);
|
||||
int optval = 1;
|
||||
assert(setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &optval,
|
||||
sizeof(optval))
|
||||
== 0);
|
||||
|
||||
(args->protocol == SOCK_STREAM) && listen(server_sock, 1);
|
||||
pthread_mutex_lock(&mut);
|
||||
server_init_complete = 1;
|
||||
pthread_mutex_unlock(&mut);
|
||||
pthread_cond_signal(&cond);
|
||||
assert(bind(server_sock, server_addr, info->addr_len) == 0);
|
||||
|
||||
addr_size = sizeof(client_addr);
|
||||
if (args->protocol == SOCK_STREAM) {
|
||||
if (info->protocol == SOCK_STREAM)
|
||||
listen(server_sock, 1);
|
||||
notify_server_started();
|
||||
|
||||
socklen_t addr_size = info->addr_len;
|
||||
if (info->protocol == SOCK_STREAM) {
|
||||
int client_sock =
|
||||
accept(server_sock, (struct sockaddr *)&client_addr, &addr_size);
|
||||
assert(client_sock >= 0);
|
||||
sendto(client_sock, buffer, strlen(buffer), 0,
|
||||
(struct sockaddr *)&client_addr, addr_size);
|
||||
|
||||
assert(close(client_sock) == 0);
|
||||
assert(recv(client_sock, buffer, sizeof(buffer), 0) > 0);
|
||||
strcpy(buffer, SERVER_MSG);
|
||||
assert(send(client_sock, buffer, sizeof(buffer), 0) > 0);
|
||||
assert(recv(client_sock, buffer, sizeof(buffer), 0) > 0);
|
||||
}
|
||||
else {
|
||||
recvfrom(server_sock, buffer, sizeof(buffer), 0,
|
||||
(struct sockaddr *)&client_addr, &addr_size);
|
||||
sendto(server_sock, buffer, strlen(buffer), 0,
|
||||
(struct sockaddr *)&client_addr, addr_size);
|
||||
|
||||
assert(close(server_sock) == 0);
|
||||
assert(recvfrom(server_sock, buffer, sizeof(buffer), 0,
|
||||
(struct sockaddr *)&client_addr, &addr_size)
|
||||
> 0);
|
||||
strcpy(buffer, SERVER_MSG);
|
||||
assert(sendto(server_sock, buffer, strlen(buffer), 0,
|
||||
(struct sockaddr *)&client_addr, addr_size)
|
||||
> 0);
|
||||
assert(recvfrom(server_sock, buffer, sizeof(buffer), 0,
|
||||
(struct sockaddr *)&client_addr, &addr_size)
|
||||
> 0);
|
||||
}
|
||||
assert(close(server_sock) == 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -118,46 +138,23 @@ server(void *arg)
|
||||
void *
|
||||
client(void *arg)
|
||||
{
|
||||
struct thread_args *args = (struct thread_args *)arg;
|
||||
assert_thread_args(args);
|
||||
char buffer[sizeof(SERVER_MSG) + 1];
|
||||
socket_info_t *info = (socket_info_t *)arg;
|
||||
int sock = info->sock;
|
||||
struct sockaddr *addr = (struct sockaddr *)&info->addr;
|
||||
|
||||
pthread_mutex_lock(&mut);
|
||||
wait_for_server(1);
|
||||
|
||||
while (server_init_complete == 0) {
|
||||
pthread_cond_wait(&cond, &mut);
|
||||
if (info->protocol == SOCK_STREAM) {
|
||||
assert(connect(sock, addr, info->addr_len) != -1);
|
||||
}
|
||||
|
||||
struct socket_info init_client_sock =
|
||||
init_socket_addr(args->family, args->protocol);
|
||||
int sock = init_client_sock.sock;
|
||||
pthread_mutex_unlock(&mut);
|
||||
|
||||
if (args->family == AF_INET) {
|
||||
struct sockaddr_in addr = init_client_sock.addr.addr_ipv4;
|
||||
if (args->protocol == SOCK_STREAM) {
|
||||
assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1);
|
||||
}
|
||||
else {
|
||||
assert(sendto(sock, buffer, strlen(buffer), 0,
|
||||
(struct sockaddr *)&addr, sizeof(addr))
|
||||
!= -1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
struct sockaddr_in6 addr = init_client_sock.addr.addr_ipv6;
|
||||
if (args->protocol == SOCK_STREAM) {
|
||||
assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1);
|
||||
}
|
||||
else {
|
||||
assert(sendto(sock, buffer, strlen(buffer), 0,
|
||||
(struct sockaddr *)&addr, sizeof(addr))
|
||||
!= -1);
|
||||
}
|
||||
}
|
||||
|
||||
recv(sock, buffer, sizeof(buffer), 0);
|
||||
assert(strcmp(buffer, SERVER_MSG) == 0);
|
||||
assert(sendto(sock, "open", strlen("open"), 0, addr, info->addr_len) > 0);
|
||||
assert(recv(sock, buffer, sizeof(buffer), 0) > 0);
|
||||
assert(strncmp(buffer, SERVER_MSG, strlen(SERVER_MSG)) == 0);
|
||||
assert(sendto(sock, "close", sizeof("close"), 0, addr, info->addr_len) > 0);
|
||||
assert(close(sock) == 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -165,17 +162,19 @@ void
|
||||
test_protocol(int family, int protocol)
|
||||
{
|
||||
pthread_t server_thread, client_thread;
|
||||
assert(pthread_cond_init(&cond, NULL) == 0);
|
||||
assert(pthread_mutex_init(&mut, NULL) == 0);
|
||||
socket_info_t server_info = init_socket_addr(family, protocol);
|
||||
socket_info_t client_info = init_socket_addr(family, protocol);
|
||||
|
||||
struct thread_args args = { family, protocol };
|
||||
assert(pthread_create(&server_thread, NULL, server, (void *)&args) == 0);
|
||||
assert(pthread_create(&client_thread, NULL, client, (void *)&args) == 0);
|
||||
printf("Testing address family: %d protocol: %d\n", family, protocol);
|
||||
|
||||
server_init_complete = 0;
|
||||
|
||||
assert(pthread_create(&server_thread, NULL, server, (void *)&server_info)
|
||||
== 0);
|
||||
assert(pthread_create(&client_thread, NULL, client, (void *)&client_info)
|
||||
== 0);
|
||||
assert(pthread_join(server_thread, NULL) == 0);
|
||||
assert(pthread_join(client_thread, NULL) == 0);
|
||||
|
||||
assert(pthread_mutex_destroy(&mut) == 0);
|
||||
assert(pthread_cond_destroy(&cond) == 0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -190,4 +189,4 @@ main(int argc, char **argv)
|
||||
test_protocol(AF_INET6, SOCK_DGRAM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
|
||||
stack_size = ((WASMModuleInstance *)module_inst)->default_wasm_stack_size;
|
||||
|
||||
if (!(new_module_inst = wasm_runtime_instantiate_internal(
|
||||
module, true, exec_env, stack_size, 0, NULL, 0)))
|
||||
module, module_inst, exec_env, stack_size, 0, NULL, 0)))
|
||||
return -1;
|
||||
|
||||
wasm_runtime_set_custom_data_internal(
|
||||
|
||||
@ -9,10 +9,13 @@ set -eo pipefail
|
||||
CC=${CC:=/opt/wasi-sdk/bin/clang}
|
||||
WAMR_DIR=../../../../..
|
||||
|
||||
# Stress tests names
|
||||
thread_start_file_exclusions=("spawn_stress_test.wasm" "linear_memory_size_update.wasm")
|
||||
|
||||
for test_c in *.c; do
|
||||
test_wasm="$(basename $test_c .c).wasm"
|
||||
|
||||
if [ $test_wasm = "linear_memory_size_update.wasm" ]; then
|
||||
if [[ " ${thread_start_file_exclusions[@]} " =~ " ${test_wasm} " ]] ; then
|
||||
thread_start_file=""
|
||||
else
|
||||
thread_start_file=$WAMR_DIR/samples/wasi-threads/wasm-apps/wasi_thread_start.S
|
||||
|
||||
3
core/iwasm/libraries/lib-wasi-threads/test/manifest.json
Normal file
3
core/iwasm/libraries/lib-wasi-threads/test/manifest.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "lib-wasi-threads tests"
|
||||
}
|
||||
5
core/iwasm/libraries/lib-wasi-threads/test/skip.json
Normal file
5
core/iwasm/libraries/lib-wasi-threads/test/skip.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"lib-wasi-threads tests": {
|
||||
"spawn_stress_test": "Stress tests are incompatible with the other part and executed differently"
|
||||
}
|
||||
}
|
||||
114
core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c
Normal file
114
core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef __wasi__
|
||||
#error This example only compiles to WASM/WASI target
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
enum CONSTANTS {
|
||||
NUM_ITER = 100000,
|
||||
NUM_RETRY = 5,
|
||||
MAX_NUM_THREADS = 8,
|
||||
};
|
||||
|
||||
unsigned prime_numbers_count = 0;
|
||||
|
||||
bool
|
||||
is_prime(unsigned int num)
|
||||
{
|
||||
for (unsigned int i = 2; i <= (unsigned int)(sqrt(num)); ++i) {
|
||||
if (num % i == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void *
|
||||
check_if_prime(void *value)
|
||||
{
|
||||
unsigned int *num = (unsigned int *)(value);
|
||||
usleep(10000);
|
||||
if (is_prime(*num)) {
|
||||
__atomic_fetch_add(&prime_numbers_count, 1, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
validate()
|
||||
{
|
||||
unsigned int counter = 0;
|
||||
for (unsigned int i = 2; i <= NUM_ITER; ++i) {
|
||||
counter += is_prime(i);
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
void
|
||||
spawn_thread(pthread_t *thread, unsigned int *arg)
|
||||
{
|
||||
int status_code = -1;
|
||||
for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) {
|
||||
status_code = pthread_create(thread, NULL, &check_if_prime, arg);
|
||||
assert(status_code == 0 || status_code == EAGAIN);
|
||||
if (status_code == EAGAIN) {
|
||||
usleep(2000);
|
||||
}
|
||||
}
|
||||
|
||||
assert(status_code == 0 && "Thread creation should succeed");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
pthread_t threads[MAX_NUM_THREADS];
|
||||
unsigned int args[MAX_NUM_THREADS];
|
||||
double percentage = 0.1;
|
||||
|
||||
for (unsigned int factorised_number = 2; factorised_number < NUM_ITER;
|
||||
++factorised_number) {
|
||||
if (factorised_number > NUM_ITER * percentage) {
|
||||
fprintf(stderr, "Stress test is %d%% finished\n",
|
||||
(unsigned int)(percentage * 100));
|
||||
percentage += 0.1;
|
||||
}
|
||||
|
||||
unsigned int thread_num = factorised_number % MAX_NUM_THREADS;
|
||||
if (threads[thread_num] != 0) {
|
||||
assert(pthread_join(threads[thread_num], NULL) == 0);
|
||||
}
|
||||
|
||||
args[thread_num] = factorised_number;
|
||||
|
||||
usleep(2000);
|
||||
spawn_thread(&threads[thread_num], &args[thread_num]);
|
||||
assert(threads[thread_num] != 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_NUM_THREADS; ++i) {
|
||||
assert(threads[i] == 0 || pthread_join(threads[i], NULL) == 0);
|
||||
}
|
||||
|
||||
// Check the test results
|
||||
assert(
|
||||
prime_numbers_count == validate()
|
||||
&& "Answer mismatch between tested code and reference implementation");
|
||||
|
||||
fprintf(stderr, "Stress test finished successfully\n");
|
||||
return 0;
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
set (LIBC_WASI_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
set (LIBUV_VERSION v1.44.2)
|
||||
set (LIBUV_VERSION v1.46.0)
|
||||
|
||||
add_definitions (-DWASM_ENABLE_LIBC_WASI=1 -DWASM_ENABLE_UVWASI=1)
|
||||
|
||||
|
||||
@ -509,7 +509,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
|
||||
#endif
|
||||
|
||||
if (!(new_module_inst = wasm_runtime_instantiate_internal(
|
||||
module, true, exec_env, stack_size, 0, NULL, 0))) {
|
||||
module, module_inst, exec_env, stack_size, 0, NULL, 0))) {
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
@ -606,7 +606,8 @@ thread_manager_start_routine(void *arg)
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
os_mutex_lock(&exec_env->wait_lock);
|
||||
if (exec_env->suspend_flags.flags & 0x08)
|
||||
if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags)
|
||||
& WASM_SUSPEND_FLAG_EXIT)
|
||||
ret = exec_env->thread_ret_value;
|
||||
os_mutex_unlock(&exec_env->wait_lock);
|
||||
#endif
|
||||
@ -993,7 +994,9 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval)
|
||||
if (exec_env->jmpbuf_stack_top) {
|
||||
/* Store the return value in exec_env */
|
||||
exec_env->thread_ret_value = retval;
|
||||
exec_env->suspend_flags.flags |= 0x08;
|
||||
|
||||
WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags,
|
||||
WASM_SUSPEND_FLAG_EXIT);
|
||||
|
||||
#ifndef BH_PLATFORM_WINDOWS
|
||||
/* Pop all jmpbuf_node except the last one */
|
||||
@ -1055,7 +1058,8 @@ set_thread_cancel_flags(WASMExecEnv *exec_env)
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||
wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM);
|
||||
#endif
|
||||
exec_env->suspend_flags.flags |= 0x01;
|
||||
WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags,
|
||||
WASM_SUSPEND_FLAG_TERMINATE);
|
||||
|
||||
os_mutex_unlock(&exec_env->wait_lock);
|
||||
}
|
||||
@ -1178,7 +1182,8 @@ void
|
||||
wasm_cluster_suspend_thread(WASMExecEnv *exec_env)
|
||||
{
|
||||
/* Set the suspend flag */
|
||||
exec_env->suspend_flags.flags |= 0x02;
|
||||
WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags,
|
||||
WASM_SUSPEND_FLAG_SUSPEND);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1214,7 +1219,8 @@ wasm_cluster_suspend_all_except_self(WASMCluster *cluster,
|
||||
void
|
||||
wasm_cluster_resume_thread(WASMExecEnv *exec_env)
|
||||
{
|
||||
exec_env->suspend_flags.flags &= ~0x02;
|
||||
WASM_SUSPEND_FLAGS_FETCH_AND(exec_env->suspend_flags,
|
||||
~WASM_SUSPEND_FLAG_SUSPEND);
|
||||
os_cond_signal(&exec_env->wait_cond);
|
||||
}
|
||||
|
||||
@ -1248,10 +1254,8 @@ set_exception_visitor(void *node, void *user_data)
|
||||
|
||||
/* 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);
|
||||
if (curr_wasm_inst->memory_count > 0)
|
||||
shared_memory_lock(curr_wasm_inst->memories[0]);
|
||||
#endif
|
||||
if (!strstr(wasm_inst->cur_exception, "wasi proc exit")) {
|
||||
bh_memcpy_s(curr_wasm_inst->cur_exception,
|
||||
@ -1260,8 +1264,8 @@ set_exception_visitor(void *node, void *user_data)
|
||||
sizeof(wasm_inst->cur_exception));
|
||||
}
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (shared_mem_node)
|
||||
os_mutex_unlock(&shared_mem_node->shared_mem_lock);
|
||||
if (curr_wasm_inst->memory_count > 0)
|
||||
shared_memory_unlock(curr_wasm_inst->memories[0]);
|
||||
#endif
|
||||
|
||||
/* Terminate the thread so it can exit from dead loops */
|
||||
@ -1280,15 +1284,13 @@ clear_exception_visitor(void *node, void *user_data)
|
||||
(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);
|
||||
if (curr_wasm_inst->memory_count > 0)
|
||||
shared_memory_lock(curr_wasm_inst->memories[0]);
|
||||
#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);
|
||||
if (curr_wasm_inst->memory_count > 0)
|
||||
shared_memory_unlock(curr_wasm_inst->memories[0]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -1343,8 +1345,10 @@ bool
|
||||
wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env)
|
||||
{
|
||||
os_mutex_lock(&exec_env->wait_lock);
|
||||
bool is_thread_terminated =
|
||||
(exec_env->suspend_flags.flags & 0x01) ? true : false;
|
||||
bool is_thread_terminated = (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags)
|
||||
& WASM_SUSPEND_FLAG_TERMINATE)
|
||||
? true
|
||||
: false;
|
||||
os_mutex_unlock(&exec_env->wait_lock);
|
||||
|
||||
return is_thread_terminated;
|
||||
|
||||
@ -5,16 +5,34 @@
|
||||
|
||||
#include "platform_api_vmcore.h"
|
||||
#include "platform_api_extension.h"
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
#include "soc/mmu.h"
|
||||
#include "rom/cache.h"
|
||||
|
||||
#define MEM_DUAL_BUS_OFFSET (IRAM0_CACHE_ADDRESS_LOW - DRAM0_CACHE_ADDRESS_LOW)
|
||||
|
||||
#define in_ibus_ext(addr) \
|
||||
(((uint32)addr >= IRAM0_CACHE_ADDRESS_LOW) \
|
||||
&& ((uint32)addr < IRAM0_CACHE_ADDRESS_HIGH))
|
||||
|
||||
static portMUX_TYPE s_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
#endif
|
||||
|
||||
void *
|
||||
os_mmap(void *hint, size_t size, int prot, int flags)
|
||||
{
|
||||
if (prot & MMAP_PROT_EXEC) {
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
uint32_t mem_caps = MALLOC_CAP_SPIRAM;
|
||||
#else
|
||||
uint32_t mem_caps = MALLOC_CAP_EXEC;
|
||||
#endif
|
||||
|
||||
// Memory allocation with MALLOC_CAP_EXEC will return 4-byte aligned
|
||||
// Reserve extra 4 byte to fixup alignment and size for the pointer to
|
||||
// the originally allocated address
|
||||
void *buf_origin =
|
||||
heap_caps_malloc(size + 4 + sizeof(uintptr_t), MALLOC_CAP_EXEC);
|
||||
heap_caps_malloc(size + 4 + sizeof(uintptr_t), mem_caps);
|
||||
if (!buf_origin) {
|
||||
return NULL;
|
||||
}
|
||||
@ -25,19 +43,35 @@ os_mmap(void *hint, size_t size, int prot, int flags)
|
||||
|
||||
uintptr_t *addr_field = buf_fixed - sizeof(uintptr_t);
|
||||
*addr_field = (uintptr_t)buf_origin;
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
return buf_fixed + MEM_DUAL_BUS_OFFSET;
|
||||
#else
|
||||
return buf_fixed;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
return os_malloc(size);
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
uint32_t mem_caps = MALLOC_CAP_SPIRAM;
|
||||
#else
|
||||
uint32_t mem_caps = MALLOC_CAP_8BIT;
|
||||
#endif
|
||||
return heap_caps_malloc(size, mem_caps);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
os_munmap(void *addr, size_t size)
|
||||
{
|
||||
char *ptr = (char *)addr;
|
||||
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
if (in_ibus_ext(ptr)) {
|
||||
ptr -= MEM_DUAL_BUS_OFFSET;
|
||||
}
|
||||
#endif
|
||||
// We don't need special handling of the executable allocations
|
||||
// here, free() of esp-idf handles it properly
|
||||
return os_free(addr);
|
||||
return os_free(ptr);
|
||||
}
|
||||
|
||||
int
|
||||
@ -47,5 +81,34 @@ os_mprotect(void *addr, size_t size, int prot)
|
||||
}
|
||||
|
||||
void
|
||||
os_dcache_flush()
|
||||
{}
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
IRAM_ATTR
|
||||
#endif
|
||||
os_dcache_flush()
|
||||
{
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
uint32_t preload;
|
||||
extern void Cache_WriteBack_All(void);
|
||||
|
||||
portENTER_CRITICAL(&s_spinlock);
|
||||
|
||||
Cache_WriteBack_All();
|
||||
preload = Cache_Disable_ICache();
|
||||
Cache_Enable_ICache(preload);
|
||||
|
||||
portEXIT_CRITICAL(&s_spinlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
void *
|
||||
os_get_dbus_mirror(void *ibus)
|
||||
{
|
||||
if (in_ibus_ext(ibus)) {
|
||||
return (void *)((char *)ibus - MEM_DUAL_BUS_OFFSET);
|
||||
}
|
||||
else {
|
||||
return ibus;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -11,3 +11,9 @@ include_directories(${PLATFORM_SHARED_DIR}/../include)
|
||||
file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
|
||||
|
||||
set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE})
|
||||
|
||||
# If enable PSRAM of ESP32-S3, it had better to put AOT into PSRAM, so that
|
||||
# users can use SRAM to for Wi-Fi/BLE and peripheral driver.
|
||||
if(CONFIG_ESP32S3_SPIRAM_SUPPORT)
|
||||
add_definitions(-DWASM_MEM_DUAL_BUS_MIRROR=1)
|
||||
endif()
|
||||
|
||||
@ -129,6 +129,11 @@ os_munmap(void *addr, size_t size);
|
||||
int
|
||||
os_mprotect(void *addr, size_t size, int prot);
|
||||
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
void *
|
||||
os_get_dbus_mirror(void *ibus);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Flush cpu data cache, in some CPUs, after applying relocation to the
|
||||
* AOT code, the code may haven't been written back to the cpu data cache,
|
||||
|
||||
@ -10,6 +10,46 @@
|
||||
#include <nuttx/arch.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARCH_CHIP_ESP32S3)
|
||||
/*
|
||||
* TODO: Move these methods below the operating system level
|
||||
*/
|
||||
#define MEM_DUAL_BUS_OFFSET (0x42000000 - 0x3C000000)
|
||||
#define IRAM0_CACHE_ADDRESS_LOW 0x42000000
|
||||
#define IRAM0_CACHE_ADDRESS_HIGH 0x44000000
|
||||
#define IRAM_ATTR locate_data(".iram1")
|
||||
|
||||
#define in_ibus_ext(addr) \
|
||||
(((uint32)addr >= IRAM0_CACHE_ADDRESS_LOW) \
|
||||
&& ((uint32)addr < IRAM0_CACHE_ADDRESS_HIGH))
|
||||
void IRAM_ATTR
|
||||
bus_sync(void)
|
||||
{
|
||||
extern void cache_writeback_all(void);
|
||||
extern uint32_t Cache_Disable_ICache(void);
|
||||
extern void Cache_Enable_ICache(uint32_t autoload);
|
||||
|
||||
irqstate_t flags;
|
||||
uint32_t preload;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
cache_writeback_all();
|
||||
preload = Cache_Disable_ICache();
|
||||
Cache_Enable_ICache(preload);
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
#else
|
||||
#define MEM_DUAL_BUS_OFFSET (0)
|
||||
#define IRAM0_CACHE_ADDRESS_LOW (0)
|
||||
#define IRAM0_CACHE_ADDRESS_HIGH (0)
|
||||
#define in_ibus_ext(addr) (0)
|
||||
static void
|
||||
bus_sync(void)
|
||||
{}
|
||||
#endif
|
||||
|
||||
int
|
||||
bh_platform_init()
|
||||
{
|
||||
@ -47,6 +87,10 @@ os_dumps_proc_mem_info(char *out, unsigned int size)
|
||||
void *
|
||||
os_mmap(void *hint, size_t size, int prot, int flags)
|
||||
{
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
void *i_addr, *d_addr;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
|
||||
if ((prot & MMAP_PROT_EXEC) != 0) {
|
||||
return up_textheap_memalign(sizeof(void *), size);
|
||||
@ -55,6 +99,17 @@ os_mmap(void *hint, size_t size, int prot, int flags)
|
||||
|
||||
if ((uint64)size >= UINT32_MAX)
|
||||
return NULL;
|
||||
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
if ((prot & MMAP_PROT_EXEC) != 0) {
|
||||
d_addr = malloc((uint32)size);
|
||||
if (d_addr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
i_addr = (void *)((uint8 *)d_addr + MEM_DUAL_BUS_OFFSET);
|
||||
return in_ibus_ext(i_addr) ? i_addr : d_addr;
|
||||
}
|
||||
#endif
|
||||
return malloc((uint32)size);
|
||||
}
|
||||
|
||||
@ -67,7 +122,14 @@ os_munmap(void *addr, size_t size)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
return free(addr);
|
||||
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
if (in_ibus_ext(addr)) {
|
||||
free((void *)((uint8 *)addr - MEM_DUAL_BUS_OFFSET));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
free(addr);
|
||||
}
|
||||
|
||||
int
|
||||
@ -78,7 +140,22 @@ os_mprotect(void *addr, size_t size, int prot)
|
||||
|
||||
void
|
||||
os_dcache_flush()
|
||||
{}
|
||||
{
|
||||
bus_sync();
|
||||
}
|
||||
|
||||
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
|
||||
void *
|
||||
os_get_dbus_mirror(void *ibus)
|
||||
{
|
||||
if (in_ibus_ext(ibus)) {
|
||||
return (void *)((uint8 *)ibus - MEM_DUAL_BUS_OFFSET);
|
||||
}
|
||||
else {
|
||||
return ibus;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If AT_FDCWD is provided, maybe we have openat family */
|
||||
#if !defined(AT_FDCWD)
|
||||
|
||||
123
core/shared/utils/bh_atomic.h
Normal file
123
core/shared/utils/bh_atomic.h
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Amazon Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _BH_ATOMIC_H
|
||||
#define _BH_ATOMIC_H
|
||||
|
||||
#include "gnuc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Why don't we use C11 stdatomics here?
|
||||
*
|
||||
* Unlike C11 stdatomics,
|
||||
*
|
||||
* - bh_atomic_xxx_t is guaranteed to have the same size as the base type.
|
||||
* Thus more friendly to our AOT conventions.
|
||||
*
|
||||
* - It's available for C++.
|
||||
* Although C++23 will have C-compatible stdatomics.h, it isn't widely
|
||||
* available yet.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note about BH_ATOMIC_32_IS_ATOMIC
|
||||
*
|
||||
* If BH_ATOMIC_32_IS_ATOMIC == 0, BH_ATOMIC_xxx operations defined below
|
||||
* are not really atomic and require an external lock.
|
||||
*
|
||||
* Expected usage is:
|
||||
*
|
||||
* bh_atomic_32_t var = 0;
|
||||
* uint32 old;
|
||||
* #if BH_ATOMIC_32_IS_ATOMIC == 0
|
||||
* lock(&some_lock);
|
||||
* #endif
|
||||
* old = BH_ATOMIC_32_FETCH_AND(var, 1);
|
||||
* #if BH_ATOMIC_32_IS_ATOMIC == 0
|
||||
* unlock(&some_lock);
|
||||
* #endif
|
||||
*/
|
||||
|
||||
typedef uint32 bh_atomic_32_t;
|
||||
|
||||
#if defined(__GNUC_PREREQ)
|
||||
#if __GNUC_PREREQ(4, 7)
|
||||
#define CLANG_GCC_HAS_ATOMIC_BUILTIN
|
||||
#endif
|
||||
#elif defined(__clang__)
|
||||
#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 0)
|
||||
#define CLANG_GCC_HAS_ATOMIC_BUILTIN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CLANG_GCC_HAS_ATOMIC_BUILTIN)
|
||||
#define BH_ATOMIC_32_IS_ATOMIC 1
|
||||
#define BH_ATOMIC_32_LOAD(v) __atomic_load_n(&(v), __ATOMIC_SEQ_CST)
|
||||
#define BH_ATOMIC_32_FETCH_OR(v, val) \
|
||||
__atomic_fetch_or(&(v), (val), __ATOMIC_SEQ_CST)
|
||||
#define BH_ATOMIC_32_FETCH_AND(v, val) \
|
||||
__atomic_fetch_and(&(v), (val), __ATOMIC_SEQ_CST)
|
||||
#define BH_ATOMIC_32_FETCH_ADD(v, val) \
|
||||
__atomic_fetch_add(&(v), (val), __ATOMIC_SEQ_CST)
|
||||
#define BH_ATOMIC_32_FETCH_SUB(v, val) \
|
||||
__atomic_fetch_sub(&(v), (val), __ATOMIC_SEQ_CST)
|
||||
#else /* else of defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) */
|
||||
#define BH_ATOMIC_32_LOAD(v) (v)
|
||||
#define BH_ATOMIC_32_FETCH_OR(v, val) nonatomic_32_fetch_or(&(v), val)
|
||||
#define BH_ATOMIC_32_FETCH_AND(v, val) nonatomic_32_fetch_and(&(v), val)
|
||||
#define BH_ATOMIC_32_FETCH_ADD(v, val) nonatomic_32_fetch_add(&(v), val)
|
||||
#define BH_ATOMIC_32_FETCH_SUB(v, val) nonatomic_32_fetch_sub(&(v), val)
|
||||
|
||||
static inline uint32
|
||||
nonatomic_32_fetch_or(bh_atomic_32_t *p, uint32 val)
|
||||
{
|
||||
uint32 old = *p;
|
||||
*p |= val;
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline uint32
|
||||
nonatomic_32_fetch_and(bh_atomic_32_t *p, uint32 val)
|
||||
{
|
||||
uint32 old = *p;
|
||||
*p &= val;
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline uint32
|
||||
nonatomic_32_fetch_add(bh_atomic_32_t *p, uint32 val)
|
||||
{
|
||||
uint32 old = *p;
|
||||
*p += val;
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline uint32
|
||||
nonatomic_32_fetch_sub(bh_atomic_32_t *p, uint32 val)
|
||||
{
|
||||
uint32 old = *p;
|
||||
*p -= val;
|
||||
return old;
|
||||
}
|
||||
|
||||
/* The flag can be defined by the user if the platform
|
||||
supports atomic access to uint32 aligned memory. */
|
||||
#ifdef WASM_UINT32_IS_ATOMIC
|
||||
#define BH_ATOMIC_32_IS_ATOMIC 1
|
||||
#else /* else of WASM_UINT32_IS_ATOMIC */
|
||||
#define BH_ATOMIC_32_IS_ATOMIC 0
|
||||
#endif /* WASM_UINT32_IS_ATOMIC */
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of _BH_ATOMIC_H */
|
||||
Reference in New Issue
Block a user