Implement Windows thread/mutex/cond APIs to support multi-thread (#627)

Implement Windows thread/mutex/cond related APIs to support Windows multi-thread feature
Change Windows HW boundary check implementation for multi-thread: change SEH to VEH
Fix wasm-c-api issue of getting AOTFunctionInstance by index, fix wasm-c-api compile warnings
Enable to build invokeNative_general.c with cmake variable
Fix several issues in lib-pthread
Disable two LLVM passes in multi-thread mode to reserve volatile semantic
Update docker script and document to build iwasm with Docker image

Signed-off-by: Wenyong Huang <wenyong.huang@intel.com>
This commit is contained in:
Wenyong Huang
2021-05-11 16:48:49 +08:00
committed by GitHub
parent 9710d9325f
commit 64b5459066
21 changed files with 1022 additions and 653 deletions

View File

@ -1191,7 +1191,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
unwind_info= (AOTUnwindInfo *)((uint8*)module->code + module->code_size
- sizeof(AOTUnwindInfo));
unwind_info->Version = 1;
unwind_info->Flags = UNW_FLAG_EHANDLER;
unwind_info->Flags = UNW_FLAG_NHANDLER;
*(uint32*)&unwind_info->UnwindCode[0] = unwind_code_offset;
size = sizeof(RUNTIME_FUNCTION) * (uint64)module->func_count;
@ -1231,7 +1231,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
rtl_func_table[i].BeginAddress = (DWORD)text_offset;
if (i > 0) {
rtl_func_table[i].EndAddress = rtl_func_table[i - 1].BeginAddress;
rtl_func_table[i - 1].EndAddress = rtl_func_table[i].BeginAddress;
}
rtl_func_table[i].UnwindInfoAddress = (DWORD)unwind_info_offset;
#endif

View File

@ -1152,13 +1152,6 @@ static os_thread_local_attribute WASMExecEnv *aot_exec_env = NULL;
#ifndef BH_PLATFORM_WINDOWS
static void
aot_signal_handler(void *sig_addr)
#else
EXCEPTION_DISPOSITION
aot_exception_handler(PEXCEPTION_RECORD ExceptionRecord,
ULONG64 EstablisherFrame,
PCONTEXT ContextRecord,
PDISPATCHER_CONTEXT DispatcherContext)
#endif
{
AOTModuleInstance *module_inst;
AOTMemoryInstance *memory_inst;
@ -1168,18 +1161,11 @@ aot_exception_handler(PEXCEPTION_RECORD ExceptionRecord,
uint8 *stack_min_addr;
uint32 page_size;
uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
#ifdef BH_PLATFORM_WINDOWS
uint8 *sig_addr = (uint8*)ExceptionRecord->ExceptionInformation[1];
#endif
/* Check whether current thread is running aot function */
if (aot_exec_env
&& aot_exec_env->handle == os_self_thread()
&& (jmpbuf_node = aot_exec_env->jmpbuf_stack_top)
#ifdef BH_PLATFORM_WINDOWS
&& ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
#endif
) {
&& (jmpbuf_node = aot_exec_env->jmpbuf_stack_top)) {
/* Get mapped mem info of current instance */
module_inst = (AOTModuleInstance *)aot_exec_env->module_inst;
/* Get the default memory instance */
@ -1211,40 +1197,58 @@ aot_exception_handler(PEXCEPTION_RECORD ExceptionRecord,
os_longjmp(jmpbuf_node->jmpbuf, 1);
}
}
#ifdef BH_PLATFORM_WINDOWS
ContextRecord->Rip += 3;
return EXCEPTION_CONTINUE_SEARCH;
(void)EstablisherFrame;
(void)ContextRecord;
(void)DispatcherContext;
#endif
}
#ifdef BH_PLATFORM_WINDOWS
#else /* else of BH_PLATFORM_WINDOWS */
static LONG
stack_overflow_handler(EXCEPTION_POINTERS *exce_info)
aot_exception_handler(EXCEPTION_POINTERS *exce_info)
{
AOTModuleInstance* module_inst;
WASMJmpBuf* jmpbuf_node;
PEXCEPTION_RECORD ExceptionRecord = exce_info->ExceptionRecord;
uint8 *sig_addr = (uint8*)ExceptionRecord->ExceptionInformation[1];
AOTModuleInstance *module_inst;
AOTMemoryInstance *memory_inst;
WASMJmpBuf *jmpbuf_node;
uint8 *mapped_mem_start_addr = NULL;
uint8 *mapped_mem_end_addr = NULL;
uint32 page_size = os_getpagesize();
/* Check whether it is stack overflow exception and
current thread is running aot function */
if (exce_info->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW
&& aot_exec_env
if (aot_exec_env
&& aot_exec_env->handle == os_self_thread()
&& (jmpbuf_node = aot_exec_env->jmpbuf_stack_top)) {
/* Set stack overflow exception and let the aot func continue
to run, when the aot func returns, the caller will check
whether the exception is thrown and return to runtime, and
the damaged stack will be recovered by _resetstkoflw(). */
module_inst = (AOTModuleInstance*)aot_exec_env->module_inst;
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
return EXCEPTION_CONTINUE_EXECUTION;
if (ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
/* Get the default memory instance */
memory_inst = aot_get_default_memory(module_inst);
if (memory_inst) {
mapped_mem_start_addr = (uint8*)memory_inst->memory_data.ptr;
mapped_mem_end_addr = (uint8*)memory_inst->memory_data.ptr
+ 8 * (uint64)BH_GB;
if (mapped_mem_start_addr <= (uint8*)sig_addr
&& (uint8*)sig_addr < mapped_mem_end_addr) {
/* The address which causes segmentation fault is inside
aot instance's guard regions.
Set exception and let the aot func continue to run, when
the aot func returns, the caller will check whether the
exception is thrown and return to runtime. */
aot_set_exception_with_id(module_inst,
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS);
/* Skip current instruction */
exce_info->ContextRecord->Rip++;
return EXCEPTION_CONTINUE_EXECUTION;
}
}
}
else if (ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
/* Set stack overflow exception and let the aot func continue
to run, when the aot func returns, the caller will check
whether the exception is thrown and return to runtime, and
the damaged stack will be recovered by _resetstkoflw(). */
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
return EXCEPTION_CONTINUE_EXECUTION;
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
#endif
#endif /* end of BH_PLATFORM_WINDOWS */
bool
aot_signal_init()
@ -1252,7 +1256,7 @@ aot_signal_init()
#ifndef BH_PLATFORM_WINDOWS
return os_signal_init(aot_signal_handler) == 0 ? true : false;
#else
return AddVectoredExceptionHandler(1, stack_overflow_handler)
return AddVectoredExceptionHandler(1, aot_exception_handler)
? true : false;
#endif
}
@ -1263,7 +1267,7 @@ aot_signal_destroy()
#ifndef BH_PLATFORM_WINDOWS
os_signal_destroy();
#else
RemoveVectoredExceptionHandler(stack_overflow_handler);
RemoveVectoredExceptionHandler(aot_exception_handler);
#endif
}

View File

@ -659,14 +659,6 @@ aot_signal_init();
void
aot_signal_destroy();
#ifdef BH_PLATFORM_WINDOWS
EXCEPTION_DISPOSITION
aot_exception_handler(PEXCEPTION_RECORD ExceptionRecord,
ULONG64 EstablisherFrame,
PCONTEXT ContextRecord,
PDISPATCHER_CONTEXT DispatcherContext);
#endif
#endif
void

View File

@ -93,7 +93,7 @@ init_plt_table(uint8 *plt)
/* mov exception_handler, rax */
*p++ = 0x48;
*p++ = 0xB8;
*(uint64*)p = (uint64)(uintptr_t)aot_exception_handler;
*(uint64*)p = 0;/*(uint64)(uintptr_t)aot_exception_handler;*/
p += sizeof(uint64);
/* jmp rax */
*p++ = 0xFF;

View File

@ -10,7 +10,17 @@ add_definitions(-DBH_FREE=wasm_runtime_free)
file (GLOB c_source_all ${IWASM_COMMON_DIR}/*.c)
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
if (WAMR_BUILD_INVOKE_NATIVE_GENERAL EQUAL 1)
# Use invokeNative C version instead of asm code version
# if WAMR_BUILD_INVOKE_NATIVE_GENERAL is explicitly set.
# Note:
# the maximum number of native arguments is limited to 20,
# and there are possible issues when passing arguments to
# native function for some cpus, e.g. int64 and double arguments
# in arm and mips need to be 8-bytes aligned, and some arguments
# of x86_64 are passed by registers but not stack
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_general.c)
elseif (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
if (NOT WAMR_BUILD_SIMD EQUAL 1)
if (WAMR_BUILD_PLATFORM STREQUAL "windows")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.asm)
@ -60,14 +70,6 @@ elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32" OR WAMR_BUILD_TARGET STREQUAL "RISC
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv32_ilp32d.s)
elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv32_ilp32.s)
elseif (WAMR_BUILD_TARGET STREQUAL "GENERAL")
# Use invokeNative_general.c instead of assembly code,
# but the maximum number of native arguments is limited to 20,
# and there are possible issues when passing arguments to
# native function for some cpus, e.g. int64 and double arguments
# in arm and mips need to be 8-bytes aligned, and some arguments
# of x86_64 are passed by registers but not stack
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_general.c)
else ()
message (FATAL_ERROR "Build target isn't set")
endif ()

File diff suppressed because it is too large Load Diff

View File

@ -71,15 +71,6 @@ fail1:
void
wasm_exec_env_destroy_internal(WASMExecEnv *exec_env)
{
#ifdef OS_ENABLE_HW_BOUND_CHECK
WASMJmpBuf *jmpbuf = exec_env->jmpbuf_stack_top;
WASMJmpBuf *jmpbuf_prev;
while (jmpbuf) {
jmpbuf_prev = jmpbuf->prev;
wasm_runtime_free(jmpbuf);
jmpbuf = jmpbuf_prev;
}
#endif
#if WASM_ENABLE_THREAD_MGR != 0
os_mutex_destroy(&exec_env->wait_lock);
os_cond_destroy(&exec_env->wait_cond);

View File

@ -7,33 +7,6 @@
#include "bh_platform.h"
#include "mem_alloc.h"
#define BH_ENABLE_MEMORY_PROFILING 0
#if BH_ENABLE_MEMORY_PROFILING != 0
/* Memory profile data of a function */
typedef struct memory_profile {
struct memory_profile *next;
const char *function_name;
const char *file_name;
int line_in_file;
int malloc_num;
int free_num;
int total_malloc;
int total_free;
} memory_profile_t;
/* Memory in use which grows when BH_MALLOC was called
* and decreases when bh_free was called */
static unsigned int memory_in_use = 0;
/* Memory profile data list */
static memory_profile_t *memory_profiles_list = NULL;
/* Lock of the memory profile list */
static korp_mutex profile_lock;
#endif /* end of BH_ENABLE_MEMORY_PROFILING */
typedef enum Memory_Mode {
MEMORY_MODE_UNKNOWN = 0,
MEMORY_MODE_POOL,
@ -58,9 +31,6 @@ wasm_memory_init_with_pool(void *mem, unsigned int bytes)
if (_allocator) {
memory_mode = MEMORY_MODE_POOL;
pool_allocator = _allocator;
#if BH_ENABLE_MEMORY_PROFILING != 0
os_mutex_init(&profile_lock);
#endif
global_pool_size = bytes;
return true;
}
@ -78,9 +48,6 @@ wasm_memory_init_with_allocator(void *_malloc_func,
malloc_func = _malloc_func;
realloc_func = _realloc_func;
free_func = _free_func;
#if BH_ENABLE_MEMORY_PROFILING != 0
os_mutex_init(&profile_lock);
#endif
return true;
}
LOG_ERROR("Init memory with allocator (%p, %p, %p) failed.\n",
@ -108,9 +75,6 @@ wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
void
wasm_runtime_memory_destroy()
{
#if BH_ENABLE_MEMORY_PROFILING != 0
os_mutex_destroy(&profile_lock);
#endif
if (memory_mode == MEMORY_MODE_POOL)
mem_allocator_destroy(pool_allocator);
memory_mode = MEMORY_MODE_UNKNOWN;
@ -201,197 +165,3 @@ wasm_runtime_free(void *ptr)
{
wasm_runtime_free_internal(ptr);
}
#if 0
static uint64 total_malloc = 0;
static uint64 total_free = 0;
void *
wasm_runtime_malloc(unsigned int size)
{
void *ret = wasm_runtime_malloc_internal(size + 8);
if (ret) {
total_malloc += size;
*(uint32 *)ret = size;
return (uint8 *)ret + 8;
}
else
return NULL;
}
void *
wasm_runtime_realloc(void *ptr, unsigned int size)
{
if (!ptr)
return wasm_runtime_malloc(size);
else {
uint8 *ptr_old = (uint8 *)ptr - 8;
uint32 size_old = *(uint32 *)ptr_old;
ptr = wasm_runtime_realloc_internal(ptr_old, size + 8);
if (ptr) {
total_free += size_old;
total_malloc += size;
*(uint32 *)ptr = size;
return (uint8 *)ptr + 8;
}
return NULL;
}
}
void
wasm_runtime_free(void *ptr)
{
if (ptr) {
uint8 *ptr_old = (uint8 *)ptr - 8;
uint32 size_old = *(uint32 *)ptr_old;
total_free += size_old;
wasm_runtime_free_internal(ptr_old);
}
}
void dump_memory_usage()
{
os_printf("Memory usage:\n");
os_printf(" total malloc: %"PRIu64"\n", total_malloc);
os_printf(" total free: %"PRIu64"\n", total_free);
}
#endif
#if BH_ENABLE_MEMORY_PROFILING != 0
void
memory_profile_print(const char *file, int line,
const char *func, int alloc)
{
os_printf("location:%s@%d:used:%d:contribution:%d\n",
func, line, memory_in_use, alloc);
}
void *
wasm_runtime_malloc_profile(const char *file, int line,
const char *func, unsigned int size)
{
void *p = wasm_runtime_malloc(size + 8);
if (p) {
memory_profile_t *profile;
os_mutex_lock(&profile_lock);
profile = memory_profiles_list;
while (profile) {
if (strcmp(profile->function_name, func) == 0
&& strcmp(profile->file_name, file) == 0) {
break;
}
profile = profile->next;
}
if (profile) {
profile->total_malloc += size;/* TODO: overflow check */
profile->malloc_num++;
} else {
profile = wasm_runtime_malloc(sizeof(memory_profile_t));
if (!profile) {
os_mutex_unlock(&profile_lock);
bh_memcpy_s(p, size + 8, &size, sizeof(size));
return (char *)p + 8;
}
memset(profile, 0, sizeof(memory_profile_t));
profile->file_name = file;
profile->line_in_file = line;
profile->function_name = func;
profile->malloc_num = 1;
profile->total_malloc = size;
profile->next = memory_profiles_list;
memory_profiles_list = profile;
}
os_mutex_unlock(&profile_lock);
bh_memcpy_s(p, size + 8, &size, sizeof(size));
memory_in_use += size;
memory_profile_print(file, line, func, size);
return (char *)p + 8;
}
return NULL;
}
void
wasm_runtime_free_profile(const char *file, int line,
const char *func, void *ptr)
{
unsigned int size = *(unsigned int *)((char *)ptr - 8);
memory_profile_t *profile;
wasm_runtime_free((char *)ptr - 8);
if (memory_in_use >= size)
memory_in_use -= size;
os_mutex_lock(&profile_lock);
profile = memory_profiles_list;
while (profile) {
if (strcmp(profile->function_name, func) == 0
&& strcmp(profile->file_name, file) == 0) {
break;
}
profile = profile->next;
}
if (profile) {
profile->total_free += size;/* TODO: overflow check */
profile->free_num++;
} else {
profile = wasm_runtime_malloc(sizeof(memory_profile_t));
if (!profile) {
os_mutex_unlock(&profile_lock);
return;
}
memset(profile, 0, sizeof(memory_profile_t));
profile->file_name = file;
profile->line_in_file = line;
profile->function_name = func;
profile->free_num = 1;
profile->total_free = size;
profile->next = memory_profiles_list;
memory_profiles_list = profile;
}
os_mutex_unlock(&profile_lock);
}
/**
* Summarize memory usage and print it out
* Can use awk to analyze the output like below:
* awk -F: '{print $2,$4,$6,$8,$9}' OFS="\t" ./out.txt | sort -n -r -k 1
*/
void memory_usage_summarize()
{
memory_profile_t *profile;
os_mutex_lock(&profile_lock);
profile = memory_profiles_list;
while (profile) {
os_printf("malloc:%d:malloc_num:%d:free:%d:free_num:%d:%s\n",
profile->total_malloc,
profile->malloc_num,
profile->total_free,
profile->free_num,
profile->function_name);
profile = profile->next;
}
os_mutex_unlock(&profile_lock);
}
#endif /* end of BH_ENABLE_MEMORY_PROFILING */

View File

@ -1542,8 +1542,12 @@ aot_create_comp_context(AOTCompData *comp_data,
LLVMAddLoopUnswitchPass(comp_ctx->pass_mgr);
LLVMAddInstructionCombiningPass(comp_ctx->pass_mgr);
LLVMAddCFGSimplificationPass(comp_ctx->pass_mgr);
LLVMAddGVNPass(comp_ctx->pass_mgr);
LLVMAddLICMPass(comp_ctx->pass_mgr);
if (!option->enable_thread_mgr) {
/* These two passes may destroy the volatile semantics,
disable them when building as multi-thread mode */
LLVMAddGVNPass(comp_ctx->pass_mgr);
LLVMAddLICMPass(comp_ctx->pass_mgr);
}
LLVMAddLoopVectorizePass(comp_ctx->pass_mgr);
LLVMAddSLPVectorizePass(comp_ctx->pass_mgr);
LLVMAddInstructionCombiningPass(comp_ctx->pass_mgr);

View File

@ -117,7 +117,7 @@ typedef struct {
} ThreadRoutineArgs;
static bh_list cluster_info_list;
static korp_mutex pthread_global_lock;
static korp_mutex thread_global_lock;
static uint32 handle_id = 1;
static void
@ -140,7 +140,7 @@ thread_info_destroy(void *node)
{
ThreadInfoNode *info_node = (ThreadInfoNode *)node;
pthread_mutex_lock(&pthread_global_lock);
os_mutex_lock(&thread_global_lock);
if (info_node->type == T_MUTEX) {
if (info_node->status != MUTEX_DESTROYED)
os_mutex_destroy(info_node->u.mutex);
@ -152,18 +152,18 @@ thread_info_destroy(void *node)
wasm_runtime_free(info_node->u.cond);
}
wasm_runtime_free(info_node);
pthread_mutex_unlock(&pthread_global_lock);
os_mutex_unlock(&thread_global_lock);
}
bool
lib_pthread_init()
{
if (0 != os_mutex_init(&pthread_global_lock))
if (0 != os_mutex_init(&thread_global_lock))
return false;
bh_list_init(&cluster_info_list);
if (!wasm_cluster_register_destroy_callback(
lib_pthread_destroy_callback)) {
os_mutex_destroy(&pthread_global_lock);
os_mutex_destroy(&thread_global_lock);
return false;
}
return true;
@ -172,7 +172,7 @@ lib_pthread_init()
void
lib_pthread_destroy()
{
os_mutex_destroy(&pthread_global_lock);
os_mutex_destroy(&thread_global_lock);
}
static ClusterInfoNode*
@ -180,17 +180,17 @@ get_cluster_info(WASMCluster *cluster)
{
ClusterInfoNode *node;
os_mutex_lock(&pthread_global_lock);
os_mutex_lock(&thread_global_lock);
node = bh_list_first_elem(&cluster_info_list);
while (node) {
if (cluster == node->cluster) {
os_mutex_unlock(&pthread_global_lock);
os_mutex_unlock(&thread_global_lock);
return node;
}
node = bh_list_elem_next(node);
}
os_mutex_unlock(&pthread_global_lock);
os_mutex_unlock(&thread_global_lock);
return NULL;
}
@ -356,10 +356,10 @@ create_cluster_info(WASMCluster *cluster)
wasm_runtime_free(node);
return NULL;
}
os_mutex_lock(&pthread_global_lock);
os_mutex_lock(&thread_global_lock);
ret = bh_list_insert(&cluster_info_list, node);
bh_assert(ret == BH_LIST_SUCCESS);
os_mutex_unlock(&pthread_global_lock);
os_mutex_unlock(&thread_global_lock);
(void)ret;
return node;
@ -375,10 +375,10 @@ destroy_cluster_info(WASMCluster *cluster)
os_mutex_destroy(&node->key_data_list_lock);
/* Remove from the cluster info list */
os_mutex_lock(&pthread_global_lock);
os_mutex_lock(&thread_global_lock);
bh_list_remove(&cluster_info_list, node);
wasm_runtime_free(node);
os_mutex_unlock(&pthread_global_lock);
os_mutex_unlock(&thread_global_lock);
return true;
}
return false;
@ -447,9 +447,9 @@ static uint32
allocate_handle()
{
uint32 id;
os_mutex_lock(&pthread_global_lock);
os_mutex_lock(&thread_global_lock);
id = handle_id++;
os_mutex_unlock(&pthread_global_lock);
os_mutex_unlock(&thread_global_lock);
return id;
}
@ -504,8 +504,6 @@ pthread_start_routine(void *arg)
/* routine exit, destroy instance */
wasm_runtime_deinstantiate_internal(module_inst, true);
info_node->status = THREAD_EXIT;
wasm_runtime_free(routine_args);
/* if the thread is joinable, store the result in its info node,
@ -516,6 +514,14 @@ 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)
/* argv[0] isn't set after longjmp(1) to
invoke_native_with_hw_bound_check */
info_node->u.ret = exec_env->thread_ret_value;
#endif
/* Update node status after ret value was set */
info_node->status = THREAD_EXIT;
}
return (void *)(uintptr_t)argv[0];
@ -711,7 +717,7 @@ pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset)
if (!args)
return;
#ifdef OS_ENABLE_HW_BOUND_CHECK
#if defined(OS_ENABLE_HW_BOUND_CHECK) && !defined(BH_PLATFORM_WINDOWS)
/* If hardware bound check enabled, don't deinstantiate module inst
and thread info node here for AoT module, as they will be freed
in pthread_start_routine */
@ -726,13 +732,13 @@ pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset)
/* routine exit, destroy instance */
wasm_runtime_deinstantiate_internal(module_inst, true);
args->info_node->status = THREAD_EXIT;
if (!args->info_node->joinable) {
delete_thread_info_node(args->info_node);
}
else {
args->info_node->u.ret = (void *)(uintptr_t)retval_offset;
/* Update node status after ret value was set */
args->info_node->status = THREAD_EXIT;
}
wasm_runtime_free(args);

View File

@ -495,20 +495,18 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval)
#ifdef OS_ENABLE_HW_BOUND_CHECK
if (exec_env->jmpbuf_stack_top) {
WASMJmpBuf *jmpbuf_node;
/* Store the return value in exec_env */
exec_env->thread_ret_value = retval;
exec_env->suspend_flags.flags |= 0x08;
/* Free all jmpbuf_node except the last one */
#ifndef BH_PLATFORM_WINDOWS
/* Pop all jmpbuf_node except the last one */
while (exec_env->jmpbuf_stack_top->prev) {
jmpbuf_node = wasm_exec_env_pop_jmpbuf(exec_env);
wasm_runtime_free(jmpbuf_node);
wasm_exec_env_pop_jmpbuf(exec_env);
}
jmpbuf_node = exec_env->jmpbuf_stack_top;
os_longjmp(jmpbuf_node->jmpbuf, 1);
os_longjmp(exec_env->jmpbuf_stack_top->jmpbuf, 1);
return;
#endif
}
#endif