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