summaryrefslogtreecommitdiff
path: root/erts/emulator/beam/erl_trace.h
blob: f564549ab9fc632babdf9ec24306f281521a1f32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*
 * %CopyrightBegin%
 *
 * Copyright Ericsson AB 2012-2018. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * %CopyrightEnd%
 */

#ifndef ERL_TRACE_H__FLAGS__
#define ERL_TRACE_H__FLAGS__
/*
 * NOTE! The bits used for these flags matter. The flag with
 * the least significant bit will take precedence!
 *
 * The "now timestamp" has highest precedence due to
 * compatibility reasons.
 */
#define ERTS_TRACE_FLG_NOW_TIMESTAMP			(1 << 0)
#define ERTS_TRACE_FLG_STRICT_MONOTONIC_TIMESTAMP	(1 << 1)
#define ERTS_TRACE_FLG_MONOTONIC_TIMESTAMP		(1 << 2)

/*
 * The bits used effects trace flags (of processes and ports)
 * as well as sequential trace flags. If changed make sure
 * these arn't messed up...
 */
#define ERTS_TRACE_TS_TYPE_BITS 			3
#define ERTS_TRACE_TS_TYPE_MASK					\
    ((1 << ERTS_TRACE_TS_TYPE_BITS) - 1)

#define ERTS_TFLGS2TSTYPE(TFLGS)				\
    ((int) (((TFLGS) >> ERTS_TRACE_FLAGS_TS_TYPE_SHIFT) 	\
	    & ERTS_TRACE_TS_TYPE_MASK))
#define ERTS_SEQTFLGS2TSTYPE(SEQTFLGS)				\
    ((int) (((SEQTFLGS) >> ERTS_SEQ_TRACE_FLAGS_TS_TYPE_SHIFT)	\
	    & ERTS_TRACE_TS_TYPE_MASK))
#define ERTS_SEQTFLGS2TFLGS(SEQTFLGS)                                   \
    (ERTS_SEQTFLGS2TSTYPE(SEQTFLGS) << ERTS_TRACE_FLAGS_TS_TYPE_SHIFT)

#endif /* ERL_TRACE_H__FLAGS__ */

#if !defined(ERL_TRACE_H__) && !defined(ERTS_ONLY_INCLUDE_TRACE_FLAGS)
#define ERL_TRACE_H__

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);
void erts_system_profile_clear(Process *c_p);

/* erl_trace.c */
void erts_init_trace(void);
void erts_trace_check_exiting(Eterm exiting);
ErtsTracer erts_set_system_seq_tracer(Process *c_p,
                                      ErtsProcLocks c_p_locks,
                                      ErtsTracer new);
ErtsTracer erts_get_system_seq_tracer(void);
void erts_change_default_proc_tracing(int setflags, Uint flagsp,
                                      const ErtsTracer tracerp);
void erts_get_default_proc_tracing(Uint *flagsp, ErtsTracer *tracerp);
void erts_change_default_port_tracing(int setflags, Uint flagsp,
                                      const ErtsTracer tracerp);
void erts_get_default_port_tracing(Uint *flagsp, ErtsTracer *tracerp);
void erts_set_system_monitor(Eterm monitor);
Eterm erts_get_system_monitor(void);
int erts_is_tracer_valid(Process* p);

void erts_check_my_tracer_proc(Process *);
void erts_block_sys_msg_dispatcher(void);
void erts_release_sys_msg_dispatcher(void);
void erts_debug_foreach_sys_msg_in_q(void (*func)(Eterm,
                                                  Eterm,
                                                  Eterm,
                                                  ErlHeapFragment *));
Eterm erts_set_system_logger(Eterm);
Eterm erts_get_system_logger(void);
void erts_queue_error_logger_message(Eterm, Eterm, ErlHeapFragment *);
void erts_send_sys_msg_proc(Eterm, Eterm, Eterm, ErlHeapFragment *);

void trace_send(Process*, Eterm, Eterm);
void trace_receive(Process*, Eterm, Eterm, ErtsTracingEvent*);
Uint32 erts_call_trace(Process *p, ErtsCodeInfo *info, struct binary *match_spec,
                       Eterm* args, int local, ErtsTracer *tracer);
void erts_trace_return(Process* p, ErtsCodeMFA *mfa, Eterm retval,
                       ErtsTracer *tracer);
void erts_trace_exception(Process* p, ErtsCodeMFA *mfa, Eterm class, Eterm value,
                          ErtsTracer *tracer);
void erts_trace_return_to(Process *p, BeamInstr *pc);
void trace_sched(Process*, ErtsProcLocks, Eterm);
void trace_proc(Process*, ErtsProcLocks, Process*, Eterm, Eterm);
void trace_proc_spawn(Process*, Eterm what, Eterm pid, Eterm mod, Eterm func, Eterm args);
void save_calls(Process *p, Export *);
void trace_gc(Process *p, Eterm what, Uint size, Eterm msg);
/* port tracing */
void trace_virtual_sched(Process*, ErtsProcLocks, Eterm);
void trace_sched_ports(Port *pp, Eterm);
void trace_sched_ports_where(Port *pp, Eterm, Eterm);
void trace_port(Port *, Eterm what, Eterm data);
void trace_port_open(Port *, Eterm calling_pid, Eterm drv_name);
void trace_port_receive(Port *, Eterm calling_pid, Eterm tag, ...);
void trace_port_send(Port *, Eterm to, Eterm msg, int exists);
void trace_port_send_binary(Port *, Eterm to, Eterm what, char *bin, Sint sz);

