Просмотр исходного кода

feat: Interrupt blocking instructions using signals (#1946)

Move "blocking instruction interruption" implementation from #1930
Enrico Loparco 3 лет назад
Родитель
Сommit
753712fdd6

+ 4 - 0
build-scripts/config_common.cmake

@@ -248,6 +248,10 @@ else ()
     add_definitions (-DWASM_DISABLE_STACK_HW_BOUND_CHECK=0)
     add_definitions (-DWASM_DISABLE_STACK_HW_BOUND_CHECK=0)
   endif ()
   endif ()
 endif ()
 endif ()
+if (WAMR_DISABLE_BLOCK_INSN_INTERRUPT EQUAL 1)
+  add_definitions (-DWASM_DISABLE_BLOCK_INSN_INTERRUPT=1)
+  message ("     Interruption of blocking instructions disabled")
+endif ()
 if (WAMR_BUILD_SIMD EQUAL 1)
 if (WAMR_BUILD_SIMD EQUAL 1)
   if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*")
   if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*")
     add_definitions (-DWASM_ENABLE_SIMD=1)
     add_definitions (-DWASM_ENABLE_SIMD=1)

+ 7 - 0
core/config.h

@@ -266,6 +266,13 @@
 #define WASM_DISABLE_STACK_HW_BOUND_CHECK 0
 #define WASM_DISABLE_STACK_HW_BOUND_CHECK 0
 #endif
 #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 */
 /* Disable SIMD unless it is manualy enabled somewhere */
 #ifndef WASM_ENABLE_SIMD
 #ifndef WASM_ENABLE_SIMD
 #define WASM_ENABLE_SIMD 0
 #define WASM_ENABLE_SIMD 0

+ 45 - 3
core/iwasm/aot/aot_runtime.c

@@ -1333,11 +1333,53 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
     (void)jmpbuf_node_pop;
     (void)jmpbuf_node_pop;
     return ret;
     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
 #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
 #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_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);
+    }
+    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
 bool
 aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
 aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
@@ -1494,7 +1536,7 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
     WASMExecEnv *exec_env = NULL, *existing_exec_env = NULL;
     WASMExecEnv *exec_env = NULL, *existing_exec_env = NULL;
     bool ret;
     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();
     existing_exec_env = exec_env = wasm_runtime_get_exec_env_tls();
 #elif WASM_ENABLE_THREAD_MGR != 0
 #elif WASM_ENABLE_THREAD_MGR != 0
     existing_exec_env = exec_env =
     existing_exec_env = exec_env =

+ 1 - 1
core/iwasm/common/wasm_exec_env.c

@@ -228,7 +228,7 @@ wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg)
 }
 }
 #endif
 #endif
 
 
-#ifdef OS_ENABLE_HW_BOUND_CHECK
+#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
 void
 void
 wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf)
 wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf)
 {
 {

+ 5 - 3
core/iwasm/common/wasm_exec_env.h

@@ -25,7 +25,7 @@ typedef struct WASMCurrentEnvStatus WASMCurrentEnvStatus;
 #endif
 #endif
 #endif
 #endif
 
 
-#ifdef OS_ENABLE_HW_BOUND_CHECK
+#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
 typedef struct WASMJmpBuf {
 typedef struct WASMJmpBuf {
     struct WASMJmpBuf *prev;
     struct WASMJmpBuf *prev;
     korp_jmpbuf jmpbuf;
     korp_jmpbuf jmpbuf;
@@ -141,8 +141,10 @@ typedef struct WASMExecEnv {
     BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
     BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
 #endif
 #endif
 
 
-#ifdef OS_ENABLE_HW_BOUND_CHECK
+#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
     WASMJmpBuf *jmpbuf_stack_top;
     WASMJmpBuf *jmpbuf_stack_top;
+#endif
+#ifdef OS_ENABLE_HW_BOUND_CHECK
     /* One guard page for the exception check */
     /* One guard page for the exception check */
     uint8 *exce_check_guard_page;
     uint8 *exce_check_guard_page;
 #endif
 #endif
@@ -301,7 +303,7 @@ void
 wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg);
 wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg);
 #endif
 #endif
 
 
-#ifdef OS_ENABLE_HW_BOUND_CHECK
+#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
 void
 void
 wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf);
 wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf);
 
 

+ 26 - 3
core/iwasm/common/wasm_runtime_common.c

@@ -134,12 +134,14 @@ static LLVMJITOptions llvm_jit_options = { 3, 3 };
 
 
 static RunningMode runtime_running_mode = Mode_Default;
 static RunningMode runtime_running_mode = Mode_Default;
 
 
-#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
 /* The exec_env of thread local storage, set before calling function
    and used in signal handler, as we cannot get it from the argument
    and used in signal handler, as we cannot get it from the argument
    of signal handler */
    of signal handler */
 static os_thread_local_attribute WASMExecEnv *exec_env_tls = NULL;
 static os_thread_local_attribute WASMExecEnv *exec_env_tls = NULL;
+#endif
 
 
+#ifdef OS_ENABLE_HW_BOUND_CHECK
 #ifndef BH_PLATFORM_WINDOWS
 #ifndef BH_PLATFORM_WINDOWS
 static void
 static void
 runtime_signal_handler(void *sig_addr)
 runtime_signal_handler(void *sig_addr)
@@ -309,7 +311,9 @@ runtime_signal_destroy()
 #endif
 #endif
     os_thread_signal_destroy();
     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
 void
 wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env)
 wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env)
 {
 {
@@ -321,7 +325,20 @@ wasm_runtime_get_exec_env_tls()
 {
 {
     return exec_env_tls;
     return exec_env_tls;
 }
 }
-#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
+#endif
+
+#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
+static void
+interrupt_block_insn_sig_handler()
+{
+    WASMJmpBuf *jmpbuf_node = exec_env_tls->jmpbuf_stack_top;
+    if (!jmpbuf_node) {
+        return;
+    }
+
+    os_longjmp(jmpbuf_node->jmpbuf, 1);
+}
+#endif /* OS_ENABLE_BLOCK_INSN_INTERRUPT */
 
 
 static bool
 static bool
 wasm_runtime_env_init()
 wasm_runtime_env_init()
@@ -354,7 +371,11 @@ wasm_runtime_env_init()
         goto fail5;
         goto fail5;
     }
     }
 #endif
 #endif
-
+#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
+    if (!os_interrupt_block_insn_init(interrupt_block_insn_sig_handler)) {
+        goto fail6;
+    }
+#endif
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 #ifdef OS_ENABLE_HW_BOUND_CHECK
     if (!runtime_signal_init()) {
     if (!runtime_signal_init()) {
         goto fail6;
         goto fail6;
@@ -410,8 +431,10 @@ fail8:
 fail7:
 fail7:
 #endif
 #endif
 #endif
 #endif
+#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 #ifdef OS_ENABLE_HW_BOUND_CHECK
     runtime_signal_destroy();
     runtime_signal_destroy();
+#endif
 fail6:
 fail6:
 #endif
 #endif
 #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_THREAD_MGR != 0)
 #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_THREAD_MGR != 0)

+ 2 - 0
core/iwasm/common/wasm_runtime_common.h

@@ -433,7 +433,9 @@ typedef struct WASMSignalInfo {
     EXCEPTION_POINTERS *exce_info;
     EXCEPTION_POINTERS *exce_info;
 #endif
 #endif
 } WASMSignalInfo;
 } WASMSignalInfo;
+#endif
 
 
+#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
 /* Set exec_env of thread local storage */
 /* Set exec_env of thread local storage */
 void
 void
 wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env);
 wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env);

+ 36 - 1
core/iwasm/interpreter/wasm_runtime.c

@@ -2318,11 +2318,45 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
     }
     }
     (void)jmpbuf_node_pop;
     (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
 #define interp_call_wasm call_wasm_with_hw_bound_check
 #else
 #else
 #define interp_call_wasm wasm_interp_call_wasm
 #define interp_call_wasm wasm_interp_call_wasm
 #endif
 #endif
 
 
+#else /* else of OS_ENABLE_BLOCK_INSN_INTERRUPT */
+
+#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
+
+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_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);
+    }
+
+    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 /* end of OS_ENABLE_BLOCK_INSN_INTERRUPT */
+
 bool
 bool
 wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
 wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
                    unsigned argc, uint32 argv[])
                    unsigned argc, uint32 argv[])
@@ -2334,6 +2368,7 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
     wasm_exec_env_set_thread_info(exec_env);
     wasm_exec_env_set_thread_info(exec_env);
 
 
     interp_call_wasm(module_inst, exec_env, function, argc, argv);
     interp_call_wasm(module_inst, exec_env, function, argc, argv);
+
     return !wasm_get_exception(module_inst) ? true : false;
     return !wasm_get_exception(module_inst) ? true : false;
 }
 }
 
 
