diff options
Diffstat (limited to 'erts/emulator/beam/erl_bif_trace.c')
-rw-r--r-- | erts/emulator/beam/erl_bif_trace.c | 132 |
1 files changed, 89 insertions, 43 deletions
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c index e3008dfcef..9f79607d97 100644 --- a/erts/emulator/beam/erl_bif_trace.c +++ b/erts/emulator/beam/erl_bif_trace.c @@ -47,7 +47,7 @@ const struct trace_pattern_flags erts_trace_pattern_flags_off = {0, 0, 0, 0, 0}; /* - * The following variables are protected by code write permission. + * The following variables are protected by code modification permission. */ static int erts_default_trace_pattern_is_on; static Binary *erts_default_match_spec; @@ -55,7 +55,7 @@ static Binary *erts_default_meta_match_spec; static struct trace_pattern_flags erts_default_trace_pattern_flags; static ErtsTracer erts_default_meta_tracer; -static struct { /* Protected by code write permission */ +static struct { /* Protected by code modification permission */ int current; int install; int local; @@ -130,7 +130,7 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) ErtsTracer meta_tracer = erts_tracer_nil; Uint freason = BADARG; - if (!erts_try_seize_code_write_permission(p)) { + if (!erts_try_seize_code_mod_permission(p)) { ERTS_BIF_YIELD3(BIF_TRAP_EXPORT(BIF_erts_internal_trace_pattern_3), p, MFA, Pattern, flaglist); } finish_bp.current = -1; @@ -213,6 +213,13 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) flags.breakpoint = 1; flags.call_time = 1; break; + case am_call_memory: + if (is_global) { + goto error; + } + flags.breakpoint = 1; + flags.call_memory = 1; + break; default: goto error; @@ -225,8 +232,8 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) p->fvalue = am_none; - if (match_prog_set && !flags.local && !flags.meta && (flags.call_count || flags.call_time)) { - /* A match prog is not allowed with just call_count or call_time*/ + if (match_prog_set && !flags.local && !flags.meta && (flags.call_count || flags.call_time || flags.call_memory)) { + /* A match prog is not allowed with just call_count or call_time or call_memory */ p->fvalue = am_call_count; goto error; } @@ -356,7 +363,7 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) ERTS_BIF_YIELD_RETURN(p, make_small(matches)); } - erts_release_code_write_permission(); + erts_release_code_mod_permission(); if (matches >= 0) { return make_small(matches); @@ -377,7 +384,7 @@ static void smp_bp_finisher(void* null) #ifdef DEBUG finish_bp.stager = NULL; #endif - erts_release_code_write_permission(); + 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); @@ -394,8 +401,8 @@ erts_get_default_trace_pattern(int *trace_pattern_is_on, struct trace_pattern_flags *trace_pattern_flags, ErtsTracer *meta_tracer) { - ERTS_LC_ASSERT(erts_has_code_write_permission() || - erts_thr_progress_is_blocking()); + ERTS_LC_ASSERT(erts_has_code_mod_permission() || + erts_thr_progress_is_blocking()); if (trace_pattern_is_on) *trace_pattern_is_on = erts_default_trace_pattern_is_on; if (match_spec) @@ -410,8 +417,8 @@ erts_get_default_trace_pattern(int *trace_pattern_is_on, int erts_is_default_trace_enabled(void) { - ERTS_LC_ASSERT(erts_has_code_write_permission() || - erts_thr_progress_is_blocking()); + ERTS_LC_ASSERT(erts_has_code_mod_permission() || + erts_thr_progress_is_blocking()); return erts_default_trace_pattern_is_on; } @@ -553,7 +560,7 @@ Eterm erts_internal_trace_3(BIF_ALIST_3) BIF_ERROR(p, BADARG | EXF_HAS_EXT_INFO); } - if (!erts_try_seize_code_write_permission(BIF_P)) { + if (!erts_try_seize_code_mod_permission(BIF_P)) { ERTS_TRACER_CLEAR(&tracer); ERTS_BIF_YIELD3(BIF_TRAP_EXPORT(BIF_erts_internal_trace_3), BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3); @@ -771,7 +778,7 @@ Eterm erts_internal_trace_3(BIF_ALIST_3) erts_thr_progress_unblock(); erts_proc_lock(p, ERTS_PROC_LOCK_MAIN); } - erts_release_code_write_permission(); + erts_release_code_mod_permission(); ERTS_TRACER_CLEAR(&tracer); BIF_RET(make_small(matches)); @@ -788,7 +795,7 @@ Eterm erts_internal_trace_3(BIF_ALIST_3) erts_thr_progress_unblock(); erts_proc_lock(p, ERTS_PROC_LOCK_MAIN); } - erts_release_code_write_permission(); + erts_release_code_mod_permission(); BIF_ERROR(p, BADARG); } @@ -804,7 +811,7 @@ Eterm trace_info_2(BIF_ALIST_2) Eterm Key = BIF_ARG_2; Eterm res; - if (!erts_try_seize_code_write_permission(p)) { + if (!erts_try_seize_code_mod_permission(p)) { ERTS_BIF_YIELD2(BIF_TRAP_EXPORT(BIF_trace_info_2), p, What, Key); } @@ -818,10 +825,10 @@ Eterm trace_info_2(BIF_ALIST_2) res = trace_info_func(p, What, Key); } else { p->fvalue = am_badopt; - erts_release_code_write_permission(); + erts_release_code_mod_permission(); BIF_ERROR(p, BADARG | EXF_HAS_EXT_INFO); } - erts_release_code_write_permission(); + erts_release_code_mod_permission(); if (is_value(res) && is_internal_ref(res)) BIF_TRAP1(erts_await_result, BIF_P, res); @@ -1029,6 +1036,7 @@ trace_info_pid(Process* p, Eterm pid_spec, Eterm key) #define FUNC_TRACE_META_TRACE (1<<3) #define FUNC_TRACE_COUNT_TRACE (1<<4) #define FUNC_TRACE_TIME_TRACE (1<<5) +#define FUNC_TRACE_MEMORY_TRACE (1<<6) /* * Returns either FUNC_TRACE_NOEXIST, FUNC_TRACE_UNTRACED, * FUNC_TRACE_GLOBAL_TRACE, or, @@ -1049,7 +1057,8 @@ static int function_is_traced(Process *p, Binary **ms_meta, /* out */ ErtsTracer *tracer_pid_meta, /* out */ Uint *count, /* out */ - Eterm *call_time) /* out */ + Eterm *call_time, /* out */ + Eterm *call_memory) /* out */ { const ErtsCodeInfo *ci; Export e; @@ -1077,9 +1086,12 @@ static int function_is_traced(Process *p, if (erts_is_mtrace_break(&ep->info, ms_meta, tracer_pid_meta)) { r |= FUNC_TRACE_META_TRACE; } - if (erts_is_time_break(p, &ep->info, call_time)) { + if (erts_is_call_break(p, 1, &ep->info, call_time)) { r |= FUNC_TRACE_TIME_TRACE; } + if (erts_is_call_break(p, 0, &ep->info, call_memory)) { + r |= FUNC_TRACE_MEMORY_TRACE; + } return r ? r : FUNC_TRACE_UNTRACED; } } @@ -1093,8 +1105,10 @@ static int function_is_traced(Process *p, ? FUNC_TRACE_META_TRACE : 0) | (erts_is_count_break(ci, count) ? FUNC_TRACE_COUNT_TRACE : 0) - | (erts_is_time_break(p, ci, call_time) - ? FUNC_TRACE_TIME_TRACE : 0); + | (erts_is_call_break(p, 1, ci, call_time) + ? FUNC_TRACE_TIME_TRACE : 0) + | (erts_is_call_break(p, 0, ci, call_memory) + ? FUNC_TRACE_MEMORY_TRACE : 0); return r ? r : FUNC_TRACE_UNTRACED; } @@ -1114,6 +1128,7 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key) Eterm retval = am_false; ErtsTracer meta = erts_tracer_nil; Eterm call_time = NIL; + Eterm call_memory = NIL; int r; @@ -1133,7 +1148,7 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key) mfa[1] = tp[2]; mfa[2] = signed_val(tp[3]); - if ( (key == am_call_time) || (key == am_all)) { + if ( (key == am_call_time) || (key == am_call_memory) || (key == am_all)) { erts_proc_unlock(p, ERTS_PROC_LOCK_MAIN); erts_thr_progress_block(); erts_proc_lock(p, ERTS_PROC_LOCK_MAIN); @@ -1141,10 +1156,10 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key) erts_mtx_lock(&erts_dirty_bp_ix_mtx); - r = function_is_traced(p, mfa, &ms, &ms_meta, &meta, &count, &call_time); + r = function_is_traced(p, mfa, &ms, &ms_meta, &meta, &count, &call_time, &call_memory); erts_mtx_unlock(&erts_dirty_bp_ix_mtx); - if ( (key == am_call_time) || (key == am_all)) { + if ( (key == am_call_time) || (key == am_call_memory) || (key == am_all)) { erts_thr_progress_unblock(); } @@ -1206,10 +1221,18 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key) retval = call_time; } break; + case am_call_memory: + if (r & FUNC_TRACE_MEMORY_TRACE) { + retval = call_memory; + } + break; case am_all: { - Eterm match_spec_meta = am_false, c = am_false, t, ct = am_false, - m = am_false; + Eterm match_spec_meta = am_false; + Eterm call_count = am_false; + Eterm t, m; + /* ToDo: Rewrite this to loop and reuse the above cases */ + if (ms) { match_spec = MatchSetGetSource(ms); match_spec = copy_object(match_spec, p); @@ -1222,19 +1245,24 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key) match_spec_meta = NIL; } if (r & FUNC_TRACE_COUNT_TRACE) { - c = erts_make_integer(count, p); + call_count = erts_make_integer(count, p); } - if (r & FUNC_TRACE_TIME_TRACE) { - ct = call_time; + if (!(r & FUNC_TRACE_TIME_TRACE)) { + call_time = am_false; + } + if (!(r & FUNC_TRACE_MEMORY_TRACE)) { + call_memory = am_false; } m = erts_tracer_to_term(p, meta); - hp = HAlloc(p, (3+2)*6); + hp = HAlloc(p, (3+2)*7); retval = NIL; - t = TUPLE2(hp, am_call_count, c); hp += 3; + t = TUPLE2(hp, am_call_count, call_count); hp += 3; retval = CONS(hp, t, retval); hp += 2; - t = TUPLE2(hp, am_call_time, ct); hp += 3; + t = TUPLE2(hp, am_call_time, call_time); hp += 3; + retval = CONS(hp, t, retval); hp += 2; + t = TUPLE2(hp, am_call_memory, call_memory); hp += 3; retval = CONS(hp, t, retval); hp += 2; t = TUPLE2(hp, am_meta_match_spec, match_spec_meta); hp += 3; retval = CONS(hp, t, retval); hp += 2; @@ -1432,19 +1460,21 @@ erts_set_trace_pattern(Process*p, ErtsCodeMFA *mfa, int specified, ErtsTracer meta_tracer, int is_blocking) { const ErtsCodeIndex code_ix = erts_active_code_ix(); - int matches = 0; - int i; - int n; + Uint i, n, matches; BpFunction* fp; erts_bp_match_export(&finish_bp.e, mfa, specified); + fp = finish_bp.e.matching; n = finish_bp.e.matched; + matches = 0; for (i = 0; i < n; i++) { - ErtsCodeInfo *ci_rw = fp[i].ci_rw; + ErtsCodeInfo *ci_rw; Export* ep; + /* Export entries are always writable, discard const. */ + ci_rw = (ErtsCodeInfo *)fp[i].code_info; ep = ErtsContainerStruct(ci_rw, Export, info); if (ep->bif_number != -1) { @@ -1504,6 +1534,9 @@ erts_set_trace_pattern(Process*p, ErtsCodeMFA *mfa, int specified, if (flags.call_time) { erts_set_time_break(&finish_bp.f, on); } + if (flags.call_memory) { + erts_set_memory_break(&finish_bp.f, on); + } } } else { if (flags.local) { @@ -1518,6 +1551,9 @@ erts_set_trace_pattern(Process*p, ErtsCodeMFA *mfa, int specified, if (flags.call_time) { erts_clear_time_break(&finish_bp.f); } + if (flags.call_memory) { + erts_clear_memory_break(&finish_bp.f); + } } finish_bp.current = 0; @@ -1583,7 +1619,7 @@ consolidate_event_tracing(ErtsTracingEvent te[]) int erts_finish_breakpointing(void) { - ERTS_LC_ASSERT(erts_has_code_write_permission()); + ERTS_LC_ASSERT(erts_has_code_mod_permission()); /* * Memory and instruction barriers will be issued for all schedulers @@ -1648,13 +1684,17 @@ erts_finish_breakpointing(void) * deallocate the GenericBp structs for them. */ clean_export_entries(&finish_bp.e); - erts_consolidate_bp_data(&finish_bp.e, 0); - erts_consolidate_bp_data(&finish_bp.f, 1); + erts_consolidate_export_bp_data(&finish_bp.e); + erts_consolidate_local_bp_data(&finish_bp.f); erts_bp_free_matched_functions(&finish_bp.e); erts_bp_free_matched_functions(&finish_bp.f); consolidate_event_tracing(erts_send_tracing); consolidate_event_tracing(erts_receive_tracing); - return 0; + return 1; + case 4: + /* All schedulers have run a code barrier (or will as soon as they + * awaken) after updating all breakpoints, it's safe to return now. */ + return 0; default: ASSERT(0); } @@ -1670,7 +1710,9 @@ install_exp_breakpoints(BpFunctions* f) Uint i; for (i = 0; i < ne; i++) { - Export* ep = ErtsContainerStruct(fp[i].ci_rw, Export, info); + /* Export entries are always writable, discard const. */ + ErtsCodeInfo *ci_rw = (ErtsCodeInfo*)fp[i].code_info; + Export* ep = ErtsContainerStruct(ci_rw, Export, info); erts_activate_export_trampoline(ep, code_ix); } } @@ -1684,7 +1726,9 @@ uninstall_exp_breakpoints(BpFunctions* f) Uint i; for (i = 0; i < ne; i++) { - Export* ep = ErtsContainerStruct(fp[i].ci_rw, Export, info); + /* Export entries are always writable, discard const. */ + ErtsCodeInfo *ci_rw = (ErtsCodeInfo*)fp[i].code_info; + Export* ep = ErtsContainerStruct(ci_rw, Export, info); if (erts_is_export_trampoline_active(ep, code_ix)) { ASSERT(BeamIsOpCode(ep->trampoline.common.op, op_trace_jump_W)); @@ -1703,7 +1747,9 @@ clean_export_entries(BpFunctions* f) Uint i; for (i = 0; i < ne; i++) { - Export* ep = ErtsContainerStruct(fp[i].ci_rw, Export, info); + /* Export entries are always writable, discard const. */ + ErtsCodeInfo *ci_rw = (ErtsCodeInfo*)fp[i].code_info; + Export* ep = ErtsContainerStruct(ci_rw, Export, info); if (erts_is_export_trampoline_active(ep, code_ix)) { continue; |