Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:26
erlang
0103-erts-Don-t-block-thread-progress-when-sett...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0103-erts-Don-t-block-thread-progress-when-setting-debug-.patch of Package erlang
From 291d2ecea839d8f3d247d6e4e3793e2c7e4e178c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org> Date: Mon, 20 Mar 2023 13:24:45 +0100 Subject: [PATCH] erts: Don't block thread progress when setting debug breakpoints --- erts/emulator/beam/beam_bp.c | 1 - erts/emulator/beam/beam_debug.c | 159 ++++++++++++++++++++++---------- 2 files changed, 112 insertions(+), 48 deletions(-) diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c index 559a417128..c55ab0930b 100644 --- a/erts/emulator/beam/beam_bp.c +++ b/erts/emulator/beam/beam_bp.c @@ -693,7 +693,6 @@ erts_clear_mtrace_break(BpFunctions* f) void erts_clear_debug_break(BpFunctions* f) { - ERTS_LC_ASSERT(erts_thr_progress_is_blocking()); clear_break(f, ERTS_BPF_DEBUG); } diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c index 3819de701f..42d5ff57a8 100644 --- a/erts/emulator/beam/beam_debug.c +++ b/erts/emulator/beam/beam_debug.c @@ -122,40 +122,112 @@ erts_debug_copy_shared_2(BIF_ALIST_2) BIF_RET(copy); } +/* Protected by code modification permission */ +static struct { + ErtsCodeBarrier barrier; + Process* process; + + BpFunctions f; + int enable; + int stage; +} finish_debug_bp; + +static void debug_bp_finisher(void *ignored) +{ + Process* p = finish_debug_bp.process; + + ERTS_LC_ASSERT(erts_has_code_mod_permission()); + + (void)ignored; + + /* Code barriers are issued before each of the stages below. */ + switch (finish_debug_bp.stage++) { + case 0: + /* Breakpoints need to be installed before they are committed, and + * committed before they are uninstalled. */ + if (finish_debug_bp.enable) { + erts_install_breakpoints(&finish_debug_bp.f); + } else { + erts_commit_staged_bp(); + } + break; + case 1: + if (!finish_debug_bp.enable) { + erts_uninstall_breakpoints(&finish_debug_bp.f); + } else { + erts_commit_staged_bp(); + } + break; + case 2: + /* Now all breakpoints have either been inserted or removed. For all + * updated breakpoints, copy the active breakpoint data to the staged + * breakpoint data to make them equal (simplifying for the next time + * breakpoints are to be updated). If any breakpoints have been totally + * disabled, deallocate their GenericBp structs. */ + erts_consolidate_local_bp_data(&finish_debug_bp.f); + erts_bp_free_matched_functions(&finish_debug_bp.f); + break; + case 3: + /* All schedulers have run a code barrier (or will as soon as they + * awaken) after updating all breakpoints, it's safe to return now. */ +#ifdef DEBUG + finish_debug_bp.process = NULL; +#endif + + erts_release_code_mod_permission(); + + erts_proc_lock(p, ERTS_PROC_LOCK_STATUS); + + if (!ERTS_PROC_IS_EXITING(p)) { + erts_resume(p, ERTS_PROC_LOCK_STATUS); + } + + erts_proc_unlock(p, ERTS_PROC_LOCK_STATUS); + erts_proc_dec_refc(p); + + return; + } + + erts_schedule_code_barrier(&finish_debug_bp.barrier, + debug_bp_finisher, NULL); +} + BIF_RETTYPE erts_debug_breakpoint_2(BIF_ALIST_2) { - Process* p = BIF_P; - Eterm MFA = BIF_ARG_1; - Eterm boolean = BIF_ARG_2; - Eterm* tp; + const Eterm mfa_pattern = BIF_ARG_1, enable = BIF_ARG_2; + int i, specified; ErtsCodeMFA mfa; - int i; - int specified = 0; - Eterm res; - BpFunctions f; + Eterm *tp; - if (boolean != am_true && boolean != am_false) - goto error; + if (enable != am_true && enable != am_false) { + BIF_ERROR(BIF_P, BADARG); + } - if (is_not_tuple(MFA)) { - goto error; + if (is_not_tuple(mfa_pattern)) { + BIF_ERROR(BIF_P, BADARG); } - tp = tuple_val(MFA); + + tp = tuple_val(mfa_pattern); if (*tp != make_arityval(3)) { - goto error; + BIF_ERROR(BIF_P, BADARG); } + if (!is_atom(tp[1]) || !is_atom(tp[2]) || - (!is_small(tp[3]) && tp[3] != am_Underscore)) { - goto error; + (!is_small(tp[3]) && tp[3] != am_Underscore)) { + BIF_ERROR(BIF_P, BADARG); } - for (i = 0; i < 3 && tp[i+1] != am_Underscore; i++, specified++) { - /* Empty loop body */ + + for (i = 0, specified = 0; + i < 3 && tp[i+1] != am_Underscore; + i++, specified++) { + /* Empty loop body */ } + for (i = specified; i < 3; i++) { - if (tp[i+1] != am_Underscore) { - goto error; - } + if (tp[i+1] != am_Underscore) { + BIF_ERROR(BIF_P, BADARG); + } } mfa.module = tp[1]; @@ -166,38 +238,31 @@ erts_debug_breakpoint_2(BIF_ALIST_2) } if (!erts_try_seize_code_mod_permission(BIF_P)) { - ERTS_BIF_YIELD2(BIF_TRAP_EXPORT(BIF_erts_debug_breakpoint_2), - BIF_P, BIF_ARG_1, BIF_ARG_2); + ERTS_BIF_YIELD2(BIF_TRAP_EXPORT(BIF_erts_debug_breakpoint_2), + BIF_P, BIF_ARG_1, BIF_ARG_2); } - erts_proc_unlock(p, ERTS_PROC_LOCK_MAIN); - erts_thr_progress_block(); + erts_bp_match_functions(&finish_debug_bp.f, &mfa, specified); + + ASSERT(finish_debug_bp.f.matched >= 0); + ASSERT(finish_debug_bp.process == NULL); + finish_debug_bp.enable = (enable == am_true); + finish_debug_bp.process = BIF_P; + finish_debug_bp.stage = 0; - erts_bp_match_functions(&f, &mfa, specified); - if (boolean == am_true) { - erts_set_debug_break(&f); - erts_install_breakpoints(&f); - erts_commit_staged_bp(); + if (finish_debug_bp.enable) { + erts_set_debug_break(&finish_debug_bp.f); } else { - erts_clear_debug_break(&f); - erts_commit_staged_bp(); - erts_uninstall_breakpoints(&f); + erts_clear_debug_break(&finish_debug_bp.f); } - erts_consolidate_local_bp_data(&f); - res = make_small(f.matched); - erts_bp_free_matched_functions(&f); - - erts_blocking_code_barrier(); - - erts_thr_progress_unblock(); - erts_proc_lock(p, ERTS_PROC_LOCK_MAIN); - - erts_release_code_mod_permission(); - - return res; - error: - BIF_ERROR(p, BADARG); + /* Adding/removing breakpoints requires multiple code barriers. Suspend + * ourselves and continue in an aux job. */ + erts_schedule_code_barrier(&finish_debug_bp.barrier, + debug_bp_finisher, NULL); + erts_proc_inc_refc(BIF_P); + erts_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, NULL); + ERTS_BIF_YIELD_RETURN(BIF_P, make_small(finish_debug_bp.f.matched)); } #if 0 /* Kept for conveninence when hard debugging. */ -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor