From 3c2f0600feb33bf700dbc50fceb9317ed08b7efd Mon Sep 17 00:00:00 2001 From: eloparco Date: Thu, 2 Feb 2023 01:08:57 +0000 Subject: [PATCH 1/5] fix(wasi-threads): interrupt blocking instructions using signals --- build-scripts/config_common.cmake | 6 +++ core/iwasm/aot/aot_runtime.c | 35 +++++++++++++--- core/iwasm/common/wasm_exec_env.c | 2 +- core/iwasm/common/wasm_exec_env.h | 8 ++-- core/iwasm/common/wasm_runtime_common.c | 42 +++++++++++++++++-- core/iwasm/common/wasm_runtime_common.h | 2 + core/iwasm/interpreter/wasm_runtime.c | 18 +++++++- .../libraries/thread-mgr/thread_manager.c | 4 ++ .../platform/android/platform_internal.h | 17 +++++--- .../platform/common/posix/posix_thread.c | 6 +++ .../platform/darwin/platform_internal.h | 17 +++++--- .../platform/freebsd/platform_internal.h | 17 +++++--- .../platform/include/platform_api_extension.h | 3 ++ .../shared/platform/linux/platform_internal.h | 17 +++++--- .../platform/vxworks/platform_internal.h | 17 +++++--- .../platform/windows/platform_internal.h | 18 ++++---- 16 files changed, 178 insertions(+), 51 deletions(-) diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 53b0207fbf..a5800f6a48 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -248,6 +248,12 @@ else () add_definitions (-DWASM_DISABLE_STACK_HW_BOUND_CHECK=0) endif () endif () +if (WAMR_DISABLE_BLOCK_INSN_INTERRUPT EQUAL 1) + add_definitions (-DWASM_DISABLE_BLOCK_INSN_INTERRUPT=1) + message (" Interruption of blocking instructions disabled") +else () + add_definitions (-DWASM_DISABLE_BLOCK_INSN_INTERRUPT=0) +endif () if (WAMR_BUILD_SIMD EQUAL 1) if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*") add_definitions (-DWASM_ENABLE_SIMD=1) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 5fa5438bd0..09a0df50b0 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1325,6 +1325,9 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, uint32 result_count = func_type->result_count; uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0; bool ret; +#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop; +#endif if (argc < func_type->param_cell_num) { char buf[108]; @@ -1385,8 +1388,19 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, } #endif - ret = invoke_native_internal(exec_env, function->u.func.func_ptr, - func_type, NULL, NULL, argv1, argc, argv); +#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); + wasm_runtime_set_exec_env_tls(exec_env); + if (os_setjmp(jmpbuf_node.jmpbuf) == 0) +#endif + ret = invoke_native_internal(exec_env, function->u.func.func_ptr, + func_type, NULL, NULL, argv1, argc, + argv); +#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + + jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env); + bh_assert(&jmpbuf_node == jmpbuf_node_pop); +#endif #if WASM_ENABLE_DUMP_CALL_STACK != 0 if (!ret) { @@ -1444,8 +1458,19 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, } #endif - ret = invoke_native_internal(exec_env, function->u.func.func_ptr, - func_type, NULL, NULL, argv, argc, argv); +#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); + wasm_runtime_set_exec_env_tls(exec_env); + if (os_setjmp(jmpbuf_node.jmpbuf) == 0) +#endif + ret = + invoke_native_internal(exec_env, function->u.func.func_ptr, + func_type, NULL, NULL, argv, argc, argv); +#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + + jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env); + bh_assert(&jmpbuf_node == jmpbuf_node_pop); +#endif #if WASM_ENABLE_DUMP_CALL_STACK != 0 if (aot_get_exception(module_inst)) { @@ -1471,7 +1496,7 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst, WASMExecEnv *exec_env = NULL, *existing_exec_env = NULL; bool ret; -#if defined(OS_ENABLE_HW_BOUND_CHECK) +#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) existing_exec_env = exec_env = wasm_runtime_get_exec_env_tls(); #elif WASM_ENABLE_THREAD_MGR != 0 existing_exec_env = exec_env = diff --git a/core/iwasm/common/wasm_exec_env.c b/core/iwasm/common/wasm_exec_env.c index 7939c75909..3015233eca 100644 --- a/core/iwasm/common/wasm_exec_env.c +++ b/core/iwasm/common/wasm_exec_env.c @@ -227,7 +227,7 @@ wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg) } #endif -#ifdef OS_ENABLE_HW_BOUND_CHECK +#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) void wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf) { diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h index 72f973e7bf..c9edd70954 100644 --- a/core/iwasm/common/wasm_exec_env.h +++ b/core/iwasm/common/wasm_exec_env.h @@ -25,7 +25,7 @@ typedef struct WASMCurrentEnvStatus WASMCurrentEnvStatus; #endif #endif -#ifdef OS_ENABLE_HW_BOUND_CHECK +#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) typedef struct WASMJmpBuf { struct WASMJmpBuf *prev; korp_jmpbuf jmpbuf; @@ -135,8 +135,10 @@ typedef struct WASMExecEnv { BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE]; #endif -#ifdef OS_ENABLE_HW_BOUND_CHECK +#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) WASMJmpBuf *jmpbuf_stack_top; +#endif +#ifdef OS_ENABLE_HW_BOUND_CHECK /* One guard page for the exception check */ uint8 *exce_check_guard_page; #endif @@ -291,7 +293,7 @@ void wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg); #endif -#ifdef OS_ENABLE_HW_BOUND_CHECK +#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) void wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf); diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index aed92edf2a..590c2a54a9 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -128,12 +128,14 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst, static JitCompOptions jit_options = { 0 }; #endif -#ifdef OS_ENABLE_HW_BOUND_CHECK +#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) /* The exec_env of thread local storage, set before calling function and used in signal handler, as we cannot get it from the argument of signal handler */ static os_thread_local_attribute WASMExecEnv *exec_env_tls = NULL; +#endif +#ifdef OS_ENABLE_HW_BOUND_CHECK #ifndef BH_PLATFORM_WINDOWS static void runtime_signal_handler(void *sig_addr) @@ -303,7 +305,9 @@ runtime_signal_destroy() #endif os_thread_signal_destroy(); } +#endif /* end of OS_ENABLE_HW_BOUND_CHECK */ +#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) void wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env) { @@ -315,7 +319,35 @@ wasm_runtime_get_exec_env_tls() { return exec_env_tls; } -#endif /* end of OS_ENABLE_HW_BOUND_CHECK */ +#endif + +#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT +static void +os_interrupt_block_insn_sig_handler(int sig) +{ + bh_assert(sig == SIGUSR1); + + WASMJmpBuf *jmpbuf_node = exec_env_tls->jmpbuf_stack_top; + bh_assert(jmpbuf_node); + + os_longjmp(jmpbuf_node->jmpbuf, 1); +} + +bool +os_interrupt_block_insn_init() +{ + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_handler = os_interrupt_block_insn_sig_handler; + sigfillset(&act.sa_mask); + if (sigaction(SIGUSR1, &act, NULL) < 0) { + LOG_ERROR("failed to set signal handler"); + return false; + } + + return true; +} +#endif static bool wasm_runtime_env_init() @@ -348,7 +380,11 @@ wasm_runtime_env_init() goto fail5; } #endif - +#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + if (!os_interrupt_block_insn_init()) { + goto fail5; + } +#endif #ifdef OS_ENABLE_HW_BOUND_CHECK if (!runtime_signal_init()) { goto fail6; diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 3e7f3725d2..8b77bc4206 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -423,7 +423,9 @@ typedef struct WASMSignalInfo { EXCEPTION_POINTERS *exce_info; #endif } WASMSignalInfo; +#endif +#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) /* Set exec_env of thread local storage */ void wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env); diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index c33ad8d018..c237e1a13f 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2137,11 +2137,25 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, { WASMModuleInstance *module_inst = (WASMModuleInstance *)exec_env->module_inst; +#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop; +#endif /* set thread handle and stack boundary */ wasm_exec_env_set_thread_info(exec_env); - interp_call_wasm(module_inst, exec_env, function, argc, argv); +#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); + wasm_runtime_set_exec_env_tls(exec_env); + if (os_setjmp(jmpbuf_node.jmpbuf) == 0) +#endif + interp_call_wasm(module_inst, exec_env, function, argc, argv); +#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + + jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env); + bh_assert(&jmpbuf_node == jmpbuf_node_pop); +#endif + return !wasm_get_exception(module_inst) ? true : false; } @@ -2153,7 +2167,7 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env = NULL, *existing_exec_env = NULL; bool ret; -#if defined(OS_ENABLE_HW_BOUND_CHECK) +#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) existing_exec_env = exec_env = wasm_runtime_get_exec_env_tls(); #elif WASM_ENABLE_THREAD_MGR != 0 existing_exec_env = exec_env = diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 8ec310d92f..6451e95a25 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -1064,6 +1064,10 @@ set_exception_visitor(void *node, void *user_data) bh_memcpy_s(curr_wasm_inst->cur_exception, sizeof(curr_wasm_inst->cur_exception), wasm_inst->cur_exception, sizeof(wasm_inst->cur_exception)); + + bh_assert(curr_exec_env->handle); + os_thread_signal(curr_exec_env->handle, SIGUSR1); + /* Terminate the thread so it can exit from dead loops */ set_thread_cancel_flags(curr_exec_env); } diff --git a/core/shared/platform/android/platform_internal.h b/core/shared/platform/android/platform_internal.h index 521fa0c555..b09bac847d 100644 --- a/core/shared/platform/android/platform_internal.h +++ b/core/shared/platform/android/platform_internal.h @@ -63,19 +63,17 @@ typedef sem_t korp_sem; #define bh_socket_t int +#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 +#define OS_ENABLE_BLOCK_INSN_INTERRUPT +#endif + #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \ || defined(BUILD_TARGET_RISCV64_LP64) -#include - #define OS_ENABLE_HW_BOUND_CHECK -typedef jmp_buf korp_jmpbuf; - -#define os_setjmp setjmp -#define os_longjmp longjmp #define os_alloca alloca #define os_getpagesize getpagesize @@ -99,6 +97,13 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK) +#include +typedef jmp_buf korp_jmpbuf; +#define os_setjmp setjmp +#define os_longjmp longjmp +#endif + typedef long int __syscall_slong_t; #if __ANDROID_API__ < 19 diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index 58370c203f..0178cfd6e2 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -346,6 +346,12 @@ os_thread_exit(void *retval) return pthread_exit(retval); } +int +os_thread_signal(korp_tid tid, int sig) +{ + return pthread_kill(tid, sig); +} + #if defined(os_thread_local_attribute) static os_thread_local_attribute uint8 *thread_stack_boundary = NULL; #endif diff --git a/core/shared/platform/darwin/platform_internal.h b/core/shared/platform/darwin/platform_internal.h index 3fd1c258e2..0feaf73a63 100644 --- a/core/shared/platform/darwin/platform_internal.h +++ b/core/shared/platform/darwin/platform_internal.h @@ -66,19 +66,17 @@ typedef sem_t korp_sem; #define bh_socket_t int +#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 +#define OS_ENABLE_BLOCK_INSN_INTERRUPT +#endif + #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \ || defined(BUILD_TARGET_RISCV64_LP64) -#include - #define OS_ENABLE_HW_BOUND_CHECK -typedef jmp_buf korp_jmpbuf; - -#define os_setjmp setjmp -#define os_longjmp longjmp #define os_alloca alloca #define os_getpagesize getpagesize @@ -102,6 +100,13 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK) +#include +typedef jmp_buf korp_jmpbuf; +#define os_setjmp setjmp +#define os_longjmp longjmp +#endif + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/freebsd/platform_internal.h b/core/shared/platform/freebsd/platform_internal.h index 7b4789c992..7242c3ab5f 100644 --- a/core/shared/platform/freebsd/platform_internal.h +++ b/core/shared/platform/freebsd/platform_internal.h @@ -65,19 +65,17 @@ typedef sem_t korp_sem; #define bh_socket_t int +#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 +#define OS_ENABLE_BLOCK_INSN_INTERRUPT +#endif + #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \ || defined(BUILD_TARGET_RISCV64_LP64) -#include - #define OS_ENABLE_HW_BOUND_CHECK -typedef jmp_buf korp_jmpbuf; - -#define os_setjmp setjmp -#define os_longjmp longjmp #define os_alloca alloca #define os_getpagesize getpagesize @@ -101,6 +99,13 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK) +#include +typedef jmp_buf korp_jmpbuf; +#define os_setjmp setjmp +#define os_longjmp longjmp +#endif + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index 42baad74f7..db67a00d33 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -92,6 +92,9 @@ int os_thread_detach(korp_tid); void os_thread_exit(void *retval); +int +os_thread_signal(korp_tid tid, int sig); + /** * Initialize current thread environment if current thread * is created by developer but not runtime diff --git a/core/shared/platform/linux/platform_internal.h b/core/shared/platform/linux/platform_internal.h index 0ac63cf5e7..7d58372f31 100644 --- a/core/shared/platform/linux/platform_internal.h +++ b/core/shared/platform/linux/platform_internal.h @@ -63,19 +63,17 @@ typedef sem_t korp_sem; #define bh_socket_t int +#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 +#define OS_ENABLE_BLOCK_INSN_INTERRUPT +#endif + #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \ || defined(BUILD_TARGET_RISCV64_LP64) -#include - #define OS_ENABLE_HW_BOUND_CHECK -typedef jmp_buf korp_jmpbuf; - -#define os_setjmp setjmp -#define os_longjmp longjmp #define os_alloca alloca #define os_getpagesize getpagesize @@ -99,6 +97,13 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK) +#include +typedef jmp_buf korp_jmpbuf; +#define os_setjmp setjmp +#define os_longjmp longjmp +#endif + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/vxworks/platform_internal.h b/core/shared/platform/vxworks/platform_internal.h index f72f603225..ddcd09f42b 100644 --- a/core/shared/platform/vxworks/platform_internal.h +++ b/core/shared/platform/vxworks/platform_internal.h @@ -60,18 +60,16 @@ typedef sem_t korp_sem; #define os_thread_local_attribute __thread +#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 +#define OS_ENABLE_BLOCK_INSN_INTERRUPT +#endif + #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ || defined(BUILD_TARGET_AARCH64) -#include - #define OS_ENABLE_HW_BOUND_CHECK -typedef jmp_buf korp_jmpbuf; - -#define os_setjmp setjmp -#define os_longjmp longjmp #define os_alloca alloca #define os_getpagesize getpagesize @@ -95,6 +93,13 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK) +#include +typedef jmp_buf korp_jmpbuf; +#define os_setjmp setjmp +#define os_longjmp longjmp +#endif + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index 1332afc2ce..ae2c2ce6ec 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -89,18 +89,15 @@ os_mem_decommit(void *ptr, size_t size); #define strncasecmp _strnicmp #define strcasecmp _stricmp +#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 +#define OS_ENABLE_BLOCK_INSN_INTERRUPT +#endif + #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) -#include - #define OS_ENABLE_HW_BOUND_CHECK -typedef jmp_buf korp_jmpbuf; - -#define os_setjmp setjmp -#define os_longjmp longjmp - int os_thread_signal_init(); @@ -116,6 +113,13 @@ os_thread_signal_inited(); #endif /* end of BUILD_TARGET_X86_64/AMD_64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK) +#include +typedef jmp_buf korp_jmpbuf; +#define os_setjmp setjmp +#define os_longjmp longjmp +#endif + #ifdef __cplusplus } #endif From 185cd4d5c9af3e4e6dbd82f826c98ed4719864f5 Mon Sep 17 00:00:00 2001 From: eloparco Date: Fri, 3 Feb 2023 00:10:36 +0000 Subject: [PATCH 2/5] fix(wasi-threads): fix platform includes --- core/iwasm/aot/aot_runtime.c | 18 +++++++++++-- core/iwasm/common/wasm_runtime_common.c | 25 +++++-------------- core/iwasm/interpreter/wasm_runtime.c | 6 ++++- .../libraries/thread-mgr/thread_manager.c | 2 ++ .../platform/android/platform_internal.h | 6 ++++- .../platform/common/posix/posix_thread.c | 17 +++++++++++++ .../platform/darwin/platform_internal.h | 6 ++++- .../platform/freebsd/platform_internal.h | 6 ++++- .../shared/platform/linux/platform_internal.h | 6 ++++- .../platform/vxworks/platform_internal.h | 6 ++++- .../platform/windows/platform_internal.h | 18 ++++++------- 11 files changed, 78 insertions(+), 38 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 09a0df50b0..9bcfa1803e 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1391,15 +1391,22 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, #ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); wasm_runtime_set_exec_env_tls(exec_env); - if (os_setjmp(jmpbuf_node.jmpbuf) == 0) + if (os_setjmp(jmpbuf_node.jmpbuf) == 0) { #endif ret = invoke_native_internal(exec_env, function->u.func.func_ptr, func_type, NULL, NULL, argv1, argc, argv); #ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + } + else { + ret = false; + } jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env); bh_assert(&jmpbuf_node == jmpbuf_node_pop); + if (!exec_env->jmpbuf_stack_top) { + wasm_runtime_set_exec_env_tls(NULL); + } #endif #if WASM_ENABLE_DUMP_CALL_STACK != 0 @@ -1461,15 +1468,22 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, #ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); wasm_runtime_set_exec_env_tls(exec_env); - if (os_setjmp(jmpbuf_node.jmpbuf) == 0) + if (os_setjmp(jmpbuf_node.jmpbuf) == 0) { #endif ret = invoke_native_internal(exec_env, function->u.func.func_ptr, func_type, NULL, NULL, argv, argc, argv); #ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + } + else { + ret = false; + } jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env); bh_assert(&jmpbuf_node == jmpbuf_node_pop); + if (!exec_env->jmpbuf_stack_top) { + wasm_runtime_set_exec_env_tls(NULL); + } #endif #if WASM_ENABLE_DUMP_CALL_STACK != 0 diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 590c2a54a9..05e6e0d87c 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -323,7 +323,7 @@ wasm_runtime_get_exec_env_tls() #ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT static void -os_interrupt_block_insn_sig_handler(int sig) +interrupt_block_insn_sig_handler(int sig) { bh_assert(sig == SIGUSR1); @@ -332,22 +332,7 @@ os_interrupt_block_insn_sig_handler(int sig) os_longjmp(jmpbuf_node->jmpbuf, 1); } - -bool -os_interrupt_block_insn_init() -{ - struct sigaction act; - memset(&act, 0, sizeof(act)); - act.sa_handler = os_interrupt_block_insn_sig_handler; - sigfillset(&act.sa_mask); - if (sigaction(SIGUSR1, &act, NULL) < 0) { - LOG_ERROR("failed to set signal handler"); - return false; - } - - return true; -} -#endif +#endif /* OS_ENABLE_BLOCK_INSN_INTERRUPT */ static bool wasm_runtime_env_init() @@ -381,8 +366,8 @@ wasm_runtime_env_init() } #endif #ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT - if (!os_interrupt_block_insn_init()) { - goto fail5; + if (!os_interrupt_block_insn_init(interrupt_block_insn_sig_handler)) { + goto fail6; } #endif #ifdef OS_ENABLE_HW_BOUND_CHECK @@ -440,8 +425,10 @@ wasm_runtime_env_init() fail7: #endif #endif +#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) #ifdef OS_ENABLE_HW_BOUND_CHECK runtime_signal_destroy(); +#endif fail6: #endif #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_THREAD_MGR != 0) diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index c237e1a13f..aa2005561d 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2147,13 +2147,17 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, #ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); wasm_runtime_set_exec_env_tls(exec_env); - if (os_setjmp(jmpbuf_node.jmpbuf) == 0) + if (os_setjmp(jmpbuf_node.jmpbuf) == 0) { #endif interp_call_wasm(module_inst, exec_env, function, argc, argv); #ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + } jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env); bh_assert(&jmpbuf_node == jmpbuf_node_pop); + if (!exec_env->jmpbuf_stack_top) { + wasm_runtime_set_exec_env_tls(NULL); + } #endif return !wasm_get_exception(module_inst) ? true : false; diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 6451e95a25..cde4b4f259 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -1065,8 +1065,10 @@ set_exception_visitor(void *node, void *user_data) sizeof(curr_wasm_inst->cur_exception), wasm_inst->cur_exception, sizeof(wasm_inst->cur_exception)); +#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT bh_assert(curr_exec_env->handle); os_thread_signal(curr_exec_env->handle, SIGUSR1); +#endif /* Terminate the thread so it can exit from dead loops */ set_thread_cancel_flags(curr_exec_env); diff --git a/core/shared/platform/android/platform_internal.h b/core/shared/platform/android/platform_internal.h index b09bac847d..85c1fc7891 100644 --- a/core/shared/platform/android/platform_internal.h +++ b/core/shared/platform/android/platform_internal.h @@ -63,8 +63,12 @@ typedef sem_t korp_sem; #define bh_socket_t int -#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 +#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 && WASM_ENABLE_THREAD_MGR != 0 #define OS_ENABLE_BLOCK_INSN_INTERRUPT + +typedef void (*os_block_insn_sig_handler)(int sig); +bool +os_interrupt_block_insn_init(os_block_insn_sig_handler handler); #endif #if WASM_DISABLE_HW_BOUND_CHECK == 0 diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index 0178cfd6e2..e51df8c9b4 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -420,6 +420,23 @@ os_thread_get_stack_boundary() return addr; } +#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT +bool +os_interrupt_block_insn_init(os_block_insn_sig_handler handler) +{ + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_handler = handler; + sigfillset(&act.sa_mask); + if (sigaction(SIGUSR1, &act, NULL) < 0) { + os_printf("failed to set signal handler\n"); + return false; + } + + return true; +} +#endif /* OS_ENABLE_BLOCK_INSN_INTERRUPT */ + #ifdef OS_ENABLE_HW_BOUND_CHECK #define SIG_ALT_STACK_SIZE (32 * 1024) diff --git a/core/shared/platform/darwin/platform_internal.h b/core/shared/platform/darwin/platform_internal.h index 0feaf73a63..a7a6ef752e 100644 --- a/core/shared/platform/darwin/platform_internal.h +++ b/core/shared/platform/darwin/platform_internal.h @@ -68,7 +68,11 @@ typedef sem_t korp_sem; #if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 #define OS_ENABLE_BLOCK_INSN_INTERRUPT -#endif + +typedef void (*os_block_insn_sig_handler)(int sig); +bool +os_interrupt_block_insn_init(os_block_insn_sig_handler handler); +#endif /* WASM_DISABLE_BLOCK_INSN_INTERRUPT */ #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ diff --git a/core/shared/platform/freebsd/platform_internal.h b/core/shared/platform/freebsd/platform_internal.h index 7242c3ab5f..d3f7c85084 100644 --- a/core/shared/platform/freebsd/platform_internal.h +++ b/core/shared/platform/freebsd/platform_internal.h @@ -67,7 +67,11 @@ typedef sem_t korp_sem; #if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 #define OS_ENABLE_BLOCK_INSN_INTERRUPT -#endif + +typedef void (*os_block_insn_sig_handler)(int sig); +bool +os_interrupt_block_insn_init(os_block_insn_sig_handler handler); +#endif /* WASM_DISABLE_BLOCK_INSN_INTERRUPT */ #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ diff --git a/core/shared/platform/linux/platform_internal.h b/core/shared/platform/linux/platform_internal.h index 7d58372f31..034b5c4497 100644 --- a/core/shared/platform/linux/platform_internal.h +++ b/core/shared/platform/linux/platform_internal.h @@ -65,7 +65,11 @@ typedef sem_t korp_sem; #if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 #define OS_ENABLE_BLOCK_INSN_INTERRUPT -#endif + +typedef void (*os_block_insn_sig_handler)(int sig); +bool +os_interrupt_block_insn_init(os_block_insn_sig_handler handler); +#endif /* WASM_DISABLE_BLOCK_INSN_INTERRUPT */ #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ diff --git a/core/shared/platform/vxworks/platform_internal.h b/core/shared/platform/vxworks/platform_internal.h index ddcd09f42b..639bdff0cc 100644 --- a/core/shared/platform/vxworks/platform_internal.h +++ b/core/shared/platform/vxworks/platform_internal.h @@ -62,7 +62,11 @@ typedef sem_t korp_sem; #if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 #define OS_ENABLE_BLOCK_INSN_INTERRUPT -#endif + +typedef void (*os_block_insn_sig_handler)(int sig); +bool +os_interrupt_block_insn_init(os_block_insn_sig_handler handler); +#endif /* WASM_DISABLE_BLOCK_INSN_INTERRUPT */ #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index ae2c2ce6ec..1332afc2ce 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -89,15 +89,18 @@ os_mem_decommit(void *ptr, size_t size); #define strncasecmp _strnicmp #define strcasecmp _stricmp -#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 -#define OS_ENABLE_BLOCK_INSN_INTERRUPT -#endif - #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) +#include + #define OS_ENABLE_HW_BOUND_CHECK +typedef jmp_buf korp_jmpbuf; + +#define os_setjmp setjmp +#define os_longjmp longjmp + int os_thread_signal_init(); @@ -113,13 +116,6 @@ os_thread_signal_inited(); #endif /* end of BUILD_TARGET_X86_64/AMD_64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ -#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK) -#include -typedef jmp_buf korp_jmpbuf; -#define os_setjmp setjmp -#define os_longjmp longjmp -#endif - #ifdef __cplusplus } #endif From f9c0bd154dfa22bd69e5f905c5d49f6e464a9c37 Mon Sep 17 00:00:00 2001 From: eloparco Date: Sat, 4 Feb 2023 01:43:54 +0000 Subject: [PATCH 3/5] refactor(wasi-threads): move platform-related code and remove "block instruction interrupt" wrapper --- build-scripts/config_common.cmake | 2 - core/config.h | 7 ++ core/iwasm/aot/aot_runtime.c | 93 ++++++++++--------- core/iwasm/common/wasm_runtime_common.c | 4 +- core/iwasm/interpreter/wasm_runtime.c | 49 ++++++---- .../libraries/thread-mgr/thread_manager.c | 2 +- .../platform/android/platform_internal.h | 2 +- .../platform/common/posix/posix_thread.c | 4 +- .../platform/darwin/platform_internal.h | 2 +- .../platform/freebsd/platform_internal.h | 2 +- .../platform/include/platform_api_extension.h | 8 +- .../shared/platform/linux/platform_internal.h | 2 +- .../platform/vxworks/platform_internal.h | 2 +- 13 files changed, 104 insertions(+), 75 deletions(-) diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index a5800f6a48..bd62735244 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -251,8 +251,6 @@ endif () if (WAMR_DISABLE_BLOCK_INSN_INTERRUPT EQUAL 1) add_definitions (-DWASM_DISABLE_BLOCK_INSN_INTERRUPT=1) message (" Interruption of blocking instructions disabled") -else () - add_definitions (-DWASM_DISABLE_BLOCK_INSN_INTERRUPT=0) endif () if (WAMR_BUILD_SIMD EQUAL 1) if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*") diff --git a/core/config.h b/core/config.h index feedb13fa6..b6b3b03328 100644 --- a/core/config.h +++ b/core/config.h @@ -277,6 +277,13 @@ #define WASM_DISABLE_STACK_HW_BOUND_CHECK 0 #endif +/* Disable the capability of interrupting blocking instructions + * (e.g. atomic.wait, sleep) when an exception (e.g. trap, proc_exit) is raised + */ +#ifndef WASM_DISABLE_BLOCK_INSN_INTERRUPT +#define WASM_DISABLE_BLOCK_INSN_INTERRUPT 0 +#endif + /* Disable SIMD unless it is manualy enabled somewhere */ #ifndef WASM_ENABLE_SIMD #define WASM_ENABLE_SIMD 0 diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 9bcfa1803e..51afa5a8a1 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1310,11 +1310,53 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr, (void)jmpbuf_node_pop; return ret; } +#endif /* end of OS_ENABLE_HW_BOUND_CHECK */ + +#ifndef OS_ENABLE_BLOCK_INSN_INTERRUPT +#ifdef OS_ENABLE_HW_BOUND_CHECK #define invoke_native_internal invoke_native_with_hw_bound_check -#else /* else of OS_ENABLE_HW_BOUND_CHECK */ +#else #define invoke_native_internal wasm_runtime_invoke_native -#endif /* end of OS_ENABLE_HW_BOUND_CHECK */ +#endif + +#else /* else of OS_ENABLE_BLOCK_INSN_INTERRUPT */ + +#ifdef OS_ENABLE_HW_BOUND_CHECK +#define invoke_native_block_insn_interrupt invoke_native_with_hw_bound_check +#else +#define invoke_native_block_insn_interrupt wasm_runtime_invoke_native +#endif + +static bool +invoke_native_internal(WASMExecEnv *exec_env, void *func_ptr, + const WASMType *func_type, const char *signature, + void *attachment, uint32 *argv, uint32 argc, + uint32 *argv_ret) +{ + int ret = false; + WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop; + wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); + wasm_runtime_set_exec_env_tls(exec_env); + + if (os_setjmp(jmpbuf_node.jmpbuf) == 0) { + ret = invoke_native_block_insn_interrupt(exec_env, func_ptr, func_type, + signature, attachment, argv, + argc, argv_ret); + } + else { + ret = false; + } + + jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env); + bh_assert(&jmpbuf_node == jmpbuf_node_pop); + if (!exec_env->jmpbuf_stack_top) { + wasm_runtime_set_exec_env_tls(NULL); + } + + return ret; +} +#endif /* end of OS_ENABLE_BLOCK_INSN_INTERRUPT */ bool aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, @@ -1325,9 +1367,6 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, uint32 result_count = func_type->result_count; uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0; bool ret; -#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT - WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop; -#endif if (argc < func_type->param_cell_num) { char buf[108]; @@ -1388,26 +1427,8 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, } #endif -#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT - wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); - wasm_runtime_set_exec_env_tls(exec_env); - if (os_setjmp(jmpbuf_node.jmpbuf) == 0) { -#endif - ret = invoke_native_internal(exec_env, function->u.func.func_ptr, - func_type, NULL, NULL, argv1, argc, - argv); -#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT - } - else { - ret = false; - } - - jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env); - bh_assert(&jmpbuf_node == jmpbuf_node_pop); - if (!exec_env->jmpbuf_stack_top) { - wasm_runtime_set_exec_env_tls(NULL); - } -#endif + ret = invoke_native_internal(exec_env, function->u.func.func_ptr, + func_type, NULL, NULL, argv1, argc, argv); #if WASM_ENABLE_DUMP_CALL_STACK != 0 if (!ret) { @@ -1465,26 +1486,8 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, } #endif -#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT - wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); - wasm_runtime_set_exec_env_tls(exec_env); - if (os_setjmp(jmpbuf_node.jmpbuf) == 0) { -#endif - ret = - invoke_native_internal(exec_env, function->u.func.func_ptr, - func_type, NULL, NULL, argv, argc, argv); -#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT - } - else { - ret = false; - } - - jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env); - bh_assert(&jmpbuf_node == jmpbuf_node_pop); - if (!exec_env->jmpbuf_stack_top) { - wasm_runtime_set_exec_env_tls(NULL); - } -#endif + ret = invoke_native_internal(exec_env, function->u.func.func_ptr, + func_type, NULL, NULL, argv, argc, argv); #if WASM_ENABLE_DUMP_CALL_STACK != 0 if (aot_get_exception(module_inst)) { diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 05e6e0d87c..100affc6a1 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -323,10 +323,8 @@ wasm_runtime_get_exec_env_tls() #ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT static void -interrupt_block_insn_sig_handler(int sig) +interrupt_block_insn_sig_handler() { - bh_assert(sig == SIGUSR1); - WASMJmpBuf *jmpbuf_node = exec_env_tls->jmpbuf_stack_top; bh_assert(jmpbuf_node); diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index aa2005561d..decba4ee63 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2126,31 +2126,35 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst, } (void)jmpbuf_node_pop; } +#endif /* end of OS_ENABLE_HW_BOUND_CHECK */ + +#ifndef OS_ENABLE_BLOCK_INSN_INTERRUPT + +#ifdef OS_ENABLE_HW_BOUND_CHECK #define interp_call_wasm call_wasm_with_hw_bound_check #else #define interp_call_wasm wasm_interp_call_wasm #endif -bool -wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, - unsigned argc, uint32 argv[]) -{ - WASMModuleInstance *module_inst = - (WASMModuleInstance *)exec_env->module_inst; -#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT - WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop; -#endif +#else /* else of OS_ENABLE_BLOCK_INSN_INTERRUPT */ - /* set thread handle and stack boundary */ - wasm_exec_env_set_thread_info(exec_env); +#ifdef OS_ENABLE_HW_BOUND_CHECK +#define call_wasm_block_insn_interrupt call_wasm_with_hw_bound_check +#else +#define call_wasm_block_insn_interrupt wasm_interp_call_wasm +#endif -#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT +static void +interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, + WASMFunctionInstance *function, unsigned argc, uint32 argv[]) +{ + WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop; wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); wasm_runtime_set_exec_env_tls(exec_env); + if (os_setjmp(jmpbuf_node.jmpbuf) == 0) { -#endif - interp_call_wasm(module_inst, exec_env, function, argc, argv); -#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT + call_wasm_block_insn_interrupt(module_inst, exec_env, function, argc, + argv); } jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env); @@ -2158,7 +2162,20 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, if (!exec_env->jmpbuf_stack_top) { wasm_runtime_set_exec_env_tls(NULL); } -#endif +} +#endif /* end of OS_ENABLE_BLOCK_INSN_INTERRUPT */ + +bool +wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, + unsigned argc, uint32 argv[]) +{ + WASMModuleInstance *module_inst = + (WASMModuleInstance *)exec_env->module_inst; + + /* set thread handle and stack boundary */ + wasm_exec_env_set_thread_info(exec_env); + + interp_call_wasm(module_inst, exec_env, function, argc, argv); return !wasm_get_exception(module_inst) ? true : false; } diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index cde4b4f259..d92b3d04b2 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -1067,7 +1067,7 @@ set_exception_visitor(void *node, void *user_data) #ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT bh_assert(curr_exec_env->handle); - os_thread_signal(curr_exec_env->handle, SIGUSR1); + os_thread_kill(curr_exec_env->handle); #endif /* Terminate the thread so it can exit from dead loops */ diff --git a/core/shared/platform/android/platform_internal.h b/core/shared/platform/android/platform_internal.h index 85c1fc7891..a8b270e17c 100644 --- a/core/shared/platform/android/platform_internal.h +++ b/core/shared/platform/android/platform_internal.h @@ -66,7 +66,7 @@ typedef sem_t korp_sem; #if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 && WASM_ENABLE_THREAD_MGR != 0 #define OS_ENABLE_BLOCK_INSN_INTERRUPT -typedef void (*os_block_insn_sig_handler)(int sig); +typedef void (*os_block_insn_sig_handler)(); bool os_interrupt_block_insn_init(os_block_insn_sig_handler handler); #endif diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index e51df8c9b4..55e83c96d5 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -347,9 +347,9 @@ os_thread_exit(void *retval) } int -os_thread_signal(korp_tid tid, int sig) +os_thread_kill(korp_tid tid) { - return pthread_kill(tid, sig); + return pthread_kill(tid, SIGUSR1); } #if defined(os_thread_local_attribute) diff --git a/core/shared/platform/darwin/platform_internal.h b/core/shared/platform/darwin/platform_internal.h index a7a6ef752e..4f96a08b86 100644 --- a/core/shared/platform/darwin/platform_internal.h +++ b/core/shared/platform/darwin/platform_internal.h @@ -69,7 +69,7 @@ typedef sem_t korp_sem; #if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 #define OS_ENABLE_BLOCK_INSN_INTERRUPT -typedef void (*os_block_insn_sig_handler)(int sig); +typedef void (*os_block_insn_sig_handler)(); bool os_interrupt_block_insn_init(os_block_insn_sig_handler handler); #endif /* WASM_DISABLE_BLOCK_INSN_INTERRUPT */ diff --git a/core/shared/platform/freebsd/platform_internal.h b/core/shared/platform/freebsd/platform_internal.h index d3f7c85084..552214f714 100644 --- a/core/shared/platform/freebsd/platform_internal.h +++ b/core/shared/platform/freebsd/platform_internal.h @@ -68,7 +68,7 @@ typedef sem_t korp_sem; #if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 #define OS_ENABLE_BLOCK_INSN_INTERRUPT -typedef void (*os_block_insn_sig_handler)(int sig); +typedef void (*os_block_insn_sig_handler)(); bool os_interrupt_block_insn_init(os_block_insn_sig_handler handler); #endif /* WASM_DISABLE_BLOCK_INSN_INTERRUPT */ diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index db67a00d33..eda1dd6d7d 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -92,8 +92,14 @@ int os_thread_detach(korp_tid); void os_thread_exit(void *retval); +/** + * Stop the thread specified + * + * @param tid id of the thread to stop + * @return 0 if success + */ int -os_thread_signal(korp_tid tid, int sig); +os_thread_kill(korp_tid tid); /** * Initialize current thread environment if current thread diff --git a/core/shared/platform/linux/platform_internal.h b/core/shared/platform/linux/platform_internal.h index 034b5c4497..0b2ebb30d5 100644 --- a/core/shared/platform/linux/platform_internal.h +++ b/core/shared/platform/linux/platform_internal.h @@ -66,7 +66,7 @@ typedef sem_t korp_sem; #if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 #define OS_ENABLE_BLOCK_INSN_INTERRUPT -typedef void (*os_block_insn_sig_handler)(int sig); +typedef void (*os_block_insn_sig_handler)(); bool os_interrupt_block_insn_init(os_block_insn_sig_handler handler); #endif /* WASM_DISABLE_BLOCK_INSN_INTERRUPT */ diff --git a/core/shared/platform/vxworks/platform_internal.h b/core/shared/platform/vxworks/platform_internal.h index 639bdff0cc..239f25acbc 100644 --- a/core/shared/platform/vxworks/platform_internal.h +++ b/core/shared/platform/vxworks/platform_internal.h @@ -63,7 +63,7 @@ typedef sem_t korp_sem; #if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 #define OS_ENABLE_BLOCK_INSN_INTERRUPT -typedef void (*os_block_insn_sig_handler)(int sig); +typedef void (*os_block_insn_sig_handler)(); bool os_interrupt_block_insn_init(os_block_insn_sig_handler handler); #endif /* WASM_DISABLE_BLOCK_INSN_INTERRUPT */ From 6eecad73b91b82c51dcd79ccbc1e4d798b527513 Mon Sep 17 00:00:00 2001 From: eloparco Date: Sun, 5 Feb 2023 03:00:10 +0000 Subject: [PATCH 4/5] feat(wasi-threads): use blocking operations in thread termination example --- samples/wasi-threads/wasm-apps/thread_termination.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/samples/wasi-threads/wasm-apps/thread_termination.c b/samples/wasi-threads/wasm-apps/thread_termination.c index dfc228eb3c..cf84a52a48 100644 --- a/samples/wasi-threads/wasm-apps/thread_termination.c +++ b/samples/wasi-threads/wasm-apps/thread_termination.c @@ -17,6 +17,7 @@ #define TEST_TERMINATION_BY_TRAP 0 // Otherwise test `proc_exit` termination #define TEST_TERMINATION_IN_MAIN_THREAD 1 +#define TEST_ATOMIC_WAIT 1 // Otherwise test `sleep` #define TIMEOUT_SECONDS 10 #define NUM_THREADS 3 @@ -30,9 +31,11 @@ typedef struct { void run_long_task() { - // Busy waiting to be interruptible by trap or `proc_exit` - for (int i = 0; i < TIMEOUT_SECONDS; i++) - sleep(1); +#if TEST_ATOMIC_WAIT == 1 + __builtin_wasm_memory_atomic_wait32(0, 0, -1); +#else + sleep(TIMEOUT_SECONDS); +#endif } void @@ -55,7 +58,7 @@ terminate_process() #if TEST_TERMINATION_BY_TRAP == 1 __builtin_trap(); #else - __wasi_proc_exit(1); + __wasi_proc_exit(33); #endif } From 9d6dc29a2d4dc85cf759dc3066741b2a832423f3 Mon Sep 17 00:00:00 2001 From: eloparco Date: Tue, 7 Feb 2023 17:07:42 +0000 Subject: [PATCH 5/5] fix(wasi-threads): handle signal handler being called before os_setjmp --- core/iwasm/aot/aot_runtime.c | 2 +- core/iwasm/common/wasm_runtime_common.c | 4 +++- core/iwasm/interpreter/wasm_runtime.c | 2 +- core/iwasm/libraries/thread-mgr/thread_manager.c | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 51afa5a8a1..be34ebaaf3 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1336,10 +1336,10 @@ invoke_native_internal(WASMExecEnv *exec_env, void *func_ptr, { int ret = false; WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop; - wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); wasm_runtime_set_exec_env_tls(exec_env); if (os_setjmp(jmpbuf_node.jmpbuf) == 0) { + wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); ret = invoke_native_block_insn_interrupt(exec_env, func_ptr, func_type, signature, attachment, argv, argc, argv_ret); diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 100affc6a1..4c646a0369 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -326,7 +326,9 @@ static void interrupt_block_insn_sig_handler() { WASMJmpBuf *jmpbuf_node = exec_env_tls->jmpbuf_stack_top; - bh_assert(jmpbuf_node); + if (!jmpbuf_node) { + return; + } os_longjmp(jmpbuf_node->jmpbuf, 1); } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index decba4ee63..81507493e9 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2149,10 +2149,10 @@ interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, WASMFunctionInstance *function, unsigned argc, uint32 argv[]) { WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop; - wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); wasm_runtime_set_exec_env_tls(exec_env); if (os_setjmp(jmpbuf_node.jmpbuf) == 0) { + wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node); call_wasm_block_insn_interrupt(module_inst, exec_env, function, argc, argv); } diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index d92b3d04b2..97d632a091 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -520,7 +520,7 @@ thread_manager_start_routine(void *arg) exec_env->handle = os_self_thread(); ret = exec_env->thread_start_routine(exec_env); -#ifdef OS_ENABLE_HW_BOUND_CHECK +#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) if (exec_env->suspend_flags.flags & 0x08) ret = exec_env->thread_ret_value; #endif @@ -826,7 +826,7 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval) { WASMCluster *cluster; -#ifdef OS_ENABLE_HW_BOUND_CHECK +#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) if (exec_env->jmpbuf_stack_top) { /* Store the return value in exec_env */ exec_env->thread_ret_value = retval;