diff options
Diffstat (limited to 'erts/emulator/beam/erl_bif_trace.c')
-rw-r--r-- | erts/emulator/beam/erl_bif_trace.c | 103 |
1 files changed, 59 insertions, 44 deletions
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c index 80f774523c..4cbfd7bab5 100644 --- a/erts/emulator/beam/erl_bif_trace.c +++ b/erts/emulator/beam/erl_bif_trace.c @@ -60,8 +60,8 @@ static Eterm trace_info_pid(Process* p, Eterm pid_spec, Eterm key); static Eterm trace_info_func(Process* p, Eterm pid_spec, Eterm key); static Eterm trace_info_on_load(Process* p, Eterm key); -static int setup_func_trace(Export* ep, void* match_prog); -static int reset_func_trace(Export* ep); +static int setup_func_trace(Export* ep, void* match_prog, ErtsCodeIndex); +static int reset_func_trace(Export* ep, ErtsCodeIndex); static void reset_bif_trace(int bif_index); static void setup_bif_trace(int bif_index); static void set_trace_bif(int bif_index, void* match_prog); @@ -98,7 +98,7 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) { DeclareTmpHeap(mfa,3,p); /* Not really heap here, but might be when setting pattern */ int i; - int matches = 0; + int matches = -1; int specified = 0; enum erts_break_op on; Binary* match_prog_set; @@ -108,6 +108,9 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) Process *meta_tracer_proc = p; Eterm meta_tracer_pid = p->id; + if (!erts_try_seize_code_write_permission(p)) { + ERTS_BIF_YIELD3(bif_export[BIF_trace_pattern_3], p, MFA, Pattern, flaglist); + } erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN); erts_smp_thr_progress_block(); @@ -241,7 +244,6 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) erts_default_meta_match_spec = NULL; erts_default_meta_tracer_pid = NIL; } - MatchSetUnref(match_prog_set); if (erts_default_trace_pattern_flags.breakpoint && flags.breakpoint) { /* Breakpoint trace -> breakpoint trace */ @@ -297,8 +299,7 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) erts_default_trace_pattern_is_on = !!flags.breakpoint; } } - - goto done; + matches = 0; } else if (is_tuple(MFA)) { Eterm *tp = tuple_val(MFA); if (tp[0] != make_arityval(3)) { @@ -322,35 +323,29 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist) if (is_small(mfa[2])) { mfa[2] = signed_val(mfa[2]); } - } else { - goto error; - } - if (meta_tracer_proc) { - meta_tracer_proc->trace_flags |= F_TRACER; - } - - - matches = erts_set_trace_pattern(mfa, specified, - match_prog_set, match_prog_set, - on, flags, meta_tracer_pid); - MatchSetUnref(match_prog_set); - - done: - UnUseTmpHeap(3,p); - erts_smp_thr_progress_unblock(); - erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN); + if (meta_tracer_proc) { + meta_tracer_proc->trace_flags |= F_TRACER; + } - return make_small(matches); + matches = erts_set_trace_pattern(mfa, specified, + match_prog_set, match_prog_set, + on, flags, meta_tracer_pid); + } error: - MatchSetUnref(match_prog_set); - UnUseTmpHeap(3,p); erts_smp_thr_progress_unblock(); erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN); - BIF_ERROR(p, BADARG); + erts_release_code_write_permission(); + + if (matches >= 0) { + return make_small(matches); + } + else { + BIF_ERROR(p, BADARG); + } } void @@ -372,7 +367,10 @@ erts_get_default_trace_pattern(int *trace_pattern_is_on, *meta_tracer_pid = erts_default_meta_tracer_pid; } - +int erts_is_default_trace_enabled(void) +{ + return erts_default_trace_pattern_is_on; +} Uint erts_trace_flag2bit(Eterm flag) @@ -466,6 +464,10 @@ Eterm trace_3(BIF_ALIST_3) BIF_ERROR(p, BADARG); } + if (!erts_try_seize_code_write_permission(BIF_P)) { + ERTS_BIF_YIELD3(bif_export[BIF_trace_3], BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3); + } + if (is_nil(tracer) || is_internal_pid(tracer)) { Process *tracer_proc = erts_pid2proc(p, ERTS_PROC_LOCK_MAIN, @@ -730,6 +732,7 @@ Eterm trace_3(BIF_ALIST_3) erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN); } #endif + erts_release_code_write_permission(); BIF_RET(make_small(matches)); @@ -745,6 +748,7 @@ Eterm trace_3(BIF_ALIST_3) erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN); } #endif + erts_release_code_write_permission(); BIF_ERROR(p, BADARG); } @@ -990,7 +994,7 @@ static int function_is_traced(Process *p, e.code[1] = mfa[1]; e.code[2] = mfa[2]; if ((ep = export_get(&e)) != NULL) { - if (ep->address == ep->code+3 && + if (ep->addressv[erts_active_code_ix()] == ep->code+3 && ep->code[3] != (BeamInstr) em_call_error_handler) { if (ep->code[3] == (BeamInstr) em_call_traced_function) { *ms = ep->match_prog_set; @@ -1333,6 +1337,7 @@ erts_set_trace_pattern(Eterm* mfa, int specified, int on, struct trace_pattern_flags flags, Eterm meta_tracer_pid) { + const ErtsCodeIndex code_ix = erts_active_code_ix(); int matches = 0; int i; @@ -1340,8 +1345,8 @@ erts_set_trace_pattern(Eterm* mfa, int specified, * First work on normal functions (not real BIFs). */ - for (i = 0; i < export_list_size(); i++) { - Export* ep = export_list(i); + for (i = 0; i < export_list_size(code_ix); i++) { + Export* ep = export_list(i, code_ix); int j; if (ExportIsBuiltIn(ep)) { @@ -1355,11 +1360,11 @@ erts_set_trace_pattern(Eterm* mfa, int specified, if (j == specified) { if (on) { if (! flags.breakpoint) - matches += setup_func_trace(ep, match_prog_set); + matches += setup_func_trace(ep, match_prog_set, code_ix); else - reset_func_trace(ep); + reset_func_trace(ep, code_ix); } else if (! flags.breakpoint) { - matches += reset_func_trace(ep); + matches += reset_func_trace(ep, code_ix); } } } @@ -1522,9 +1527,11 @@ erts_set_trace_pattern(Eterm* mfa, int specified, */ static int -setup_func_trace(Export* ep, void* match_prog) +setup_func_trace(Export* ep, void* match_prog, ErtsCodeIndex code_ix) { - if (ep->address == ep->code+3) { + Module* modp; + + if (ep->addressv[code_ix] == ep->code+3) { if (ep->code[3] == (BeamInstr) em_call_error_handler) { return 0; } else if (ep->code[3] == (BeamInstr) em_call_traced_function) { @@ -1543,15 +1550,19 @@ setup_func_trace(Export* ep, void* match_prog) /* * Currently no trace support for native code. */ - if (erts_is_native_break(ep->address)) { + if (erts_is_native_break(ep->addressv[code_ix])) { return 0; } - + ep->code[3] = (BeamInstr) em_call_traced_function; - ep->code[4] = (BeamInstr) ep->address; - ep->address = ep->code+3; + ep->code[4] = (BeamInstr) ep->addressv[code_ix]; + ep->addressv[code_ix] = ep->code+3; ep->match_prog_set = match_prog; MatchSetRef(ep->match_prog_set); + + modp = erts_get_module(ep->code[0], code_ix); + ASSERT(modp); + modp->curr.num_traced_exports++; return 1; } @@ -1584,13 +1595,17 @@ static void set_trace_bif(int bif_index, void* match_prog) { */ static int -reset_func_trace(Export* ep) +reset_func_trace(Export* ep, ErtsCodeIndex code_ix) { - if (ep->address == ep->code+3) { + if (ep->addressv[code_ix] == ep->code+3) { if (ep->code[3] == (BeamInstr) em_call_error_handler) { return 0; } else if (ep->code[3] == (BeamInstr) em_call_traced_function) { - ep->address = (Uint *) ep->code[4]; + Module* modp = erts_get_module(ep->code[0], code_ix); + ASSERT(modp); + modp->curr.num_traced_exports--; + + ep->addressv[code_ix] = (Uint *) ep->code[4]; MatchSetUnref(ep->match_prog_set); ep->match_prog_set = NULL; return 1; @@ -1605,7 +1620,7 @@ reset_func_trace(Export* ep) /* * Currently no trace support for native code. */ - if (erts_is_native_break(ep->address)) { + if (erts_is_native_break(ep->addressv[code_ix])) { return 0; } |