wasm-micro-runtime/core/iwasm/libraries/thread-mgr/thread_manager.h
Enrico Loparco ff25110840
Return stack frames of crashed thread when using wasm-c-api (#2908)
When using the wasm-c-api and there's a trap, `wasm_func_call()` returns
a `wasm_trap_t *` object. No matter which thread crashes, the trap contains
the stack frames of the main thread.

With this PR, when there's an exception, the stack frames of the thread
where the exception occurs are stored into the thread cluster.
`wasm_func_call()` can then return those stack frames.
2024-01-11 12:13:05 +08:00

245 lines
6.2 KiB
C

/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _THREAD_MANAGER_H
#define _THREAD_MANAGER_H
#include "bh_common.h"
#include "bh_log.h"
#include "wasm_export.h"
#include "../interpreter/wasm.h"
#include "../common/wasm_runtime_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
typedef struct WASMDebugInstance WASMDebugInstance;
#endif
struct WASMCluster {
struct WASMCluster *next;
korp_mutex lock;
bh_list exec_env_list;
#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
/* The aux stack of a module with shared memory will be
divided into several segments. This array store the
stack top of different segments */
uint32 *stack_tops;
/* Record which segments are occupied */
bool *stack_segment_occupied;
#endif
/* Size of every stack segment */
uint32 stack_size;
/* When has_exception == true, this cluster should refuse any spawn thread
* requests, this flag can be cleared by calling
* wasm_runtime_clear_exception on instances of any threads of this cluster
*/
bool has_exception;
/* When processing is true, this cluster should refuse any spawn thread
* requests. This is a short-lived state, must be cleared immediately once
* the processing finished.
* This is used to avoid dead lock when one thread waiting another thread
* with lock, see wams_cluster_wait_for_all and wasm_cluster_terminate_all
*/
bool processing;
#if WASM_ENABLE_DEBUG_INTERP != 0
WASMDebugInstance *debug_inst;
#endif
#if WASM_ENABLE_DUMP_CALL_STACK != 0
/* When an exception occurs in a thread, the stack frames of that thread are
* saved into the cluster
*/
Vector exception_frames;
#endif
};
void
wasm_cluster_set_max_thread_num(uint32 num);
bool
thread_manager_init();
void
thread_manager_destroy();
/* Create cluster */
WASMCluster *
wasm_cluster_create(WASMExecEnv *exec_env);
/* Destroy cluster */
void
wasm_cluster_destroy(WASMCluster *cluster);
/* Get the cluster of the current exec_env */
WASMCluster *
wasm_exec_env_get_cluster(WASMExecEnv *exec_env);
/* Forward registered functions to a new thread */
bool
wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst,
const WASMModuleInstanceCommon *module_inst_src);
int32
wasm_cluster_create_thread(WASMExecEnv *exec_env,
wasm_module_inst_t module_inst,
bool is_aux_stack_allocated, uint32 aux_stack_start,
uint32 aux_stack_size,
void *(*thread_routine)(void *), void *arg);
int32
wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val);
int32
wasm_cluster_detach_thread(WASMExecEnv *exec_env);
int32
wasm_cluster_cancel_thread(WASMExecEnv *exec_env);
void
wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval);
bool
wasm_cluster_register_destroy_callback(void (*callback)(WASMCluster *));
void
wasm_cluster_cancel_all_callbacks();
void
wasm_cluster_suspend_all(WASMCluster *cluster);
void
wasm_cluster_suspend_all_except_self(WASMCluster *cluster,
WASMExecEnv *exec_env);
void
wasm_cluster_suspend_thread(WASMExecEnv *exec_env);
void
wasm_cluster_resume_thread(WASMExecEnv *exec_env);
void
wasm_cluster_resume_all(WASMCluster *cluster);
void
wasm_cluster_terminate_all(WASMCluster *cluster);
void
wasm_cluster_terminate_all_except_self(WASMCluster *cluster,
WASMExecEnv *exec_env);
void
wams_cluster_wait_for_all(WASMCluster *cluster);
void
wasm_cluster_wait_for_all_except_self(WASMCluster *cluster,
WASMExecEnv *exec_env);
bool
wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env);
WASMExecEnv *
wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst);
void
wasm_cluster_set_exception(WASMExecEnv *exec_env, const char *exception);
WASMExecEnv *
wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env);
void
wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env);
void
wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
void *custom_data);
void
wasm_cluster_set_context(WASMModuleInstanceCommon *module_inst, void *key,
void *ctx);
bool
wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env);
#if WASM_ENABLE_DEBUG_INTERP != 0
#define WAMR_SIG_TRAP (5)
#define WAMR_SIG_STOP (19)
#define WAMR_SIG_TERM (15)
#define WAMR_SIG_SINGSTEP (0x1ff)
#define STATUS_RUNNING (0)
#define STATUS_STOP (1)
#define STATUS_EXIT (2)
#define STATUS_STEP (3)
#define IS_WAMR_TERM_SIG(signo) ((signo) == WAMR_SIG_TERM)
#define IS_WAMR_STOP_SIG(signo) \
((signo) == WAMR_SIG_STOP || (signo) == WAMR_SIG_TRAP)
struct WASMCurrentEnvStatus {
uint64 signal_flag : 32;
uint64 step_count : 16;
uint64 running_status : 16;
};
WASMCurrentEnvStatus *
wasm_cluster_create_exenv_status();
void
wasm_cluster_destroy_exenv_status(WASMCurrentEnvStatus *status);
void
wasm_cluster_send_signal_all(WASMCluster *cluster, uint32 signo);
/* This function must be called with exec_env->wait_lock locked, otherwise we
* may miss the signal from debugger thread, see
* https://github.com/bytecodealliance/wasm-micro-runtime/issues/1860 */
void
wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env);
void
wasm_cluster_wait_thread_status(WASMExecEnv *exec_env, uint32 *status);
void
wasm_cluster_thread_exited(WASMExecEnv *exec_env);
void
wasm_cluster_thread_continue(WASMExecEnv *exec_env);
void
wasm_cluster_thread_send_signal(WASMExecEnv *exec_env, uint32 signo);
void
wasm_cluster_thread_step(WASMExecEnv *exec_env);
void
wasm_cluster_set_debug_inst(WASMCluster *cluster, WASMDebugInstance *inst);
#endif /* end of WASM_ENABLE_DEBUG_INTERP != 0 */
void
wasm_cluster_traverse_lock(WASMExecEnv *exec_env);
void
wasm_cluster_traverse_unlock(WASMExecEnv *exec_env);
bool
wasm_cluster_allocate_aux_stack(WASMExecEnv *exec_env, uint32 *p_start,
uint32 *p_size);
bool
wasm_cluster_free_aux_stack(WASMExecEnv *exec_env, uint32 start);
#ifdef __cplusplus
}
#endif
#endif /* end of _THREAD_MANAGER_H */