680
static ERTS_INLINE void
681
send_to_tracer(Process *tracee,
682
ERTS_TRACER_REF_TYPE tracer_ref,
688
ERTS_SMP_LC_ASSERT(erts_proc_lc_my_proc_locks(tracee));
690
erts_smp_mtx_lock(&smq_mtx);
692
if (tracee->trace_flags & F_TIMESTAMP)
693
*hpp = patch_ts(msg, *hpp);
695
if (is_internal_pid(tracee->tracer_proc))
696
ERTS_ENQ_TRACE_MSG(tracee->id, tracer_ref, msg, bp);
698
ASSERT(is_internal_port(tracee->tracer_proc));
699
send_to_port(no_fake_sched ? NULL : tracee,
701
&tracee->tracer_proc,
702
&tracee->trace_flags);
705
erts_smp_mtx_unlock(&smq_mtx);
710
trace_sched_aux(Process *p, Eterm what, int never_fake_sched)
712
Eterm local_heap[5+4+1+TS_HEAP_WORDS];
713
Eterm tmp, mess, *hp;
714
ErlHeapFragment *bp = NULL;
715
ErlOffHeap *off_heap;
716
ERTS_TRACER_REF_TYPE tracer_ref = ERTS_NULL_TRACER_REF;
717
int sched_no, curr_func, to_port, no_fake_sched;
719
if (is_nil(p->tracer_proc))
722
no_fake_sched = never_fake_sched;
738
sched_no = IS_TRACED_FL(p, F_TRACE_SCHED_NO);
739
to_port = is_internal_port(p->tracer_proc);
742
ASSERT(is_internal_pid(p->tracer_proc)
743
&& internal_pid_index(p->tracer_proc) < erts_max_processes);
745
ERTS_GET_TRACER_REF(tracer_ref, p->tracer_proc, p->trace_flags);
748
if (ERTS_PROC_IS_EXITING(p)
750
|| p->status == P_FREE
757
p->current = find_function_from_pc(p->i);
758
curr_func = p->current != NULL;
770
hp = ERTS_ALLOC_SYSMSG_HEAP(size, &bp, &off_heap, tracer_ref);
776
tmp = TUPLE3(hp,p->current[0],p->current[1],make_small(p->current[2]));
781
mess = TUPLE4(hp, am_trace, p->id, what, tmp);
786
Eterm sched_id = make_small(p->scheduler_data->no);
788
Eterm sched_id = make_small(1);
790
mess = TUPLE5(hp, am_trace, p->id, what, sched_id, tmp);
794
send_to_tracer(p, tracer_ref, mess, &hp, bp, no_fake_sched);
678
797
/* Send {trace_ts, Pid, What, {Mod, Func, Arity}, Timestamp}
679
798
* or {trace, Pid, What, {Mod, Func, Arity}}
681
* where 'What' is supposed to be 'in' or 'out'.
800
* where 'What' is supposed to be 'in', 'out', 'in_exiting',
801
* 'out_exiting', or 'out_exited'.
684
804
trace_sched(Process *p, Eterm what)
692
if (is_internal_port(p->tracer_proc)) {
693
Eterm local_heap[4+5+6];
696
if (p->current == NULL) {
697
p->current = find_function_from_pc(p->i);
699
if (p->current == NULL) {
702
tmp = TUPLE3(hp, p->current[0], p->current[1], make_small(p->current[2]));
706
if (IS_TRACED_FL(p, F_TRACE_SCHED_NO)) {
708
if (p->scheduler_data) sched_id = make_small(p->scheduler_data->no);
709
else sched_id = am_undefined;
711
sched_id = make_small(1);
713
mess = TUPLE5(hp, am_trace, p->id, what, sched_id, tmp);
716
mess = TUPLE4(hp, am_trace, p->id, what, tmp);
723
erts_smp_mtx_lock(&smq_mtx);
724
if (p->trace_flags & F_TIMESTAMP) {
725
hp = patch_ts(mess, hp);
727
if (what != am_out) {
728
send_to_port(p, mess, &p->tracer_proc, &p->trace_flags);
730
send_to_port(NULL, mess, &p->tracer_proc, &p->trace_flags);
732
erts_smp_mtx_unlock(&smq_mtx);
735
ErlOffHeap *off_heap;
736
ERTS_TRACER_REF_TYPE tracer_ref;
738
ASSERT(is_internal_pid(p->tracer_proc)
739
&& internal_pid_index(p->tracer_proc) < erts_max_processes);
741
ERTS_GET_TRACER_REF(tracer_ref, p->tracer_proc, p->trace_flags);
743
hp = ERTS_ALLOC_SYSMSG_HEAP(4 + ws + TS_SIZE(p), &bp, &off_heap, tracer_ref);
745
if (p->current == NULL) {
746
p->current = find_function_from_pc(p->i);
748
if (p->current == NULL) {
751
tmp = TUPLE3(hp, p->current[0], p->current[1], make_small(p->current[2]));
755
if (IS_TRACED_FL(p, F_TRACE_SCHED_NO)) {
757
if (p->scheduler_data) sched_id = make_small(p->scheduler_data->no);
758
else sched_id = make_small(am_undefined);
760
sched_id = make_small(1);
762
mess = TUPLE5(hp, am_trace,p->id/* Local pid */, what, sched_id, tmp);
765
mess = TUPLE4(hp, am_trace, p->id, what, tmp);
770
erts_smp_mtx_lock(&smq_mtx);
772
if (p->trace_flags & F_TIMESTAMP) {
773
hp = patch_ts(mess, hp);
776
ERTS_ENQ_TRACE_MSG(p->id, tracer_ref, mess, bp);
777
erts_smp_mtx_unlock(&smq_mtx);
806
trace_sched_aux(p, what, 0);
782
809
/* Send {trace_ts, Pid, Send, Msg, DestPid, Timestamp}
783
810
* or {trace, Pid, Send, Msg, DestPid}
1521
* Because of the delayed sub-binary creation optimization introduced in
1522
* R12B, (at most) one of arguments can be a match context instead of
1523
* a binary. Since we don't want to handle match contexts in utility functions
1524
* such as size_object() and copy_struct(), we must make sure that we
1525
* temporarily convert any match contexts to sub binaries.
1529
sub_bin_heap.thing_word = 0;
1531
for (i = 0; i < arity; i++) {
1532
Eterm arg = args[i];
1533
if (is_boxed(arg) && header_is_bin_matchstate(*boxed_val(arg))) {
1534
ErlBinMatchState* ms = (ErlBinMatchState *) boxed_val(arg);
1535
ErlBinMatchBuffer* mb = &ms->mb;
1536
ErlSubBin* sb = &sub_bin_heap;
1539
ASSERT(sub_bin_heap.thing_word == 0); /* At most one of match context */
1541
bit_size = mb->size - mb->offset;
1542
sb->thing_word = HEADER_SUB_BIN;
1543
sb->size = BYTE_OFFSET(bit_size);
1544
sb->bitsize = BIT_OFFSET(bit_size);
1545
sb->offs = BYTE_OFFSET(mb->offset);
1546
sb->bitoffs = BIT_OFFSET(mb->offset);
1547
sb->is_writable = 0;
1548
sb->orig = mb->orig;
1550
arg = make_binary(sb);
1552
transformed_args[i] = arg;
1554
args = transformed_args;
1491
1556
if (is_internal_port(*tracer_pid)) {
1492
1557
Eterm local_heap[64+MAX_ARG];
1493
1558
hp = local_heap;
2442
void trace_virtual_sched(Process *p, Eterm what) {
2446
Eterm sched_id = am_undefined;
2449
if (is_internal_port(p->tracer_proc)) {
2450
Eterm local_heap[4+5+6];
2453
if (p->current == NULL) {
2454
p->current = find_function_from_pc(p->i);
2456
if (p->current == NULL) {
2457
tmp = make_small(0);
2459
tmp = TUPLE3(hp, p->current[0], p->current[1], make_small(p->current[2]));
2463
if (IS_TRACED_FL(p, F_TRACE_SCHED_NO)) {
2465
if (p->scheduler_data) sched_id = make_small(p->scheduler_data->no);
2466
else sched_id = am_undefined;
2468
sched_id = make_small(1);
2470
mess = TUPLE5(hp, am_trace, p->id, what, sched_id, tmp);
2473
mess = TUPLE4(hp, am_trace, p->id, what, tmp);
2479
erts_smp_mtx_lock(&smq_mtx);
2480
if (p->trace_flags & F_TIMESTAMP) {
2481
hp = patch_ts(mess, hp);
2483
send_to_port(NULL, mess, &p->tracer_proc, &p->trace_flags);
2484
erts_smp_mtx_unlock(&smq_mtx);
2486
ErlHeapFragment *bp;
2487
ErlOffHeap *off_heap;
2488
ERTS_TRACER_REF_TYPE tracer_ref;
2489
ASSERT(is_internal_pid(p->tracer_proc)
2490
&& internal_pid_index(p->tracer_proc) < erts_max_processes);
2492
if (IS_TRACED_FL(p, F_TRACE_SCHED_NO)) ws_id = 6; /* Make place for scheduler id */
2494
ERTS_GET_TRACER_REF(tracer_ref, p->tracer_proc, p->trace_flags);
2496
hp = ERTS_ALLOC_SYSMSG_HEAP(ws_id + 4 + TS_SIZE(p),
2501
if (p->current == NULL) {
2502
p->current = find_function_from_pc(p->i);
2504
if (p->current == NULL) {
2505
tmp = make_small(0);
2507
tmp = TUPLE3(hp, p->current[0], p->current[1], make_small(p->current[2]));
2511
if (IS_TRACED_FL(p, F_TRACE_SCHED_NO)) {
2513
if (p->scheduler_data) sched_id = make_small(p->scheduler_data->no);
2514
else sched_id = am_undefined;
2516
sched_id = make_small(1);
2518
mess = TUPLE5(hp, am_trace,p->id/* Local pid */, what, sched_id, tmp);
2520
mess = TUPLE4(hp, am_trace, p->id, what, tmp);
2525
erts_smp_mtx_lock(&smq_mtx);
2527
if (p->trace_flags & F_TIMESTAMP) {
2528
hp = patch_ts(mess, hp);
2531
ERTS_ENQ_TRACE_MSG(p->id, tracer_ref, mess, bp);
2532
erts_smp_mtx_unlock(&smq_mtx);
2505
void trace_virtual_sched(Process *p, Eterm what)
2507
trace_sched_aux(p, what, 1);
2536
2510
/* Port profiling */