⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 erl_trace.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 5 页
字号:
#define TS_SIZE(p) (((p)->trace_flags & F_TIMESTAMP) ? 5 : 0)/* * Patch a timestamp into a tuple.  The tuple must be the last thing * built on the heap. * * Returns the new hp pointer.*/static Eterm*patch_ts(Eterm tuple, Eterm* hp){    Uint ms, s, us;    Eterm* ptr = tuple_val(tuple);    int arity = arityval(*ptr);    ASSERT((ptr+arity+1) == hp);    ptr[0] = make_arityval(arity+1);    ptr[1] = am_trace_ts;    GET_NOW(&ms, &s, &us);    *hp = TUPLE3(hp+1, make_small(ms), make_small(s), make_small(us));    return hp+5;}/* Send {trace_ts, Pid, What, {Mod, Func, Arity}, Timestamp} * or   {trace, Pid, What, {Mod, Func, Arity}} * * where 'What' is supposed to be 'in' or 'out'. */voidtrace_sched(Process *p, Eterm what){    Eterm tmp;    Eterm mess;    Eterm* hp;    if (is_internal_port(p->tracer_proc)) {	Eterm local_heap[4+5+5];	hp = local_heap;	if (p->current == NULL) {	    p->current = find_function_from_pc(p->i);	}	if (p->current == NULL) {	    tmp = make_small(0);	} else {	    tmp = TUPLE3(hp, p->current[0], p->current[1], make_small(p->current[2]));	    hp += 4;	}	mess = TUPLE4(hp, am_trace, p->id, what, tmp);	hp += 5;	erts_smp_mtx_lock(&smq_mtx);	if (p->trace_flags & F_TIMESTAMP) {	    hp = patch_ts(mess, hp);	}	if (what != am_out) {	    send_to_port(p, mess, &p->tracer_proc, &p->trace_flags);	} else {	    send_to_port(NULL, mess, &p->tracer_proc, &p->trace_flags);	}	erts_smp_mtx_unlock(&smq_mtx);    } else {	ErlHeapFragment *bp;	ErlOffHeap *off_heap;#ifndef ERTS_SMP	Process *tracer;#endif	ASSERT(is_internal_pid(p->tracer_proc)	       && internal_pid_index(p->tracer_proc) < erts_max_processes);#ifdef ERTS_SMP	bp = new_message_buffer(9 + TS_SIZE(p));	hp = bp->mem;	off_heap = &bp->off_heap;#else	tracer = process_tab[internal_pid_index(p->tracer_proc)];	if (INVALID_PID(tracer, p->tracer_proc) 	    || (tracer->trace_flags & F_TRACER) == 0) {	    p->trace_flags &= ~TRACEE_FLAGS;	    p->tracer_proc = NIL;	    return;	}	hp = erts_alloc_message_heap(9 + TS_SIZE(p), &bp, &off_heap, tracer, 0);#endif		if (p->current == NULL) {	    p->current = find_function_from_pc(p->i);	}	if (p->current == NULL) {	    tmp = make_small(0);	} else {	    tmp = TUPLE3(hp, p->current[0], p->current[1], make_small(p->current[2]));	    hp += 4;	}	mess = TUPLE4(hp, am_trace,p->id/* Local pid */, what, tmp);	hp += 5;	erts_smp_mtx_lock(&smq_mtx);	if (p->trace_flags & F_TIMESTAMP) {	    hp = patch_ts(mess, hp);	}#ifdef ERTS_SMP	enqueue_sys_msg_unlocked(SYS_MSG_TYPE_TRACE,				 p->id, p->tracer_proc, mess, bp);	erts_smp_mtx_unlock(&smq_mtx);#else	erts_queue_message(tracer, 0, bp, mess, NIL);#endif    }}/* Send {trace_ts, Pid, Send, Msg, DestPid, Timestamp} * or   {trace, Pid, Send, Msg, DestPid} * * where 'Send' is 'send' or 'send_to_non_existing_process'. */voidtrace_send(Process *p, Eterm to, Eterm msg){    Eterm operation;    unsigned sz_msg;    unsigned sz_to;    Eterm* hp;    Eterm mess;        if (!ARE_TRACE_FLAGS_ON(p, F_TRACE_SEND)) {	return;    }    operation = am_send;    if (is_internal_pid(to)) {	if (!erts_pid2proc(p, ERTS_PROC_LOCK_MAIN, to, 0))	    goto send_to_non_existing_process;    }    else if(is_external_pid(to)	    && external_pid_dist_entry(to) == erts_this_dist_entry) {	char *s;    send_to_non_existing_process:	s = "send_to_non_existing_process";	operation = am_atom_put(s, sys_strlen(s));    }    if (is_internal_port(p->tracer_proc)) {	Eterm local_heap[11];	hp = local_heap;	mess = TUPLE5(hp, am_trace, p->id, operation, msg, to);	hp += 6;	erts_smp_mtx_lock(&smq_mtx);	if (p->trace_flags & F_TIMESTAMP) {	    hp = patch_ts(mess, hp);	}	send_to_port(p, mess, &p->tracer_proc, &p->trace_flags);	erts_smp_mtx_unlock(&smq_mtx);    } else {	Uint need;	ErlHeapFragment *bp;	ErlOffHeap *off_heap;#ifndef ERTS_SMP	Process *tracer;#endif	ASSERT(is_internal_pid(p->tracer_proc)	       && internal_pid_index(p->tracer_proc) < erts_max_processes);#ifndef ERTS_SMP	tracer = process_tab[internal_pid_index(p->tracer_proc)];	if (INVALID_PID(tracer, p->tracer_proc)	    || (tracer->trace_flags & F_TRACER) == 0) {	    p->trace_flags &= ~TRACEE_FLAGS;	    p->tracer_proc = NIL;	    return;	}#endif	sz_msg = size_object(msg);	sz_to  = size_object(to);	need = sz_msg + sz_to + 6 + TS_SIZE(p);	#ifdef ERTS_SMP	bp = new_message_buffer(need);	hp = bp->mem;	off_heap = &bp->off_heap;#else	hp = erts_alloc_message_heap(need, &bp, &off_heap, tracer, 0);#endif	to = copy_struct(to,			 sz_to,			 &hp,			 off_heap);	msg = copy_struct(msg,			  sz_msg,			  &hp,			  off_heap);	mess = TUPLE5(hp, am_trace, p->id/* Local pid */, operation, msg, to);	hp += 6;	erts_smp_mtx_lock(&smq_mtx);	if (p->trace_flags & F_TIMESTAMP) {	    patch_ts(mess, hp);	}#ifdef ERTS_SMP	enqueue_sys_msg_unlocked(SYS_MSG_TYPE_TRACE, p->id, p->tracer_proc, mess, bp);	erts_smp_mtx_unlock(&smq_mtx);#else	erts_queue_message(tracer, 0, bp, mess, NIL);#endif    }}/* Send {trace_ts, Pid, receive, Msg, Timestamp} * or   {trace, Pid, receive, Msg} */voidtrace_receive(Process *rp, Eterm msg){    Eterm mess;    size_t sz_msg;    Eterm* hp;    if (is_internal_port(rp->tracer_proc)) {	Eterm local_heap[10];	hp = local_heap;	mess = TUPLE4(hp, am_trace, rp->id, am_receive, msg);	hp += 5;	erts_smp_mtx_lock(&smq_mtx);	if (rp->trace_flags & F_TIMESTAMP) {	    hp = patch_ts(mess, hp);	}	send_to_port(rp, mess, &rp->tracer_proc, &rp->trace_flags);	erts_smp_mtx_unlock(&smq_mtx);    } else {	Uint hsz;	ErlHeapFragment *bp;	ErlOffHeap *off_heap;#ifndef ERTS_SMP	Process *tracer;#endif	ASSERT(is_internal_pid(rp->tracer_proc)	       && internal_pid_index(rp->tracer_proc) < erts_max_processes);#ifndef ERTS_SMP	tracer = process_tab[internal_pid_index(rp->tracer_proc)];	if (INVALID_PID(tracer, rp->tracer_proc)	    || (tracer->trace_flags & F_TRACER) == 0) {	    rp->trace_flags &= ~TRACEE_FLAGS;	    rp->tracer_proc = NIL;	    return;	}#endif	sz_msg = size_object(msg);	hsz = sz_msg + 5 + TS_SIZE(rp);#ifdef ERTS_SMP	bp = new_message_buffer(hsz);	hp = bp->mem;	off_heap = &bp->off_heap;#else	hp = erts_alloc_message_heap(hsz, &bp, &off_heap, tracer, 0);#endif	msg = copy_struct(msg, sz_msg, &hp, off_heap);	mess = TUPLE4(hp, am_trace, rp->id/* Local pid */, am_receive, msg);	hp += 5;	erts_smp_mtx_lock(&smq_mtx);	if (rp->trace_flags & F_TIMESTAMP) {	    patch_ts(mess, hp);	}#ifdef ERTS_SMP	enqueue_sys_msg_unlocked(SYS_MSG_TYPE_TRACE,				   rp->id, rp->tracer_proc, mess, bp);	erts_smp_mtx_unlock(&smq_mtx);#else	erts_queue_message(tracer, 0, bp, mess, NIL);#endif    }}intseq_trace_update_send(Process *p){    Eterm seq_tracer = erts_get_system_seq_tracer();    ASSERT((is_tuple(SEQ_TRACE_TOKEN(p)) || is_nil(SEQ_TRACE_TOKEN(p))));    if ( (p->id == seq_tracer) || (SEQ_TRACE_TOKEN(p) == NIL))	return 0;    SEQ_TRACE_TOKEN_SENDER(p) = p->id; /* Internal pid */    SEQ_TRACE_TOKEN_SERIAL(p) = 	make_small(++(p -> seq_trace_clock));    SEQ_TRACE_TOKEN_LASTCNT(p) = 	make_small(p -> seq_trace_lastcnt);    return 1;}/* Send a sequential trace message to the sequential tracer. * p is the caller (which contains the trace token),  * msg is the original message, type is trace type (SEQ_TRACE_SEND etc), * and receiver is the receiver of the message. * * The message to be received by the sequential tracer is: *  *    TraceMsg =  *   {seq_trace, Label, {Type, {Lastcnt, Serial}, Sender, Receiver, Msg} [,Timestamp] } * */void seq_trace_output_generic(Eterm token, Eterm msg, Uint type,			 Eterm receiver, Process *process, Eterm exitfrom){    Eterm mess;    ErlHeapFragment* bp;    Eterm* hp;    Eterm label;    Eterm lastcnt_serial;    Eterm type_atom;    int sz_exit;    Eterm seq_tracer;    seq_tracer = erts_get_system_seq_tracer();    ASSERT(is_tuple(token) || is_nil(token));    if (SEQ_TRACE_T_SENDER(token) == seq_tracer || token == NIL ||	(process && process->trace_flags & F_SENSITIVE)) {	return;    }    switch (type) {    case SEQ_TRACE_SEND:    type_atom = am_send; break;    case SEQ_TRACE_PRINT:   type_atom = am_print; break;    case SEQ_TRACE_RECEIVE: type_atom = am_receive; break;    default:	erl_exit(1, "invalid type in seq_trace_output_generic: %d:\n", type);	return;			/* To avoid warning */    }    if ((unsigned_val(SEQ_TRACE_T_FLAGS(token)) & type) == 0) {	/* No flags set, nothing to do */	return;    }    if (seq_tracer == am_false) {	return;			/* no need to send anything */    }    if (is_internal_port(seq_tracer)) {	Eterm local_heap[64];	hp = local_heap;	label = SEQ_TRACE_T_LABEL(token);	lastcnt_serial = TUPLE2(hp, SEQ_TRACE_T_LASTCNT(token),				SEQ_TRACE_T_SERIAL(token));	hp += 3;	if (exitfrom != NIL) {	    msg = TUPLE3(hp, am_EXIT, exitfrom, msg);	    hp += 4;	}	mess = TUPLE5(hp, type_atom, lastcnt_serial, SEQ_TRACE_T_SENDER(token),		      receiver, msg);	hp += 6;	erts_smp_mtx_lock(&smq_mtx);	if ((unsigned_val(SEQ_TRACE_T_FLAGS(token)) & SEQ_TRACE_TIMESTAMP) == 0) {	    mess = TUPLE3(hp, am_seq_trace, label, mess);	    seq_trace_send_to_port(NULL, seq_tracer, mess, NIL);	} else {	    Uint ms,s,us,ts;	    GET_NOW(&ms, &s, &us);	    ts = TUPLE3(hp, make_small(ms),make_small(s), make_small(us));	    hp += 4;	    mess = TUPLE4(hp, am_seq_trace, label, mess, ts);	    seq_trace_send_to_port(process, seq_tracer, mess, ts);	}	erts_smp_mtx_unlock(&smq_mtx);    } else {#ifndef ERTS_SMP	Process* tracer;#endif	Eterm sender_copy;	Eterm receiver_copy;	Eterm m2;	Uint sz_label, sz_lastcnt_serial, sz_msg, sz_ts, sz_sender,	    sz_exitfrom, sz_receiver;	ASSERT(is_internal_pid(seq_tracer)	       && internal_pid_index(seq_tracer) < erts_max_processes);#ifndef ERTS_SMP	tracer = process_tab[internal_pid_index(seq_tracer)];	if (INVALID_PID(tracer, tracer->id)) {	    system_seq_tracer = am_false;	    return; /* no need to send anything */	}#endif	if (receiver == seq_tracer) {	    return; /* no need to send anything */	}	sz_label = size_object(SEQ_TRACE_T_LABEL(token));	sz_sender = size_object(SEQ_TRACE_T_SENDER(token));	sz_receiver = size_object(receiver);	sz_lastcnt_serial = 3; /* TUPLE2 */	sz_msg = size_object(msg);	sz_ts = ((unsigned_val(SEQ_TRACE_T_FLAGS(token)) & SEQ_TRACE_TIMESTAMP) ? 		 5 : 0);	if (exitfrom != NIL) {	    sz_exit = 4; /* create {'EXIT',exitfrom,msg} */	    sz_exitfrom = size_object(exitfrom);	}	else {	    sz_exit = 0;	    sz_exitfrom = 0;	}	bp = new_message_buffer(4 /* TUPLE3 */ + sz_ts + 6 /* TUPLE5 */ 				+ sz_lastcnt_serial + sz_label + sz_msg				+ sz_exit + sz_exitfrom				+ sz_sender + sz_receiver);	hp = bp->mem;	label = copy_struct(SEQ_TRACE_T_LABEL(token), sz_label, &hp, &bp->off_heap);	lastcnt_serial = TUPLE2(hp,SEQ_TRACE_T_LASTCNT(token),SEQ_TRACE_T_SERIAL(token));	hp += 3;	m2 = copy_struct(msg, sz_msg, &hp, &bp->off_heap);	if (sz_exit) {	    Eterm exitfrom_copy = copy_struct(exitfrom,					      sz_exitfrom,					      &hp,					      &bp->off_heap);	    m2 = TUPLE3(hp, am_EXIT, exitfrom_copy, m2);	    hp += 4;	}	sender_copy = copy_struct(SEQ_TRACE_T_SENDER(token),				  sz_sender,				  &hp,				  &bp->off_heap);	receiver_copy = copy_struct(receiver,				    sz_receiver,				    &hp,				    &bp->off_heap);	mess = TUPLE5(hp,		      type_atom,		      lastcnt_serial,		      sender_copy,		      receiver_copy,		      m2);	hp += 6;	erts_smp_mtx_lock(&smq_mtx);	if (sz_ts) {/* timestamp should be included */	    Uint ms,s,us,ts;	    GET_NOW(&ms, &s, &us);	    ts = TUPLE3(hp, make_small(ms),make_small(s), make_small(us));	    hp += 4;	    mess = TUPLE4(hp, am_seq_trace, label, mess, ts);	} else {	    mess = TUPLE3(hp, am_seq_trace, label, mess);	}#ifdef ERTS_SMP	enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SEQTRACE, NIL, NIL, mess, bp);	erts_smp_mtx_unlock(&smq_mtx);#else	erts_queue_message(tracer, 0, bp, mess, NIL); /* trace_token must be NIL here */#endif    }}/* Send {trace_ts, Pid, return_to, {Mod, Func, Arity}, Timestamp} * or   {trace, Pid, return_to, {Mod, Func, Arity}} */void erts_trace_return_to(Process *p, Uint *pc){    Eterm* hp;    Eterm mfa;    Eterm mess;    Eterm local_heap[4+5+5];    Eterm *code_ptr = find_function_from_pc(pc);    hp = local_heap;    if (!code_ptr) {	mfa = am_undefined;    } else {	mfa = TUPLE3(hp, code_ptr[0], code_ptr[1], make_small(code_ptr[2]));	hp += 4;    }	    mess = TUPLE4(hp, am_trace, p->id, am_return_to, mfa);    hp += 5;    erts_smp_mtx_lock(&smq_mtx);    if (p->trace_flags & F_TIMESTAMP) {	hp = patch_ts(mess, hp);    }    if (is_internal_port(p->tracer_proc)) {	send_to_port(p, mess, &p->tracer_proc, &p->trace_flags);    } else {	ErlHeapFragment *bp;	ErlOffHeap *off_heap;#ifndef ERTS_SMP	Process *tracer;#endif	unsigned size;	/*	 * Find the tracer.	 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -