Skip to content

Commit 3c2f060

Browse files
committed
fix(wasi-threads): interrupt blocking instructions using signals
1 parent 2eed50b commit 3c2f060

File tree

16 files changed

+178
-51
lines changed

16 files changed

+178
-51
lines changed

build-scripts/config_common.cmake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ 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+
else ()
255+
add_definitions (-DWASM_DISABLE_BLOCK_INSN_INTERRUPT=0)
256+
endif ()
251257
if (WAMR_BUILD_SIMD EQUAL 1)
252258
if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*")
253259
add_definitions (-DWASM_ENABLE_SIMD=1)

core/iwasm/aot/aot_runtime.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,9 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
13251325
uint32 result_count = func_type->result_count;
13261326
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
13271327
bool ret;
1328+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
1329+
WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop;
1330+
#endif
13281331

13291332
if (argc < func_type->param_cell_num) {
13301333
char buf[108];
@@ -1385,8 +1388,19 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
13851388
}
13861389
#endif
13871390

1388-
ret = invoke_native_internal(exec_env, function->u.func.func_ptr,
1389-
func_type, NULL, NULL, argv1, argc, argv);
1391+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
1392+
wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
1393+
wasm_runtime_set_exec_env_tls(exec_env);
1394+
if (os_setjmp(jmpbuf_node.jmpbuf) == 0)
1395+
#endif
1396+
ret = invoke_native_internal(exec_env, function->u.func.func_ptr,
1397+
func_type, NULL, NULL, argv1, argc,
1398+
argv);
1399+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
1400+
1401+
jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env);
1402+
bh_assert(&jmpbuf_node == jmpbuf_node_pop);
1403+
#endif
13901404

13911405
#if WASM_ENABLE_DUMP_CALL_STACK != 0
13921406
if (!ret) {
@@ -1444,8 +1458,19 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
14441458
}
14451459
#endif
14461460

1447-
ret = invoke_native_internal(exec_env, function->u.func.func_ptr,
1448-
func_type, NULL, NULL, argv, argc, argv);
1461+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
1462+
wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
1463+
wasm_runtime_set_exec_env_tls(exec_env);
1464+
if (os_setjmp(jmpbuf_node.jmpbuf) == 0)
1465+
#endif
1466+
ret =
1467+
invoke_native_internal(exec_env, function->u.func.func_ptr,
1468+
func_type, NULL, NULL, argv, argc, argv);
1469+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
1470+
1471+
jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env);
1472+
bh_assert(&jmpbuf_node == jmpbuf_node_pop);
1473+
#endif
14491474

14501475
#if WASM_ENABLE_DUMP_CALL_STACK != 0
14511476
if (aot_get_exception(module_inst)) {
@@ -1471,7 +1496,7 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
14711496
WASMExecEnv *exec_env = NULL, *existing_exec_env = NULL;
14721497
bool ret;
14731498

1474-
#if defined(OS_ENABLE_HW_BOUND_CHECK)
1499+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
14751500
existing_exec_env = exec_env = wasm_runtime_get_exec_env_tls();
14761501
#elif WASM_ENABLE_THREAD_MGR != 0
14771502
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
@@ -227,7 +227,7 @@ wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg)
227227
}
228228
#endif
229229

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

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;
@@ -135,8 +135,10 @@ typedef struct WASMExecEnv {
135135
BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
136136
#endif
137137

138-
#ifdef OS_ENABLE_HW_BOUND_CHECK
138+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
139139
WASMJmpBuf *jmpbuf_stack_top;
140+
#endif
141+
#ifdef OS_ENABLE_HW_BOUND_CHECK
140142
/* One guard page for the exception check */
141143
uint8 *exce_check_guard_page;
142144
#endif
@@ -291,7 +293,7 @@ void
291293
wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg);
292294
#endif
293295

294-
#ifdef OS_ENABLE_HW_BOUND_CHECK
296+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
295297
void
296298
wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf);
297299

core/iwasm/common/wasm_runtime_common.c

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,14 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
128128
static JitCompOptions jit_options = { 0 };
129129
#endif
130130

131-
#ifdef OS_ENABLE_HW_BOUND_CHECK
131+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
132132
/* The exec_env of thread local storage, set before calling function
133133
and used in signal handler, as we cannot get it from the argument
134134
of signal handler */
135135
static os_thread_local_attribute WASMExecEnv *exec_env_tls = NULL;
136+
#endif
136137

138+
#ifdef OS_ENABLE_HW_BOUND_CHECK
137139
#ifndef BH_PLATFORM_WINDOWS
138140
static void
139141
runtime_signal_handler(void *sig_addr)
@@ -303,7 +305,9 @@ runtime_signal_destroy()
303305
#endif
304306
os_thread_signal_destroy();
305307
}
308+
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
306309