@@ -2345,7 +2380,7 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
     WASMExecEnv *exec_env = NULL, *existing_exec_env = NULL;
     WASMExecEnv *exec_env = NULL, *existing_exec_env = NULL;
     bool ret;
     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();
     existing_exec_env = exec_env = wasm_runtime_get_exec_env_tls();
 #elif WASM_ENABLE_THREAD_MGR != 0
 #elif WASM_ENABLE_THREAD_MGR != 0
     existing_exec_env = exec_env =
     existing_exec_env = exec_env =

+ 8 - 2
core/iwasm/libraries/thread-mgr/thread_manager.c

@@ -522,7 +522,7 @@ thread_manager_start_routine(void *arg)
     exec_env->handle = os_self_thread();
     exec_env->handle = os_self_thread();
     ret = exec_env->thread_start_routine(exec_env);
     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)
     if (exec_env->suspend_flags.flags & 0x08)
         ret = exec_env->thread_ret_value;
         ret = exec_env->thread_ret_value;
 #endif
 #endif
@@ -821,7 +821,7 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval)
 {
 {
     WASMCluster *cluster;
     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) {
     if (exec_env->jmpbuf_stack_top) {
         /* Store the return value in exec_env */
         /* Store the return value in exec_env */
         exec_env->thread_ret_value = retval;
         exec_env->thread_ret_value = retval;
@@ -1058,6 +1058,12 @@ set_exception_visitor(void *node, void *user_data)
         bh_memcpy_s(curr_wasm_inst->cur_exception,
         bh_memcpy_s(curr_wasm_inst->cur_exception,
                     sizeof(curr_wasm_inst->cur_exception),
                     sizeof(curr_wasm_inst->cur_exception),
                     wasm_inst->cur_exception, sizeof(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_kill(curr_exec_env->handle);
+#endif
+
         /* Terminate the thread so it can exit from dead loops */
         /* Terminate the thread so it can exit from dead loops */
         set_thread_cancel_flags(curr_exec_env);
         set_thread_cancel_flags(curr_exec_env);
     }
     }

+ 15 - 6
core/shared/platform/android/platform_internal.h

@@ -63,19 +63,21 @@ typedef sem_t korp_sem;
 
 
 #define bh_socket_t int
 #define bh_socket_t int
 
 
+#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)();
+bool
+os_interrupt_block_insn_init(os_block_insn_sig_handler handler);
+#endif
+
 #if WASM_DISABLE_HW_BOUND_CHECK == 0
 #if WASM_DISABLE_HW_BOUND_CHECK == 0
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)            \
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)            \
     || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
     || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
     || defined(BUILD_TARGET_RISCV64_LP64)
     || defined(BUILD_TARGET_RISCV64_LP64)
 
 
-#include <setjmp.h>
-
 #define OS_ENABLE_HW_BOUND_CHECK
 #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_alloca alloca
 
 
 #define os_getpagesize getpagesize
 #define os_getpagesize getpagesize
@@ -99,6 +101,13 @@ os_sigreturn();
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 
 
+#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK)
+#include <setjmp.h>
+typedef jmp_buf korp_jmpbuf;
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#endif
+
 typedef long int __syscall_slong_t;
 typedef long int __syscall_slong_t;
 
 
 #if __ANDROID_API__ < 19
 #if __ANDROID_API__ < 19

+ 23 - 0
core/shared/platform/common/posix/posix_thread.c

@@ -346,6 +346,12 @@ os_thread_exit(void *retval)
     return pthread_exit(retval);
     return pthread_exit(retval);
 }
 }
 
 
+int
+os_thread_kill(korp_tid tid)
+{
+    return pthread_kill(tid, SIGUSR1);
+}
+
 #if defined(os_thread_local_attribute)
 #if defined(os_thread_local_attribute)
 static os_thread_local_attribute uint8 *thread_stack_boundary = NULL;
 static os_thread_local_attribute uint8 *thread_stack_boundary = NULL;
 #endif
 #endif
@@ -414,6 +420,23 @@ os_thread_get_stack_boundary()
     return addr;
     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
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 
 
 #define SIG_ALT_STACK_SIZE (32 * 1024)
 #define SIG_ALT_STACK_SIZE (32 * 1024)

+ 15 - 6
core/shared/platform/darwin/platform_internal.h

@@ -66,19 +66,21 @@ typedef sem_t korp_sem;
 
 
 #define bh_socket_t int
 #define bh_socket_t int
 
 
