Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
53f1655
some logic to terminate blocking op
yamt Aug 28, 2023
5ea4c03
avoid sleeping with a mutex held
yamt Aug 28, 2023
6fbe85c
comment
yamt Aug 30, 2023
63bdb21
fix an inverted condition
yamt Aug 30, 2023
1bfc737
wasm_export.h: add wasm_runtime_{begin|end}_blocking_op
yamt Aug 30, 2023
ec28fa2
make set_thread_cancel_flags interrupt blocking op
yamt Aug 30, 2023
acfd426
wasi: mark blocking ops explicitly
yamt Aug 30, 2023
3114f90
separate blocking op initialization from thread signal init
yamt Aug 30, 2023
0dbcee3
nuttx: update the file list
yamt Aug 30, 2023
f8c8070
wasm_blocking_op.c: this stuff doesn't make sense w/o threads
yamt Aug 30, 2023
dee874b
add dummy wasm_runtime_begin_blocking_op and wasm_runtime_end_blockin…
yamt Aug 30, 2023
a5c3fe0
fix build
yamt Aug 30, 2023
926ad88
OS_ENABLE_WAKEUP_BLOCKING_OP
yamt Aug 31, 2023
4d9668e
OS_ENABLE_WAKEUP_BLOCKING_OP
yamt Aug 31, 2023
71f390d
call os_end_blocking_op in the intended function
yamt Aug 31, 2023
0e856d2
add a missing os_end_blocking_op
yamt Aug 31, 2023
3ee082d
move blocking op wrapper into a separate file
yamt Sep 7, 2023
62a5e23
wasi: WIP adapt more ops
yamt Sep 7, 2023
e41f4e3
wasi: adapt connect, accept
yamt Sep 7, 2023
798a2fe
wasm_runtime_end_blocking_op: preserve errno
yamt Sep 7, 2023
ed8851e
apply clang-format
yamt Sep 7, 2023
a3fc491
nuttx/wamr.mk: add blocking_op.c
yamt Sep 7, 2023
e1379c5
some platforms doesn't seem to have sys/uio.h
yamt Sep 7, 2023
29422d2
wasi: adapt send_to/recv_from
yamt Sep 7, 2023
1a04b48
wasi: adapt socket_addr_resolve
yamt Sep 7, 2023
0fe0f1c
wasi: fix comments
yamt Sep 7, 2023
896cfeb
add a comment
yamt Sep 7, 2023
8775b9a
comment
yamt Sep 7, 2023
0454842
wasi: adapt openat
yamt Sep 8, 2023
a770e37
comment
yamt Sep 8, 2023
6643822
add os_set_signal_number_for_blocking_op
yamt Sep 13, 2023
33d23f0
comment
yamt Sep 13, 2023
143a7d6
posix_blocking_op.c: use pthread_sigmask instead of sigprocmask
yamt Sep 14, 2023
fd13caf
add a comment about getaddrinfo
yamt Sep 14, 2023
5ac3cb5
comment
yamt Sep 15, 2023
0daf3d7
comments
yamt Sep 19, 2023
b5399cd
comment
yamt Sep 19, 2023
ecf798a
add a build-time config WAMR_DISABLE_WAKEUP_BLOCKING_OP
yamt Sep 19, 2023
3be54a0
add messages
yamt Sep 19, 2023
778d2b2
add a missing unlock
yamt Sep 19, 2023
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
7 changes: 7 additions & 0 deletions build-scripts/config_common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,13 @@ else ()
add_definitions (-DWASM_DISABLE_STACK_HW_BOUND_CHECK=0)
endif ()
endif ()
if (WAMR_DISABLE_WAKEUP_BLOCKING_OP EQUAL 1)
add_definitions (-DWASM_DISABLE_WAKEUP_BLOCKING_OP=1)
message (" Wakeup of blocking operations disabled")
else ()
add_definitions (-DWASM_DISABLE_WAKEUP_BLOCKING_OP=0)
message (" Wakeup of blocking operations enabled")
endif ()
if (WAMR_BUILD_SIMD EQUAL 1)
if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*")
add_definitions (-DWASM_ENABLE_SIMD=1)
Expand Down
92 changes: 92 additions & 0 deletions core/iwasm/common/wasm_blocking_op.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright (C) 2023 Midokura Japan KK. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/

#include "wasm_runtime_common.h"

#include "bh_platform.h"
#include "bh_common.h"
#include "bh_assert.h"

#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)

#define LOCK(env) WASM_SUSPEND_FLAGS_LOCK((env)->wait_lock)
#define UNLOCK(env) WASM_SUSPEND_FLAGS_UNLOCK((env)->wait_lock)

