Skip to content

Commit 753712f

Browse files
authored
feat: Interrupt blocking instructions using signals (#1946)
Move "blocking instruction interruption" implementation from #1930
1 parent 89c11c5 commit 753712f

File tree

16 files changed

+241
-43
lines changed

16 files changed

+241
-43
lines changed

build-scripts/config_common.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,10 @@ else ()
248248
add_definitions (-DWASM_DISABLE_STACK_HW_BOUND_CHECK=0)
249249
endif ()
250250
endif ()
251+
if (WAMR_DISABLE_BLOCK_INSN_INTERRUPT EQUAL 1)
252+
add_definitions (-DWASM_DISABLE_BLOCK_INSN_INTERRUPT=1)
253+
message (" Interruption of blocking instructions disabled")
254+
endif ()
251255
if (WAMR_BUILD_SIMD EQUAL 1)
252256
if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*")
253257
add_definitions (-DWASM_ENABLE_SIMD=1)

core/config.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,13 @@
266266
#define WASM_DISABLE_STACK_HW_BOUND_CHECK 0
267267
#endif
268268

269+
/* Disable the capability of interrupting blocking instructions
270+
* (e.g. atomic.wait, sleep) when an exception (e.g. trap, proc_exit) is raised
271+
*/
272+
#ifndef WASM_DISABLE_BLOCK_INSN_INTERRUPT
273+
#define WASM_DISABLE_BLOCK_INSN_INTERRUPT 0
274+
#endif
275+
269276
/* Disable SIMD unless it is manualy enabled somewhere */
270277
#ifndef WASM_ENABLE_SIMD
271278
#define WASM_ENABLE_SIMD 0

core/iwasm/aot/aot_runtime.c

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,11 +1333,53 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
13331333
(void)jmpbuf_node_pop;
13341334
return ret;
13351335
}
1336+
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
1337+
1338+
#ifndef OS_ENABLE_BLOCK_INSN_INTERRUPT
13361339

1340+
#ifdef OS_ENABLE_HW_BOUND_CHECK
13371341
#define invoke_native_internal invoke_native_with_hw_bound_check
1338-
#else /* else of OS_ENABLE_HW_BOUND_CHECK */
1342+
#else
13391343
#define invoke_native_internal wasm_runtime_invoke_native
1340-
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
1344+
#endif
1345+
1346+
#else /* else of OS_ENABLE_BLOCK_INSN_INTERRUPT */
1347+
1348+
#ifdef OS_ENABLE_HW_BOUND_CHECK
1349+
#define invoke_native_block_insn_interrupt invoke_native_with_hw_bound_check
1350+
#else
1351+
#define invoke_native_block_insn_interrupt wasm_runtime_invoke_native
1352+
#endif
1353+
1354+
static bool
1355+
invoke_native_internal(WASMExecEnv *exec_env, void *func_ptr,
1356+
const WASMType *func_type, const char *signature,
1357+
void *attachment, uint32 *argv, uint32 argc,
1358+
uint32 *argv_ret)
1359+
{
1360+
int ret = false;
1361+
WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop;
1362+
wasm_runtime_set_exec_env_tls(exec_env);
1363+
1364+
if (os_setjmp(jmpbuf_node.jmpbuf) == 0) {
1365+
wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
1366+
ret = invoke_native_block_insn_interrupt(exec_env, func_ptr, func_type,
1367+
signature, attachment, argv,
1368+
argc, argv_ret);
1369+
}
1370+
else {
1371+
ret = false;
1372+
}
1373+
1374+
jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env);
1375+
bh_assert(&jmpbuf_node == jmpbuf_node_pop);
1376+
if (!exec_env->jmpbuf_stack_top) {
1377+
wasm_runtime_set_exec_env_tls(NULL);
1378+
}
1379+
1380+
return ret;
1381+
}
1382+
#endif /* end of OS_ENABLE_BLOCK_INSN_INTERRUPT */
13411383

13421384
bool
13431385
aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
@@ -1494,7 +1536,7 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
14941536
WASMExecEnv *exec_env = NULL, *existing_exec_env = NULL;
14951537
bool ret;
14961538

1497-
#if defined(OS_ENABLE_HW_BOUND_CHECK)
1539+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
14981540
existing_exec_env = exec_env = wasm_runtime_get_exec_env_tls();
14991541
#elif WASM_ENABLE_THREAD_MGR != 0
15001542
existing_exec_env = exec_env =

core/iwasm/common/wasm_exec_env.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg)
228228
}
229229
#endif
230230

231-
#ifdef OS_ENABLE_HW_BOUND_CHECK
231+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
232232
void
233233
wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf)
234234
{

core/iwasm/common/wasm_exec_env.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ typedef struct WASMCurrentEnvStatus WASMCurrentEnvStatus;
2525
#endif
2626
#endif
2727

28-
#ifdef OS_ENABLE_HW_BOUND_CHECK
28+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
2929
typedef struct WASMJmpBuf {
3030
struct WASMJmpBuf *prev;
3131
korp_jmpbuf jmpbuf;
@@ -141,8 +141,10 @@ typedef struct WASMExecEnv {
141141
BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
142142
#endif
143143

144-
#ifdef OS_ENABLE_HW_BOUND_CHECK
144+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
145145
WASMJmpBuf *jmpbuf_stack_top;
146+
#endif
147+
#ifdef OS_ENABLE_HW_BOUND_CHECK
146148
/* One guard page for the exception check */
147149
uint8 *exce_check_guard_page;
148150
#endif
@@ -301,7 +303,7 @@ void
301303
wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg);
302304
#endif
303305

304-
#ifdef OS_ENABLE_HW_BOUND_CHECK
306+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
305307
void
306308
wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf);
307309

core/iwasm/common/wasm_runtime_common.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,14 @@ static LLVMJITOptions llvm_jit_options = { 3, 3 };
134134

135135
static RunningMode runtime_running_mode = Mode_Default;
136136

137-
#ifdef OS_ENABLE_HW_BOUND_CHECK
137+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
138138
/* The exec_env of thread local storage, set before calling function
139139
and used in signal handler, as we cannot get it from the argument
140140
of signal handler */
141141
static os_thread_local_attribute WASMExecEnv *exec_env_tls = NULL;
142+
#endif
142143

144+
#ifdef OS_ENABLE_HW_BOUND_CHECK
143145
#ifndef BH_PLATFORM_WINDOWS
144146
static void
145147
runtime_signal_handler(void *sig_addr)
@@ -309,7 +311,9 @@ runtime_signal_destroy()
309311
#endif
310312
os_thread_signal_destroy();
311313
}
314+
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
312315

316+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
313317
void
314318
wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env)
315319
{
@@ -321,7 +325,20 @@ wasm_runtime_get_exec_env_tls()
321325
{
322326
return exec_env_tls;
323327
}
324-
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
328+
#endif
329+
330+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
331+
static void
332+
interrupt_block_insn_sig_handler()
333+
{
334+
WASMJmpBuf *jmpbuf_node = exec_env_tls->jmpbuf_stack_top;
335+
if (!jmpbuf_node) {
336+
return;
337+
}
338+
339+
os_longjmp(jmpbuf_node->jmpbuf, 1);
340+
}
341+
#endif /* OS_ENABLE_BLOCK_INSN_INTERRUPT */
325342

326343
static bool
327344
wasm_runtime_env_init()
@@ -354,7 +371,11 @@ wasm_runtime_env_init()
354371
goto fail5;
355372
}
356373
#endif
357-
374+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
375+
if (!os_interrupt_block_insn_init(interrupt_block_insn_sig_handler)) {
376+
goto fail6;
377+
}
378+
#endif
358379
#ifdef OS_ENABLE_HW_BOUND_CHECK
359380
if (!runtime_signal_init()) {
360381
goto fail6;
@@ -410,8 +431,10 @@ wasm_runtime_env_init()
410431
fail7:
411432
#endif
412433
#endif
434+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
413435
#ifdef OS_ENABLE_HW_BOUND_CHECK
414436
runtime_signal_destroy();
437+
#endif
415438
fail6:
416439
#endif
417440
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_THREAD_MGR != 0)

core/iwasm/common/wasm_runtime_common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,9 @@ typedef struct WASMSignalInfo {
433433
EXCEPTION_POINTERS *exce_info;
434434
#endif
435435
} WASMSignalInfo;
436+
#endif
436437

438+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
437439
/* Set exec_env of thread local storage */
438440
void
439441
wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env);

core/iwasm/interpreter/wasm_runtime.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2318,11 +2318,45 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
23182318
}
23192319
(void)jmpbuf_node_pop;
23202320
}
2321+
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
2322+
2323+
#ifndef OS_ENABLE_BLOCK_INSN_INTERRUPT
2324+
2325+
#ifdef OS_ENABLE_HW_BOUND_CHECK
23212326
#define interp_call_wasm call_wasm_with_hw_bound_check
23222327
#else
23232328
#define interp_call_wasm wasm_interp_call_wasm
23242329
#endif
23252330

