1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2012-2018. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 
21 #ifndef ERL_TRACE_H__FLAGS__
22 #define ERL_TRACE_H__FLAGS__
23 /*
24  * NOTE! The bits used for these flags matter. The flag with
25  * the least significant bit will take precedence!
26  *
27  * The "now timestamp" has highest precedence due to
28  * compatibility reasons.
29  */
30 #define ERTS_TRACE_FLG_NOW_TIMESTAMP			(1 << 0)
31 #define ERTS_TRACE_FLG_STRICT_MONOTONIC_TIMESTAMP	(1 << 1)
32 #define ERTS_TRACE_FLG_MONOTONIC_TIMESTAMP		(1 << 2)
33 
34 /*
35  * The bits used effects trace flags (of processes and ports)
36  * as well as sequential trace flags. If changed make sure
37  * these arn't messed up...
38  */
39 #define ERTS_TRACE_TS_TYPE_BITS 			3
40 #define ERTS_TRACE_TS_TYPE_MASK					\
41     ((1 << ERTS_TRACE_TS_TYPE_BITS) - 1)
42 
43 #define ERTS_TFLGS2TSTYPE(TFLGS)				\
44     ((int) (((TFLGS) >> ERTS_TRACE_FLAGS_TS_TYPE_SHIFT) 	\
45 	    & ERTS_TRACE_TS_TYPE_MASK))
46 #define ERTS_SEQTFLGS2TSTYPE(SEQTFLGS)				\
47     ((int) (((SEQTFLGS) >> ERTS_SEQ_TRACE_FLAGS_TS_TYPE_SHIFT)	\
48 	    & ERTS_TRACE_TS_TYPE_MASK))
49 #define ERTS_SEQTFLGS2TFLGS(SEQTFLGS)                                   \
50     (ERTS_SEQTFLGS2TSTYPE(SEQTFLGS) << ERTS_TRACE_FLAGS_TS_TYPE_SHIFT)
51 
52 #endif /* ERL_TRACE_H__FLAGS__ */
53 
54 #if !defined(ERL_TRACE_H__) && !defined(ERTS_ONLY_INCLUDE_TRACE_FLAGS)
55 #define ERL_TRACE_H__
56 
57 struct binary;
58 
59 typedef struct
60 {
61     int on;
62     struct binary* match_spec;
63 } ErtsTracingEvent;
64 
65 extern ErtsTracingEvent erts_send_tracing[];
66 extern ErtsTracingEvent erts_receive_tracing[];
67 
68 /* erl_bif_trace.c */
69 Eterm erl_seq_trace_info(Process *p, Eterm arg1);
70 void erts_system_monitor_clear(Process *c_p);
71 void erts_system_profile_clear(Process *c_p);
72 
73 /* erl_trace.c */
74 void erts_init_trace(void);
75 void erts_trace_check_exiting(Eterm exiting);
76 ErtsTracer erts_set_system_seq_tracer(Process *c_p,
77                                       ErtsProcLocks c_p_locks,
78                                       ErtsTracer new);
79 ErtsTracer erts_get_system_seq_tracer(void);
80 void erts_change_default_proc_tracing(int setflags, Uint flagsp,
81                                       const ErtsTracer tracerp);
82 void erts_get_default_proc_tracing(Uint *flagsp, ErtsTracer *tracerp);
83 void erts_change_default_port_tracing(int setflags, Uint flagsp,
84                                       const ErtsTracer tracerp);
85 void erts_get_default_port_tracing(Uint *flagsp, ErtsTracer *tracerp);
86 void erts_set_system_monitor(Eterm monitor);
87 Eterm erts_get_system_monitor(void);
88 int erts_is_tracer_valid(Process* p);
89 
90 void erts_check_my_tracer_proc(Process *);
91 void erts_block_sys_msg_dispatcher(void);
92 void erts_release_sys_msg_dispatcher(void);
93 void erts_debug_foreach_sys_msg_in_q(void (*func)(Eterm,
94                                                   Eterm,
95                                                   Eterm,
96                                                   ErlHeapFragment *));
97 Eterm erts_set_system_logger(Eterm);
98 Eterm erts_get_system_logger(void);
99 void erts_queue_error_logger_message(Eterm, Eterm, ErlHeapFragment *);
100 void erts_send_sys_msg_proc(Eterm, Eterm, Eterm, ErlHeapFragment *);
101 
102 void trace_send(Process*, Eterm, Eterm);
103 void trace_receive(Process*, Eterm, Eterm, ErtsTracingEvent*);
104 Uint32 erts_call_trace(Process *p, ErtsCodeInfo *info, struct binary *match_spec,
105                        Eterm* args, int local, ErtsTracer *tracer);
106 void erts_trace_return(Process* p, ErtsCodeMFA *mfa, Eterm retval,
107                        ErtsTracer *tracer);
108 void erts_trace_exception(Process* p, ErtsCodeMFA *mfa, Eterm class, Eterm value,
109                           ErtsTracer *tracer);
110 void erts_trace_return_to(Process *p, BeamInstr *pc);
111 void trace_sched(Process*, ErtsProcLocks, Eterm);
112 void trace_proc(Process*, ErtsProcLocks, Process*, Eterm, Eterm);
113 void trace_proc_spawn(Process*, Eterm what, Eterm pid, Eterm mod, Eterm func, Eterm args);
114 void save_calls(Process *p, Export *);
115 void trace_gc(Process *p, Eterm what, Uint size, Eterm msg);
116 /* port tracing */
117 void trace_virtual_sched(Process*, ErtsProcLocks, Eterm);
118 void trace_sched_ports(Port *pp, Eterm);
119 void trace_sched_ports_where(Port *pp, Eterm, Eterm);
120 void trace_port(Port *, Eterm what, Eterm data);
121 void trace_port_open(Port *, Eterm calling_pid, Eterm drv_name);
122 void trace_port_receive(Port *, Eterm calling_pid, Eterm tag, ...);
123 void trace_port_send(Port *, Eterm to, Eterm msg, int exists);
124 void trace_port_send_binary(Port *, Eterm to, Eterm what, char *bin, Sint sz);
125 
126 /* system_profile */
127 void erts_set_system_profile(Eterm profile);
128 Eterm erts_get_system_profile(void);
129 void profile_scheduler(Eterm scheduler_id, Eterm);
130 void profile_scheduler_q(Eterm scheduler_id, Eterm state, Eterm no_schedulers, Uint Ms, Uint s, Uint us);
131 void profile_runnable_proc(Process* p, Eterm status);
132 void profile_runnable_port(Port* p, Eterm status);
133 void erts_system_profile_setup_active_schedulers(void);
134 
135 /* system_monitor */
136 void monitor_long_gc(Process *p, Uint time);
137 void monitor_long_schedule_proc(Process *p, ErtsCodeMFA *in_i,
138                                 ErtsCodeMFA *out_i, Uint time);
139 void monitor_long_schedule_port(Port *pp, ErtsPortTaskType type, Uint time);
140 void monitor_large_heap(Process *p);
141 void monitor_generic(Process *p, Eterm type, Eterm spec);
142 Uint erts_trace_flag2bit(Eterm flag);
143 int erts_trace_flags(Eterm List,
144 		 Uint *pMask, ErtsTracer *pTracer, int *pCpuTimestamp);
145 Eterm erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr *I);
146 Eterm
147 erts_bif_trace_epilogue(Process *p, Eterm result, int applying,
148 			Export* ep, BeamInstr *cp, Uint32 flags,
149 			Uint32 flags_meta, BeamInstr* I,
150 			ErtsTracer meta_tracer);
151 
152 void erts_send_pending_trace_msgs(ErtsSchedulerData *esdp);
153 #define ERTS_CHK_PEND_TRACE_MSGS(ESDP)				\
154 do {									\
155     if ((ESDP)->pending_trace_msgs)					\
156 	erts_send_pending_trace_msgs((ESDP));				\
157 } while (0)
158 
159 #define seq_trace_output(token, msg, type, receiver, process) \
160 seq_trace_output_generic((token), (msg), (type), (receiver), (process), NIL)
161 #define seq_trace_output_exit(token, msg, type, receiver, exitfrom) \
162 seq_trace_output_generic((token), (msg), (type), (receiver), NULL, (exitfrom))
163 void seq_trace_output_generic(Eterm token, Eterm msg, Uint type,
164 			      Eterm receiver, Process *process, Eterm exitfrom);
165 
166 int seq_trace_update_send(Process *process);
167 
168 Eterm erts_seq_trace(Process *process,
169 		     Eterm atom_type, Eterm atom_true_or_false,
170 		     int build_result);
171 
172 struct trace_pattern_flags {
173     unsigned int breakpoint : 1; /* Set if any other is set */
174     unsigned int local      : 1; /* Local call trace breakpoint */
175     unsigned int meta       : 1; /* Metadata trace breakpoint */
176     unsigned int call_count : 1; /* Fast call count breakpoint */
177     unsigned int call_time  : 1; /* Fast call time breakpoint */
178 };
179 extern const struct trace_pattern_flags erts_trace_pattern_flags_off;
180 extern int erts_call_time_breakpoint_tracing;
181 int erts_set_trace_pattern(Process*p, ErtsCodeMFA *mfa, int specified,
182 			   struct binary* match_prog_set,
183 			   struct binary *meta_match_prog_set,
184 			   int on, struct trace_pattern_flags,
185 			   ErtsTracer meta_tracer, int is_blocking);
186 void
187 erts_get_default_trace_pattern(int *trace_pattern_is_on,
188 			       struct binary **match_spec,
189 			       struct binary **meta_match_spec,
190 			       struct trace_pattern_flags *trace_pattern_flags,
191 			       ErtsTracer *meta_tracer);
192 int erts_is_default_trace_enabled(void);
193 void erts_bif_trace_init(void);
194 int erts_finish_breakpointing(void);
195 
196 /* Nif tracer functions */
197 int erts_is_tracer_proc_enabled(Process *c_p, ErtsProcLocks c_p_locks,
198                                 ErtsPTabElementCommon *t_p);
199 int erts_is_tracer_proc_enabled_send(Process* c_p, ErtsProcLocks c_p_locks,
200                                      ErtsPTabElementCommon *t_p);
201 int erts_is_tracer_enabled(const ErtsTracer tracer, ErtsPTabElementCommon *t_p);
202 Eterm erts_tracer_to_term(Process *p, ErtsTracer tracer);
203 Eterm erts_build_tracer_to_term(Eterm **hpp, ErlOffHeap *ohp, Uint *szp, ErtsTracer tracer);
204 
205 ErtsTracer erts_term_to_tracer(Eterm prefix, Eterm term);
206 void erts_tracer_replace(ErtsPTabElementCommon *t_p,
207                          const ErtsTracer new_tracer);
208 void erts_tracer_update(ErtsTracer *tracer, const ErtsTracer new_tracer);
209 int erts_tracer_nif_clear(void);
210 
211 #define erts_tracer_update(t,n) do { if (*(t) != (n)) erts_tracer_update(t,n); } while(0)
212 #define ERTS_TRACER_CLEAR(t) erts_tracer_update(t, erts_tracer_nil)
213 
214 static const ErtsTracer
215 ERTS_DECLARE_DUMMY(erts_tracer_true) = am_true;
216 
217 static const ErtsTracer
218 ERTS_DECLARE_DUMMY(erts_tracer_nil) = NIL;
219 
220 #define ERTS_TRACER_COMPARE(t1, t2)                     \
221     (EQ((t1), (t2)))
222 
223 #define ERTS_TRACER_IS_NIL(t1) ERTS_TRACER_COMPARE(t1, erts_tracer_nil)
224 
225 #define IS_TRACER_VALID(tracer)                                         \
226     (ERTS_TRACER_COMPARE(tracer,erts_tracer_true)                       \
227      || ERTS_TRACER_IS_NIL(tracer)                                      \
228      || (is_list(tracer) && is_atom(CAR(list_val(tracer)))))
229 
230 #define ERTS_TRACER_FROM_ETERM(termp) \
231     ((ErtsTracer*)(termp))
232 
233 #endif /* ERL_TRACE_H__ */
234