Merge branch main into dev/wasi-libc-windows

This commit is contained in:
Wenyong Huang
2023-10-08 15:03:35 +08:00
151 changed files with 5909 additions and 2046 deletions

View File

@ -107,7 +107,34 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
the actual main function. Directly calling main function
may cause exception thrown. */
if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) {
return wasm_runtime_call_wasm(exec_env, func, 0, NULL);
const char *wasi_proc_exit_exception = "wasi proc exit";
ret = wasm_runtime_call_wasm(exec_env, func, 0, NULL);
#if WASM_ENABLE_THREAD_MGR != 0
if (ret) {
/* On a successful return from the `_start` function,
we terminate other threads by mimicing wasi:proc_exit(0).
Note:
- A return from the `main` function is an equivalent of
exit(). (C standard)
- When exit code is 0, wasi-libc's `_start` function just
returns w/o calling `proc_exit`.
- A process termination should terminate threads in
the process. */
wasm_runtime_set_exception(module_inst, wasi_proc_exit_exception);
/* exit_code is zero-initialized */
ret = false;
}
#endif
/* report wasm proc exit as a success */
WASMModuleInstance *inst = (WASMModuleInstance *)module_inst;
if (!ret && strstr(inst->cur_exception, wasi_proc_exit_exception)) {
inst->cur_exception[0] = 0;
ret = true;
}
return ret;
}
#endif /* end of WASM_ENABLE_LIBC_WASI */
@ -204,7 +231,7 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
char *argv[])
{
bool ret;
#if (WASM_ENABLE_MEMORY_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
#if (WASM_ENABLE_MEMORY_PROFILING != 0)
WASMExecEnv *exec_env;
#endif
@ -224,14 +251,6 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
if (ret)
ret = wasm_runtime_get_exception(module_inst) == NULL;
#if WASM_ENABLE_DUMP_CALL_STACK != 0
if (!ret) {
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
if (exec_env)
wasm_runtime_dump_call_stack(exec_env);
}
#endif
return ret;
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2023 Midokura Japan KK. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wasm_runtime_common.h"
#include "bh_platform.h"
#include "bh_common.h"
#include "bh_assert.h"
#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
#define LOCK(env) WASM_SUSPEND_FLAGS_LOCK((env)->wait_lock)
#define UNLOCK(env) WASM_SUSPEND_FLAGS_UNLOCK((env)->wait_lock)
#define ISSET(env, bit) \
((WASM_SUSPEND_FLAGS_GET((env)->suspend_flags) & WASM_SUSPEND_FLAG_##bit) \
!= 0)
#define SET(env, bit) \
WASM_SUSPEND_FLAGS_FETCH_OR((env)->suspend_flags, WASM_SUSPEND_FLAG_##bit)
#define CLR(env, bit) \
WASM_SUSPEND_FLAGS_FETCH_AND((env)->suspend_flags, ~WASM_SUSPEND_FLAG_##bit)
bool
wasm_runtime_begin_blocking_op(wasm_exec_env_t env)
{
LOCK(env);
bh_assert(!ISSET(env, BLOCKING));
SET(env, BLOCKING);
if (ISSET(env, TERMINATE)) {
CLR(env, BLOCKING);
UNLOCK(env);
return false;
}
UNLOCK(env);
os_begin_blocking_op();
return true;
}
void
wasm_runtime_end_blocking_op(wasm_exec_env_t env)
{
int saved_errno = errno;
LOCK(env);
bh_assert(ISSET(env, BLOCKING));
CLR(env, BLOCKING);
UNLOCK(env);
os_end_blocking_op();
errno = saved_errno;
}
void
wasm_runtime_interrupt_blocking_op(wasm_exec_env_t env)
{
/*
* ISSET(BLOCKING) here means that the target thread
* is in somewhere between wasm_begin_blocking_op and
* wasm_end_blocking_op.
* keep waking it up until it reaches wasm_end_blocking_op,
* which clears the BLOCKING bit.
*
* this dumb loop is necessary because posix doesn't provide
* a way to unmask signal and block atomically.
*/
LOCK(env);
SET(env, TERMINATE);
while (ISSET(env, BLOCKING)) {
UNLOCK(env);
os_wakeup_blocking_op(env->handle);
/* relax a bit */
os_usleep(50 * 1000);
LOCK(env);
}
UNLOCK(env);
}
#else /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */
bool
wasm_runtime_begin_blocking_op(wasm_exec_env_t env)
{
return true;
}
void
wasm_runtime_end_blocking_op(wasm_exec_env_t env)
{}
#endif /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */

View File

@ -8,6 +8,7 @@
#include "../aot/aot_runtime.h"
#include "bh_platform.h"
#include "mem_alloc.h"
#include "wasm_memory.h"
#if WASM_ENABLE_SHARED_MEMORY != 0
#include "../common/wasm_shared_memory.h"
@ -24,6 +25,9 @@ static Memory_Mode memory_mode = MEMORY_MODE_UNKNOWN;
static mem_allocator_t pool_allocator = NULL;
static enlarge_memory_error_callback_t enlarge_memory_error_cb;
static void *enlarge_memory_error_user_data;
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
static void *allocator_user_data = NULL;
static void *(*malloc_func)(void *user_data, unsigned int size) = NULL;
@ -570,13 +574,16 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
{
WASMMemoryInstance *memory = wasm_get_default_memory(module);
uint8 *memory_data_old, *memory_data_new, *heap_data_old;
uint32 num_bytes_per_page, heap_size, total_size_old;
uint32 num_bytes_per_page, heap_size, total_size_old = 0;
uint32 cur_page_count, max_page_count, total_page_count;
uint64 total_size_new;
bool ret = true;
enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR;
if (!memory)
return false;
if (!memory) {
ret = false;
goto return_func;
}
heap_data_old = memory->heap_data;
heap_size = (uint32)(memory->heap_data_end - memory->heap_data);
@ -594,9 +601,15 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
/* No need to enlarge memory */
return true;
if (total_page_count < cur_page_count /* integer overflow */
|| total_page_count > max_page_count) {
return false;
if (total_page_count < cur_page_count) { /* integer overflow */
ret = false;
goto return_func;
}
if (total_page_count > max_page_count) {
failure_reason = MAX_SIZE_REACHED;
ret = false;
goto return_func;
}
bh_assert(total_size_new <= 4 * (uint64)BH_GB);
@ -622,14 +635,16 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
if (heap_size > 0) {
if (mem_allocator_is_heap_corrupted(memory->heap_handle)) {
wasm_runtime_show_app_heap_corrupted_prompt();
return false;
ret = false;
goto return_func;
}
}
if (!(memory_data_new =
wasm_runtime_realloc(memory_data_old, (uint32)total_size_new))) {
if (!(memory_data_new = wasm_runtime_malloc((uint32)total_size_new))) {
return false;
ret = false;
goto return_func;
}
if (memory_data_old) {
bh_memcpy_s(memory_data_new, (uint32)total_size_new,
@ -685,6 +700,27 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
os_writegsbase(memory_data_new);
#endif
return_func:
if (!ret && enlarge_memory_error_cb) {
WASMExecEnv *exec_env = NULL;
#if WASM_ENABLE_INTERP != 0
if (module->module_type == Wasm_Module_Bytecode)
exec_env =
((WASMModuleInstanceExtra *)module->e)->common.cur_exec_env;
#endif
#if WASM_ENABLE_AOT != 0
if (module->module_type == Wasm_Module_AoT)
exec_env =
((AOTModuleInstanceExtra *)module->e)->common.cur_exec_env;
#endif
enlarge_memory_error_cb(inc_page_count, total_size_old, 0,
failure_reason,
(WASMModuleInstanceCommon *)module, exec_env,
enlarge_memory_error_user_data);
}
return ret;
}
#else
@ -692,12 +728,16 @@ bool
wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
{
WASMMemoryInstance *memory = wasm_get_default_memory(module);
uint32 num_bytes_per_page, total_size_old;
uint32 num_bytes_per_page, total_size_old = 0;
uint32 cur_page_count, max_page_count, total_page_count;
uint64 total_size_new;
bool ret = true;
enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR;
if (!memory)
return false;
if (!memory) {
ret = false;
goto return_func;
}
num_bytes_per_page = memory->num_bytes_per_page;
cur_page_count = memory->cur_page_count;
@ -710,9 +750,15 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
/* No need to enlarge memory */
return true;
if (total_page_count < cur_page_count /* integer overflow */
|| total_page_count > max_page_count) {
return false;
if (total_page_count < cur_page_count) { /* integer overflow */
ret = false;
goto return_func;
}
if (total_page_count > max_page_count) {
failure_reason = MAX_SIZE_REACHED;
ret = false;
goto return_func;
}
bh_assert(total_size_new <= 4 * (uint64)BH_GB);
@ -727,7 +773,8 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
if (!os_mem_commit(memory->memory_data_end,
(uint32)total_size_new - total_size_old,
MMAP_PROT_READ | MMAP_PROT_WRITE)) {
return false;
ret = false;
goto return_func;
}
#endif
@ -739,7 +786,8 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
os_mem_decommit(memory->memory_data_end,
(uint32)total_size_new - total_size_old);
#endif
return false;
ret = false;
goto return_func;
}
/* The increased pages are filled with zero by the OS when os_mmap,
@ -759,10 +807,39 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
memory->mem_bound_check_16bytes.u64 = total_size_new - 16;
#endif
return true;
return_func:
if (!ret && enlarge_memory_error_cb) {
WASMExecEnv *exec_env = NULL;
#if WASM_ENABLE_INTERP != 0
if (module->module_type == Wasm_Module_Bytecode)
exec_env =
((WASMModuleInstanceExtra *)module->e)->common.cur_exec_env;
#endif
#if WASM_ENABLE_AOT != 0
if (module->module_type == Wasm_Module_AoT)
exec_env =
((AOTModuleInstanceExtra *)module->e)->common.cur_exec_env;
#endif
enlarge_memory_error_cb(inc_page_count, total_size_old, 0,
failure_reason,
(WASMModuleInstanceCommon *)module, exec_env,
enlarge_memory_error_user_data);
}
return ret;
}
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
void
wasm_runtime_set_enlarge_mem_error_callback(
const enlarge_memory_error_callback_t callback, void *user_data)
{
enlarge_memory_error_cb = callback;
enlarge_memory_error_user_data = user_data;
}
bool
wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
{

View File

@ -24,6 +24,10 @@ wasm_runtime_memory_destroy();
unsigned
wasm_runtime_memory_pool_size();
void
wasm_runtime_set_enlarge_mem_error_callback(
const enlarge_memory_error_callback_t callback, void *user_data);
#ifdef __cplusplus
}
#endif

View File

@ -6,6 +6,15 @@
#include "wasm_native.h"
#include "wasm_runtime_common.h"
#include "bh_log.h"
#if WASM_ENABLE_INTERP != 0
#include "../interpreter/wasm_runtime.h"
#endif
#if WASM_ENABLE_AOT != 0
#include "../aot/aot_runtime.h"
#endif
#if WASM_ENABLE_THREAD_MGR != 0
#include "../libraries/thread-mgr/thread_manager.h"
#endif
#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \
&& !defined(BH_PLATFORM_OPENRTOS) && !defined(BH_PLATFORM_ESP_IDF)
@ -22,6 +31,10 @@
static NativeSymbolsList g_native_symbols_list = NULL;
#if WASM_ENABLE_LIBC_WASI != 0
static void *g_wasi_context_key;
#endif /* WASM_ENABLE_LIBC_WASI */
uint32
get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
@ -394,6 +407,155 @@ wasm_native_unregister_natives(const char *module_name,
return false;
}
#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
static uint32
context_key_to_idx(void *key)
{
bh_assert(key != NULL);
uint32 idx = (uint32)(uintptr_t)key;
bh_assert(idx > 0);
bh_assert(idx <= WASM_MAX_INSTANCE_CONTEXTS);
return idx - 1;
}
static void *
context_idx_to_key(uint32 idx)
{
bh_assert(idx < WASM_MAX_INSTANCE_CONTEXTS);
return (void *)(uintptr_t)(idx + 1);
}
typedef void (*dtor_t)(WASMModuleInstanceCommon *, void *);
static dtor_t g_context_dtors[WASM_MAX_INSTANCE_CONTEXTS];
static void
dtor_noop(WASMModuleInstanceCommon *inst, void *ctx)
{}
void *
wasm_native_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
void *ctx))
{
uint32 i;
for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) {
if (g_context_dtors[i] == NULL) {
if (dtor == NULL) {
dtor = dtor_noop;
}
g_context_dtors[i] = dtor;
return context_idx_to_key(i);
}
}
LOG_ERROR("failed to allocate instance context key");
return NULL;
}
void
wasm_native_destroy_context_key(void *key)
{
uint32 idx = context_key_to_idx(key);
bh_assert(g_context_dtors[idx] != NULL);
g_context_dtors[idx] = NULL;
}
static WASMModuleInstanceExtraCommon *
wasm_module_inst_extra_common(WASMModuleInstanceCommon *inst)
{
#if WASM_ENABLE_INTERP != 0
if (inst->module_type == Wasm_Module_Bytecode) {
return &((WASMModuleInstance *)inst)->e->common;
}
#endif
#if WASM_ENABLE_AOT != 0
if (inst->module_type == Wasm_Module_AoT) {
return &((AOTModuleInstanceExtra *)((AOTModuleInstance *)inst)->e)
->common;
}
#endif
bh_assert(false);
return NULL;
}
void
wasm_native_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx)
{
uint32 idx = context_key_to_idx(key);
WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
common->contexts[idx] = ctx;
}
void
wasm_native_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
void *ctx)
{
#if WASM_ENABLE_THREAD_MGR != 0
wasm_cluster_set_context(inst, key, ctx);
#else
wasm_native_set_context(inst, key, ctx);
#endif
}
void *
wasm_native_get_context(WASMModuleInstanceCommon *inst, void *key)
{
uint32 idx = context_key_to_idx(key);
WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
return common->contexts[idx];
}
void
wasm_native_call_context_dtors(WASMModuleInstanceCommon *inst)
{
WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
uint32 i;
for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) {
dtor_t dtor = g_context_dtors[i];
if (dtor != NULL) {
dtor(inst, common->contexts[i]);
}
}
}
void
wasm_native_inherit_contexts(WASMModuleInstanceCommon *child,
WASMModuleInstanceCommon *parent)
{
WASMModuleInstanceExtraCommon *parent_common =
wasm_module_inst_extra_common(parent);
WASMModuleInstanceExtraCommon *child_common =
wasm_module_inst_extra_common(child);
bh_memcpy_s(child_common->contexts,
sizeof(*child_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS,
parent_common->contexts,
sizeof(*parent_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS);
}
#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */
#if WASM_ENABLE_LIBC_WASI != 0
WASIContext *
wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm)
{
return wasm_native_get_context(module_inst_comm, g_wasi_context_key);
}
void
wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm,
WASIContext *wasi_ctx)
{
return wasm_native_set_context(module_inst_comm, g_wasi_context_key,
wasi_ctx);
}
static void
wasi_context_dtor(WASMModuleInstanceCommon *inst, void *ctx)
{
if (ctx == NULL) {
return;
}
wasm_runtime_destroy_wasi(inst);
}
#endif /* end of WASM_ENABLE_LIBC_WASI */
bool
wasm_native_init()
{
@ -420,6 +582,10 @@ wasm_native_init()
#endif /* WASM_ENABLE_SPEC_TEST */
#if WASM_ENABLE_LIBC_WASI != 0
g_wasi_context_key = wasm_native_create_context_key(wasi_context_dtor);
if (g_wasi_context_key == NULL) {
goto fail;
}
n_native_symbols = get_libc_wasi_export_apis(&native_symbols);
if (!wasm_native_register_natives("wasi_unstable", native_symbols,
n_native_symbols))
@ -507,6 +673,12 @@ wasm_native_destroy()
{
NativeSymbolsNode *node, *node_next;
#if WASM_ENABLE_LIBC_WASI != 0
if (g_wasi_context_key != NULL) {
wasm_native_destroy_context_key(g_wasi_context_key);
g_wasi_context_key = NULL;
}
#endif
#if WASM_ENABLE_LIB_PTHREAD != 0
lib_pthread_destroy();
#endif

View File

@ -68,6 +68,36 @@ bool
wasm_native_unregister_natives(const char *module_name,
NativeSymbol *native_symbols);
#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
struct WASMModuleInstanceCommon;
void *
wasm_native_create_context_key(
void (*dtor)(struct WASMModuleInstanceCommon *inst, void *ctx));
void
wasm_native_destroy_context_key(void *key);
void
wasm_native_set_context(struct WASMModuleInstanceCommon *inst, void *key,
void *ctx);
void
wasm_native_set_context_spread(struct WASMModuleInstanceCommon *inst, void *key,
void *ctx);
void *
wasm_native_get_context(struct WASMModuleInstanceCommon *inst, void *key);
void
wasm_native_call_context_dtors(struct WASMModuleInstanceCommon *inst);
void
wasm_native_inherit_contexts(struct WASMModuleInstanceCommon *child,
struct WASMModuleInstanceCommon *parent);
#else /* WASM_ENABLE_MODULE_INST_CONTEXT */
#define wasm_native_call_context_dtors(inst) (void)(inst)
#define wasm_native_inherit_contexts(child, parent) (void)(parent)
#endif /* WASM_ENABLE_MODULE_INST_CONTEXT */
bool
wasm_native_init();

View File

@ -125,6 +125,34 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
return mem;
}
#if WASM_ENABLE_MULTI_MODULE != 0
/* TODO: Let loader_malloc be a general API both for AOT and WASM. */
#define loader_malloc(size, error_buf, error_buf_size) \
runtime_malloc(size, NULL, error_buf, error_buf_size)
static void
set_error_buf_v(const WASMModuleCommon *module, char *error_buf,
uint32 error_buf_size, const char *format, ...)
{
va_list args;
char buf[128];
if (error_buf != NULL) {
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
if (module->module_type == Wasm_Module_AoT) {
snprintf(error_buf, error_buf_size, "AOT module load failed: %s",
buf);
}
else if (module->module_type == Wasm_Module_Bytecode) {
snprintf(error_buf, error_buf_size, "WASM module load failed: %s",
buf);
}
}
}
#endif
#if WASM_ENABLE_FAST_JIT != 0
static JitCompOptions jit_options = { 0 };
#endif
@ -457,8 +485,21 @@ wasm_runtime_env_init()
}
#endif
#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
if (os_blocking_op_init() != BHT_OK) {
goto fail11;
}
os_end_blocking_op();
#endif
return true;
#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
fail11:
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
aot_compiler_destroy();
#endif
#endif
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
fail10:
#if WASM_ENABLE_FAST_JIT != 0
@ -1185,27 +1226,34 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
if (get_package_type(buf, size) == Wasm_Module_Bytecode) {
#if WASM_ENABLE_INTERP != 0
module_common =
(WASMModuleCommon *)wasm_load(buf, size, error_buf, error_buf_size);
return register_module_with_null_name(module_common, error_buf,
error_buf_size);
(WASMModuleCommon *)wasm_load(buf, size,
#if WASM_ENABLE_MULTI_MODULE != 0
true,
#endif
error_buf, error_buf_size);
#endif
}
else if (get_package_type(buf, size) == Wasm_Module_AoT) {
#if WASM_ENABLE_AOT != 0
module_common = (WASMModuleCommon *)aot_load_from_aot_file(
buf, size, error_buf, error_buf_size);
return register_module_with_null_name(module_common, error_buf,
error_buf_size);
#endif
}
if (size < 4)
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: unexpected end");
else
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: magic header not detected");
return NULL;
else {
if (size < 4)
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: unexpected end");
else
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: magic header not detected");
return NULL;
}
if (!module_common) {
LOG_DEBUG("WASM module load failed");
return NULL;
}
return register_module_with_null_name(module_common, error_buf,
error_buf_size);
}
WASMModuleCommon *
@ -1218,6 +1266,10 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot,
#if WASM_ENABLE_INTERP != 0
module_common = (WASMModuleCommon *)wasm_load_from_sections(
section_list, error_buf, error_buf_size);
if (!module_common) {
LOG_DEBUG("WASM module load failed from sections");
return NULL;
}
return register_module_with_null_name(module_common, error_buf,
error_buf_size);
#endif
@ -1226,6 +1278,10 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot,
#if WASM_ENABLE_AOT != 0
module_common = (WASMModuleCommon *)aot_load_from_sections(
section_list, error_buf, error_buf_size);
if (!module_common) {
LOG_DEBUG("WASM module load failed from sections");
return NULL;
}
return register_module_with_null_name(module_common, error_buf,
error_buf_size);
#endif
@ -1392,6 +1448,10 @@ wasm_runtime_init_thread_env(void)
}
#endif
#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
os_end_blocking_op();
#endif
return true;
}
@ -1938,33 +1998,6 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
}
#endif
static bool
clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm)
{
#if WASM_ENABLE_LIBC_WASI != 0
bool has_exception;
char exception[EXCEPTION_BUF_LEN];
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
has_exception = wasm_copy_exception(module_inst, exception);
if (has_exception && !strcmp(exception, "Exception: wasi proc exit")) {
/* The "wasi proc exit" exception is thrown by native lib to
let wasm app exit, which is a normal behavior, we clear
the exception here. And just clear the exception of current
thread, don't call `wasm_set_exception(module_inst, NULL)`
which will clear the exception of all threads. */
module_inst->cur_exception[0] = '\0';
return true;
}
return false;
#else
return false;
#endif
}
bool
wasm_runtime_call_wasm(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function, uint32 argc,
@ -2005,15 +2038,10 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
param_argc, new_argv);
#endif
if (!ret) {
if (clear_wasi_proc_exit_exception(exec_env->module_inst)) {
ret = true;
}
else {
if (new_argv != argv) {
wasm_runtime_free(new_argv);
}
return false;
if (new_argv != argv) {
wasm_runtime_free(new_argv);
}
return false;
}
#if WASM_ENABLE_REF_TYPES != 0
@ -2374,15 +2402,10 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm)
return module_inst->exec_env_singleton;
}
void
wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
static void
wasm_set_exception_local(WASMModuleInstance *module_inst, const char *exception)
{
WASMExecEnv *exec_env = NULL;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (module_inst->memory_count > 0)
shared_memory_lock(module_inst->memories[0]);
#endif
exception_lock(module_inst);
if (exception) {
snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception),
"Exception: %s", exception);
@ -2390,19 +2413,23 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
else {
module_inst->cur_exception[0] = '\0';
}
#if WASM_ENABLE_SHARED_MEMORY != 0
if (module_inst->memory_count > 0)
shared_memory_unlock(module_inst->memories[0]);
#endif
exception_unlock(module_inst);
}
void
wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
{
#if WASM_ENABLE_THREAD_MGR != 0
exec_env =
WASMExecEnv *exec_env =
wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst);
if (exec_env) {
wasm_cluster_spread_exception(exec_env, exception ? false : true);
wasm_cluster_set_exception(exec_env, exception);
}
else {
wasm_set_exception_local(module_inst, exception);
}
#else
(void)exec_env;
wasm_set_exception_local(module_inst, exception);
#endif
}
@ -2453,10 +2480,7 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf)
{
bool has_exception = false;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (module_inst->memory_count > 0)
shared_memory_lock(module_inst->memories[0]);
#endif
exception_lock(module_inst);
if (module_inst->cur_exception[0] != '\0') {
/* NULL is passed if the caller is not interested in getting the
* exception content, but only in knowing if an exception has been
@ -2468,10 +2492,7 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf)
sizeof(module_inst->cur_exception));
has_exception = true;
}
#if WASM_ENABLE_SHARED_MEMORY != 0
if (module_inst->memory_count > 0)
shared_memory_unlock(module_inst->memories[0]);
#endif
exception_unlock(module_inst);
return has_exception;
}
@ -2516,6 +2537,18 @@ wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst_comm)
wasm_runtime_set_exception(module_inst_comm, NULL);
}
#if WASM_ENABLE_THREAD_MGR != 0
void
wasm_runtime_terminate(WASMModuleInstanceCommon *module_inst_comm)
{
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
wasm_set_exception(module_inst, "terminated by user");
}
#endif
void
wasm_runtime_set_custom_data_internal(
WASMModuleInstanceCommon *module_inst_comm, void *custom_data)
@ -3338,27 +3371,6 @@ wasm_runtime_get_wasi_exit_code(WASMModuleInstanceCommon *module_inst)
#endif
return wasi_ctx->exit_code;
}
WASIContext *
wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm)
{
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
return module_inst->wasi_ctx;
}
void
wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm,
WASIContext *wasi_ctx)
{
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
module_inst->wasi_ctx = wasi_ctx;
}
#endif /* end of WASM_ENABLE_LIBC_WASI */
WASMModuleCommon *
@ -4621,10 +4633,6 @@ wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_index,
ret = aot_call_indirect(exec_env, 0, element_index, argc, argv);
#endif
if (!ret && clear_wasi_proc_exit_exception(exec_env->module_inst)) {
ret = true;
}
return ret;
}
@ -5708,3 +5716,345 @@ wasm_runtime_is_import_global_linked(const char *module_name,
return false;
#endif
}
#if WASM_ENABLE_LIBC_WASI != 0 || WASM_ENABLE_MULTI_MODULE != 0
WASMExport *
loader_find_export(const WASMModuleCommon *module, const char *module_name,
const char *field_name, uint8 export_kind, char *error_buf,
uint32 error_buf_size)
{
WASMExport *exports = NULL, *result = NULL, *export;
uint32 export_count = 0, i;
#if WASM_ENABLE_AOT != 0
if (module->module_type == Wasm_Module_AoT) {
AOTModule *aot_module = (AOTModule *)module;
exports = (WASMExport *)aot_module->exports;
export_count = aot_module->export_count;
}
#endif
#if WASM_ENABLE_INTERP != 0
if (module->module_type == Wasm_Module_Bytecode) {
WASMModule *wasm_module = (WASMModule *)module;
exports = wasm_module->exports;
export_count = wasm_module->export_count;
}
#endif
for (i = 0, export = exports; i < export_count; ++i, ++export) {
if (export->kind == export_kind && !strcmp(field_name, export->name)) {
result = export;
goto exit;
}
}
if (i == export_count) {
LOG_DEBUG("can not find an export %d named %s in the module %s",
export_kind, field_name, module_name);
set_error_buf(error_buf, error_buf_size,
"unknown import or incompatible import type");
}
exit:
return result;
}
#endif
#if WASM_ENABLE_MULTI_MODULE != 0
WASMModuleCommon *
wasm_runtime_search_sub_module(const WASMModuleCommon *parent_module,
const char *sub_module_name)
{
WASMRegisteredModule *node = NULL;
#if WASM_ENABLE_AOT != 0
if (parent_module->module_type == Wasm_Module_AoT) {
node = bh_list_first_elem(
((AOTModule *)parent_module)->import_module_list);
}
#endif
#if WASM_ENABLE_INTERP != 0
if (parent_module->module_type == Wasm_Module_Bytecode) {
node = bh_list_first_elem(
((WASMModule *)parent_module)->import_module_list);
}
#endif
while (node && strcmp(sub_module_name, node->module_name)) {
node = bh_list_elem_next(node);
}
return node ? node->module : NULL;
}
bool
wasm_runtime_register_sub_module(const WASMModuleCommon *parent_module,
const char *sub_module_name,
WASMModuleCommon *sub_module)
{
/* register sub_module into its parent sub module list */
WASMRegisteredModule *node = NULL;
bh_list_status ret;
if (wasm_runtime_search_sub_module(parent_module, sub_module_name)) {
LOG_DEBUG("%s has been registered in its parent", sub_module_name);
return true;
}
node = loader_malloc(sizeof(WASMRegisteredModule), NULL, 0);
if (!node) {
return false;
}
node->module_name = sub_module_name;
node->module = sub_module;
#if WASM_ENABLE_AOT != 0
if (parent_module->module_type == Wasm_Module_AoT) {
ret = bh_list_insert(((AOTModule *)parent_module)->import_module_list,
node);
}
#endif
#if WASM_ENABLE_INTERP != 0
if (parent_module->module_type == Wasm_Module_Bytecode) {
ret = bh_list_insert(((WASMModule *)parent_module)->import_module_list,
node);
}
#endif
bh_assert(BH_LIST_SUCCESS == ret);
(void)ret;
return true;
}
WASMModuleCommon *
wasm_runtime_load_depended_module(const WASMModuleCommon *parent_module,
const char *sub_module_name, char *error_buf,
uint32 error_buf_size)
{
WASMModuleCommon *sub_module = NULL;
bool ret = false;
uint8 *buffer = NULL;
uint32 buffer_size = 0;
/* check the registered module list of the parent */
sub_module = wasm_runtime_search_sub_module(parent_module, sub_module_name);
if (sub_module) {
LOG_DEBUG("%s has been loaded before", sub_module_name);
return sub_module;
}
/* check the global registered module list */
sub_module = wasm_runtime_find_module_registered(sub_module_name);
if (sub_module) {
LOG_DEBUG("%s has been loaded", sub_module_name);
goto wasm_runtime_register_sub_module;
}
LOG_VERBOSE("loading %s", sub_module_name);
if (!reader) {
set_error_buf_v(parent_module, error_buf, error_buf_size,
"no sub module reader to load %s", sub_module_name);
return NULL;
}
/* start to maintain a loading module list */
ret = wasm_runtime_is_loading_module(sub_module_name);
if (ret) {
set_error_buf_v(parent_module, error_buf, error_buf_size,
"found circular dependency on %s", sub_module_name);
return NULL;
}
ret = wasm_runtime_add_loading_module(sub_module_name, error_buf,
error_buf_size);
if (!ret) {
LOG_DEBUG("can not add %s into loading module list\n", sub_module_name);
return NULL;
}
ret = reader(parent_module->module_type, sub_module_name, &buffer,
&buffer_size);
if (!ret) {
LOG_DEBUG("read the file of %s failed", sub_module_name);
set_error_buf_v(parent_module, error_buf, error_buf_size,
"unknown import", sub_module_name);
goto delete_loading_module;
}
if (get_package_type(buffer, buffer_size) != parent_module->module_type) {
LOG_DEBUG("moudle %s type error", sub_module_name);
goto delete_loading_module;
}
if (get_package_type(buffer, buffer_size) == Wasm_Module_Bytecode) {
#if WASM_ENABLE_INTERP != 0
sub_module = (WASMModuleCommon *)wasm_load(buffer, buffer_size, false,
error_buf, error_buf_size);
#endif
}
else if (get_package_type(buffer, buffer_size) == Wasm_Module_AoT) {
#if WASM_ENABLE_AOT != 0
sub_module = (WASMModuleCommon *)aot_load_from_aot_file(
buffer, buffer_size, error_buf, error_buf_size);
#endif
}
if (!sub_module) {
LOG_DEBUG("error: can not load the sub_module %s", sub_module_name);
/* others will be destroyed in runtime_destroy() */
goto destroy_file_buffer;
}
wasm_runtime_delete_loading_module(sub_module_name);
/* register on a global list */
ret = wasm_runtime_register_module_internal(
sub_module_name, (WASMModuleCommon *)sub_module, buffer, buffer_size,
error_buf, error_buf_size);
if (!ret) {
LOG_DEBUG("error: can not register module %s globally\n",
sub_module_name);
/* others will be unloaded in runtime_destroy() */
goto unload_module;
}
/* register into its parent list */
wasm_runtime_register_sub_module:
ret = wasm_runtime_register_sub_module(parent_module, sub_module_name,
sub_module);
if (!ret) {
set_error_buf_v(parent_module, error_buf, error_buf_size,
"failed to register sub module %s", sub_module_name);
/* since it is in the global module list, no need to
* unload the module. the runtime_destroy() will do it
*/
return NULL;
}
return sub_module;
unload_module:
wasm_runtime_unload(sub_module);
destroy_file_buffer:
if (destroyer) {
destroyer(buffer, buffer_size);
}
else {
LOG_WARNING("need to release the reading buffer of %s manually",
sub_module_name);
}
delete_loading_module:
wasm_runtime_delete_loading_module(sub_module_name);
return NULL;
}
bool
wasm_runtime_sub_module_instantiate(WASMModuleCommon *module,
WASMModuleInstanceCommon *module_inst,
uint32 stack_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size)
{
bh_list *sub_module_inst_list = NULL;
WASMRegisteredModule *sub_module_list_node = NULL;
#if WASM_ENABLE_AOT != 0
if (module->module_type == Wasm_Module_AoT) {
sub_module_inst_list =
((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e)
->sub_module_inst_list;
sub_module_list_node =
bh_list_first_elem(((AOTModule *)module)->import_module_list);
}
#endif
#if WASM_ENABLE_INTERP != 0
if (module->module_type == Wasm_Module_Bytecode) {
sub_module_inst_list =
((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e)
->sub_module_inst_list;
sub_module_list_node =
bh_list_first_elem(((WASMModule *)module)->import_module_list);
}
#endif
while (sub_module_list_node) {
WASMSubModInstNode *sub_module_inst_list_node = NULL;
WASMModuleCommon *sub_module = sub_module_list_node->module;
WASMModuleInstanceCommon *sub_module_inst = NULL;
sub_module_inst = wasm_runtime_instantiate_internal(
sub_module, NULL, NULL, stack_size, heap_size, error_buf,
error_buf_size);
if (!sub_module_inst) {
LOG_DEBUG("instantiate %s failed",
sub_module_list_node->module_name);
return false;
}
sub_module_inst_list_node = loader_malloc(sizeof(WASMSubModInstNode),
error_buf, error_buf_size);
if (!sub_module_inst_list_node) {
LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d",
sizeof(WASMSubModInstNode));
if (sub_module_inst)
wasm_runtime_deinstantiate_internal(sub_module_inst, false);
return false;
}
sub_module_inst_list_node->module_inst =
(WASMModuleInstance *)sub_module_inst;
sub_module_inst_list_node->module_name =
sub_module_list_node->module_name;
bh_list_status ret =
bh_list_insert(sub_module_inst_list, sub_module_inst_list_node);
bh_assert(BH_LIST_SUCCESS == ret);
(void)ret;
sub_module_list_node = bh_list_elem_next(sub_module_list_node);
}
return true;
}
void
wasm_runtime_sub_module_deinstantiate(WASMModuleInstanceCommon *module_inst)
{
bh_list *list = NULL;
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT) {
list = ((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e)
->sub_module_inst_list;
}
#endif
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode) {
list =
((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e)
->sub_module_inst_list;
}
#endif
WASMSubModInstNode *node = bh_list_first_elem(list);
while (node) {
WASMSubModInstNode *next_node = bh_list_elem_next(node);
bh_list_remove(list, node);
wasm_runtime_deinstantiate_internal(
(WASMModuleInstanceCommon *)node->module_inst, false);
wasm_runtime_free(node);
node = next_node;
}
}
#endif /* end of WASM_ENABLE_MULTI_MODULE */
#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
void *
wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
void *ctx))
{
return wasm_native_create_context_key(dtor);
}
void
wasm_runtime_destroy_context_key(void *key)
{
wasm_native_destroy_context_key(key);
}
void
wasm_runtime_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx)
{
wasm_native_set_context(inst, key, ctx);
}
void
wasm_runtime_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
void *ctx)
{
wasm_native_set_context_spread(inst, key, ctx);
}
void *
wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key)
{
return wasm_native_get_context(inst, key);
}
#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */

