Merge pull request #2426 from bytecodealliance/main

Merge branch main into dev/wasi-libc-windows
This commit is contained in:
Wenyong Huang
2023-08-06 08:50:21 +08:00
committed by GitHub
66 changed files with 2278 additions and 1401 deletions

View File

@ -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_ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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 */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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.
*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -46,6 +46,7 @@ test_nslookup_mt(void *params)
{
int *af = (int *)params;
test_nslookup(*af);
return NULL;
}
int

View File

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

View File

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

View File

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

View File

@ -0,0 +1,3 @@
{
"name": "lib-wasi-threads tests"
}

View File

@ -0,0 +1,5 @@
{
"lib-wasi-threads tests": {
"spawn_stress_test": "Stress tests are incompatible with the other part and executed differently"
}
}

View 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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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 */