/* system_profile */
void erts_set_system_profile(Eterm profile);
Eterm erts_get_system_profile(void);
void profile_scheduler(Eterm scheduler_id, Eterm);
void profile_scheduler_q(Eterm scheduler_id, Eterm state, Eterm no_schedulers, Uint Ms, Uint s, Uint us);
void profile_runnable_proc(Process* p, Eterm status);
void profile_runnable_port(Port* p, Eterm status);
void erts_system_profile_setup_active_schedulers(void);

/* system_monitor */
void monitor_long_gc(Process *p, Uint time);
void monitor_long_schedule_proc(Process *p, ErtsCodeMFA *in_i,
                                ErtsCodeMFA *out_i, Uint time);
void monitor_long_schedule_port(Port *pp, ErtsPortTaskType type, Uint time);
void monitor_large_heap(Process *p);
void monitor_generic(Process *p, Eterm type, Eterm spec);
Uint erts_trace_flag2bit(Eterm flag);
int erts_trace_flags(Eterm List, 
		 Uint *pMask, ErtsTracer *pTracer, int *pCpuTimestamp);
Eterm erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr *I);
Eterm
erts_bif_trace_epilogue(Process *p, Eterm result, int applying,
			Export* ep, Uint32 flags,
			Uint32 flags_meta, BeamInstr* I,
			ErtsTracer meta_tracer);

void erts_send_pending_trace_msgs(ErtsSchedulerData *esdp);
#define ERTS_CHK_PEND_TRACE_MSGS(ESDP)				\
do {									\
    if ((ESDP)->pending_trace_msgs)					\
	erts_send_pending_trace_msgs((ESDP));				\
} while (0)

#define seq_trace_output(token, msg, type, receiver, process) \
seq_trace_output_generic((token), (msg), (type), (receiver), (process), NIL)
#define seq_trace_output_exit(token, msg, type, receiver, exitfrom) \
seq_trace_output_generic((token), (msg), (type), (receiver), NULL, (exitfrom))
void seq_trace_output_generic(Eterm token, Eterm msg, Uint type, 
			      Eterm receiver, Process *process, Eterm exitfrom);

/* Bump the sequence number if tracing is enabled; must be used before sending
 * send/spawn trace messages. */
int seq_trace_update_serial(Process *process);

Eterm erts_seq_trace(Process *process, 
		     Eterm atom_type, Eterm atom_true_or_false, 
		     int build_result);

struct trace_pattern_flags {
    unsigned int breakpoint : 1; /* Set if any other is set */
    unsigned int local      : 1; /* Local call trace breakpoint */
    unsigned int meta       : 1; /* Metadata trace breakpoint */
    unsigned int call_count : 1; /* Fast call count breakpoint */
    unsigned int call_time  : 1; /* Fast call time breakpoint */
};
extern const struct trace_pattern_flags erts_trace_pattern_flags_off;
extern int erts_call_time_breakpoint_tracing;
int erts_set_trace_pattern(Process*p, ErtsCodeMFA *mfa, int specified,
			   struct binary* match_prog_set,
			   struct binary *meta_match_prog_set,
			   int on, struct trace_pattern_flags,
			   ErtsTracer meta_tracer, int is_blocking);
void
erts_get_default_trace_pattern(int *trace_pattern_is_on,
			       struct binary **match_spec,
			       struct binary **meta_match_spec,
			       struct trace_pattern_flags *trace_pattern_flags,
			       ErtsTracer *meta_tracer);
int erts_is_default_trace_enabled(void);
void erts_bif_trace_init(void);
int erts_finish_breakpointing(void);

/* Nif tracer functions */
int erts_is_tracer_proc_enabled(Process *c_p, ErtsProcLocks c_p_locks,
                                ErtsPTabElementCommon *t_p);
int erts_is_tracer_proc_enabled_send(Process* c_p, ErtsProcLocks c_p_locks,
                                     ErtsPTabElementCommon *t_p);
int erts_is_tracer_enabled(const ErtsTracer tracer, ErtsPTabElementCommon *t_p);
Eterm erts_tracer_to_term(Process *p, ErtsTracer tracer);
Eterm erts_build_tracer_to_term(Eterm **hpp, ErlOffHeap *ohp, Uint *szp, ErtsTracer tracer);

ErtsTracer erts_term_to_tracer(Eterm prefix, Eterm term);
void erts_tracer_replace(ErtsPTabElementCommon *t_p,
                         const ErtsTracer new_tracer);
void erts_tracer_update(ErtsTracer *tracer, const ErtsTracer new_tracer);
int erts_tracer_nif_clear(void);

#define erts_tracer_update(t,n) do { if (*(t) != (n)) erts_tracer_update(t,n); } while(0)
#define ERTS_TRACER_CLEAR(t) erts_tracer_update(t, erts_tracer_nil)

static const ErtsTracer
ERTS_DECLARE_DUMMY(erts_tracer_true) = am_true;

static const ErtsTracer
ERTS_DECLARE_DUMMY(erts_tracer_nil) = NIL;

#define ERTS_TRACER_COMPARE(t1, t2)                     \
    (EQ((t1), (t2)))

#define ERTS_TRACER_IS_NIL(t1) ERTS_TRACER_COMPARE(t1, erts_tracer_nil)

#define IS_TRACER_VALID(tracer)                                         \
    (ERTS_TRACER_COMPARE(tracer,erts_tracer_true)                       \
     || ERTS_TRACER_IS_NIL(tracer)                                      \
     || (is_list(tracer) && is_atom(CAR(list_val(tracer)))))

#define ERTS_TRACER_FROM_ETERM(termp) \
    ((ErtsTracer*)(termp))

#endif /* ERL_TRACE_H__ */