2331+
#else /* else of OS_ENABLE_BLOCK_INSN_INTERRUPT */
2332+
2333+
#ifdef OS_ENABLE_HW_BOUND_CHECK
2334+
#define call_wasm_block_insn_interrupt call_wasm_with_hw_bound_check
2335+
#else
2336+
#define call_wasm_block_insn_interrupt wasm_interp_call_wasm
2337+
#endif
2338+
2339+
static void
2340+
interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
2341+
WASMFunctionInstance *function, unsigned argc, uint32 argv[])
2342+
{
2343+
WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop;
2344+
wasm_runtime_set_exec_env_tls(exec_env);
2345+
2346+
if (os_setjmp(jmpbuf_node.jmpbuf) == 0) {
2347+
wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
2348+
call_wasm_block_insn_interrupt(module_inst, exec_env, function, argc,
2349+
argv);
2350+
}
2351+
2352+
jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env);
2353+
bh_assert(&jmpbuf_node == jmpbuf_node_pop);
2354+
if (!exec_env->jmpbuf_stack_top) {
2355+
wasm_runtime_set_exec_env_tls(NULL);
2356+
}
2357+
}
2358+
#endif /* end of OS_ENABLE_BLOCK_INSN_INTERRUPT */
2359+
23262360
bool
23272361
wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
23282362
unsigned argc, uint32 argv[])
@@ -2334,6 +2368,7 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
23342368
wasm_exec_env_set_thread_info(exec_env);
23352369

23362370
interp_call_wasm(module_inst, exec_env, function, argc, argv);
2371+
23372372
return !wasm_get_exception(module_inst) ? true : false;
23382373
}
23392374

@@ -2345,7 +2380,7 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
23452380
WASMExecEnv *exec_env = NULL, *existing_exec_env = NULL;
23462381
bool ret;
23472382

2348-
#if defined(OS_ENABLE_HW_BOUND_CHECK)
2383+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
23492384
existing_exec_env = exec_env = wasm_runtime_get_exec_env_tls();
23502385
#elif WASM_ENABLE_THREAD_MGR != 0
23512386
existing_exec_env = exec_env =

core/iwasm/libraries/thread-mgr/thread_manager.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ thread_manager_start_routine(void *arg)
522522
exec_env->handle = os_self_thread();
523523
ret = exec_env->thread_start_routine(exec_env);
524524

525-
#ifdef OS_ENABLE_HW_BOUND_CHECK
525+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
526526
if (exec_env->suspend_flags.flags & 0x08)
527527
ret = exec_env->thread_ret_value;
528528
#endif
@@ -821,7 +821,7 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval)
821821
{
822822
WASMCluster *cluster;
823823

824-
#ifdef OS_ENABLE_HW_BOUND_CHECK
824+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
825825
if (exec_env->jmpbuf_stack_top) {
826826
/* Store the return value in exec_env */
827827
exec_env->thread_ret_value = retval;
@@ -1058,6 +1058,12 @@ set_exception_visitor(void *node, void *user_data)
10581058
bh_memcpy_s(curr_wasm_inst->cur_exception,
10591059
sizeof(curr_wasm_inst->cur_exception),
10601060
wasm_inst->cur_exception, sizeof(wasm_inst->cur_exception));
1061+
1062+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
1063+
bh_assert(curr_exec_env->handle);
1064+
os_thread_kill(curr_exec_env->handle);
1065+
#endif
1066+
10611067
/* Terminate the thread so it can exit from dead loops */
10621068
set_thread_cancel_flags(curr_exec_env);
10631069
}

core/shared/platform/android/platform_internal.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,21 @@ typedef sem_t korp_sem;
6363

6464
#define bh_socket_t int
6565

66+
#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0 && WASM_ENABLE_THREAD_MGR != 0
67+
#define OS_ENABLE_BLOCK_INSN_INTERRUPT
68+
69+
typedef void (*os_block_insn_sig_handler)();
70+
bool
71+
os_interrupt_block_insn_init(os_block_insn_sig_handler handler);
72+
#endif
73+
6674
#if WASM_DISABLE_HW_BOUND_CHECK == 0
6775
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
6876
|| defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
6977
|| defined(BUILD_TARGET_RISCV64_LP64)
7078

71-
#include <setjmp.h>
72-
7379
#define OS_ENABLE_HW_BOUND_CHECK
7480

75-
typedef jmp_buf korp_jmpbuf;
76-
77-
#define os_setjmp setjmp
78-
#define os_longjmp longjmp
7981
#define os_alloca alloca
8082

8183
#define os_getpagesize getpagesize
@@ -99,6 +101,13 @@ os_sigreturn();
99101
#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
100102
#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
101103

104+
#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK)
105+
#include <setjmp.h>
106+
typedef jmp_buf korp_jmpbuf;
107+
#define os_setjmp setjmp
108+
#define os_longjmp longjmp
109+
#endif
110+
102111
typedef long int __syscall_slong_t;
103112

104113
#if __ANDROID_API__ < 19

0 commit comments

Comments
 (0)