aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2016-04-05 11:26:52 +0200
committerLukas Larsson <[email protected]>2016-04-15 15:08:52 +0200
commitc3e7acb4fe304d117f7361292d36f5d73df3e1c7 (patch)
tree50777c8c13d2e4eeba302b446c14683821dcd83b
parenta1b352dfc68d501a385240cdb7f45a96cf9e3358 (diff)
downloadotp-c3e7acb4fe304d117f7361292d36f5d73df3e1c7.tar.gz
otp-c3e7acb4fe304d117f7361292d36f5d73df3e1c7.tar.bz2
otp-c3e7acb4fe304d117f7361292d36f5d73df3e1c7.zip
erts: Make trace_delivered go via sys msg dispatcher again
This is needed as otherwise messages from system_profile will not be guaranteed to arrive before trace delivered.
-rw-r--r--erts/doc/src/erlang.xml13
-rw-r--r--erts/emulator/beam/erl_bif_trace.c23
-rw-r--r--erts/emulator/beam/erl_trace.c16
-rw-r--r--erts/emulator/beam/erl_trace.h1
4 files changed, 42 insertions, 11 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index fde04504c8..423ccdf98f 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -8958,7 +8958,11 @@ timestamp() ->
<name name="trace_delivered" arity="1"/>
<fsummary>Notification when trace has been delivered.</fsummary>
<desc>
- <p>The delivery of trace messages is dislocated on the time-line
+ <p>The delivery of trace messages (generated by
+ <seealso marker="#trace/3"><c>erlang:trace/3</c></seealso>,
+ <seealso marker="kernel:seq_trace"><c>seq_trace</c></seealso> or
+ <seealso marker="#system_profile/2"><c>erlang:system_profile/2</c></seealso>)
+ is dislocated on the time-line
compared to other events in the system. If you know that
<c><anno>Tracee</anno></c> has passed some specific point
in its execution,
@@ -8984,8 +8988,11 @@ timestamp() ->
or previously existing on the same node as the caller of
<c>erlang:trace_delivered(<anno>Tracee</anno>)</c> resides on.
The special <c><anno>Tracee</anno></c> atom <c>all</c>
- denotes all processes
- that currently are traced in the node.</p>
+ denotes all processes that currently are traced in the node.</p>
+ <p>When used together with an <seealso marker="#erl_tracer">
+ Tracer Module</seealso> any message sent in the trace callback
+ is guaranteed to have reached it's recipient before the
+ <c>trace_delivered</c> message is sent.</p>
<p>Example: Process <c>A</c> is <c><anno>Tracee</anno></c>,
port <c>B</c> is tracer, and process <c>C</c> is the port
owner of <c>B</c>. <c>C</c> wants to close <c>B</c> when
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 7e2fe7fcd4..ff2018aa27 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -2253,25 +2253,32 @@ static void
reply_trace_delivered_all(void *vtdarp)
{
ErtsTraceDeliveredAll *tdarp = (ErtsTraceDeliveredAll *) vtdarp;
- ErtsProcLocks rp_locks = 0;
if (erts_smp_atomic32_dec_read_nob(&tdarp->refc) == 0) {
+ Eterm ref_copy, msg;
Process *rp = tdarp->proc;
Eterm *hp = NULL;
- ErlOffHeap *ohp = NULL;
- ErtsMessage *mp = NULL;
- Eterm ref_copy, msg;
-
+ ErlOffHeap *ohp;
+#ifdef ERTS_SMP
+ ErlHeapFragment *bp;
+ bp = new_message_buffer(4 + NC_HEAP_SIZE(tdarp->ref));
+ hp = &bp->mem[0];
+ ohp = &bp->off_heap;
+#else
+ ErtsProcLocks rp_locks = 0;
+ ErtsMessage *mp;
mp = erts_alloc_message_heap(
rp, &rp_locks, 4 + NC_HEAP_SIZE(tdarp->ref), &hp, &ohp);
+#endif
ref_copy = STORE_NC(&hp, ohp, tdarp->ref);
msg = TUPLE3(hp, am_trace_delivered, tdarp->target, ref_copy);
+#ifdef ERTS_SMP
+ erts_send_sys_msg_proc(rp->common.id, rp->common.id, msg, bp);
+#else
erts_queue_message(rp, &rp_locks, mp, msg);
-
- if (rp_locks)
- erts_smp_proc_unlock(rp, rp_locks);
+#endif
erts_free(ERTS_ALC_T_MISC_AUX_WORK, vtdarp);
erts_proc_dec_refc(rp);
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index cd3c14e213..bd88769dfc 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -84,6 +84,7 @@ enum ErtsSysMsgType {
SYS_MSG_TYPE_UNDEFINED,
SYS_MSG_TYPE_SYSMON,
SYS_MSG_TYPE_ERRLGR,
+ SYS_MSG_TYPE_PROC_MSG,
SYS_MSG_TYPE_SYSPROF
};
@@ -2157,6 +2158,13 @@ erts_queue_error_logger_message(Eterm from, Eterm msg, ErlHeapFragment *bp)
enqueue_sys_msg(SYS_MSG_TYPE_ERRLGR, from, am_error_logger, msg, bp);
}
+void
+erts_send_sys_msg_proc(Eterm from, Eterm to, Eterm msg, ErlHeapFragment *bp)
+{
+ ASSERT(is_internal_pid(to));
+ enqueue_sys_msg(SYS_MSG_TYPE_PROC_MSG, from, to, msg, bp);
+}
+
#ifdef DEBUG_PRINTOUTS
static void
print_msg_type(ErtsSysMsgQ *smqp)
@@ -2171,6 +2179,9 @@ print_msg_type(ErtsSysMsgQ *smqp)
case SYS_MSG_TYPE_ERRLGR:
erts_fprintf(stderr, "ERRLGR ");
break;
+ case SYS_MSG_TYPE_PROC_MSG:
+ erts_fprintf(stderr, "PROC_MSG ");
+ break;
default:
erts_fprintf(stderr, "??? ");
break;
@@ -2241,6 +2252,8 @@ sys_msg_disp_failure(ErtsSysMsgQ *smqp, Eterm receiver)
no_elgger, tag, CAR(list_val(tp[3])));
break;
}
+ case SYS_MSG_TYPE_PROC_MSG:
+ break;
default:
ASSERT(0);
}
@@ -2358,6 +2371,9 @@ sys_msg_dispatcher_func(void *unused)
print_msg_type(smqp);
#endif
switch (smqp->type) {
+ case SYS_MSG_TYPE_PROC_MSG:
+ receiver = smqp->to;
+ break;
case SYS_MSG_TYPE_SYSMON:
receiver = erts_get_system_monitor();
if (smqp->from == receiver) {
diff --git a/erts/emulator/beam/erl_trace.h b/erts/emulator/beam/erl_trace.h
index 14d0c36016..177fd373a6 100644
--- a/erts/emulator/beam/erl_trace.h
+++ b/erts/emulator/beam/erl_trace.h
@@ -87,6 +87,7 @@ void erts_foreach_sys_msg_in_q(void (*func)(Eterm,
Eterm,
ErlHeapFragment *));
void erts_queue_error_logger_message(Eterm, Eterm, ErlHeapFragment *);
+void erts_send_sys_msg_proc(Eterm, Eterm, Eterm, ErlHeapFragment *);
#endif
void trace_send(Process*, Eterm, Eterm);