Fix issues in the libc-wasi poll_oneoff when thread-mgr is enabled (#1980)

Fix issues in the libc-wasi `poll_oneoff` when thread manager is enabled:
-  The exception of a thread may be cleared when other thread runs into
   `proc_exit` and then calls `clear_wasi_proc_exit_exception`, so should not
   use `wasm_runtime_get_exception` to check whether an exception was
    thrown, use `wasm_cluster_is_thread_terminated` instead
- We divided one time poll_oneoff into many times poll_oneoff to check
   the exception to avoid long time waiting in previous PR, but if all events
   returned by one time poll are all waiting events, we need to continue to
   wait but not return directly.

Follow-up on #1951. Tested with multiple timeout values, with and without
interruption and measured the time spent sleeping.
This commit is contained in:
Enrico Loparco 2023-02-23 09:11:33 +01:00 committed by GitHub
parent 92c4bbebad
commit 63273a1673
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 25 deletions

View File

@ -6,6 +6,11 @@
#include "libc_wasi_wrapper.h" #include "libc_wasi_wrapper.h"
#include "bh_platform.h" #include "bh_platform.h"
#include "wasm_export.h" #include "wasm_export.h"
#include "wasm_runtime_common.h"
#if WASM_ENABLE_THREAD_MGR != 0
#include "../../../thread-mgr/thread_manager.h"
#endif
void void
wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
@ -46,19 +51,7 @@ typedef struct iovec_app {
uint32 buf_len; uint32 buf_len;
} iovec_app_t; } iovec_app_t;
typedef struct WASIContext { typedef struct WASIContext *wasi_ctx_t;
struct fd_table *curfds;
struct fd_prestats *prestats;
struct argv_environ_values *argv_environ;
struct addr_pool *addr_pool;
char *ns_lookup_buf;
char **ns_lookup_list;
char *argv_buf;
char **argv_list;
char *env_buf;
char **env_list;
uint32_t exit_code;
} * wasi_ctx_t;
wasi_ctx_t wasi_ctx_t
wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst); wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst);
@ -989,13 +982,12 @@ update_clock_subscription_data(wasi_subscription_t *in, uint32 nsubscriptions,
} }
static wasi_errno_t static wasi_errno_t
execute_interruptible_poll_oneoff(wasm_module_inst_t module_inst, execute_interruptible_poll_oneoff(
#if !defined(WASMTIME_SSP_STATIC_CURFDS) #if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct fd_table *curfds,
#endif #endif
const __wasi_subscription_t *in, const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions,
__wasi_event_t *out, size_t nsubscriptions, size_t *nevents, wasm_exec_env_t exec_env)
size_t *nevents)
{ {
if (nsubscriptions == 0) { if (nsubscriptions == 0) {
*nevents = 0; *nevents = 0;
@ -1004,6 +996,8 @@ execute_interruptible_poll_oneoff(wasm_module_inst_t module_inst,
wasi_errno_t err; wasi_errno_t err;
__wasi_timestamp_t elapsed = 0; __wasi_timestamp_t elapsed = 0;
bool all_outs_are_type_clock;
uint32 i;
const __wasi_timestamp_t timeout = get_timeout_for_poll_oneoff( const __wasi_timestamp_t timeout = get_timeout_for_poll_oneoff(
in, nsubscriptions), in, nsubscriptions),
@ -1021,25 +1015,35 @@ execute_interruptible_poll_oneoff(wasm_module_inst_t module_inst,
bh_memcpy_s(in_copy, size_to_copy, in, size_to_copy); bh_memcpy_s(in_copy, size_to_copy, in, size_to_copy);
while (timeout == (__wasi_timestamp_t)-1 || elapsed <= timeout) { while (timeout == (__wasi_timestamp_t)-1 || elapsed <= timeout) {
elapsed += time_quant;
/* update timeout for clock subscription events */ /* update timeout for clock subscription events */
update_clock_subscription_data(in_copy, nsubscriptions, update_clock_subscription_data(in_copy, nsubscriptions,
min(time_quant, timeout - elapsed)); min(time_quant, timeout - elapsed));
err = wasmtime_ssp_poll_oneoff(curfds, in_copy, out, nsubscriptions, err = wasmtime_ssp_poll_oneoff(curfds, in_copy, out, nsubscriptions,
nevents); nevents);
elapsed += time_quant;
if (err) { if (err) {
wasm_runtime_free(in_copy); wasm_runtime_free(in_copy);
return err; return err;
} }
if (wasm_runtime_get_exception(module_inst) || *nevents > 0) { if (wasm_cluster_is_thread_terminated(exec_env)) {
wasm_runtime_free(in_copy); wasm_runtime_free(in_copy);
return EINTR;
}
else if (*nevents > 0) {
all_outs_are_type_clock = true;
for (i = 0; i < *nevents; i++) {
if (out[i].type != __WASI_EVENTTYPE_CLOCK) {
all_outs_are_type_clock = false;
break;
}
}
if (*nevents) { if (!all_outs_are_type_clock) {
wasm_runtime_free(in_copy);
return __WASI_ESUCCESS; return __WASI_ESUCCESS;
} }
return EINTR;
} }
} }
@ -1069,8 +1073,8 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in,
#if WASM_ENABLE_THREAD_MGR == 0 #if WASM_ENABLE_THREAD_MGR == 0
err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents); err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents);
#else #else
err = execute_interruptible_poll_oneoff(module_inst, curfds, in, out, err = execute_interruptible_poll_oneoff(curfds, in, out, nsubscriptions,
nsubscriptions, &nevents); &nevents, exec_env);
#endif #endif
if (err) if (err)
return err; return err;

View File

@ -2613,6 +2613,8 @@ wasmtime_ssp_poll_oneoff(
} }
#endif #endif
*nevents = 1; *nevents = 1;
if (out[0].error != 0)
return convert_errno(out[0].error);
return 0; return 0;
} }

View File

@ -1198,3 +1198,9 @@ wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
os_mutex_unlock(&cluster->lock); os_mutex_unlock(&cluster->lock);
} }
} }
bool
wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env)
{
return (exec_env->suspend_flags.flags & 0x01) ? true : false;
}

View File

@ -146,6 +146,9 @@ void
wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst, wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
void *custom_data); void *custom_data);
bool
wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env);
#if WASM_ENABLE_DEBUG_INTERP != 0 #if WASM_ENABLE_DEBUG_INTERP != 0
#define WAMR_SIG_TRAP (5) #define WAMR_SIG_TRAP (5)
#define WAMR_SIG_STOP (19) #define WAMR_SIG_STOP (19)