Bladeren bron

feat: Interrupt blocking instructions using signals (#1946)

Move "blocking instruction interruption" implementation from #1930
Enrico Loparco 3 jaren geleden
bovenliggende
commit
753712fdd6

+ 4 - 0
build-scripts/config_common.cmake

@@ -248,6 +248,10 @@ 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")
+endif ()
 if (WAMR_BUILD_SIMD EQUAL 1)
   if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*")
     add_definitions (-DWASM_ENABLE_SIMD=1)

+ 7 - 0
core/config.h

@@ -266,6 +266,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

+ 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;
     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_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
 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;
     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 =

+ 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
 
-#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)
 {

+ 5 - 3
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;
@@ -141,8 +141,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
@@ -301,7 +303,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);
 

+ 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;
 
-#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)
@@ -309,7 +311,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)
 {
@@ -321,7 +325,20 @@ 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
+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
 wasm_runtime_env_init()
@@ -354,7 +371,11 @@ wasm_runtime_env_init()
         goto fail5;
     }
 #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
     if (!runtime_signal_init()) {
         goto fail6;
@@ -410,8 +431,10 @@ fail8:
 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)

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

@@ -433,7 +433,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);

+ 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;
 }
+#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
 
+#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
 wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
                    unsigned argc, uint32 argv[])
@@ -2334,6 +2368,7 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
     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;
 }
 
@@ -2345,7 +2380,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 =

+ 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();
     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
@@ -821,7 +821,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;
@@ -1058,6 +1058,12 @@ 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));
+
+#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 */
         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
 
+#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 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 <setjmp.h>
-
 #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 +101,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 <setjmp.h>
+typedef jmp_buf korp_jmpbuf;
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#endif
+
 typedef long int __syscall_slong_t;
 
 #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);
 }
 
+int
+os_thread_kill(korp_tid tid)
+{
+    return pthread_kill(tid, SIGUSR1);
+}
+
 #if defined(os_thread_local_attribute)
 static os_thread_local_attribute uint8 *thread_stack_boundary = NULL;
 #endif
@@ -414,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)

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

@@ -66,19 +66,21 @@ typedef sem_t korp_sem;
 
 #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 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 <setjmp.h>
-
 #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 +104,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 <setjmp.h>
+typedef jmp_buf korp_jmpbuf;
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#endif
+
 #ifdef __cplusplus
 }
 #endif

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

@@ -65,19 +65,21 @@ typedef sem_t korp_sem;
 
 #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 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 <setjmp.h>
-
 #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 +103,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 <setjmp.h>
+typedef jmp_buf korp_jmpbuf;
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#endif
+
 #ifdef __cplusplus
 }
 #endif

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

@@ -92,6 +92,15 @@ 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_kill(korp_tid tid);
+
 /**
  * Initialize current thread environment if current thread
  * 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
 
+#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 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 <setjmp.h>
-
 #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 +101,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 <setjmp.h>
+typedef jmp_buf korp_jmpbuf;
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#endif
+
 #ifdef __cplusplus
 }
 #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
 
+#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 defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
     || defined(BUILD_TARGET_AARCH64)
 
-#include <setjmp.h>
-
 #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 +97,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 <setjmp.h>
+typedef jmp_buf korp_jmpbuf;
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#endif
+
 #ifdef __cplusplus
 }
 #endif