#define ISSET(env, bit) \
((WASM_SUSPEND_FLAGS_GET((env)->suspend_flags) & WASM_SUSPEND_FLAG_##bit) \
!= 0)
#define SET(env, bit) \
WASM_SUSPEND_FLAGS_FETCH_OR((env)->suspend_flags, WASM_SUSPEND_FLAG_##bit)
#define CLR(env, bit) \
WASM_SUSPEND_FLAGS_FETCH_AND((env)->suspend_flags, ~WASM_SUSPEND_FLAG_##bit)

bool
wasm_runtime_begin_blocking_op(wasm_exec_env_t env)
{
LOCK(env);
bh_assert(!ISSET(env, BLOCKING));
SET(env, BLOCKING);
if (ISSET(env, TERMINATE)) {
CLR(env, BLOCKING);
UNLOCK(env);
return false;
}
UNLOCK(env);
os_begin_blocking_op();
return true;
}

void
wasm_runtime_end_blocking_op(wasm_exec_env_t env)
{
int saved_errno = errno;
LOCK(env);
bh_assert(ISSET(env, BLOCKING));
CLR(env, BLOCKING);
UNLOCK(env);
os_end_blocking_op();
errno = saved_errno;
}

void
wasm_runtime_interrupt_blocking_op(wasm_exec_env_t env)
{
/*
* ISSET(BLOCKING) here means that the target thread
* is in somewhere between wasm_begin_blocking_op and
* wasm_end_blocking_op.
* keep waking it up until it reaches wasm_end_blocking_op,
* which clears the BLOCKING bit.
*
* this dumb loop is necessary because posix doesn't provide
* a way to unmask signal and block atomically.
*/

LOCK(env);
SET(env, TERMINATE);
while (ISSET(env, BLOCKING)) {
UNLOCK(env);
os_wakeup_blocking_op(env->handle);

/* relax a bit */
os_usleep(50 * 1000);
LOCK(env);
}
UNLOCK(env);
}

#else /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */

bool
wasm_runtime_begin_blocking_op(wasm_exec_env_t env)
{
return true;
}

void
wasm_runtime_end_blocking_op(wasm_exec_env_t env)
{}

#endif /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */
17 changes: 17 additions & 0 deletions core/iwasm/common/wasm_runtime_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -457,8 +457,21 @@ wasm_runtime_env_init()
}
#endif

#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
if (os_blocking_op_init() != BHT_OK) {
goto fail11;
}
os_end_blocking_op();
#endif

return true;

#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
fail11:
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
aot_compiler_destroy();
#endif
#endif
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
fail10:
#if WASM_ENABLE_FAST_JIT != 0
Expand Down Expand Up @@ -1392,6 +1405,10 @@ wasm_runtime_init_thread_env(void)
}
#endif

#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
os_end_blocking_op();
#endif

return true;
}

Expand Down
9 changes: 9 additions & 0 deletions core/iwasm/common/wasm_runtime_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,15 @@ WASM_RUNTIME_API_EXTERN bool
wasm_runtime_is_import_global_linked(const char *module_name,
const char *global_name);

WASM_RUNTIME_API_EXTERN bool
wasm_runtime_begin_blocking_op(WASMExecEnv *exec_env);

WASM_RUNTIME_API_EXTERN void
wasm_runtime_end_blocking_op(WASMExecEnv *exec_env);

void
wasm_runtime_interrupt_blocking_op(WASMExecEnv *exec_env);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions core/iwasm/common/wasm_suspend_flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ extern "C" {
#define WASM_SUSPEND_FLAG_BREAKPOINT 0x4
/* Return from pthread_exit */
#define WASM_SUSPEND_FLAG_EXIT 0x8
/* The thread might be blocking */
#define WASM_SUSPEND_FLAG_BLOCKING 0x10

typedef union WASMSuspendFlags {
bh_atomic_32_t flags;
Expand Down
44 changes: 44 additions & 0 deletions core/iwasm/include/wasm_export.h
Original file line number Diff line number Diff line change
Expand Up @@ -1546,6 +1546,50 @@ wasm_runtime_set_context_spread(wasm_module_inst_t inst, void *key,
WASM_RUNTIME_API_EXTERN void *
wasm_runtime_get_context(wasm_module_inst_t inst, void *key);

/*
* wasm_runtime_begin_blocking_op/wasm_runtime_end_blocking_op
*
* These APIs are intended to be used by the implementations of
* host functions. It wraps an operation which possibly blocks for long
* to prepare for async termination.
*
* eg.
*
* if (!wasm_runtime_begin_blocking_op(exec_env)) {
* return EINTR;
* }
* ret = possibly_blocking_op();
* wasm_runtime_end_blocking_op(exec_env);
* return ret;
*
* If threading support (WASM_ENABLE_THREAD_MGR) is not enabled,
* these functions are no-op.
*
* If the underlying platform support (OS_ENABLE_WAKEUP_BLOCKING_OP) is
* not available, these functions are no-op. In that case, the runtime
* might not terminate a blocking thread in a timely manner.
*
* If the underlying platform support is available, it's used to wake up
* the thread for async termination. The expectation here is that a
* `os_wakeup_blocking_op` call makes the blocking operation
* (`possibly_blocking_op` in the above example) return in a timely manner.
*
* The actual wake up mechanism used by `os_wakeup_blocking_op` is
* platform-dependent. It might impose some platform-dependent restrictions
* on the implementation of the blocking opearation.
*
* For example, on POSIX-like platforms, a signal (by default SIGUSR1) is
* used. The signal delivery configurations (eg. signal handler, signal mask,
* etc) for the signal are set up by the runtime. You can change the signal
* to use for this purpose by calling os_set_signal_number_for_blocking_op
* before the runtime initialization.
*/
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_begin_blocking_op(wasm_exec_env_t exec_env);

WASM_RUNTIME_API_EXTERN void
wasm_runtime_end_blocking_op(wasm_exec_env_t exec_env);

/* clang-format on */

#ifdef __cplusplus
Expand Down
Loading