Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor interrupting blocking threads #1948

Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions build-scripts/config_common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,9 @@ 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")
if (WAMR_BUILD_INTERRUPT_BLOCK_INSN EQUAL 1)
add_definitions (-DWASM_ENABLE_INTERRUPT_BLOCK_INSN=1)
message (" Interruption of blocking instructions enabled")
endif ()
if (WAMR_BUILD_SIMD EQUAL 1)
if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*")
Expand Down
6 changes: 3 additions & 3 deletions core/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,11 +266,11 @@
#define WASM_DISABLE_STACK_HW_BOUND_CHECK 0
#endif

/* Disable the capability of interrupting blocking instructions
/* Enable 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
#ifndef WASM_ENABLE_INTERRUPT_BLOCK_INSN
#define WASM_ENABLE_INTERRUPT_BLOCK_INSN 0
#endif

/* Disable SIMD unless it is manualy enabled somewhere */
Expand Down
40 changes: 32 additions & 8 deletions core/iwasm/aot/aot_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -1276,10 +1276,16 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
return false;
}

#ifdef OS_ENABLE_INTERRUPT_BLOCK_INSN
exec_env->canjump = 0;
#endif
wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);

wasm_runtime_set_exec_env_tls(exec_env);

if (os_setjmp(jmpbuf_node.jmpbuf) == 0) {
#ifdef OS_ENABLE_INTERRUPT_BLOCK_INSN
exec_env->canjump = 1;
#endif
/* Quick call with func_ptr if the function signature is simple */
if (!signature && param_count == 1 && types[0] == VALUE_TYPE_I32) {
if (result_count == 0) {
Expand Down Expand Up @@ -1321,6 +1327,10 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
ret = false;
}

#ifdef OS_ENABLE_INTERRUPT_BLOCK_INSN
exec_env->canjump = 0;
#endif

jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env);
bh_assert(&jmpbuf_node == jmpbuf_node_pop);
if (!exec_env->jmpbuf_stack_top) {
Expand All @@ -1330,20 +1340,24 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
os_sigreturn();
os_signal_unmask();
}

#ifdef OS_ENABLE_INTERRUPT_BLOCK_INSN
exec_env->canjump = 1;
#endif
(void)jmpbuf_node_pop;
return ret;
}
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */

#ifndef OS_ENABLE_BLOCK_INSN_INTERRUPT
#ifndef OS_ENABLE_INTERRUPT_BLOCK_INSN

#ifdef OS_ENABLE_HW_BOUND_CHECK
#define invoke_native_internal invoke_native_with_hw_bound_check
#else
#define invoke_native_internal wasm_runtime_invoke_native
#endif

#else /* else of OS_ENABLE_BLOCK_INSN_INTERRUPT */
#else /* else of OS_ENABLE_INTERRUPT_BLOCK_INSN */

#ifdef OS_ENABLE_HW_BOUND_CHECK
#define invoke_native_block_insn_interrupt invoke_native_with_hw_bound_check
Expand All @@ -1357,29 +1371,39 @@ invoke_native_internal(WASMExecEnv *exec_env, void *func_ptr,
void *attachment, uint32 *argv, uint32 argc,
uint32 *argv_ret)
{
int ret = false;
bool ret;
WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop;

exec_env->canjump = 0;
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);
exec_env->canjump = 1;
ret = invoke_native_block_insn_interrupt(exec_env, func_ptr, func_type,
signature, attachment, argv,
argc, argv_ret);
}
else {
/* Exception has been set in signal handler before calling longjmp */
ret = false;
}

exec_env->canjump = 0;
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);
}

if (!ret) {
os_sigreturn();
os_signal_unmask();
}
exec_env->canjump = 1;
(void)jmpbuf_node_pop;
return ret;
}
#endif /* end of OS_ENABLE_BLOCK_INSN_INTERRUPT */
#endif /* end of OS_ENABLE_INTERRUPT_BLOCK_INSN */

bool
aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
Expand Down Expand Up @@ -1536,7 +1560,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) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
existing_exec_env = exec_env = wasm_runtime_get_exec_env_tls();
#elif WASM_ENABLE_THREAD_MGR != 0
existing_exec_env = exec_env =
Expand Down
2 changes: 1 addition & 1 deletion core/iwasm/common/wasm_exec_env.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg)
}
#endif

