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:
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
@ -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);
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user