aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/beam_emu.c2
-rw-r--r--erts/emulator/beam/erl_bif_trace.c40
-rw-r--r--erts/emulator/beam/erl_db.c3
-rw-r--r--erts/emulator/beam/erl_db_util.c62
-rw-r--r--erts/emulator/beam/erl_db_util.h3
-rw-r--r--erts/emulator/beam/erl_message.c37
-rw-r--r--erts/emulator/beam/erl_trace.c48
-rw-r--r--erts/emulator/beam/erl_trace.h19
-rw-r--r--erts/emulator/beam/global.h4
-rw-r--r--erts/emulator/hipe/hipe_native_bif.c2
-rw-r--r--erts/emulator/test/trace_SUITE.erl20
11 files changed, 166 insertions, 74 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 72526bca5e..7eecd059a5 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -2166,7 +2166,7 @@ void process_main(void)
PreFetch(0, next);
if (IS_TRACED_FL(c_p, F_TRACE_RECEIVE)) {
- trace_receive(c_p, am_timeout);
+ trace_receive(c_p, c_p, am_timeout, NULL);
}
if (ERTS_PROC_GET_SAVED_CALLS_BUF(c_p)) {
save_calls(c_p, &exp_timeout);
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 6b5bb2f889..7b21ff0110 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -68,8 +68,8 @@ static struct { /* Protected by code write permission */
static Eterm
trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist);
-static void
-erts_set_trace_send_pattern(Process*, Binary*, int on);
+static int
+erts_set_tracing_event_pattern(Eterm event, Binary*, int on);
#ifdef ERTS_SMP
static void smp_bp_finisher(void* arg);
@@ -89,6 +89,7 @@ static void uninstall_exp_breakpoints(BpFunctions* f);
static void clean_export_entries(BpFunctions* f);
ErtsTracingEvent erts_send_tracing[ERTS_NUM_BP_IX];
+ErtsTracingEvent erts_receive_tracing[ERTS_NUM_BP_IX];
void
erts_bif_trace_init(void)
@@ -104,6 +105,8 @@ erts_bif_trace_init(void)
for (i=0; i<ERTS_NUM_BP_IX; i++) {
erts_send_tracing[i].on = 1;
erts_send_tracing[i].match_spec = NULL;
+ erts_receive_tracing[i].on = 1;
+ erts_receive_tracing[i].match_spec = NULL;
}
}
@@ -326,15 +329,13 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
matches = erts_set_trace_pattern(p, mfa, specified,
match_prog_set, match_prog_set,
on, flags, meta_tracer, 0);
- } else if (MFA == am_send) {
+ } else if (is_atom(MFA)) {
if (is_global || flags.breakpoint || on > ERTS_BREAK_SET) {
goto error;
}
- erts_set_trace_send_pattern(p, match_prog_set, on);
- matches = 1;
+ matches = erts_set_tracing_event_pattern(MFA, match_prog_set, on);
}
-
error:
MatchSetUnref(match_prog_set);
UnUseTmpHeap(3,p);
@@ -1486,10 +1487,17 @@ erts_set_trace_pattern(Process*p, Eterm* mfa, int specified,
return matches;
}
-void
-erts_set_trace_send_pattern(Process*p, Binary* match_spec, int on)
+int
+erts_set_tracing_event_pattern(Eterm event, Binary* match_spec, int on)
{
- ErtsTracingEvent* st = &erts_send_tracing[erts_staging_bp_ix()];
+ ErtsBpIndex ix = erts_staging_bp_ix();
+ ErtsTracingEvent* st;
+
+ switch (event) {
+ case am_send: st = &erts_send_tracing[ix]; break;
+ case am_receive: st = &erts_receive_tracing[ix]; break;
+ default: return -1;
+ }
MatchSetUnref(st->match_spec);
@@ -1497,7 +1505,7 @@ erts_set_trace_send_pattern(Process*p, Binary* match_spec, int on)
st->match_spec = match_spec;
MatchSetRef(match_spec);
- finish_bp.current = 1; /* prepare phase not needed for send trace */
+ finish_bp.current = 1; /* prepare phase not needed for event trace */
finish_bp.install = on;
finish_bp.e.matched = 0;
finish_bp.e.matching = NULL;
@@ -1509,13 +1517,14 @@ erts_set_trace_send_pattern(Process*p, Binary* match_spec, int on)
/* Empty loop body */
}
#endif
+ return 1;
}
static void
-consolidate_send_tracing(void)
+consolidate_event_tracing(ErtsTracingEvent te[])
{
- ErtsTracingEvent* src = &erts_send_tracing[erts_active_bp_ix()];
- ErtsTracingEvent* dst = &erts_send_tracing[erts_staging_bp_ix()];
+ ErtsTracingEvent* src = &te[erts_active_bp_ix()];
+ ErtsTracingEvent* dst = &te[erts_staging_bp_ix()];
MatchSetUnref(dst->match_spec);
dst->on = src->on;
@@ -1529,7 +1538,7 @@ erts_finish_breakpointing(void)
ERTS_SMP_LC_ASSERT(erts_has_code_write_permission());
/*
- * Memory barriers will be issued for all processes *before*
+ * Memory barriers will be issued for all schedulers *before*
* each of the stages below. (Unless the other schedulers
* are blocked, in which case memory barriers will be issued
* when they are awaken.)
@@ -1598,7 +1607,8 @@ erts_finish_breakpointing(void)
erts_consolidate_bp_data(&finish_bp.f, 1);
erts_bp_free_matched_functions(&finish_bp.e);
erts_bp_free_matched_functions(&finish_bp.f);
- consolidate_send_tracing();
+ consolidate_event_tracing(erts_send_tracing);
+ consolidate_event_tracing(erts_receive_tracing);
return 0;
default:
ASSERT(0);
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index 615d23402b..acaca54e9a 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -2833,7 +2833,8 @@ BIF_RETTYPE ets_match_spec_run_r_3(BIF_ALIST_3)
BIF_TRAP3(bif_export[BIF_ets_match_spec_run_r_3],
BIF_P,lst,BIF_ARG_2,ret);
}
- res = db_prog_match(BIF_P, mp, CAR(list_val(lst)), NULL, 0,
+ res = db_prog_match(BIF_P, BIF_P,
+ mp, CAR(list_val(lst)), NULL, 0,
ERTS_PAM_COPY_RESULT, &dummy);
if (is_value(res)) {
hp = HAlloc(BIF_P, 2);
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index a1f458038e..72d59df813 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -1202,14 +1202,16 @@ done:
return ret;
}
-Eterm erts_match_set_run(Process *p, Binary *mpsp,
+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)
{
Eterm ret;
- ret = db_prog_match(p, mpsp, NIL, args, num_args,
+ ret = db_prog_match(c_p, self, mpsp, NIL, args, num_args,
in_flags, return_flags);
#if defined(HARDDEBUG)
if (is_non_value(ret)) {
@@ -1234,7 +1236,8 @@ static Eterm erts_match_set_run_ets(Process *p, Binary *mpsp,
{
Eterm ret;
- ret = db_prog_match(p, mpsp, args, NULL, num_args,
+ ret = db_prog_match(p, p,
+ mpsp, args, NULL, num_args,
ERTS_PAM_COPY_RESULT,
return_flags);
#if defined(HARDDEBUG)
@@ -1730,7 +1733,9 @@ static Eterm dpm_array_to_list(Process *psp, Eterm *arr, int arity)
** the parameter 'arity' is only used if 'term' is actually an array,
** i.e. 'DCOMP_TRACE' was specified
*/
-Eterm db_prog_match(Process *c_p, Binary *bprog,
+Eterm db_prog_match(Process *c_p,
+ Process *self,
+ Binary *bprog,
Eterm term,
Eterm *termp,
int arity,
@@ -1746,7 +1751,7 @@ Eterm db_prog_match(Process *c_p, Binary *bprog,
UWord *pc = prog->text;
Eterm *ehp;
Eterm ret;
- Uint n = 0; /* To avoid warning. */
+ Uint n;
int i;
unsigned do_catch;
ErtsMatchPseudoProcess *mpsp;
@@ -1764,6 +1769,8 @@ Eterm db_prog_match(Process *c_p, Binary *bprog,
Uint save_op;
#endif /* DMC_DEBUG */
+ ERTS_UNDEF(n,0);
+
mpsp = get_match_pseudo_process(c_p, prog->heap_size);
psp = &mpsp->process;
@@ -2233,7 +2240,7 @@ restart:
pc += n;
break;
case matchSelf:
- *esp++ = c_p->common.id;
+ *esp++ = self->common.id;
break;
case matchWaste:
--esp;
@@ -2243,6 +2250,7 @@ restart:
break;
case matchProcessDump: {
erts_dsprintf_buf_t *dsbufp = erts_create_tmp_dsbuf(0);
+ ASSERT(c_p == self);
print_process_info(ERTS_PRINT_DSBUF, (void *) dsbufp, c_p);
*esp++ = new_binary(build_proc, (byte *)dsbufp->str,
dsbufp->str_len);
@@ -2261,14 +2269,16 @@ restart:
*return_flags |= MATCH_SET_EXCEPTION_TRACE;
*esp++ = am_true;
break;
- case matchIsSeqTrace:
+ case matchIsSeqTrace:
+ ASSERT(c_p == self);
if (have_seqtrace(SEQ_TRACE_TOKEN(c_p)))
*esp++ = am_true;
else
*esp++ = am_false;
break;
case matchSetSeqToken:
- t = erts_seq_trace(c_p, esp[-1], esp[-2], 0);
+ ASSERT(c_p == self);
+ t = erts_seq_trace(c_p, esp[-1], esp[-2], 0);
if (is_non_value(t)) {
esp[-2] = FAIL_TERM;
} else {
@@ -2276,7 +2286,8 @@ restart:
}
--esp;
break;
- case matchSetSeqTokenFake:
+ case matchSetSeqTokenFake:
+ ASSERT(c_p == self);
t = seq_trace_fake(c_p, esp[-1]);
if (is_non_value(t)) {
esp[-2] = FAIL_TERM;
@@ -2285,7 +2296,8 @@ restart:
}
--esp;
break;
- case matchGetSeqToken:
+ case matchGetSeqToken:
+ ASSERT(c_p == self);
if (have_no_seqtrace(SEQ_TRACE_TOKEN(c_p)))
*esp++ = NIL;
else {
@@ -2309,7 +2321,8 @@ restart:
ASSERT(is_immed(ehp[5]));
}
break;
- case matchEnableTrace:
+ case matchEnableTrace:
+ ASSERT(c_p == self);
if ( (n = erts_trace_flag2bit(esp[-1]))) {
erts_smp_proc_lock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);
set_tracee_flags(c_p, ERTS_TRACER(c_p), 0, n);
@@ -2319,7 +2332,8 @@ restart:
esp[-1] = FAIL_TERM;
}
break;
- case matchEnableTrace2:
+ case matchEnableTrace2:
+ ASSERT(c_p == self);
n = erts_trace_flag2bit((--esp)[-1]);
esp[-1] = FAIL_TERM;
if (n) {
@@ -2334,7 +2348,8 @@ restart:
}
}
break;
- case matchDisableTrace:
+ case matchDisableTrace:
+ ASSERT(c_p == self);
if ( (n = erts_trace_flag2bit(esp[-1]))) {
erts_smp_proc_lock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);
set_tracee_flags(c_p, ERTS_TRACER(c_p), n, 0);
@@ -2344,7 +2359,8 @@ restart:
esp[-1] = FAIL_TERM;
}
break;
- case matchDisableTrace2:
+ case matchDisableTrace2:
+ ASSERT(c_p == self);
n = erts_trace_flag2bit((--esp)[-1]);
esp[-1] = FAIL_TERM;
if (n) {
@@ -2359,7 +2375,8 @@ restart:
}
}
break;
- case matchCaller:
+ case matchCaller:
+ ASSERT(c_p == self);
if (!(c_p->cp) || !(cp = find_function_from_pc(c_p->cp))) {
*esp++ = am_undefined;
} else {
@@ -2371,7 +2388,8 @@ restart:
ehp[3] = make_small((Uint) cp[2]);
}
break;
- case matchSilent:
+ case matchSilent:
+ ASSERT(c_p == self);
--esp;
if (in_flags & ERTS_PAM_IGNORE_TRACE_SILENT)
break;
@@ -2386,7 +2404,8 @@ restart:
erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);
}
break;
- case matchTrace2:
+ case matchTrace2:
+ ASSERT(c_p == self);
{
/* disable enable */
Uint d_flags = 0, e_flags = 0; /* process trace flags */
@@ -2418,7 +2437,8 @@ restart:
ERTS_TRACER_CLEAR(&tracer);
}
break;
- case matchTrace3:
+ case matchTrace3:
+ ASSERT(c_p == self);
{
/* disable enable */
Uint d_flags = 0, e_flags = 0; /* process trace flags */
@@ -5080,7 +5100,8 @@ 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, mps, arr, n,
+ res = erts_match_set_run(p, p,
+ mps, arr, n,
ERTS_PAM_COPY_RESULT|ERTS_PAM_IGNORE_TRACE_SILENT,
&ret_flags);
p->cp = save_cp;
@@ -5163,7 +5184,8 @@ Eterm db_match_dbterm(DbTableCommon* tb, Process* c_p, Binary* bprog,
obj = db_alloc_tmp_uncompressed(tb, obj);
}
- res = db_prog_match(c_p, bprog, make_tuple(obj->tpl), NULL, 0,
+ res = db_prog_match(c_p, c_p,
+ bprog, make_tuple(obj->tpl), NULL, 0,
ERTS_PAM_COPY_RESULT|ERTS_PAM_CONTIGUOUS_TUPLE, &dummy);
if (is_value(res) && hpp!=NULL) {
diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h
index 5d7946a525..c3eb82a44a 100644
--- a/erts/emulator/beam/erl_db_util.h
+++ b/erts/emulator/beam/erl_db_util.h
@@ -435,7 +435,8 @@ Binary *db_match_compile(Eterm *matchexpr, Eterm *guards,
Eterm db_match_dbterm(DbTableCommon* tb, Process* c_p, Binary* bprog,
int all, DbTerm* obj, Eterm** hpp, Uint extra);
-Eterm db_prog_match(Process *p, Binary *prog, Eterm term,
+Eterm db_prog_match(Process *p, Process *self,
+ Binary *prog, Eterm term,
Eterm *termp, int arity,
enum erts_pam_run_flags in_flags,
Uint32 *return_flags /* Zeroed on enter */);
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index 9beff52835..ee8a7702ce 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -32,6 +32,7 @@
#include "erl_process.h"
#include "erl_binary.h"
#include "dtrace-wrapper.h"
+#include "beam_bp.h"
ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(message_ref,
ErtsMessageRef,
@@ -369,11 +370,12 @@ static Sint
queue_messages(Process *c_p,
Process* receiver,
erts_aint32_t *receiver_state,
- ErtsProcLocks *receiver_locks,
+ ErtsProcLocks receiver_locks,
ErtsMessage* first,
ErtsMessage** last,
Uint len)
{
+ ErtsTracingEvent* te;
Sint res;
int locked_msgq = 0;
erts_aint32_t state;
@@ -386,12 +388,12 @@ queue_messages(Process *c_p,
#ifdef ERTS_SMP
#ifdef ERTS_ENABLE_LOCK_CHECK
ERTS_SMP_LC_ASSERT(erts_proc_lc_my_proc_locks(receiver) < ERTS_PROC_LOCK_MSGQ ||
- *receiver_locks == erts_proc_lc_my_proc_locks(receiver));
+ receiver_locks == erts_proc_lc_my_proc_locks(receiver));
#endif
- if (!(*receiver_locks & ERTS_PROC_LOCK_MSGQ)) {
+ if (!(receiver_locks & ERTS_PROC_LOCK_MSGQ)) {
if (erts_smp_proc_trylock(receiver, ERTS_PROC_LOCK_MSGQ) == EBUSY) {
- ErtsProcLocks need_locks = ERTS_PROC_LOCK_MSGQ;
+ ErtsProcLocks need_locks;
if (receiver_state)
state = *receiver_state;
@@ -400,10 +402,11 @@ queue_messages(Process *c_p,
if (state & (ERTS_PSFLG_EXITING|ERTS_PSFLG_PENDING_EXIT))
goto exiting;
- if (*receiver_locks & ERTS_PROC_LOCK_STATUS) {
- erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_STATUS);
- need_locks |= ERTS_PROC_LOCK_STATUS;
+ need_locks = receiver_locks & (ERTS_PROC_LOCK_STATUS|ERTS_PROC_LOCK_TRACE);
+ if (need_locks) {
+ erts_smp_proc_unlock(receiver, need_locks);
}
+ need_locks |= ERTS_PROC_LOCK_MSGQ;
erts_smp_proc_lock(receiver, need_locks);
}
locked_msgq = 1;
@@ -426,7 +429,7 @@ queue_messages(Process *c_p,
res = receiver->msg.len;
#ifdef ERTS_SMP
- if (*receiver_locks & ERTS_PROC_LOCK_MAIN) {
+ if (receiver_locks & ERTS_PROC_LOCK_MAIN) {
/*
* We move 'in queue' to 'private queue' and place
* message at the end of 'private queue' in order
@@ -445,7 +448,10 @@ queue_messages(Process *c_p,
LINK_MESSAGE(receiver, first, last, len);
}
- if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)) {
+ if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)
+ && (te = &erts_receive_tracing[erts_active_bp_ix()],
+ te->on)) {
+
ErtsMessage *msg = first;
#ifdef USE_VM_PROBES
@@ -468,19 +474,18 @@ queue_messages(Process *c_p,
tok_label, tok_lastcnt, tok_serial);
}
#endif
-
while (msg) {
- trace_receive(receiver, ERL_MESSAGE_TERM(msg));
+ trace_receive(c_p, receiver, ERL_MESSAGE_TERM(msg), te);
msg = msg->next;
}
}
-
- if (locked_msgq)
+ if (locked_msgq) {
erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_MSGQ);
+ }
#ifdef ERTS_SMP
- erts_proc_notify_new_message(receiver, *receiver_locks);
+ erts_proc_notify_new_message(receiver, receiver_locks);
#else
erts_proc_notify_new_message(receiver, 0);
ERTS_HOLE_CHECK(receiver);
@@ -496,7 +501,7 @@ queue_message(Process *c_p,
ErtsMessage* mp, Eterm msg)
{
ERL_MESSAGE_TERM(mp) = msg;
- return queue_messages(c_p, receiver, receiver_state, receiver_locks,
+ return queue_messages(c_p, receiver, receiver_state, *receiver_locks,
mp, &mp->next, 1 );
}
@@ -512,7 +517,7 @@ Sint
erts_queue_messages(Process* receiver, ErtsProcLocks *receiver_locks,
ErtsMessage* first, ErtsMessage** last, Uint len)
{
- return queue_messages(NULL, receiver, NULL, receiver_locks,
+ return queue_messages(NULL, receiver, NULL, *receiver_locks,
first, last, len);
}
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index e8516cd09c..755deda9c1 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -238,7 +238,6 @@ write_timestamp(ErtsTraceTimeStamp *tsp, Eterm **hpp)
}
#ifdef ERTS_SMP
-#define PATCH_TS_SIZE(p) patch_ts_size(TFLGS_TS_TYPE(p))
static ERTS_INLINE Uint
patch_ts_size(int ts_type)
@@ -258,7 +257,7 @@ patch_ts_size(int ts_type)
return 0;
}
}
-#endif
+#endif /* ERTS_SMP */
/*
* Write a timestamp. The timestamp MUST be the last
@@ -826,7 +825,8 @@ trace_send(Process *p, Eterm to, Eterm msg)
Uint32 return_flags;
args[0] = to;
args[1] = msg;
- pam_result = erts_match_set_run(p, te->match_spec, args, 2,
+ 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
@@ -859,14 +859,43 @@ trace_send(Process *p, Eterm to, Eterm msg)
* or {trace, Pid, receive, Msg}
*/
void
-trace_receive(Process *c_p, Eterm msg)
+trace_receive(Process *c_p,
+ Process* receiver,
+ Eterm msg, ErtsTracingEvent* te)
{
ErtsTracerNif *tnif = NULL;
- if (is_tracer_enabled(NULL, 0, &c_p->common, &tnif,
- TRACE_FUN_E_RECEIVE, am_receive))
- send_to_tracer_nif(NULL, &c_p->common, c_p->common.id,
+ Eterm pam_result;
+
+ if (!te) {
+ te = &erts_receive_tracing[erts_active_bp_ix()];
+ if (!te->on)
+ return;
+ }
+
+ if (te->match_spec) {
+ Eterm args[2];
+ Uint32 return_flags;
+ args[0] = am_undefined; /* ToDo: from who? */
+ args[1] = msg;
+ pam_result = erts_match_set_run(c_p, receiver,
+ te->match_spec, args, 2,
+ 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(c_p);
+ return;
+ }
+ } else
+ pam_result = am_true;
+
+ if (is_tracer_enabled(NULL, 0, &receiver->common, &tnif,
+ TRACE_FUN_E_RECEIVE, am_receive)) {
+ send_to_tracer_nif(NULL, &receiver->common, receiver->common.id,
tnif, TRACE_FUN_T_RECEIVE,
- am_receive, msg, THE_NON_VALUE, am_true);
+ am_receive, msg, THE_NON_VALUE, pam_result);
+ }
+ erts_match_set_release_result(c_p);
}
int
@@ -1226,7 +1255,8 @@ 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, match_spec, args, arity,
+ 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);
diff --git a/erts/emulator/beam/erl_trace.h b/erts/emulator/beam/erl_trace.h
index e8e968c0cf..040aa296a1 100644
--- a/erts/emulator/beam/erl_trace.h
+++ b/erts/emulator/beam/erl_trace.h
@@ -56,6 +56,15 @@
struct binary;
+typedef struct
+{
+ int on;
+ struct binary* match_spec;
+} ErtsTracingEvent;
+
+extern ErtsTracingEvent erts_send_tracing[];
+extern ErtsTracingEvent erts_receive_tracing[];
+
/* erl_bif_trace.c */
Eterm erl_seq_trace_info(Process *p, Eterm arg1);
void erts_system_monitor_clear(Process *c_p);
@@ -91,7 +100,7 @@ void erts_send_sys_msg_proc(Eterm, Eterm, Eterm, ErlHeapFragment *);
#endif
void trace_send(Process*, Eterm, Eterm);
-void trace_receive(Process *, Eterm);
+void trace_receive(Process*, Process*, Eterm, ErtsTracingEvent*);
Uint32 erts_call_trace(Process *p, BeamInstr mfa[], struct binary *match_spec,
Eterm* args, int local, ErtsTracer *tracer);
void erts_trace_return(Process* p, BeamInstr* fi, Eterm retval,
@@ -220,12 +229,4 @@ ERTS_DECLARE_DUMMY(erts_tracer_nil) = NIL;
&& erts_is_tracer_proc_enabled(PROC, ERTS_PROC_LOCK_MAIN, \
&(PROC)->common, am_trace_status))
-typedef struct
-{
- int on;
- struct binary* match_spec;
-} ErtsTracingEvent;
-
-extern ErtsTracingEvent erts_send_tracing[];
-
#endif /* ERL_TRACE_H__ */
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index a7bc990deb..916c6277c1 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -1493,7 +1493,9 @@ enum erts_pam_run_flags {
ERTS_PAM_CONTIGUOUS_TUPLE=4,
ERTS_PAM_IGNORE_TRACE_SILENT=8
};
-extern Eterm erts_match_set_run(Process *p, Binary *mpsp,
+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);
diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c
index 00b572029a..d8076a3e02 100644
--- a/erts/emulator/hipe/hipe_native_bif.c
+++ b/erts/emulator/hipe/hipe_native_bif.c
@@ -601,7 +601,7 @@ void hipe_clear_timeout(Process *c_p)
}
#endif
if (IS_TRACED_FL(c_p, F_TRACE_RECEIVE)) {
- trace_receive(c_p, am_timeout);
+ trace_receive(c_p, c_p, am_timeout, NULL);
}
c_p->flags &= ~F_TIMO;
JOIN_MESSAGE(c_p);
diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl
index c8cc0fc6e8..7eb52dcdeb 100644
--- a/erts/emulator/test/trace_SUITE.erl
+++ b/erts/emulator/test/trace_SUITE.erl
@@ -94,6 +94,26 @@ receive_trace(Config) when is_list(Config) ->
{trace, Receiver, 'receive', Hello2} = receive_first_trace(),
receive_nothing(),
+ %% Test 'receive' with matchspec
+ F1 = fun ({Pat, IsMatching}) ->
+ set_trace_pattern('receive', Pat, []),
+ Receiver ! Hello,
+ case IsMatching of
+ true ->
+ {trace, Receiver, 'receive', Hello} = receive_first_trace();
+ false ->
+ ok
+ end,
+ receive_nothing()
+ end,
+ lists:foreach(F1, [{no, true},
+ {[{[undefined,"Unexpected"],[],[]}], false},
+ {[{['_','_'],[],[]}], true},
+ {[{['$1','_'],[{is_integer,'$1'}],[]}], false},
+ {[{['_','$1'],[{is_tuple,'$1'}],[]}], true},
+ {false, false},
+ {true, true}]),
+
%% Another process should not be able to trace Receiver.
Intruder = fun_spawn(fun() -> erlang:trace(Receiver, true, ['receive']) end),
{'EXIT', Intruder, {badarg, _}} = receive_first(),