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