View File

@ -675,6 +675,10 @@ wasm_runtime_get_exception(WASMModuleInstanceCommon *module);
WASM_RUNTIME_API_EXTERN void
wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void
wasm_runtime_terminate(WASMModuleInstanceCommon *module);
/* Internal API */
void
wasm_runtime_set_custom_data_internal(WASMModuleInstanceCommon *module_inst,
@ -784,6 +788,9 @@ wasm_runtime_register_module_internal(const char *module_name,
void
wasm_runtime_unregister_module(const WASMModuleCommon *module);
WASMModuleCommon *
wasm_runtime_find_module_registered(const char *module_name);
bool
wasm_runtime_add_loading_module(const char *module_name, char *error_buf,
uint32 error_buf_size);
@ -796,6 +803,35 @@ wasm_runtime_is_loading_module(const char *module_name);
void
wasm_runtime_destroy_loading_module_list();
WASMModuleCommon *
wasm_runtime_search_sub_module(const WASMModuleCommon *parent_module,
const char *sub_module_name);
bool
wasm_runtime_register_sub_module(const WASMModuleCommon *parent_module,
const char *sub_module_name,
WASMModuleCommon *sub_module);
WASMModuleCommon *
wasm_runtime_load_depended_module(const WASMModuleCommon *parent_module,
const char *sub_module_name, char *error_buf,
uint32 error_buf_size);
bool
wasm_runtime_sub_module_instantiate(WASMModuleCommon *module,
WASMModuleInstanceCommon *module_inst,
uint32 stack_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size);
void
wasm_runtime_sub_module_deinstantiate(WASMModuleInstanceCommon *module_inst);
#endif
#if WASM_ENABLE_LIBC_WASI != 0 || WASM_ENABLE_MULTI_MODULE != 0
WASMExport *
loader_find_export(const WASMModuleCommon *module, const char *module_name,
const char *field_name, uint8 export_kind, char *error_buf,
uint32 error_buf_size);
#endif /* WASM_ENALBE_MULTI_MODULE */
bool
@ -939,6 +975,26 @@ WASM_RUNTIME_API_EXTERN bool
wasm_runtime_unregister_natives(const char *module_name,
NativeSymbol *native_symbols);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void *
wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
void *ctx));
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void
wasm_runtime_destroy_context_key(void *key);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
void *ctx);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void *
wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key);
bool
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
@ -1016,6 +1072,15 @@ WASM_RUNTIME_API_EXTERN bool
wasm_runtime_is_import_global_linked(const char *module_name,
const char *global_name);
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_begin_blocking_op(WASMExecEnv *exec_env);
WASM_RUNTIME_API_EXTERN void
wasm_runtime_end_blocking_op(WASMExecEnv *exec_env);
void
wasm_runtime_interrupt_blocking_op(WASMExecEnv *exec_env);
#ifdef __cplusplus
}
#endif

View File

@ -20,6 +20,8 @@ extern "C" {
#define WASM_SUSPEND_FLAG_BREAKPOINT 0x4
/* Return from pthread_exit */
#define WASM_SUSPEND_FLAG_EXIT 0x8
/* The thread might be blocking */
#define WASM_SUSPEND_FLAG_BLOCKING 0x10
typedef union WASMSuspendFlags {
bh_atomic_32_t flags;