mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-03-12 08:55:28 +00:00

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.
245 lines
6.2 KiB
C
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 */
|