310+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
307311
void
308312
wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env)
309313
{
@@ -315,7 +319,35 @@ wasm_runtime_get_exec_env_tls()
315319
{
316320
return exec_env_tls;
317321
}
318-
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
322+
#endif
323+
324+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
325+
static void
326+
os_interrupt_block_insn_sig_handler(int sig)
327+
{
328+
bh_assert(sig == SIGUSR1);
329+
330+
WASMJmpBuf *jmpbuf_node = exec_env_tls->jmpbuf_stack_top;
331+
bh_assert(jmpbuf_node);
332+
333+
os_longjmp(jmpbuf_node->jmpbuf, 1);
334+
}
335+
336+
bool
337+
os_interrupt_block_insn_init()
338+
{
339+
struct sigaction act;
340+
memset(&act, 0, sizeof(act));
341+
act.sa_handler = os_interrupt_block_insn_sig_handler;
342+
sigfillset(&act.sa_mask);
343+
if (sigaction(SIGUSR1, &act, NULL) < 0) {
344+
LOG_ERROR("failed to set signal handler");
345+
return false;
346+
}
347+
348+
return true;
349+
}
350+
#endif
319351

320352
static bool
321353
wasm_runtime_env_init()
@@ -348,7 +380,11 @@ wasm_runtime_env_init()
348380
goto fail5;
349381
}
350382
#endif
351-
383+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
384+
if (!os_interrupt_block_insn_init()) {
385+
goto fail5;
386+
}
387+
#endif
352388
#ifdef OS_ENABLE_HW_BOUND_CHECK
353389
if (!runtime_signal_init()) {
354390
goto fail6;

core/iwasm/common/wasm_runtime_common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,9 @@ typedef struct WASMSignalInfo {
423423
EXCEPTION_POINTERS *exce_info;
424424
#endif
425425
} WASMSignalInfo;
426+
#endif
426427

428+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
427429
/* Set exec_env of thread local storage */
428430
void
429431
wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env);

core/iwasm/interpreter/wasm_runtime.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2137,11 +2137,25 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
21372137
{
21382138
WASMModuleInstance *module_inst =
21392139
(WASMModuleInstance *)exec_env->module_inst;
2140+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
2141+
WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop;
2142+
#endif
21402143

21412144
/* set thread handle and stack boundary */
21422145
wasm_exec_env_set_thread_info(exec_env);
21432146

2144-
interp_call_wasm(module_inst, exec_env, function, argc, argv);
2147+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
2148+
wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
2149+
wasm_runtime_set_exec_env_tls(exec_env);
2150+
if (os_setjmp(jmpbuf_node.jmpbuf) == 0)
2151+
#endif
2152+
interp_call_wasm(module_inst, exec_env, function, argc, argv);
2153+
#ifdef OS_ENABLE_BLOCK_INSN_INTERRUPT
2154+
2155+
jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env);
2156+
bh_assert(&jmpbuf_node == jmpbuf_node_pop);
2157+
#endif
2158+
21452159
return !wasm_get_exception(module_inst) ? true : false;
21462160
}
21472161

@@ -2153,7 +2167,7 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
21532167
WASMExecEnv *exec_env = NULL, *existing_exec_env = NULL;
21542168
bool ret;
21552169

2156-
#if defined(OS_ENABLE_HW_BOUND_CHECK)
2170+
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
21572171
existing_exec_env = exec_env = wasm_runtime_get_exec_env_tls();
21582172
#elif WASM_ENABLE_THREAD_MGR != 0
21592173
existing_exec_env = exec_env =

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,10 @@ set_exception_visitor(void *node, void *user_data)
10641064
bh_memcpy_s(curr_wasm_inst->cur_exception,
10651065
sizeof(curr_wasm_inst->cur_exception),
10661066
wasm_inst->cur_exception, sizeof(wasm_inst->cur_exception));
1067+
1068+
bh_assert(curr_exec_env->handle);
1069+
os_thread_signal(curr_exec_env->handle, SIGUSR1);
1070+
10671071
/* Terminate the thread so it can exit from dead loops */
10681072
set_thread_cancel_flags(curr_exec_env);
10691073
}

core/shared/platform/android/platform_internal.h

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

6464
#define bh_socket_t int
6565

66+
#if WASM_DISABLE_BLOCK_INSN_INTERRUPT == 0
67+
#define OS_ENABLE_BLOCK_INSN_INTERRUPT
68+
#endif
69+
6670
#if WASM_DISABLE_HW_BOUND_CHECK == 0
6771
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
6872
|| defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
6973
|| defined(BUILD_TARGET_RISCV64_LP64)
7074

71-
#include <setjmp.h>
72-
7375
#define OS_ENABLE_HW_BOUND_CHECK
7476

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

8179
#define os_getpagesize getpagesize
@@ -99,6 +97,13 @@ os_sigreturn();
9997
#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
10098
#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
10199

100+
#if defined(OS_ENABLE_BLOCK_INSN_INTERRUPT) || defined(OS_ENABLE_HW_BOUND_CHECK)
101+
#include <setjmp.h>
102+
typedef jmp_buf korp_jmpbuf;
103+
#define os_setjmp setjmp
104+
#define os_longjmp longjmp
105+
#endif
106+
102107
typedef long int __syscall_slong_t;
103108

104109
#if __ANDROID_API__ < 19

core/shared/platform/common/posix/posix_thread.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,12 @@ os_thread_exit(void *retval)
346346
return pthread_exit(retval);
347347
}
348348

349+
int
350+
os_thread_signal(korp_tid tid, int sig)
351+
{
352+
return pthread_kill(tid, sig);
353+
}
354+
349355
#if defined(os_thread_local_attribute)
350356
static os_thread_local_attribute uint8 *thread_stack_boundary = NULL;
351357
#endif

0 commit comments

Comments
 (0)