+#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0
+#define OS_ENABLE_BLOCK_INSN_INTERRUPT
+
+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 */
+
 #if WASM_DISABLE_HW_BOUND_CHECK == 0
 #if WASM_DISABLE_HW_BOUND_CHECK == 0
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)            \
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)            \
     || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
     || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
     || defined(BUILD_TARGET_RISCV64_LP64)
     || defined(BUILD_TARGET_RISCV64_LP64)
 
 
-#include <setjmp.h>
-
 #define OS_ENABLE_HW_BOUND_CHECK
 #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_alloca alloca
 
 
 #define os_getpagesize getpagesize
 #define os_getpagesize getpagesize
@@ -102,6 +104,13 @@ os_sigreturn();
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 
 
+#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK)
+#include <setjmp.h>
+typedef jmp_buf korp_jmpbuf;
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#endif
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 15 - 6
core/shared/platform/freebsd/platform_internal.h

@@ -65,19 +65,21 @@ typedef sem_t korp_sem;
 
 
 #define bh_socket_t int
 #define bh_socket_t int
 
 
+#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0
+#define OS_ENABLE_BLOCK_INSN_INTERRUPT
+
+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 */
+
 #if WASM_DISABLE_HW_BOUND_CHECK == 0
 #if WASM_DISABLE_HW_BOUND_CHECK == 0
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)            \
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)            \
     || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
     || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
     || defined(BUILD_TARGET_RISCV64_LP64)
     || defined(BUILD_TARGET_RISCV64_LP64)
 
 
-#include <setjmp.h>
-
 #define OS_ENABLE_HW_BOUND_CHECK
 #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_alloca alloca
 
 
 #define os_getpagesize getpagesize
 #define os_getpagesize getpagesize
@@ -101,6 +103,13 @@ os_sigreturn();
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 
 
+#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK)
+#include <setjmp.h>
+typedef jmp_buf korp_jmpbuf;
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#endif
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 9 - 0
core/shared/platform/include/platform_api_extension.h

@@ -92,6 +92,15 @@ int os_thread_detach(korp_tid);
 void
 void
 os_thread_exit(void *retval);
 os_thread_exit(void *retval);
 
 
+/**
+ * Stop the thread specified
+ *
+ * @param tid id of the thread to stop
+ * @return 0 if success
+ */
+int
+os_thread_kill(korp_tid tid);
+
 /**
 /**
  * Initialize current thread environment if current thread
  * Initialize current thread environment if current thread
  * is created by developer but not runtime
  * is created by developer but not runtime

+ 15 - 6
core/shared/platform/linux/platform_internal.h

@@ -63,19 +63,21 @@ typedef sem_t korp_sem;
 
 
 #define bh_socket_t int
 #define bh_socket_t int
 
 
+#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0
+#define OS_ENABLE_BLOCK_INSN_INTERRUPT
+
+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 */
+
 #if WASM_DISABLE_HW_BOUND_CHECK == 0
 #if WASM_DISABLE_HW_BOUND_CHECK == 0
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)            \
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)            \
     || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
     || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
     || defined(BUILD_TARGET_RISCV64_LP64)
     || defined(BUILD_TARGET_RISCV64_LP64)
 
 
-#include <setjmp.h>
-
 #define OS_ENABLE_HW_BOUND_CHECK
 #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_alloca alloca
 
 
 #define os_getpagesize getpagesize
 #define os_getpagesize getpagesize
@@ -99,6 +101,13 @@ os_sigreturn();
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 
 
+#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK)
+#include <setjmp.h>
+typedef jmp_buf korp_jmpbuf;
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#endif
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 15 - 6
core/shared/platform/vxworks/platform_internal.h

@@ -60,18 +60,20 @@ typedef sem_t korp_sem;
 
 
 #define os_thread_local_attribute __thread
 #define os_thread_local_attribute __thread
 
 
+#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0
+#define OS_ENABLE_BLOCK_INSN_INTERRUPT
+
+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 */
+
 #if WASM_DISABLE_HW_BOUND_CHECK == 0
 #if WASM_DISABLE_HW_BOUND_CHECK == 0
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
     || defined(BUILD_TARGET_AARCH64)
     || defined(BUILD_TARGET_AARCH64)
 
 
-#include <setjmp.h>
-
 #define OS_ENABLE_HW_BOUND_CHECK
 #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_alloca alloca
 
 
 #define os_getpagesize getpagesize
 #define os_getpagesize getpagesize
@@ -95,6 +97,13 @@ os_sigreturn();
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64 */
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64 */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 
 
+#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK)
+#include <setjmp.h>
+typedef jmp_buf korp_jmpbuf;
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#endif
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif