diff options
author | Sverker Eriksson <[email protected]> | 2016-04-29 17:50:18 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2016-05-04 19:53:37 +0200 |
commit | 14b81c60f0c6403e9371be420a6df4d414180c68 (patch) | |
tree | 13b956613e00ab6776325b27ccd37313ea116efe | |
parent | 36e9d73aa08930ddf3e3587addfb9a647a41b3e7 (diff) | |
download | otp-14b81c60f0c6403e9371be420a6df4d414180c68.tar.gz otp-14b81c60f0c6403e9371be420a6df4d414180c68.tar.bz2 otp-14b81c60f0c6403e9371be420a6df4d414180c68.zip |
erts: Fix PAM to be callable from non-scheduler thread
also simplified the interface to to run PAM from trace
-rw-r--r-- | erts/emulator/beam/erl_db_util.c | 73 | ||||
-rw-r--r-- | erts/emulator/beam/erl_trace.c | 61 | ||||
-rw-r--r-- | erts/emulator/beam/global.h | 22 |
3 files changed, 88 insertions, 68 deletions
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index 7d64529250..051c107d1f 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -414,19 +414,27 @@ get_match_pseudo_process(Process *c_p, Uint heap_size) { ErtsMatchPseudoProcess *mpsp; #ifdef ERTS_SMP - ErtsSchedulerData *esdp = c_p ? c_p->scheduler_data : erts_get_scheduler_data(); + ErtsSchedulerData *esdp; + + esdp = c_p ? c_p->scheduler_data : erts_get_scheduler_data(); + + mpsp = esdp ? esdp->match_pseudo_process : + (ErtsMatchPseudoProcess*) erts_smp_tsd_get(match_pseudo_process_key); - mpsp = (ErtsMatchPseudoProcess *) esdp->match_pseudo_process; - if (mpsp) + if (mpsp) { + ASSERT(mpsp == erts_smp_tsd_get(match_pseudo_process_key)); + ASSERT(mpsp->process.scheduler_data == esdp); cleanup_match_pseudo_process(mpsp, 0); + } else { ASSERT(erts_smp_tsd_get(match_pseudo_process_key) == NULL); mpsp = create_match_pseudo_process(); - esdp->match_pseudo_process = (void *) mpsp; + if (esdp) { + esdp->match_pseudo_process = (void *) mpsp; + } + mpsp->process.scheduler_data = esdp; erts_smp_tsd_set(match_pseudo_process_key, (void *) mpsp); } - ASSERT(mpsp == erts_smp_tsd_get(match_pseudo_process_key)); - mpsp->process.scheduler_data = esdp; #else mpsp = match_pseudo_process; cleanup_match_pseudo_process(mpsp, 0); @@ -1206,32 +1214,37 @@ done: return ret; } -Eterm erts_match_set_run(Process *c_p, - Process *self, - Binary *mpsp, - Eterm *args, int num_args, - enum erts_pam_run_flags in_flags, - Uint32 *return_flags) +/* Returns + * am_false if no match or + * if {message,false} has been called, + * am_true if {message,_} has NOT been called or + * if {message,true} has been called, + * Msg if {message,Msg} has been called. + * + * If return value is_not_immed + * then erts_match_set_release_result_trace() must be called to release it. + */ +Eterm erts_match_set_run_trace(Process *c_p, + Process *self, + Binary *mpsp, + Eterm *args, int num_args, + enum erts_pam_run_flags in_flags, + Uint32 *return_flags) { Eterm ret; ret = db_prog_match(c_p, self, mpsp, NIL, args, num_args, in_flags, return_flags); -#if defined(HARDDEBUG) - if (is_non_value(ret)) { - erts_fprintf(stderr, "Failed\n"); - } else { - erts_fprintf(stderr, "Returning : %T\n", ret); + + ASSERT(!(is_non_value(ret) && *return_flags)); + + if (is_non_value(ret) || ret == am_false) { + erts_match_set_release_result(c_p); + return am_false; } -#endif + if (is_immed(ret)) + erts_match_set_release_result(c_p); return ret; - /* Returns - * THE_NON_VALUE if no match - * am_false if {message,false} has been called, - * am_true if {message,_} has not been called or - * if {message,true} has been called, - * Msg if {message,Msg} has been called. - */ } static Eterm erts_match_set_run_ets(Process *p, Binary *mpsp, @@ -1774,6 +1787,7 @@ Eterm db_prog_match(Process *c_p, #endif /* DMC_DEBUG */ ERTS_UNDEF(n,0); + ERTS_UNDEF(current_scheduled,NULL); ASSERT(c_p || !(in_flags & ERTS_PAM_COPY_RESULT)); @@ -1784,8 +1798,8 @@ Eterm db_prog_match(Process *c_p, because of floating point exceptions. Do *after* mpsp is set!!! */ esdp = ERTS_GET_SCHEDULER_DATA_FROM_PROC(psp); - ASSERT(esdp != NULL); - current_scheduled = esdp->current_process; + if (esdp) + current_scheduled = esdp->current_process; /* SMP: psp->scheduler_data is set by get_match_pseudo_process */ #ifdef DMC_DEBUG @@ -2517,7 +2531,8 @@ success: } #endif - esdp->current_process = current_scheduled; + if (esdp) + esdp->current_process = current_scheduled; return ret; #undef FAIL @@ -5073,7 +5088,7 @@ static Eterm match_spec_test(Process *p, Eterm against, Eterm spec, int trace) } save_cp = p->cp; p->cp = NULL; - res = erts_match_set_run(p, p, + res = erts_match_set_run_trace(p, p, mps, arr, n, ERTS_PAM_COPY_RESULT|ERTS_PAM_IGNORE_TRACE_SILENT, &ret_flags); diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index be0d2f0939..9f3341537d 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -825,13 +825,13 @@ trace_send(Process *p, Eterm to, Eterm msg) Uint32 return_flags; args[0] = to; args[1] = msg; - pam_result = erts_match_set_run(p, p, - te->match_spec, args, 2, - ERTS_PAM_TMP_RESULT, &return_flags); - if (is_non_value(pam_result) - || pam_result == am_false - || (ERTS_TRACE_FLAGS(p) & F_TRACE_SILENT)) { - erts_match_set_release_result(p); + pam_result = erts_match_set_run_trace(p, p, + te->match_spec, args, 2, + ERTS_PAM_TMP_RESULT, &return_flags); + if (pam_result == am_false) + return; + if (ERTS_TRACE_FLAGS(p) & F_TRACE_SILENT) { + erts_match_set_release_result_trace(p, pam_result); return; } } else @@ -850,9 +850,9 @@ trace_send(Process *p, Eterm to, Eterm msg) if (is_tracer_enabled(p, ERTS_PROC_LOCK_MAIN, &p->common, &tnif, TRACE_FUN_E_SEND, operation)) { send_to_tracer_nif(p, &p->common, p->common.id, tnif, TRACE_FUN_T_SEND, - operation, msg, to, pam_result); + operation, msg, to, pam_result); } - erts_match_set_release_result(p); + erts_match_set_release_result_trace(p, pam_result); } /* Send {trace_ts, Pid, receive, Msg, Timestamp} @@ -886,13 +886,13 @@ trace_receive(Process* receiver, args[1] = am_undefined; } args[2] = msg; - pam_result = erts_match_set_run(NULL, receiver, - te->match_spec, args, 3, - ERTS_PAM_TMP_RESULT, &return_flags); - if (is_non_value(pam_result) - || pam_result == am_false - || (ERTS_TRACE_FLAGS(receiver) & F_TRACE_SILENT)) { - erts_match_set_release_result(NULL); + pam_result = erts_match_set_run_trace(NULL, receiver, + te->match_spec, args, 3, + ERTS_PAM_TMP_RESULT, &return_flags); + if (pam_result == am_false) + return; + if (ERTS_TRACE_FLAGS(receiver) & F_TRACE_SILENT) { + erts_match_set_release_result_trace(NULL, pam_result); return; } } else @@ -904,7 +904,7 @@ trace_receive(Process* receiver, tnif, TRACE_FUN_T_RECEIVE, am_receive, msg, THE_NON_VALUE, pam_result); } - erts_match_set_release_result(NULL); + erts_match_set_release_result_trace(NULL, pam_result); } int @@ -1264,21 +1264,14 @@ erts_call_trace(Process* p, BeamInstr mfa[3], Binary *match_spec, may remove it, and we still want to generate a trace message */ erts_tracer_update(&pre_ms_tracer, *tracer); tracer = &pre_ms_tracer; - pam_result = erts_match_set_run(p, p, - match_spec, args, arity, - ERTS_PAM_TMP_RESULT, &return_flags); - if (is_non_value(pam_result)) { - erts_match_set_release_result(p); - UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); - ERTS_TRACER_CLEAR(&pre_ms_tracer); - return 0; - } + pam_result = erts_match_set_run_trace(p, p, + match_spec, args, arity, + ERTS_PAM_TMP_RESULT, &return_flags); } if (tracee_flags == &meta_flags) { /* Meta trace */ if (pam_result == am_false) { - erts_match_set_release_result(p); UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); ERTS_TRACER_CLEAR(&pre_ms_tracer); return return_flags; @@ -1286,13 +1279,12 @@ erts_call_trace(Process* p, BeamInstr mfa[3], Binary *match_spec, } else { /* Non-meta trace */ if (*tracee_flags & F_TRACE_SILENT) { - erts_match_set_release_result(p); + erts_match_set_release_result_trace(p, pam_result); UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); ERTS_TRACER_CLEAR(&pre_ms_tracer); return 0; } if (pam_result == am_false) { - erts_match_set_release_result(p); UnUseTmpHeap(ERL_SUB_BIN_SIZE,p); ERTS_TRACER_CLEAR(&pre_ms_tracer); return return_flags; @@ -1328,11 +1320,14 @@ erts_call_trace(Process* p, BeamInstr mfa[3], Binary *match_spec, * Build the trace tuple and send it to the port. */ send_to_tracer_nif_raw(p, NULL, *tracer, *tracee_flags, p->common.id, - tnif, TRACE_FUN_T_CALL, am_call, mfa_tuple, THE_NON_VALUE, pam_result); - erts_match_set_release_result(p); + tnif, TRACE_FUN_T_CALL, am_call, mfa_tuple, + THE_NON_VALUE, pam_result); - if (match_spec && tracer == &pre_ms_tracer) - ERTS_TRACER_CLEAR(&pre_ms_tracer); + if (match_spec) { + erts_match_set_release_result_trace(p, pam_result); + if (tracer == &pre_ms_tracer) + ERTS_TRACER_CLEAR(&pre_ms_tracer); + } return return_flags; } diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 328bfe344c..baa0a201d1 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1486,6 +1486,16 @@ do { \ extern Binary *erts_match_set_compile(Process *p, Eterm matchexpr, Eterm MFA); Eterm erts_match_set_lint(Process *p, Eterm matchexpr); extern void erts_match_set_release_result(Process* p); +ERTS_GLB_INLINE void erts_match_set_release_result_trace(Process* p, Eterm); + +#if ERTS_GLB_INLINE_INCL_FUNC_DEF +ERTS_GLB_INLINE +void erts_match_set_release_result_trace(Process* p, Eterm pam_result) +{ + if (is_not_immed(pam_result)) + erts_match_set_release_result(p); +} +#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */ enum erts_pam_run_flags { ERTS_PAM_TMP_RESULT=1, @@ -1493,12 +1503,12 @@ enum erts_pam_run_flags { ERTS_PAM_CONTIGUOUS_TUPLE=4, ERTS_PAM_IGNORE_TRACE_SILENT=8 }; -extern Eterm erts_match_set_run(Process *p, - Process *self, - Binary *mpsp, - Eterm *args, int num_args, - enum erts_pam_run_flags in_flags, - Uint32 *return_flags); +extern Eterm erts_match_set_run_trace(Process *p, + Process *self, + Binary *mpsp, + Eterm *args, int num_args, + enum erts_pam_run_flags in_flags, + Uint32 *return_flags); extern Eterm erts_match_set_get_source(Binary *mpsp); extern void erts_match_prog_foreach_offheap(Binary *b, void (*)(ErlOffHeap *, void *), |