aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2016-04-29 17:50:18 +0200
committerSverker Eriksson <[email protected]>2016-05-04 19:53:37 +0200
commit14b81c60f0c6403e9371be420a6df4d414180c68 (patch)
tree13b956613e00ab6776325b27ccd37313ea116efe
parent36e9d73aa08930ddf3e3587addfb9a647a41b3e7 (diff)
downloadotp-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.c73
-rw-r--r--erts/emulator/beam/erl_trace.c61
-rw-r--r--erts/emulator/beam/global.h22
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 *),