debug-interp: Only add lock when signal_flag is SIG_SINGSTEP (#3704)
As reported in #3500, when debug interpreter is enabled, the classic interpreter performs a lock operation to read `exec_env->current_status->signal_flag` and do further handling before fetching next opcode, which makes the interpreter run slower. This PR atomic loads the `exec_env->current_status->signal_flag` without mutex lock when 32-bit atomic load is supported, and only adding lock for further handling when the signal_flag is WAMR_SIG_SINGSTEP, which improves the performance.
This commit is contained in:
@ -1399,26 +1399,48 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
|
|||||||
#endif /* WASM_ENABLE_DEBUG_INTERP */
|
#endif /* WASM_ENABLE_DEBUG_INTERP */
|
||||||
#endif /* WASM_ENABLE_THREAD_MGR */
|
#endif /* WASM_ENABLE_THREAD_MGR */
|
||||||
|
|
||||||
|
#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0
|
||||||
|
#if BH_ATOMIC_32_IS_ATOMIC != 0
|
||||||
|
#define GET_SIGNAL_FLAG() \
|
||||||
|
do { \
|
||||||
|
signal_flag = \
|
||||||
|
BH_ATOMIC_32_LOAD(exec_env->current_status->signal_flag); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define GET_SIGNAL_FLAG() \
|
||||||
|
do { \
|
||||||
|
os_mutex_lock(&exec_env->wait_lock); \
|
||||||
|
signal_flag = exec_env->current_status->signal_flag; \
|
||||||
|
os_mutex_unlock(&exec_env->wait_lock); \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
||||||
|
|
||||||
#define HANDLE_OP(opcode) HANDLE_##opcode:
|
#define HANDLE_OP(opcode) HANDLE_##opcode:
|
||||||
#define FETCH_OPCODE_AND_DISPATCH() goto *handle_table[*frame_ip++]
|
#define FETCH_OPCODE_AND_DISPATCH() goto *handle_table[*frame_ip++]
|
||||||
|
|
||||||
#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0
|
#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0
|
||||||
#define HANDLE_OP_END() \
|
#define HANDLE_OP_END() \
|
||||||
do { \
|
do { \
|
||||||
/* Record the current frame_ip, so when exception occurs, \
|
/* Record the current frame_ip, so when exception occurs, \
|
||||||
debugger can know the exact opcode who caused the exception */ \
|
debugger can know the exact opcode who caused the exception */ \
|
||||||
frame_ip_orig = frame_ip; \
|
frame_ip_orig = frame_ip; \
|
||||||
os_mutex_lock(&exec_env->wait_lock); \
|
/* Atomic load the exec_env's signal_flag first, and then handle \
|
||||||
while (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \
|
more with lock if it is WAMR_SIG_SINGSTEP */ \
|
||||||
&& exec_env->current_status->step_count++ == 1) { \
|
GET_SIGNAL_FLAG(); \
|
||||||
exec_env->current_status->step_count = 0; \
|
if (signal_flag == WAMR_SIG_SINGSTEP) { \
|
||||||
SYNC_ALL_TO_FRAME(); \
|
os_mutex_lock(&exec_env->wait_lock); \
|
||||||
wasm_cluster_thread_waiting_run(exec_env); \
|
while (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \
|
||||||
} \
|
&& exec_env->current_status->step_count++ == 1) { \
|
||||||
os_mutex_unlock(&exec_env->wait_lock); \
|
exec_env->current_status->step_count = 0; \
|
||||||
goto *handle_table[*frame_ip++]; \
|
SYNC_ALL_TO_FRAME(); \
|
||||||
|
wasm_cluster_thread_waiting_run(exec_env); \
|
||||||
|
} \
|
||||||
|
os_mutex_unlock(&exec_env->wait_lock); \
|
||||||
|
} \
|
||||||
|
goto *handle_table[*frame_ip++]; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
#else
|
||||||
#define HANDLE_OP_END() FETCH_OPCODE_AND_DISPATCH()
|
#define HANDLE_OP_END() FETCH_OPCODE_AND_DISPATCH()
|
||||||
@ -1427,16 +1449,24 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
|
|||||||
#else /* else of WASM_ENABLE_LABELS_AS_VALUES */
|
#else /* else of WASM_ENABLE_LABELS_AS_VALUES */
|
||||||
#define HANDLE_OP(opcode) case opcode:
|
#define HANDLE_OP(opcode) case opcode:
|
||||||
#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0
|
#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0
|
||||||
#define HANDLE_OP_END() \
|
#define HANDLE_OP_END() \
|
||||||
os_mutex_lock(&exec_env->wait_lock); \
|
/* Record the current frame_ip, so when exception occurs, \
|
||||||
if (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \
|
debugger can know the exact opcode who caused the exception */ \
|
||||||
&& exec_env->current_status->step_count++ == 1) { \
|
frame_ip_orig = frame_ip; \
|
||||||
exec_env->current_status->step_count = 0; \
|
/* Atomic load the exec_env's signal_flag first, and then handle \
|
||||||
SYNC_ALL_TO_FRAME(); \
|
more with lock if it is WAMR_SIG_SINGSTEP */ \
|
||||||
wasm_cluster_thread_waiting_run(exec_env); \
|
GET_SIGNAL_FLAG(); \
|
||||||
} \
|
if (signal_flag == WAMR_SIG_SINGSTEP) { \
|
||||||
os_mutex_unlock(&exec_env->wait_lock); \
|
os_mutex_lock(&exec_env->wait_lock); \
|
||||||
continue
|
while (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \
|
||||||
|
&& exec_env->current_status->step_count++ == 1) { \
|
||||||
|
exec_env->current_status->step_count = 0; \
|
||||||
|
SYNC_ALL_TO_FRAME(); \
|
||||||
|
wasm_cluster_thread_waiting_run(exec_env); \
|
||||||
|
} \
|
||||||
|
os_mutex_unlock(&exec_env->wait_lock); \
|
||||||
|
} \
|
||||||
|
continue;
|
||||||
#else
|
#else
|
||||||
#define HANDLE_OP_END() continue
|
#define HANDLE_OP_END() continue
|
||||||
#endif
|
#endif
|
||||||
@ -1545,6 +1575,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||||||
debug_instance ? &debug_instance->watch_point_list_read : NULL;
|
debug_instance ? &debug_instance->watch_point_list_read : NULL;
|
||||||
bh_list *watch_point_list_write =
|
bh_list *watch_point_list_write =
|
||||||
debug_instance ? &debug_instance->watch_point_list_write : NULL;
|
debug_instance ? &debug_instance->watch_point_list_write : NULL;
|
||||||
|
#if WASM_ENABLE_THREAD_MGR != 0
|
||||||
|
uint32 signal_flag;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
||||||
|
|||||||
@ -184,9 +184,9 @@ wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env);
|
|||||||
((signo) == WAMR_SIG_STOP || (signo) == WAMR_SIG_TRAP)
|
((signo) == WAMR_SIG_STOP || (signo) == WAMR_SIG_TRAP)
|
||||||
|
|
||||||
struct WASMCurrentEnvStatus {
|
struct WASMCurrentEnvStatus {
|
||||||
uint64 signal_flag : 32;
|
uint32 signal_flag;
|
||||||
uint64 step_count : 16;
|
uint16 step_count;
|
||||||
uint64 running_status : 16;
|
uint16 running_status;
|
||||||
};
|
};
|
||||||
|
|
||||||
WASMCurrentEnvStatus *
|
WASMCurrentEnvStatus *
|
||||||
|
|||||||
Reference in New Issue
Block a user