xref: /aosp_15_r20/external/libtracefs/Documentation/libtracefs-synth2.txt (revision 287e80b3a36113050663245e7f2c00d274188f18)
1*287e80b3SSadaf Ebrahimilibtracefs(3)
2*287e80b3SSadaf Ebrahimi=============
3*287e80b3SSadaf Ebrahimi
4*287e80b3SSadaf EbrahimiNAME
5*287e80b3SSadaf Ebrahimi----
6*287e80b3SSadaf Ebrahimitracefs_synth_create, tracefs_synth_destroy, tracefs_synth_complete,
7*287e80b3SSadaf Ebrahimitracefs_synth_trace, tracefs_synth_snapshot, tracefs_synth_save
8*287e80b3SSadaf Ebrahimi- Creation of synthetic events
9*287e80b3SSadaf Ebrahimi
10*287e80b3SSadaf EbrahimiSYNOPSIS
11*287e80b3SSadaf Ebrahimi--------
12*287e80b3SSadaf Ebrahimi[verse]
13*287e80b3SSadaf Ebrahimi--
14*287e80b3SSadaf Ebrahimi*#include <tracefs.h>*
15*287e80b3SSadaf Ebrahimi
16*287e80b3SSadaf Ebrahimiint *tracefs_synth_create*(struct tracefs_synth pass:[*]_synth_);
17*287e80b3SSadaf Ebrahimiint *tracefs_synth_destroy*(struct tracefs_synth pass:[*]_synth_);
18*287e80b3SSadaf Ebrahimibool *tracefs_synth_complete*(struct tracefs_synth pass:[*]_synth_);
19*287e80b3SSadaf Ebrahimi
20*287e80b3SSadaf Ebrahimiint *tracefs_synth_trace*(struct tracefs_synth pass:[*]_synth_,
21*287e80b3SSadaf Ebrahimi			enum tracefs_synth_handler _type_, const char pass:[*]_var_);
22*287e80b3SSadaf Ebrahimiint *tracefs_synth_snapshot*(struct tracefs_synth pass:[*]_synth_,
23*287e80b3SSadaf Ebrahimi			   enum tracefs_synth_handler _type_, const char pass:[*]_var_);
24*287e80b3SSadaf Ebrahimiint *tracefs_synth_save*(struct tracefs_synth pass:[*]_synth_,
25*287e80b3SSadaf Ebrahimi		       enum tracefs_synth_handler _type_, const char pass:[*]_var_,
26*287e80b3SSadaf Ebrahimi		       char pass:[**]_save_fields_);
27*287e80b3SSadaf Ebrahimi--
28*287e80b3SSadaf Ebrahimi
29*287e80b3SSadaf EbrahimiDESCRIPTION
30*287e80b3SSadaf Ebrahimi-----------
31*287e80b3SSadaf EbrahimiSynthetic events are dynamic events that are created by matching
32*287e80b3SSadaf Ebrahimitwo other events which triggers a synthetic event. One event is the starting
33*287e80b3SSadaf Ebrahimievent which some field is recorded, and when the second event is executed,
34*287e80b3SSadaf Ebrahimiif it has a field (or fields) that matches the starting event's field (or fields)
35*287e80b3SSadaf Ebrahimithen it will trigger the synthetic event. The field values other than the matching
36*287e80b3SSadaf Ebrahimifields may be passed from the starting event to the end event to perform calculations
37*287e80b3SSadaf Ebrahimion, or to simply pass as a parameter to the synthetic event.
38*287e80b3SSadaf Ebrahimi
39*287e80b3SSadaf EbrahimiOne common use case is to set "sched_waking" as the starting event. This event is
40*287e80b3SSadaf Ebrahimitriggered when a process is awoken. Then set "sched_switch" as the ending event.
41*287e80b3SSadaf EbrahimiThis event is triggered when a new task is scheduled on the CPU. By setting
42*287e80b3SSadaf Ebrahimithe "common_pid" of both events as the matching fields, the time between the
43*287e80b3SSadaf Ebrahimitwo events is considered the wake up latency of that process. Use *TRACEFS_TIMESTAMP*
44*287e80b3SSadaf Ebrahimias a field for both events to calculate the delta in nanoseconds, or use
45*287e80b3SSadaf Ebrahimi*TRACEFS_TIMESTAMP_USECS* as the compare fields for both events to calculate the
46*287e80b3SSadaf Ebrahimidelta in microseconds. This is used as the example below.
47*287e80b3SSadaf Ebrahimi
48*287e80b3SSadaf Ebrahimi*tracefs_synth_create*() creates the synthetic event in the system. The synthetic events apply
49*287e80b3SSadaf Ebrahimiacross all instances. A synthetic event must be created with *tracefs_synth_alloc*(3) before
50*287e80b3SSadaf Ebrahimiit can be created.
51*287e80b3SSadaf Ebrahimi
52*287e80b3SSadaf Ebrahimi*tracefs_synth_destroy*() destroys the synthetic event. It will attempt to stop the running of it in
53*287e80b3SSadaf Ebrahimiits instance (top by default), but if its running in another instance this may fail as busy.
54*287e80b3SSadaf Ebrahimi
55*287e80b3SSadaf Ebrahimi*tracefs_synth_complete*() returns true if the synthetic event _synth_ has both
56*287e80b3SSadaf Ebrahimia starting and ending event.
57*287e80b3SSadaf Ebrahimi
58*287e80b3SSadaf Ebrahimi*tracefs_synth_trace*() Instead of doing just a trace on matching of the start and
59*287e80b3SSadaf Ebrahimiend events, do the _type_ handler where *TRACEFS_SYNTH_HANDLE_MAX* will do a trace
60*287e80b3SSadaf Ebrahimiwhen the given variable _var_ hits a new max for the matching keys. Or
61*287e80b3SSadaf Ebrahimi*TRACEFS_SYNTH_HANDLE_CHANGE* for when the _var_ changes. _var_ must be one of
62*287e80b3SSadaf Ebrahimithe _name_ elements used in *tracefs_synth_add_end_field*(3).
63*287e80b3SSadaf Ebrahimi
64*287e80b3SSadaf Ebrahimi*tracefs_synth_snapshot*() When the given variable _var_ is either a new max if
65*287e80b3SSadaf Ebrahimi_handler_ is *TRACEFS_SYNTH_HANDLE_MAX* or simply changed if *TRACEFS_SYNTH_HANDLE_CHANGE*
66*287e80b3SSadaf Ebrahimithen take a "snapshot" of the buffer. The snapshot moves the normal "trace" buffer
67*287e80b3SSadaf Ebrahimiinto a "snapshot" buffer, that can be accessed via the "snapshot" file in the
68*287e80b3SSadaf Ebrahimitop level tracefs directory, or one of the instances.  _var_ changes. _var_ must be one of
69*287e80b3SSadaf Ebrahimithe _name_ elements used in *tracefs_synth_add_end_field*(3).
70*287e80b3SSadaf Ebrahimi
71*287e80b3SSadaf Ebrahimi*tracefs_synth_save*() When the given variable _var_ is either a new max if
72*287e80b3SSadaf Ebrahimi_handler_ is *TRACEFS_SYNTH_HANDLE_MAX* or simpy changed if *TRACEFS_SYNTH_HANDLE_CHANGE*
73*287e80b3SSadaf Ebrahimithen save the given _save_fields_ list. The fields will be stored in the histogram
74*287e80b3SSadaf Ebrahimi"hist" file of the event that can be retrieved with *tracefs_event_file_read*(3).
75*287e80b3SSadaf Ebrahimi_var_ must be one of the _name_ elements used in *tracefs_synth_add_end_field*(3).
76*287e80b3SSadaf Ebrahimi
77*287e80b3SSadaf EbrahimiRETURN VALUE
78*287e80b3SSadaf Ebrahimi------------
79*287e80b3SSadaf EbrahimiAll functions return zero on success or -1 on error.
80*287e80b3SSadaf Ebrahimi
81*287e80b3SSadaf EbrahimiERRORS
82*287e80b3SSadaf Ebrahimi------
83*287e80b3SSadaf EbrahimiThe following errors are for all the above calls:
84*287e80b3SSadaf Ebrahimi
85*287e80b3SSadaf Ebrahimi*EPERM* Not run as root user when required.
86*287e80b3SSadaf Ebrahimi
87*287e80b3SSadaf Ebrahimi*EINVAL* Either a parameter is not valid (NULL when it should not be)
88*287e80b3SSadaf Ebrahimi  or a field that is not compatible for calculations.
89*287e80b3SSadaf Ebrahimi
90*287e80b3SSadaf Ebrahimi*ENODEV* An event or one of its fields is not found.
91*287e80b3SSadaf Ebrahimi
92*287e80b3SSadaf Ebrahimi*EBADE* The fields of the start and end events are not compatible for
93*287e80b3SSadaf Ebrahimi  either matching or comparing.
94*287e80b3SSadaf Ebrahimi
95*287e80b3SSadaf Ebrahimi*ENOMEM* not enough memory is available.
96*287e80b3SSadaf Ebrahimi
97*287e80b3SSadaf EbrahimiAnd more errors may have happened from the system calls to the system.
98*287e80b3SSadaf Ebrahimi
99*287e80b3SSadaf EbrahimiEXAMPLE
100*287e80b3SSadaf Ebrahimi-------
101*287e80b3SSadaf EbrahimiSee *tracefs_sql*(3) for a more indepth use of some of this code.
102*287e80b3SSadaf Ebrahimi
103*287e80b3SSadaf Ebrahimi[source,c]
104*287e80b3SSadaf Ebrahimi--
105*287e80b3SSadaf Ebrahimi#include <stdlib.h>
106*287e80b3SSadaf Ebrahimi#include <tracefs.h>
107*287e80b3SSadaf Ebrahimi
108*287e80b3SSadaf Ebrahimi#define start_event "sched_waking"
109*287e80b3SSadaf Ebrahimi#define start_field "pid"
110*287e80b3SSadaf Ebrahimi
111*287e80b3SSadaf Ebrahimi#define end_event "sched_switch"
112*287e80b3SSadaf Ebrahimi#define end_field "next_pid"
113*287e80b3SSadaf Ebrahimi
114*287e80b3SSadaf Ebrahimi#define match_name "pid"
115*287e80b3SSadaf Ebrahimi
116*287e80b3SSadaf Ebrahimistatic struct tracefs_synth *synth;
117*287e80b3SSadaf Ebrahimi
118*287e80b3SSadaf Ebrahimistatic void make_event(void)
119*287e80b3SSadaf Ebrahimi{
120*287e80b3SSadaf Ebrahimi	struct tep_handle *tep;
121*287e80b3SSadaf Ebrahimi
122*287e80b3SSadaf Ebrahimi	/* Load all events from the system */
123*287e80b3SSadaf Ebrahimi	tep = tracefs_local_events(NULL);
124*287e80b3SSadaf Ebrahimi
125*287e80b3SSadaf Ebrahimi	/* Initialize the synthetic event */
126*287e80b3SSadaf Ebrahimi	synth = tracefs_synth_alloc(tep, "wakeup_lat",
127*287e80b3SSadaf Ebrahimi				    NULL, start_event,
128*287e80b3SSadaf Ebrahimi				    NULL, end_event,
129*287e80b3SSadaf Ebrahimi				    start_field, end_field,
130*287e80b3SSadaf Ebrahimi				    match_name);
131*287e80b3SSadaf Ebrahimi
132*287e80b3SSadaf Ebrahimi	/* The tep is no longer needed */
133*287e80b3SSadaf Ebrahimi	tep_free(tep);
134*287e80b3SSadaf Ebrahimi
135*287e80b3SSadaf Ebrahimi
136*287e80b3SSadaf Ebrahimi	/* Save the "prio" field as "prio" from the start event */
137*287e80b3SSadaf Ebrahimi	tracefs_synth_add_start_field(synth, "prio", NULL);
138*287e80b3SSadaf Ebrahimi
139*287e80b3SSadaf Ebrahimi	/* Save the "next_comm" as "comm" from the end event */
140*287e80b3SSadaf Ebrahimi	tracefs_synth_add_end_field(synth, "next_comm", "comm");
141*287e80b3SSadaf Ebrahimi
142*287e80b3SSadaf Ebrahimi	/* Save the "prev_prio" as "prev_prio" from the end event */
143*287e80b3SSadaf Ebrahimi	tracefs_synth_add_end_field(synth, "prev_prio", NULL);
144*287e80b3SSadaf Ebrahimi
145*287e80b3SSadaf Ebrahimi	/*
146*287e80b3SSadaf Ebrahimi	 * Take a microsecond time difference between end and start
147*287e80b3SSadaf Ebrahimi	 * and record as "delta"
148*287e80b3SSadaf Ebrahimi	 */
149*287e80b3SSadaf Ebrahimi	tracefs_synth_add_compare_field(synth, TRACEFS_TIMESTAMP_USECS,
150*287e80b3SSadaf Ebrahimi					TRACEFS_TIMESTAMP_USECS,
151*287e80b3SSadaf Ebrahimi					TRACEFS_SYNTH_DELTA_END, "delta");
152*287e80b3SSadaf Ebrahimi
153*287e80b3SSadaf Ebrahimi	/* Only record if start event "prio" is less than 100 */
154*287e80b3SSadaf Ebrahimi	tracefs_synth_append_start_filter(synth, TRACEFS_FILTER_COMPARE,
155*287e80b3SSadaf Ebrahimi					  "prio", TRACEFS_COMPARE_LT, "100");
156*287e80b3SSadaf Ebrahimi
157*287e80b3SSadaf Ebrahimi	/*
158*287e80b3SSadaf Ebrahimi	 * Only record if end event "next_prio" is less than 50
159*287e80b3SSadaf Ebrahimi	 * or the previous task's prio was not greater than or equal to 100.
160*287e80b3SSadaf Ebrahimi	 *   next_prio < 50 || !(prev_prio >= 100)
161*287e80b3SSadaf Ebrahimi	 */
162*287e80b3SSadaf Ebrahimi	tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_COMPARE,
163*287e80b3SSadaf Ebrahimi					"next_prio", TRACEFS_COMPARE_LT, "50");
164*287e80b3SSadaf Ebrahimi	tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_OR, NULL, 0, NULL);
165*287e80b3SSadaf Ebrahimi	tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_NOT, NULL, 0, NULL);
166*287e80b3SSadaf Ebrahimi	tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_OPEN_PAREN, NULL, 0, NULL);
167*287e80b3SSadaf Ebrahimi	tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_COMPARE,
168*287e80b3SSadaf Ebrahimi					"prev_prio", TRACEFS_COMPARE_GE, "100");
169*287e80b3SSadaf Ebrahimi	/*
170*287e80b3SSadaf Ebrahimi	 * Note, the above only added: "next_prio < 50 || !(prev_prio >= 100"
171*287e80b3SSadaf Ebrahimi	 * That's because, when the synth is executed, the remaining close parenthesis
172*287e80b3SSadaf Ebrahimi	 * will be added. That is, the string will end up being:
173*287e80b3SSadaf Ebrahimi	 * "next_prio < 50 || !(prev_prio >= 100)" when one of tracefs_sync_create()
174*287e80b3SSadaf Ebrahimi	 * or tracefs_sync_echo_cmd() is run.
175*287e80b3SSadaf Ebrahimi	 */
176*287e80b3SSadaf Ebrahimi}
177*287e80b3SSadaf Ebrahimi
178*287e80b3SSadaf Ebrahimi/* Display how to create the synthetic event */
179*287e80b3SSadaf Ebrahimistatic void show_event(void)
180*287e80b3SSadaf Ebrahimi{
181*287e80b3SSadaf Ebrahimi	struct trace_seq s;
182*287e80b3SSadaf Ebrahimi
183*287e80b3SSadaf Ebrahimi	trace_seq_init(&s);
184*287e80b3SSadaf Ebrahimi
185*287e80b3SSadaf Ebrahimi	tracefs_synth_echo_cmd(&s, synth);
186*287e80b3SSadaf Ebrahimi	trace_seq_terminate(&s);
187*287e80b3SSadaf Ebrahimi	trace_seq_do_printf(&s);
188*287e80b3SSadaf Ebrahimi	trace_seq_destroy(&s);
189*287e80b3SSadaf Ebrahimi}
190*287e80b3SSadaf Ebrahimi
191*287e80b3SSadaf Ebrahimiint main (int argc, char **argv)
192*287e80b3SSadaf Ebrahimi{
193*287e80b3SSadaf Ebrahimi	make_event();
194*287e80b3SSadaf Ebrahimi
195*287e80b3SSadaf Ebrahimi	if (argc > 1) {
196*287e80b3SSadaf Ebrahimi		if (!strcmp(argv[1], "create")) {
197*287e80b3SSadaf Ebrahimi			/* Create the synthetic event */
198*287e80b3SSadaf Ebrahimi			tracefs_synth_create(synth);
199*287e80b3SSadaf Ebrahimi		} else if (!strcmp(argv[1], "delete")) {
200*287e80b3SSadaf Ebrahimi			/* Delete the synthetic event */
201*287e80b3SSadaf Ebrahimi			tracefs_synth_destroy(synth);
202*287e80b3SSadaf Ebrahimi		} else {
203*287e80b3SSadaf Ebrahimi			printf("usage: %s [create|delete]\n", argv[0]);
204*287e80b3SSadaf Ebrahimi			exit(-1);
205*287e80b3SSadaf Ebrahimi		}
206*287e80b3SSadaf Ebrahimi	} else
207*287e80b3SSadaf Ebrahimi		show_event();
208*287e80b3SSadaf Ebrahimi
209*287e80b3SSadaf Ebrahimi	tracefs_synth_free(synth);
210*287e80b3SSadaf Ebrahimi
211*287e80b3SSadaf Ebrahimi	return 0;
212*287e80b3SSadaf Ebrahimi}
213*287e80b3SSadaf Ebrahimi--
214*287e80b3SSadaf Ebrahimi
215*287e80b3SSadaf EbrahimiFILES
216*287e80b3SSadaf Ebrahimi-----
217*287e80b3SSadaf Ebrahimi[verse]
218*287e80b3SSadaf Ebrahimi--
219*287e80b3SSadaf Ebrahimi*tracefs.h*
220*287e80b3SSadaf Ebrahimi	Header file to include in order to have access to the library APIs.
221*287e80b3SSadaf Ebrahimi*-ltracefs*
222*287e80b3SSadaf Ebrahimi	Linker switch to add when building a program that uses the library.
223*287e80b3SSadaf Ebrahimi--
224*287e80b3SSadaf Ebrahimi
225*287e80b3SSadaf EbrahimiSEE ALSO
226*287e80b3SSadaf Ebrahimi--------
227*287e80b3SSadaf Ebrahimi*libtracefs*(3),
228*287e80b3SSadaf Ebrahimi*libtraceevent*(3),
229*287e80b3SSadaf Ebrahimi*trace-cmd*(1),
230*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc*(3),
231*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_2d*(3),
232*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd*(3),
233*287e80b3SSadaf Ebrahimi*tracefs_hist_free*(3),
234*287e80b3SSadaf Ebrahimi*tracefs_hist_add_key*(3),
235*287e80b3SSadaf Ebrahimi*tracefs_hist_add_value*(3),
236*287e80b3SSadaf Ebrahimi*tracefs_hist_add_name*(3),
237*287e80b3SSadaf Ebrahimi*tracefs_hist_start*(3),
238*287e80b3SSadaf Ebrahimi*tracefs_hist_destory*(3),
239*287e80b3SSadaf Ebrahimi*tracefs_hist_add_sort_key*(3),
240*287e80b3SSadaf Ebrahimi*tracefs_hist_sort_key_direction*(3),
241*287e80b3SSadaf Ebrahimi*tracefs_synth_alloc*(3),
242*287e80b3SSadaf Ebrahimi*tracefs_synth_add_match_field*(3),
243*287e80b3SSadaf Ebrahimi*tracefs_synth_add_compare_field*(3),
244*287e80b3SSadaf Ebrahimi*tracefs_synth_add_start_field*(3),
245*287e80b3SSadaf Ebrahimi*tracefs_synth_add_end_field*(3),
246*287e80b3SSadaf Ebrahimi*tracefs_synth_append_start_filter*(3),
247*287e80b3SSadaf Ebrahimi*tracefs_synth_append_end_filter*(3),
248*287e80b3SSadaf Ebrahimi*tracefs_synth_free*(3),
249*287e80b3SSadaf Ebrahimi*tracefs_synth_echo_cmd*(3),
250*287e80b3SSadaf Ebrahimi*tracefs_synth_get_start_hist*(3),
251*287e80b3SSadaf Ebrahimi*tracefs_synth_get_name*(3),
252*287e80b3SSadaf Ebrahimi*tracefs_synth_raw_fmt*(3),
253*287e80b3SSadaf Ebrahimi*tracefs_synth_show_event*(3),
254*287e80b3SSadaf Ebrahimi*tracefs_synth_show_start_hist*(3),
255*287e80b3SSadaf Ebrahimi*tracefs_synth_show_end_hist*(3),
256*287e80b3SSadaf Ebrahimi*tracefs_synth_get_event*(3),
257*287e80b3SSadaf Ebrahimi
258*287e80b3SSadaf EbrahimiAUTHOR
259*287e80b3SSadaf Ebrahimi------
260*287e80b3SSadaf Ebrahimi[verse]
261*287e80b3SSadaf Ebrahimi--
262*287e80b3SSadaf Ebrahimi*Steven Rostedt* <[email protected]>
263*287e80b3SSadaf Ebrahimi*Tzvetomir Stoyanov* <[email protected]>
264*287e80b3SSadaf Ebrahimi*sameeruddin shaik* <[email protected]>
265*287e80b3SSadaf Ebrahimi--
266*287e80b3SSadaf EbrahimiREPORTING BUGS
267*287e80b3SSadaf Ebrahimi--------------
268*287e80b3SSadaf EbrahimiReport bugs to  <[email protected]>
269*287e80b3SSadaf Ebrahimi
270*287e80b3SSadaf EbrahimiLICENSE
271*287e80b3SSadaf Ebrahimi-------
272*287e80b3SSadaf Ebrahimilibtracefs is Free Software licensed under the GNU LGPL 2.1
273*287e80b3SSadaf Ebrahimi
274*287e80b3SSadaf EbrahimiRESOURCES
275*287e80b3SSadaf Ebrahimi---------
276*287e80b3SSadaf Ebrahimihttps://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/
277*287e80b3SSadaf Ebrahimi
278*287e80b3SSadaf EbrahimiCOPYING
279*287e80b3SSadaf Ebrahimi-------
280*287e80b3SSadaf EbrahimiCopyright \(C) 2020 VMware, Inc. Free use of this software is granted under
281*287e80b3SSadaf Ebrahimithe terms of the GNU Public License (GPL).
282