xref: /aosp_15_r20/external/libtracefs/Documentation/libtracefs-hist-mod.txt (revision 287e80b3a36113050663245e7f2c00d274188f18)
1*287e80b3SSadaf Ebrahimilibtracefs(3)
2*287e80b3SSadaf Ebrahimi=============
3*287e80b3SSadaf Ebrahimi
4*287e80b3SSadaf EbrahimiNAME
5*287e80b3SSadaf Ebrahimi----
6*287e80b3SSadaf Ebrahimitracefs_hist_add_sort_key, tracefs_hist_set_sort_key, tracefs_hist_sort_key_direction,
7*287e80b3SSadaf Ebrahimitracefs_hist_add_name, tracefs_hist_append_filter, tracefs_hist_echo_cmd, tracefs_hist_command,
8*287e80b3SSadaf Ebrahimitracefs_hist_get_name, tracefs_hist_get_event, tracefs_hist_get_system - Update and describe an event histogram
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_hist_add_sort_key*(struct tracefs_hist pass:[*]_hist_,
17*287e80b3SSadaf Ebrahimi			      const char pass:[*]_sort_key_);
18*287e80b3SSadaf Ebrahimi
19*287e80b3SSadaf Ebrahimiint *tracefs_hist_set_sort_key*(struct tracefs_hist pass:[*]_hist_,
20*287e80b3SSadaf Ebrahimi			      const char pass:[*]_sort_key_, _..._);
21*287e80b3SSadaf Ebrahimiint *tracefs_hist_sort_key_direction*(struct tracefs_hist pass:[*]_hist_,
22*287e80b3SSadaf Ebrahimi				    const char pass:[*]_sort_key_,
23*287e80b3SSadaf Ebrahimi				    enum tracefs_hist_sort_direction _dir_);
24*287e80b3SSadaf Ebrahimi
25*287e80b3SSadaf Ebrahimiint *tracefs_hist_add_name*(struct tracefs_hist pass:[*]_hist_, const char pass:[*]_name_);
26*287e80b3SSadaf Ebrahimi
27*287e80b3SSadaf Ebrahimiint *tracefs_hist_append_filter*(struct tracefs_hist pass:[*]_hist_,
28*287e80b3SSadaf Ebrahimi			       enum tracefs_filter _type_,
29*287e80b3SSadaf Ebrahimi			       const char pass:[*]_field_,
30*287e80b3SSadaf Ebrahimi			       enum tracefs_compare _compare_,
31*287e80b3SSadaf Ebrahimi			       const char pass:[*]_val_);
32*287e80b3SSadaf Ebrahimi
33*287e80b3SSadaf Ebrahimiint *tracefs_hist_echo_cmd*(struct trace_seq pass:[*]_s_, struct tracefs_instance pass:[*]_instance_,
34*287e80b3SSadaf Ebrahimi			  struct tracefs_hist pass:[*]_hist_,
35*287e80b3SSadaf Ebrahimi			  enum tracefs_hist_command _command_);
36*287e80b3SSadaf Ebrahimi
37*287e80b3SSadaf Ebrahimiint *tracefs_hist_command*(struct tracefs_instance pass:[*]_instance_,
38*287e80b3SSadaf Ebrahimi			 struct tracefs_hist pass:[*]_hist_,
39*287e80b3SSadaf Ebrahimi			 enum tracefs_hist_command _command_);
40*287e80b3SSadaf Ebrahimi
41*287e80b3SSadaf Ebrahimiconst char pass:[*]*tracefs_hist_get_name*(struct tracefs_hist pass:[*]_hist_);
42*287e80b3SSadaf Ebrahimi
43*287e80b3SSadaf Ebrahimiconst char pass:[*]*tracefs_hist_get_event*(struct tracefs_hist pass:[*]_hist_);
44*287e80b3SSadaf Ebrahimi
45*287e80b3SSadaf Ebrahimiconst char pass:[*]*tracefs_hist_get_system*(struct tracefs_hist pass:[*]_hist_);
46*287e80b3SSadaf Ebrahimi
47*287e80b3SSadaf Ebrahimi--
48*287e80b3SSadaf Ebrahimi
49*287e80b3SSadaf EbrahimiDESCRIPTION
50*287e80b3SSadaf Ebrahimi-----------
51*287e80b3SSadaf EbrahimiEvent histograms are created by the trigger file in the event directory.
52*287e80b3SSadaf EbrahimiThe syntax can be complex and difficult to get correct. This API handles the
53*287e80b3SSadaf Ebrahimisyntax, and facilitates the creation and interaction with the event histograms.
54*287e80b3SSadaf EbrahimiSee https://www.kernel.org/doc/html/latest/trace/histogram.html for more information.
55*287e80b3SSadaf Ebrahimi
56*287e80b3SSadaf Ebrahimi*tracefs_hist_add_sort_key*() will add a key to sort on. The _hist_ is the
57*287e80b3SSadaf Ebrahimihistogram descriptor to add the sort key to. The _sort_key_ is a string
58*287e80b3SSadaf Ebrahimithat must match either an already defined key of the histogram, or an already
59*287e80b3SSadaf Ebrahimidefined value. If _hist_  already has sorting keys (previously added) the new
60*287e80b3SSadaf Ebrahimi_sort_key_ will have lower priority(be secondary or so on) when sorting.
61*287e80b3SSadaf Ebrahimi
62*287e80b3SSadaf Ebrahimi*tracefs_hist_set_sort_key*() will reset the list of key to sort on. The _hist_ is
63*287e80b3SSadaf Ebrahimithe histogram descriptor to reset the sort key to. The _sort_key_ is a string
64*287e80b3SSadaf Ebrahimithat must match either an already defined key of the histogram, or an already
65*287e80b3SSadaf Ebrahimidefined value. Multiple sort keys may be added to denote a secondary, sort order
66*287e80b3SSadaf Ebrahimiand so on, but all sort keys must match an existing key or value, or be
67*287e80b3SSadaf EbrahimiTRACEFS_HIST_HITCOUNT. The last parameter of *tracefs_hist_add_sort_key*() must
68*287e80b3SSadaf Ebrahimibe NULL.
69*287e80b3SSadaf Ebrahimi
70*287e80b3SSadaf Ebrahimi*tracefs_hist_sort_key_direction*() allows to change the direction of an
71*287e80b3SSadaf Ebrahimiexisting sort key of _hist_. The _sort_key_ is the sort key to change, and
72*287e80b3SSadaf Ebrahimi_dir_ can be either TRACEFS_HIST_SORT_ASCENDING or TRACEFS_HIST_SORT_DESCENDING,
73*287e80b3SSadaf Ebrahimito make the direction of the sort key either ascending or descending respectively.
74*287e80b3SSadaf Ebrahimi
75*287e80b3SSadaf Ebrahimi*tracefs_hist_add_name*() adds a name to a histogram. A histogram may be
76*287e80b3SSadaf Ebrahiminamed and if the name matches between more than one event, and they have
77*287e80b3SSadaf Ebrahimicompatible keys, the multiple histograms with the same name will be merged
78*287e80b3SSadaf Ebrahimiinto a single histogram (shown by either event's hist file). The _hist_
79*287e80b3SSadaf Ebrahimiis the histogram to name, and the _name_ is the name to give it.
80*287e80b3SSadaf Ebrahimi
81*287e80b3SSadaf Ebrahimi*tracefs_hist_append_filter*() creates a filter or appends to it for the
82*287e80b3SSadaf Ebrahimihistogram  event. Depending on _type_, it will build a string of tokens for
83*287e80b3SSadaf Ebrahimiparenthesis or logic statements, or it may add a comparison of _field_
84*287e80b3SSadaf Ebrahimito _val_ based on _compare_.
85*287e80b3SSadaf Ebrahimi
86*287e80b3SSadaf EbrahimiIf _type_ is:
87*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_COMPARE*     -  See below
88*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_AND*         -  Append "&&" to the filter
89*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_OR*          -  Append "||" to the filter
90*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_NOT*         -  Append "!" to the filter
91*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_OPEN_PAREN*  -  Append "(" to the filter
92*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_CLOSE_PAREN* -  Append ")" to the filter
93*287e80b3SSadaf Ebrahimi
94*287e80b3SSadaf Ebrahimi_field_, _compare_, and _val_ are ignored unless _type_ is equal to
95*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_COMPARE*, then _compare_ will be used for the following:
96*287e80b3SSadaf Ebrahimi
97*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_EQ* - _field_ == _val_
98*287e80b3SSadaf Ebrahimi
99*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_NE* - _field_ != _val_
100*287e80b3SSadaf Ebrahimi
101*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_GT* - _field_ > _val_
102*287e80b3SSadaf Ebrahimi
103*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_GE* - _field_ >= _val_
104*287e80b3SSadaf Ebrahimi
105*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_LT* - _field_ < _val_
106*287e80b3SSadaf Ebrahimi
107*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_LE* - _field_ <pass:[=] _val_
108*287e80b3SSadaf Ebrahimi
109*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_RE* - _field_ ~ "_val_" : where _field_ is a string.
110*287e80b3SSadaf Ebrahimi
111*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_AND* - _field_ & _val_ : where _field_ is a flags field.
112*287e80b3SSadaf Ebrahimi
113*287e80b3SSadaf Ebrahimi*trace_hist_echo_cmd*() prints the commands needed to create the given histogram
114*287e80b3SSadaf Ebrahimiin the given _instance_, or NULL for the top level, into the _seq_.
115*287e80b3SSadaf EbrahimiThe command that is printed is described by _command_ and shows the functionality
116*287e80b3SSadaf Ebrahimithat would be done by *tracefs_hist_command*(3).
117*287e80b3SSadaf Ebrahimi
118*287e80b3SSadaf Ebrahimi*tracefs_hist_command*() is called to process a command on the histogram
119*287e80b3SSadaf Ebrahimi_hist_ for its event in the given _instance_, or NULL for the top level.
120*287e80b3SSadaf EbrahimiThe _cmd_ can be one of:
121*287e80b3SSadaf Ebrahimi
122*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_CMD_START* or zero to start execution of the histogram.
123*287e80b3SSadaf Ebrahimi
124*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_CMD_PAUSE* to pause the given histogram.
125*287e80b3SSadaf Ebrahimi
126*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_CMD_CONT* to continue a paused histogram.
127*287e80b3SSadaf Ebrahimi
128*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_CMD_CLEAR* to reset the values of a histogram.
129*287e80b3SSadaf Ebrahimi
130*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_CMD_DESTROY* to destroy the histogram (undo a START).
131*287e80b3SSadaf Ebrahimi
132*287e80b3SSadaf EbrahimiThe below functions are wrappers to tracefs_hist_command() to make the
133*287e80b3SSadaf Ebrahimicalling conventions a bit easier to understand what is happening.
134*287e80b3SSadaf Ebrahimi
135*287e80b3SSadaf EbrahimiKEY TYPES
136*287e80b3SSadaf Ebrahimi---------
137*287e80b3SSadaf Ebrahimi
138*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd*() and *tracefs_hist_add_key*() both add a key and requires
139*287e80b3SSadaf Ebrahimithat key to have a type. The types may be:
140*287e80b3SSadaf Ebrahimi
141*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_NORMAL* or zero (0) which is to not modify the type.
142*287e80b3SSadaf Ebrahimi
143*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_HEX* to display the key in hex.
144*287e80b3SSadaf Ebrahimi
145*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_SYM* to display the key as a kernel symbol (if found). If
146*287e80b3SSadaf Ebrahimithe key is an address, this is useful as it will display the function names instead
147*287e80b3SSadaf Ebrahimiof just a number.
148*287e80b3SSadaf Ebrahimi
149*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_SYM_OFFSET* similar to *TRACEFS_HIST_KEY_SYM* but will also include
150*287e80b3SSadaf Ebrahimithe offset of the function to match the exact address.
151*287e80b3SSadaf Ebrahimi
152*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_SYSCALL* If the key is a system call "id" (the number passed from user
153*287e80b3SSadaf Ebrahimispace to the kernel to tell it what system call it is calling), then the name of
154*287e80b3SSadaf Ebrahimithe system call is displayed.
155*287e80b3SSadaf Ebrahimi
156*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_EXECNAME* If "common_pid" is the key (the pid of the executing task),
157*287e80b3SSadaf Ebrahimiinstead of showing the number, show the name of the running task.
158*287e80b3SSadaf Ebrahimi
159*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_LOG* will display the key in a binary logarithmic scale.
160*287e80b3SSadaf Ebrahimi
161*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_USECS* for use with "common_timestamp" or TRACEFS_HIST_TIMESTAMP,
162*287e80b3SSadaf Ebrahimiin which case it will show the timestamp in microseconds instead of nanoseconds.
163*287e80b3SSadaf Ebrahimi
164*287e80b3SSadaf EbrahimiRETURN VALUE
165*287e80b3SSadaf Ebrahimi------------
166*287e80b3SSadaf Ebrahimi*tracefs_hist_get_name*() returns the name of the histogram or NULL on error.
167*287e80b3SSadaf EbrahimiThe returned string belongs to the histogram object and is freed with the histogram
168*287e80b3SSadaf Ebrahimiby *tracefs_hist_free*().
169*287e80b3SSadaf Ebrahimi
170*287e80b3SSadaf Ebrahimi*tracefs_hist_get_event*() returns the event name of the histogram or NULL on error.
171*287e80b3SSadaf EbrahimiThe returned string belongs to the histogram object and is freed with the histogram
172*287e80b3SSadaf Ebrahimiby *tracefs_hist_free*().
173*287e80b3SSadaf Ebrahimi
174*287e80b3SSadaf Ebrahimi*tracefs_hist_get_system*() returns the system name of the histogram or NULL on error.
175*287e80b3SSadaf EbrahimiThe returned string belongs to the histogram object and is freed with the histogram
176*287e80b3SSadaf Ebrahimiby *tracefs_hist_free*().
177*287e80b3SSadaf Ebrahimi
178*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd*() returns an allocated histogram descriptor which must
179*287e80b3SSadaf Ebrahimibe freed by *tracefs_hist_free*() or NULL on error.
180*287e80b3SSadaf Ebrahimi
181*287e80b3SSadaf Ebrahimi*tracefs_hist_get_name*(), *tracefs_hist_get_event*() and *tracefs_hist_get_system*()
182*287e80b3SSadaf Ebrahimireturn strings owned by the histogram object.
183*287e80b3SSadaf Ebrahimi
184*287e80b3SSadaf EbrahimiAll the other functions return zero on success or -1 on error.
185*287e80b3SSadaf Ebrahimi
186*287e80b3SSadaf EbrahimiEXAMPLE
187*287e80b3SSadaf Ebrahimi-------
188*287e80b3SSadaf Ebrahimi[source,c]
189*287e80b3SSadaf Ebrahimi--
190*287e80b3SSadaf Ebrahimi#include <stdlib.h>
191*287e80b3SSadaf Ebrahimi#include <unistd.h>
192*287e80b3SSadaf Ebrahimi#include <tracefs.h>
193*287e80b3SSadaf Ebrahimi
194*287e80b3SSadaf Ebrahimienum commands {
195*287e80b3SSadaf Ebrahimi	START,
196*287e80b3SSadaf Ebrahimi	PAUSE,
197*287e80b3SSadaf Ebrahimi	CONT,
198*287e80b3SSadaf Ebrahimi	RESET,
199*287e80b3SSadaf Ebrahimi	DELETE,
200*287e80b3SSadaf Ebrahimi	SHOW,
201*287e80b3SSadaf Ebrahimi};
202*287e80b3SSadaf Ebrahimi
203*287e80b3SSadaf Ebrahimistatic void parse_system_event(char *group, char **system, char **event)
204*287e80b3SSadaf Ebrahimi{
205*287e80b3SSadaf Ebrahimi	*system = strtok(group, "/");
206*287e80b3SSadaf Ebrahimi	*event = strtok(NULL, "/");
207*287e80b3SSadaf Ebrahimi	if (!*event) {
208*287e80b3SSadaf Ebrahimi		*event = *system;
209*287e80b3SSadaf Ebrahimi		*system = NULL;
210*287e80b3SSadaf Ebrahimi	}
211*287e80b3SSadaf Ebrahimi}
212*287e80b3SSadaf Ebrahimi
213*287e80b3SSadaf Ebrahimistatic int parse_keys(char *keys, struct tracefs_hist_axis **axes)
214*287e80b3SSadaf Ebrahimi{
215*287e80b3SSadaf Ebrahimi	char *sav = NULL;
216*287e80b3SSadaf Ebrahimi	char *key;
217*287e80b3SSadaf Ebrahimi	int cnt = 0;
218*287e80b3SSadaf Ebrahimi
219*287e80b3SSadaf Ebrahimi	for (key = strtok_r(keys, ",", &sav); key; key = strtok_r(NULL, ",", &sav)) {
220*287e80b3SSadaf Ebrahimi		struct tracefs_hist_axis *ax;
221*287e80b3SSadaf Ebrahimi		char *att;
222*287e80b3SSadaf Ebrahimi
223*287e80b3SSadaf Ebrahimi		ax = realloc(*axes, sizeof(*ax) * (cnt + 2));
224*287e80b3SSadaf Ebrahimi		if (!ax) {
225*287e80b3SSadaf Ebrahimi			perror("Failed to allocate axes");
226*287e80b3SSadaf Ebrahimi			exit(-1);
227*287e80b3SSadaf Ebrahimi		}
228*287e80b3SSadaf Ebrahimi		ax[cnt].key = key;
229*287e80b3SSadaf Ebrahimi		ax[cnt].type = 0;
230*287e80b3SSadaf Ebrahimi		ax[cnt + 1].key = NULL;
231*287e80b3SSadaf Ebrahimi		ax[cnt + 1].type = 0;
232*287e80b3SSadaf Ebrahimi
233*287e80b3SSadaf Ebrahimi		*axes = ax;
234*287e80b3SSadaf Ebrahimi
235*287e80b3SSadaf Ebrahimi		att = strchr(key, '.');
236*287e80b3SSadaf Ebrahimi		if (att) {
237*287e80b3SSadaf Ebrahimi			*att++ = '\0';
238*287e80b3SSadaf Ebrahimi			if (strcmp(att, "hex") == 0)
239*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_HEX;
240*287e80b3SSadaf Ebrahimi			else if (strcmp(att, "sym") == 0)
241*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_SYM;
242*287e80b3SSadaf Ebrahimi			else if (strcmp(att, "sym_offset") == 0)
243*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_SYM_OFFSET;
244*287e80b3SSadaf Ebrahimi			else if (strcmp(att, "syscall") == 0)
245*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_SYSCALL;
246*287e80b3SSadaf Ebrahimi			else if (strcmp(att, "exec") == 0)
247*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_EXECNAME;
248*287e80b3SSadaf Ebrahimi			else if (strcmp(att, "log") == 0)
249*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_LOG;
250*287e80b3SSadaf Ebrahimi			else if (strcmp(att, "usecs") == 0)
251*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_USECS;
252*287e80b3SSadaf Ebrahimi			else {
253*287e80b3SSadaf Ebrahimi				fprintf(stderr, "Undefined attribute '%s'\n", att);
254*287e80b3SSadaf Ebrahimi				fprintf(stderr,"  Acceptable attributes:\n");
255*287e80b3SSadaf Ebrahimi				fprintf(stderr,"    hex, sym, sym_offset, syscall, exe, log, usecs\n");
256*287e80b3SSadaf Ebrahimi				exit(-1);
257*287e80b3SSadaf Ebrahimi			}
258*287e80b3SSadaf Ebrahimi		}
259*287e80b3SSadaf Ebrahimi		cnt++;
260*287e80b3SSadaf Ebrahimi	}
261*287e80b3SSadaf Ebrahimi	return cnt;
262*287e80b3SSadaf Ebrahimi}
263*287e80b3SSadaf Ebrahimi
264*287e80b3SSadaf Ebrahimistatic void process_hist(enum commands cmd, const char *instance_name,
265*287e80b3SSadaf Ebrahimi			 char *group, char *keys, char *vals, char *sort,
266*287e80b3SSadaf Ebrahimi			 char *ascend, char *desc)
267*287e80b3SSadaf Ebrahimi{
268*287e80b3SSadaf Ebrahimi	struct tracefs_instance *instance = NULL;
269*287e80b3SSadaf Ebrahimi	struct tracefs_hist *hist;
270*287e80b3SSadaf Ebrahimi	struct tep_handle *tep;
271*287e80b3SSadaf Ebrahimi	struct tracefs_hist_axis *axes = NULL;
272*287e80b3SSadaf Ebrahimi	char *system;
273*287e80b3SSadaf Ebrahimi	char *event;
274*287e80b3SSadaf Ebrahimi	char *sav;
275*287e80b3SSadaf Ebrahimi	char *val;
276*287e80b3SSadaf Ebrahimi	int ret;
277*287e80b3SSadaf Ebrahimi	int cnt;
278*287e80b3SSadaf Ebrahimi
279*287e80b3SSadaf Ebrahimi	if (instance_name) {
280*287e80b3SSadaf Ebrahimi		instance = tracefs_instance_create(instance_name);
281*287e80b3SSadaf Ebrahimi		if (!instance) {
282*287e80b3SSadaf Ebrahimi			fprintf(stderr, "Failed instance create\n");
283*287e80b3SSadaf Ebrahimi			exit(-1);
284*287e80b3SSadaf Ebrahimi		}
285*287e80b3SSadaf Ebrahimi	}
286*287e80b3SSadaf Ebrahimi
287*287e80b3SSadaf Ebrahimi	tep = tracefs_local_events(NULL);
288*287e80b3SSadaf Ebrahimi	if (!tep) {
289*287e80b3SSadaf Ebrahimi		perror("Could not read events");
290*287e80b3SSadaf Ebrahimi		exit(-1);
291*287e80b3SSadaf Ebrahimi	}
292*287e80b3SSadaf Ebrahimi
293*287e80b3SSadaf Ebrahimi	parse_system_event(group, &system, &event);
294*287e80b3SSadaf Ebrahimi
295*287e80b3SSadaf Ebrahimi	if (cmd == SHOW) {
296*287e80b3SSadaf Ebrahimi		char *content;
297*287e80b3SSadaf Ebrahimi		content = tracefs_event_file_read(instance, system, event,
298*287e80b3SSadaf Ebrahimi						  "hist", NULL);
299*287e80b3SSadaf Ebrahimi		if (!content) {
300*287e80b3SSadaf Ebrahimi			perror("Reading hist file");
301*287e80b3SSadaf Ebrahimi			exit(-1);
302*287e80b3SSadaf Ebrahimi		}
303*287e80b3SSadaf Ebrahimi		printf("%s\n", content);
304*287e80b3SSadaf Ebrahimi		free(content);
305*287e80b3SSadaf Ebrahimi		return;
306*287e80b3SSadaf Ebrahimi	}
307*287e80b3SSadaf Ebrahimi
308*287e80b3SSadaf Ebrahimi	if (!keys) {
309*287e80b3SSadaf Ebrahimi		fprintf(stderr, "Command needs -k option\n");
310*287e80b3SSadaf Ebrahimi		exit(-1);
311*287e80b3SSadaf Ebrahimi	}
312*287e80b3SSadaf Ebrahimi
313*287e80b3SSadaf Ebrahimi	cnt = parse_keys(keys, &axes);
314*287e80b3SSadaf Ebrahimi	if (!cnt) {
315*287e80b3SSadaf Ebrahimi		fprintf(stderr, "No keys??\n");
316*287e80b3SSadaf Ebrahimi		exit(-1);
317*287e80b3SSadaf Ebrahimi	}
318*287e80b3SSadaf Ebrahimi
319*287e80b3SSadaf Ebrahimi	/* Show examples of hist1d and hist2d */
320*287e80b3SSadaf Ebrahimi	switch (cnt) {
321*287e80b3SSadaf Ebrahimi	case 1:
322*287e80b3SSadaf Ebrahimi		hist = tracefs_hist_alloc(tep, system, event,
323*287e80b3SSadaf Ebrahimi					  axes[0].key, axes[0].type);
324*287e80b3SSadaf Ebrahimi		break;
325*287e80b3SSadaf Ebrahimi	case 2:
326*287e80b3SSadaf Ebrahimi		hist = tracefs_hist_alloc_2d(tep, system, event,
327*287e80b3SSadaf Ebrahimi					     axes[0].key, axes[0].type,
328*287e80b3SSadaf Ebrahimi					     axes[1].key, axes[1].type);
329*287e80b3SSadaf Ebrahimi		break;
330*287e80b3SSadaf Ebrahimi	default:
331*287e80b3SSadaf Ebrahimi		/* Really, 1 and 2 could use this too */
332*287e80b3SSadaf Ebrahimi		hist = tracefs_hist_alloc_nd(tep, system, event, axes);
333*287e80b3SSadaf Ebrahimi	}
334*287e80b3SSadaf Ebrahimi	if (!hist) {
335*287e80b3SSadaf Ebrahimi		fprintf(stderr, "Failed hist create\n");
336*287e80b3SSadaf Ebrahimi		exit(-1);
337*287e80b3SSadaf Ebrahimi	}
338*287e80b3SSadaf Ebrahimi
339*287e80b3SSadaf Ebrahimi	if (vals) {
340*287e80b3SSadaf Ebrahimi		sav = NULL;
341*287e80b3SSadaf Ebrahimi		for (val = strtok_r(vals, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) {
342*287e80b3SSadaf Ebrahimi			ret = tracefs_hist_add_value(hist, val);
343*287e80b3SSadaf Ebrahimi			if (ret) {
344*287e80b3SSadaf Ebrahimi				fprintf(stderr, "Failed to add value %s\n", val);
345*287e80b3SSadaf Ebrahimi				exit(-1);
346*287e80b3SSadaf Ebrahimi			}
347*287e80b3SSadaf Ebrahimi		}
348*287e80b3SSadaf Ebrahimi	}
349*287e80b3SSadaf Ebrahimi
350*287e80b3SSadaf Ebrahimi	if (sort) {
351*287e80b3SSadaf Ebrahimi		sav = NULL;
352*287e80b3SSadaf Ebrahimi		for (val = strtok_r(sort, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) {
353*287e80b3SSadaf Ebrahimi			ret = tracefs_hist_add_sort_key(hist, val);
354*287e80b3SSadaf Ebrahimi			if (ret) {
355*287e80b3SSadaf Ebrahimi				fprintf(stderr, "Failed to add sort key/val %s\n", val);
356*287e80b3SSadaf Ebrahimi				exit(-1);
357*287e80b3SSadaf Ebrahimi			}
358*287e80b3SSadaf Ebrahimi		}
359*287e80b3SSadaf Ebrahimi	}
360*287e80b3SSadaf Ebrahimi
361*287e80b3SSadaf Ebrahimi	if (ascend) {
362*287e80b3SSadaf Ebrahimi		sav = NULL;
363*287e80b3SSadaf Ebrahimi		for (val = strtok_r(ascend, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) {
364*287e80b3SSadaf Ebrahimi			ret = tracefs_hist_sort_key_direction(hist, val, TRACEFS_HIST_SORT_ASCENDING);
365*287e80b3SSadaf Ebrahimi			if (ret) {
366*287e80b3SSadaf Ebrahimi				fprintf(stderr, "Failed to add ascending key/val %s\n", val);
367*287e80b3SSadaf Ebrahimi				exit(-1);
368*287e80b3SSadaf Ebrahimi			}
369*287e80b3SSadaf Ebrahimi		}
370*287e80b3SSadaf Ebrahimi	}
371*287e80b3SSadaf Ebrahimi
372*287e80b3SSadaf Ebrahimi	if (desc) {
373*287e80b3SSadaf Ebrahimi		sav = NULL;
374*287e80b3SSadaf Ebrahimi		for (val = strtok_r(desc, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) {
375*287e80b3SSadaf Ebrahimi			ret = tracefs_hist_sort_key_direction(hist, val, TRACEFS_HIST_SORT_DESCENDING);
376*287e80b3SSadaf Ebrahimi			if (ret) {
377*287e80b3SSadaf Ebrahimi				fprintf(stderr, "Failed to add descending key/val %s\n", val);
378*287e80b3SSadaf Ebrahimi				exit(-1);
379*287e80b3SSadaf Ebrahimi			}
380*287e80b3SSadaf Ebrahimi		}
381*287e80b3SSadaf Ebrahimi	}
382*287e80b3SSadaf Ebrahimi
383*287e80b3SSadaf Ebrahimi	tracefs_error_clear(instance);
384*287e80b3SSadaf Ebrahimi
385*287e80b3SSadaf Ebrahimi	switch (cmd) {
386*287e80b3SSadaf Ebrahimi	case START:
387*287e80b3SSadaf Ebrahimi		ret = tracefs_hist_start(instance, hist);
388*287e80b3SSadaf Ebrahimi		if (ret) {
389*287e80b3SSadaf Ebrahimi			char *err = tracefs_error_last(instance);
390*287e80b3SSadaf Ebrahimi			if (err)
391*287e80b3SSadaf Ebrahimi				fprintf(stderr, "\n%s\n", err);
392*287e80b3SSadaf Ebrahimi		}
393*287e80b3SSadaf Ebrahimi		break;
394*287e80b3SSadaf Ebrahimi	case PAUSE:
395*287e80b3SSadaf Ebrahimi		ret = tracefs_hist_pause(instance, hist);
396*287e80b3SSadaf Ebrahimi		break;
397*287e80b3SSadaf Ebrahimi	case CONT:
398*287e80b3SSadaf Ebrahimi		ret = tracefs_hist_continue(instance, hist);
399*287e80b3SSadaf Ebrahimi		break;
400*287e80b3SSadaf Ebrahimi	case RESET:
401*287e80b3SSadaf Ebrahimi		ret = tracefs_hist_reset(instance, hist);
402*287e80b3SSadaf Ebrahimi		break;
403*287e80b3SSadaf Ebrahimi	case DELETE:
404*287e80b3SSadaf Ebrahimi		ret = tracefs_hist_destroy(instance, hist);
405*287e80b3SSadaf Ebrahimi		break;
406*287e80b3SSadaf Ebrahimi	case SHOW:
407*287e80b3SSadaf Ebrahimi		/* Show was already done */
408*287e80b3SSadaf Ebrahimi		break;
409*287e80b3SSadaf Ebrahimi	}
410*287e80b3SSadaf Ebrahimi	if (ret)
411*287e80b3SSadaf Ebrahimi		fprintf(stderr, "Failed: command\n");
412*287e80b3SSadaf Ebrahimi	exit(ret);
413*287e80b3SSadaf Ebrahimi}
414*287e80b3SSadaf Ebrahimi
415*287e80b3SSadaf Ebrahimiint main (int argc, char **argv, char **env)
416*287e80b3SSadaf Ebrahimi{
417*287e80b3SSadaf Ebrahimi	enum commands cmd;
418*287e80b3SSadaf Ebrahimi	char *instance = NULL;
419*287e80b3SSadaf Ebrahimi	char *cmd_str;
420*287e80b3SSadaf Ebrahimi	char *event = NULL;
421*287e80b3SSadaf Ebrahimi	char *keys = NULL;
422*287e80b3SSadaf Ebrahimi	char *vals = NULL;
423*287e80b3SSadaf Ebrahimi	char *sort = NULL;
424*287e80b3SSadaf Ebrahimi	char *desc = NULL;
425*287e80b3SSadaf Ebrahimi	char *ascend = NULL;
426*287e80b3SSadaf Ebrahimi
427*287e80b3SSadaf Ebrahimi	if (argc < 2) {
428*287e80b3SSadaf Ebrahimi		fprintf(stderr, "usage: %s command [-B instance][-e [system/]event][-k keys][-v vals][-s sort]\n", argv[0]);
429*287e80b3SSadaf Ebrahimi		fprintf(stderr, "      [-a ascending][-d descending]\n");
430*287e80b3SSadaf Ebrahimi		exit(-1);
431*287e80b3SSadaf Ebrahimi	}
432*287e80b3SSadaf Ebrahimi
433*287e80b3SSadaf Ebrahimi	cmd_str = argv[1];
434*287e80b3SSadaf Ebrahimi
435*287e80b3SSadaf Ebrahimi	if (!strcmp(cmd_str, "start"))
436*287e80b3SSadaf Ebrahimi		cmd = START;
437*287e80b3SSadaf Ebrahimi	else if (!strcmp(cmd_str, "pause"))
438*287e80b3SSadaf Ebrahimi		cmd = PAUSE;
439*287e80b3SSadaf Ebrahimi	else if (!strcmp(cmd_str, "cont"))
440*287e80b3SSadaf Ebrahimi		cmd = CONT;
441*287e80b3SSadaf Ebrahimi	else if (!strcmp(cmd_str, "reset"))
442*287e80b3SSadaf Ebrahimi		cmd = RESET;
443*287e80b3SSadaf Ebrahimi	else if (!strcmp(cmd_str, "delete"))
444*287e80b3SSadaf Ebrahimi		cmd = DELETE;
445*287e80b3SSadaf Ebrahimi	else if (!strcmp(cmd_str, "show"))
446*287e80b3SSadaf Ebrahimi		cmd = SHOW;
447*287e80b3SSadaf Ebrahimi	else {
448*287e80b3SSadaf Ebrahimi		fprintf(stderr, "Unknown command %s\n", cmd_str);
449*287e80b3SSadaf Ebrahimi		exit(-1);
450*287e80b3SSadaf Ebrahimi	}
451*287e80b3SSadaf Ebrahimi
452*287e80b3SSadaf Ebrahimi	for (;;) {
453*287e80b3SSadaf Ebrahimi		int c;
454*287e80b3SSadaf Ebrahimi
455*287e80b3SSadaf Ebrahimi		c = getopt(argc - 1, argv + 1, "e:k:v:B:s:d:a:");
456*287e80b3SSadaf Ebrahimi		if (c == -1)
457*287e80b3SSadaf Ebrahimi			break;
458*287e80b3SSadaf Ebrahimi
459*287e80b3SSadaf Ebrahimi		switch (c) {
460*287e80b3SSadaf Ebrahimi		case 'e':
461*287e80b3SSadaf Ebrahimi			event = optarg;
462*287e80b3SSadaf Ebrahimi			break;
463*287e80b3SSadaf Ebrahimi		case 'k':
464*287e80b3SSadaf Ebrahimi			keys = optarg;
465*287e80b3SSadaf Ebrahimi			break;
466*287e80b3SSadaf Ebrahimi		case 'v':
467*287e80b3SSadaf Ebrahimi			vals = optarg;
468*287e80b3SSadaf Ebrahimi			break;
469*287e80b3SSadaf Ebrahimi		case 'B':
470*287e80b3SSadaf Ebrahimi			instance = optarg;
471*287e80b3SSadaf Ebrahimi			break;
472*287e80b3SSadaf Ebrahimi		case 's':
473*287e80b3SSadaf Ebrahimi			sort = optarg;
474*287e80b3SSadaf Ebrahimi			break;
475*287e80b3SSadaf Ebrahimi		case 'd':
476*287e80b3SSadaf Ebrahimi			desc = optarg;
477*287e80b3SSadaf Ebrahimi			break;
478*287e80b3SSadaf Ebrahimi		case 'a':
479*287e80b3SSadaf Ebrahimi			ascend = optarg;
480*287e80b3SSadaf Ebrahimi			break;
481*287e80b3SSadaf Ebrahimi		}
482*287e80b3SSadaf Ebrahimi	}
483*287e80b3SSadaf Ebrahimi	if (!event) {
484*287e80b3SSadaf Ebrahimi		event = "kmem/kmalloc";
485*287e80b3SSadaf Ebrahimi		if (!keys)
486*287e80b3SSadaf Ebrahimi			keys = "call_site.sym,bytes_req";
487*287e80b3SSadaf Ebrahimi		if (!vals)
488*287e80b3SSadaf Ebrahimi			vals = "bytes_alloc";
489*287e80b3SSadaf Ebrahimi		if (!sort)
490*287e80b3SSadaf Ebrahimi			sort = "bytes_req,bytes_alloc";
491*287e80b3SSadaf Ebrahimi		if (!desc)
492*287e80b3SSadaf Ebrahimi			desc = "bytes_alloc";
493*287e80b3SSadaf Ebrahimi	}
494*287e80b3SSadaf Ebrahimi	process_hist(cmd, instance, event, keys, vals, sort, ascend, desc);
495*287e80b3SSadaf Ebrahimi}
496*287e80b3SSadaf Ebrahimi--
497*287e80b3SSadaf Ebrahimi
498*287e80b3SSadaf EbrahimiFILES
499*287e80b3SSadaf Ebrahimi-----
500*287e80b3SSadaf Ebrahimi[verse]
501*287e80b3SSadaf Ebrahimi--
502*287e80b3SSadaf Ebrahimi*tracefs.h*
503*287e80b3SSadaf Ebrahimi	Header file to include in order to have access to the library APIs.
504*287e80b3SSadaf Ebrahimi*-ltracefs*
505*287e80b3SSadaf Ebrahimi	Linker switch to add when building a program that uses the library.
506*287e80b3SSadaf Ebrahimi--
507*287e80b3SSadaf Ebrahimi
508*287e80b3SSadaf EbrahimiSEE ALSO
509*287e80b3SSadaf Ebrahimi--------
510*287e80b3SSadaf Ebrahimi*libtracefs*(3),
511*287e80b3SSadaf Ebrahimi*libtraceevent*(3),
512*287e80b3SSadaf Ebrahimi*trace-cmd*(1),
513*287e80b3SSadaf Ebrahimi*tracefs_hist_pause*(3),
514*287e80b3SSadaf Ebrahimi*tracefs_hist_continue*(3),
515*287e80b3SSadaf Ebrahimi*tracefs_hist_reset*(3)
516*287e80b3SSadaf Ebrahimi
517*287e80b3SSadaf EbrahimiAUTHOR
518*287e80b3SSadaf Ebrahimi------
519*287e80b3SSadaf Ebrahimi[verse]
520*287e80b3SSadaf Ebrahimi--
521*287e80b3SSadaf Ebrahimi*Steven Rostedt* <[email protected]>
522*287e80b3SSadaf Ebrahimi*Tzvetomir Stoyanov* <[email protected]>
523*287e80b3SSadaf Ebrahimi*sameeruddin shaik* <[email protected]>
524*287e80b3SSadaf Ebrahimi--
525*287e80b3SSadaf EbrahimiREPORTING BUGS
526*287e80b3SSadaf Ebrahimi--------------
527*287e80b3SSadaf EbrahimiReport bugs to  <[email protected]>
528*287e80b3SSadaf Ebrahimi
529*287e80b3SSadaf EbrahimiLICENSE
530*287e80b3SSadaf Ebrahimi-------
531*287e80b3SSadaf Ebrahimilibtracefs is Free Software licensed under the GNU LGPL 2.1
532*287e80b3SSadaf Ebrahimi
533*287e80b3SSadaf EbrahimiRESOURCES
534*287e80b3SSadaf Ebrahimi---------
535*287e80b3SSadaf Ebrahimihttps://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/
536*287e80b3SSadaf Ebrahimi
537*287e80b3SSadaf EbrahimiCOPYING
538*287e80b3SSadaf Ebrahimi-------
539*287e80b3SSadaf EbrahimiCopyright \(C) 2020 VMware, Inc. Free use of this software is granted under
540*287e80b3SSadaf Ebrahimithe terms of the GNU Public License (GPL).
541