#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
void
wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf)
{
Expand Down
12 changes: 9 additions & 3 deletions core/iwasm/common/wasm_exec_env.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ typedef struct WASMCurrentEnvStatus WASMCurrentEnvStatus;
#endif
#endif

#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
typedef struct WASMJmpBuf {
struct WASMJmpBuf *prev;
korp_jmpbuf jmpbuf;
Expand Down Expand Up @@ -120,6 +120,12 @@ typedef struct WASMExecEnv {

/* whether current thread is detached */
bool thread_is_detached;

#ifdef OS_ENABLE_INTERRUPT_BLOCK_INSN
/* Whether the signal handler of interrupting blocking instruction
feature can longjmp to the place of setjmp */
volatile sig_atomic_t canjump;
#endif
#endif

#if WASM_ENABLE_DEBUG_INTERP != 0
Expand All @@ -141,7 +147,7 @@ typedef struct WASMExecEnv {
BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
#endif

#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
WASMJmpBuf *jmpbuf_stack_top;
#endif
#ifdef OS_ENABLE_HW_BOUND_CHECK
Expand Down Expand Up @@ -303,7 +309,7 @@ void
wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg);
#endif

#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
void
wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf);

Expand Down
88 changes: 52 additions & 36 deletions core/iwasm/common/wasm_runtime_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,17 +134,17 @@ static LLVMJITOptions llvm_jit_options = { 3, 3 };

static RunningMode runtime_running_mode = Mode_Default;

#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
/* 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

#ifdef OS_ENABLE_HW_BOUND_CHECK
static void
runtime_signal_handler(void *sig_addr)
hw_bound_check_sig_handler(void *sig_addr)
{
WASMModuleInstance *module_inst;
WASMMemoryInstance *memory_inst;
Expand Down Expand Up @@ -200,7 +200,38 @@ runtime_signal_handler(void *sig_addr)
}
}
}
#else
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */

#ifdef OS_ENABLE_INTERRUPT_BLOCK_INSN
static void
interrupt_block_insn_sig_handler()
{
WASMJmpBuf *jmpbuf_node;

/* Check whether current thread is running wasm function */
if (exec_env_tls && exec_env_tls->handle == os_self_thread()
&& exec_env_tls->canjump
&& (jmpbuf_node = exec_env_tls->jmpbuf_stack_top)) {
os_longjmp(jmpbuf_node->jmpbuf, 1);
}
}
#endif /* end of OS_ENABLE_INTERRUPT_BLOCK_INSN */

static void
runtime_signal_handler(int sig, void *sig_addr)
{
#ifdef OS_ENABLE_HW_BOUND_CHECK
if (sig == OS_SIGSEGV || sig == OS_SIGBUS)
hw_bound_check_sig_handler(sig_addr);
#endif
#ifdef OS_ENABLE_INTERRUPT_BLOCK_INSN
if (sig == OS_SIGUSR1)
interrupt_block_insn_sig_handler();
#endif
}

#else /* else if BH_PLATFORM_WINDOWS */

static LONG
runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
{
Expand Down Expand Up @@ -284,6 +315,7 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
sig_addr);
return EXCEPTION_CONTINUE_SEARCH;
}

#endif /* end of BH_PLATFORM_WINDOWS */

static bool
Expand Down Expand Up @@ -311,9 +343,7 @@ 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)
{
Expand All @@ -325,20 +355,8 @@ wasm_runtime_get_exec_env_tls()
{
return exec_env_tls;
}
#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 */
#endif /* end of defined(OS_ENABLE_HW_BOUND_CHECK) || \
defined(OS_ENABLE_INTERRUPT_BLOCK_INSN) */

static bool
wasm_runtime_env_init()
Expand Down Expand Up @@ -371,12 +389,7 @@ 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 defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
if (!runtime_signal_init()) {
goto fail6;
}
Expand Down Expand Up @@ -431,10 +444,8 @@ 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
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
runtime_signal_destroy();
#endif
fail6:
#endif
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_THREAD_MGR != 0)
Expand Down Expand Up @@ -494,7 +505,7 @@ wasm_runtime_destroy()
#endif
#endif

#ifdef OS_ENABLE_HW_BOUND_CHECK
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
runtime_signal_destroy();
#endif

Expand Down Expand Up @@ -1333,7 +1344,7 @@ wasm_runtime_init_thread_env(void)
return false;
#endif

#ifdef OS_ENABLE_HW_BOUND_CHECK
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
if (!runtime_signal_init()) {
#ifdef BH_PLATFORM_WINDOWS
os_thread_env_destroy();
Expand All @@ -1348,7 +1359,7 @@ wasm_runtime_init_thread_env(void)
void
wasm_runtime_destroy_thread_env(void)
{
#ifdef OS_ENABLE_HW_BOUND_CHECK
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
runtime_signal_destroy();
#endif

Expand All @@ -1365,11 +1376,9 @@ wasm_runtime_thread_env_inited(void)
return false;
#endif

#if WASM_ENABLE_AOT != 0
#ifdef OS_ENABLE_HW_BOUND_CHECK
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
if (!os_thread_signal_inited())
return false;
#endif
#endif
return true;
}
Expand Down Expand Up @@ -2346,6 +2355,13 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
(WASMModuleInstanceCommon *)module_inst);
}
#endif
#ifdef OS_ENABLE_INTERRUPT_BLOCK_INSN
if (exec_env) {
/* Kill the blocking threads after exception was spreaded and
atomic waiting nodes were notified */
wasm_cluster_kill_all_except_self(exec_env->cluster, exec_env);
}
#endif
#else
(void)exec_env;
#endif
Expand Down
2 changes: 1 addition & 1 deletion core/iwasm/common/wasm_runtime_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ typedef struct WASMSignalInfo {
} WASMSignalInfo;
#endif

#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_BLOCK_INSN_INTERRUPT)
#if defined(OS_ENABLE_HW_BOUND_CHECK) || defined(OS_ENABLE_INTERRUPT_BLOCK_INSN)
/* Set exec_env of thread local storage */
void
wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env);
Expand Down
Loading