xref: /aosp_15_r20/external/libtracefs/Documentation/libtracefs-hist.txt (revision 287e80b3a36113050663245e7f2c00d274188f18)
1*287e80b3SSadaf Ebrahimilibtracefs(3)
2*287e80b3SSadaf Ebrahimi=============
3*287e80b3SSadaf Ebrahimi
4*287e80b3SSadaf EbrahimiNAME
5*287e80b3SSadaf Ebrahimi----
6*287e80b3SSadaf Ebrahimitracefs_hist_alloc, tracefs_hist_alloc_2d, tracefs_hist_alloc_nd, tracefs_hist_alloc_nd_cnt, tracefs_hist_free,
7*287e80b3SSadaf Ebrahimitracefs_hist_add_key, tracefs_hist_add_key_cnt, tracefs_hist_add_value - Create and destroy event histograms
8*287e80b3SSadaf Ebrahimi
9*287e80b3SSadaf EbrahimiSYNOPSIS
10*287e80b3SSadaf Ebrahimi--------
11*287e80b3SSadaf Ebrahimi[verse]
12*287e80b3SSadaf Ebrahimi--
13*287e80b3SSadaf Ebrahimi*#include <tracefs.h>*
14*287e80b3SSadaf Ebrahimi
15*287e80b3SSadaf Ebrahimienum *tracefs_hist_key_type* {
16*287e80b3SSadaf Ebrahimi	*TRACEFS_HIST_KEY_NORMAL* = 0,
17*287e80b3SSadaf Ebrahimi	*TRACEFS_HIST_KEY_HEX*,
18*287e80b3SSadaf Ebrahimi	*TRACEFS_HIST_KEY_SYM*,
19*287e80b3SSadaf Ebrahimi	*TRACEFS_HIST_KEY_SYM_OFFSET*,
20*287e80b3SSadaf Ebrahimi	*TRACEFS_HIST_KEY_SYSCALL*,
21*287e80b3SSadaf Ebrahimi	*TRACEFS_HIST_KEY_EXECNAME*,
22*287e80b3SSadaf Ebrahimi	*TRACEFS_HIST_KEY_LOG*,
23*287e80b3SSadaf Ebrahimi	*TRACEFS_HIST_KEY_USECS*,
24*287e80b3SSadaf Ebrahimi	*TRACEFS_HIST_KEY_MAX*
25*287e80b3SSadaf Ebrahimi};
26*287e80b3SSadaf Ebrahimi
27*287e80b3SSadaf Ebrahimistruct *tracefs_hist_axis* {
28*287e80b3SSadaf Ebrahimi	const char pass:[*]_key_;
29*287e80b3SSadaf Ebrahimi	enum tracefs_hist_key_type _type_;
30*287e80b3SSadaf Ebrahimi};
31*287e80b3SSadaf Ebrahimi
32*287e80b3SSadaf Ebrahimistruct tracefs_hist pass:[*]*tracefs_hist_alloc*(struct tracefs_tep pass:[*] _tep_,
33*287e80b3SSadaf Ebrahimi			const char pass:[*]_system_, const char pass:[*]_event_,
34*287e80b3SSadaf Ebrahimi			const char pass:[*]_key_, enum tracefs_hist_key_type _type_);
35*287e80b3SSadaf Ebrahimistruct tracefs_hist pass:[*]*tracefs_hist_alloc_2d*(struct tracefs_tep pass:[*] _tep_,
36*287e80b3SSadaf Ebrahimi			const char pass:[*]_system_, const char pass:[*]_event_,
37*287e80b3SSadaf Ebrahimi			const char pass:[*]_key1_, enum tracefs_hist_key_type _type1_,
38*287e80b3SSadaf Ebrahimi			const char pass:[*]_key2_, enum tracefs_hist_key_type _type2_));
39*287e80b3SSadaf Ebrahimistruct tracefs_hist pass:[*]*tracefs_hist_alloc_nd*(struct tracefs_tep pass:[*] _tep_,
40*287e80b3SSadaf Ebrahimi			const char pass:[*]_system_, const char pass:[*]_event_,
41*287e80b3SSadaf Ebrahimi			struct tracefs_hist_axis pass:[*]_axes_);
42*287e80b3SSadaf Ebrahimistruct tracefs_hist pass:[*]*tracefs_hist_alloc_nd_cnt*(struct tep_handle pass:[*]_tep_,
43*287e80b3SSadaf Ebrahimi			  const char pass:[*]_system_, const char pass:[*]_event_name_,
44*287e80b3SSadaf Ebrahimi			  struct tracefs_hist_axis_cnt pass:[*]_axes_);
45*287e80b3SSadaf Ebrahimivoid *tracefs_hist_free*(struct tracefs_hist pass:[*]_hist_);
46*287e80b3SSadaf Ebrahimi
47*287e80b3SSadaf Ebrahimiint *tracefs_hist_add_key*(struct tracefs_hist pass:[*]_hist_, const char pass:[*]_key_,
48*287e80b3SSadaf Ebrahimi			 enum tracefs_hist_key_type _type_);
49*287e80b3SSadaf Ebrahimiint *tracefs_hist_add_key_cnt*(struct tracefs_hist pass:[*]_hist_, const char pass:[*]_key_,
50*287e80b3SSadaf Ebrahimi			 enum tracefs_hist_key_type _type_, int _cnt_);
51*287e80b3SSadaf Ebrahimiint *tracefs_hist_add_value*(struct tracefs_hist pass:[*]_hist_, const char pass:[*]_value_);
52*287e80b3SSadaf Ebrahimi--
53*287e80b3SSadaf Ebrahimi
54*287e80b3SSadaf EbrahimiDESCRIPTION
55*287e80b3SSadaf Ebrahimi-----------
56*287e80b3SSadaf EbrahimiEvent histograms are created by the trigger file in the event directory.
57*287e80b3SSadaf EbrahimiThe syntax can be complex and difficult to get correct. This API handles the
58*287e80b3SSadaf Ebrahimisyntax, and facilitates the creation and interaction with the event histograms.
59*287e80b3SSadaf EbrahimiSee https://www.kernel.org/doc/html/latest/trace/histogram.html for more information.
60*287e80b3SSadaf Ebrahimi
61*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc*() allocates a "struct tracefs_hist" descriptor of a one-dimensional
62*287e80b3SSadaf Ebrahimihistogram and returns the address of it. This descriptor must be freed by *tracefs_hist_free*().
63*287e80b3SSadaf EbrahimiThe _tep_ is a trace event handle (see *tracefs_local_events*(3)), that holds the
64*287e80b3SSadaf Ebrahimi_system_ and _event_ that the histogram will be attached to. The _system_ is the
65*287e80b3SSadaf Ebrahimisystem or group of the event. The _event_ is the event to attach the histogram to.
66*287e80b3SSadaf EbrahimiThe _key_ is a field of the event that will be used as the key(dimension) of the histogram.
67*287e80b3SSadaf EbrahimiThe _type_ is the type of the _key_. See KEY TYPES below.
68*287e80b3SSadaf Ebrahimi
69*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_2d*() allocates a "struct tracefs_hist" descriptor of a two-dimensional
70*287e80b3SSadaf Ebrahimihistogram and returns the address of it. This descriptor must be freed by *tracefs_hist_free*().
71*287e80b3SSadaf EbrahimiThe _tep_ is a trace event handle (see *tracefs_local_events*(3)), that holds the
72*287e80b3SSadaf Ebrahimi_system_ and _event_ that the histogram will be attached to. The _system_ is the
73*287e80b3SSadaf Ebrahimisystem or group of the event. The _event_ is the event to attach the histogram to.
74*287e80b3SSadaf EbrahimiThe _key1_ is the first field of the event that will be used as the key(dimension)
75*287e80b3SSadaf Ebrahimiof the histogram. The _type1_ is the type of the _key1_. See KEY TYPES below.
76*287e80b3SSadaf EbrahimiThe _key2_ is the second field of the event that will be used as the key(dimension)
77*287e80b3SSadaf Ebrahimiof the histogram. The _type2_ is the type of the _key2_. See KEY TYPES below.
78*287e80b3SSadaf Ebrahimi
79*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd*() allocates a "struct tracefs_hist" descriptor of an N-dimensional
80*287e80b3SSadaf Ebrahimihistogram and returns the address of it. This descriptor must be freed by *tracefs_hist_free*().
81*287e80b3SSadaf EbrahimiThe _tep_ is a trace event handle (see *tracefs_local_events*(3)), that holds the
82*287e80b3SSadaf Ebrahimi_system_ and _event_ that the histogram will be attached to. The _system_ is the
83*287e80b3SSadaf Ebrahimisystem or group of the event. The _event_ is the event to attach the histogram to.
84*287e80b3SSadaf EbrahimiThe _axes_ is an array of _key_ / _type_ pairs, defining the dimensions of the histogram.
85*287e80b3SSadaf Ebrahimi
86*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd_cnt*() will initialize a histogram descriptor that will be attached to
87*287e80b3SSadaf Ebrahimithe _system_/_event_. This only initializes the descriptor with the given _axes_ keys as primaries.
88*287e80b3SSadaf EbrahimiThis only initializes the descriptor, it does not start the histogram in the kernel.
89*287e80b3SSadaf EbrahimiThe difference between this and *tracefs_hist_alloc_nd()* is that the _axes_ parameter
90*287e80b3SSadaf Ebrahimiis of type *struct tracefs_hist_axis_cnt* and not *struct tracefs_hist_axis*.
91*287e80b3SSadaf Ebrahimi
92*287e80b3SSadaf Ebrahimi*tracefs_hist_free*() frees the _tracefs_hist_ descriptor. Note, it does not stop
93*287e80b3SSadaf Ebrahimior disable the running histogram if it was started. *tracefs_hist_destroy*() needs
94*287e80b3SSadaf Ebrahimito be called to do so.
95*287e80b3SSadaf Ebrahimi
96*287e80b3SSadaf Ebrahimi*tracefs_hist_add_key*() Adds a secondary or tertiary key to the histogram.
97*287e80b3SSadaf EbrahimiThe key passed to *tracefs_hist_alloc_nd*() is the primary key of the histogram.
98*287e80b3SSadaf EbrahimiThe first time this function is called, it will add a secondary key (or two dimensional
99*287e80b3SSadaf Ebrahimihistogram). If this function is called again on the same histogram, it will add
100*287e80b3SSadaf Ebrahimia _tertiary_ key (or three dimensional histogram). The _hist_ parameter is the
101*287e80b3SSadaf Ebrahimihistogram descriptor to add the _key_ to. The _type_ is the type of key to add
102*287e80b3SSadaf Ebrahimi(See KEY TYPES below).
103*287e80b3SSadaf Ebrahimi
104*287e80b3SSadaf EbrahimiThe *tracefs_hist_add_key_cnt*() is the same as *tracefs_hist_add_key*() except
105*287e80b3SSadaf Ebrahimithat it allows to add a counter for the given type. Currently, there's only
106*287e80b3SSadaf Ebrahimithe *buckets* type that requires a counter. When adding a key with the buckets
107*287e80b3SSadaf Ebrahimitype, *tracefs_hist_add_key*() is not sufficient, as the *buckets* type requires
108*287e80b3SSadaf Ebrahimia counter or bucket size. Use *tracefs_hist_add_key_cnt*() when specifing
109*287e80b3SSadaf Ebrahimia key that is broken up into  buckets, and pass in the size of those buckets
110*287e80b3SSadaf Ebrahimiinto _cnt_.
111*287e80b3SSadaf Ebrahimi
112*287e80b3SSadaf Ebrahimi*tracefs_hist_add_value*() will add a value to record. By default, the value is
113*287e80b3SSadaf Ebrahimisimply the "hitcount" of the number of times a instance of the histogram's
114*287e80b3SSadaf Ebrahimikey was hit. The _hist_ is the histogram descriptor to add the value to.
115*287e80b3SSadaf EbrahimiThe _value_ is a field in the histogram to add to when an instance of the
116*287e80b3SSadaf Ebrahimikey is hit.
117*287e80b3SSadaf Ebrahimi
118*287e80b3SSadaf EbrahimiKEY TYPES
119*287e80b3SSadaf Ebrahimi---------
120*287e80b3SSadaf Ebrahimi
121*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd*() and *tracefs_hist_add_key*() both add a key and requires
122*287e80b3SSadaf Ebrahimithat key to have a type. The types may be:
123*287e80b3SSadaf Ebrahimi
124*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_NORMAL* or zero (0) which is to not modify the type.
125*287e80b3SSadaf Ebrahimi
126*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_HEX* to display the key in hex.
127*287e80b3SSadaf Ebrahimi
128*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_SYM* to display the key as a kernel symbol (if found). If
129*287e80b3SSadaf Ebrahimithe key is an address, this is useful as it will display the function names instead
130*287e80b3SSadaf Ebrahimiof just a number.
131*287e80b3SSadaf Ebrahimi
132*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_SYM_OFFSET* similar to *TRACEFS_HIST_KEY_SYM* but will also include
133*287e80b3SSadaf Ebrahimithe offset of the function to match the exact address.
134*287e80b3SSadaf Ebrahimi
135*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_SYSCALL* If the key is a system call "id" (the number passed from user
136*287e80b3SSadaf Ebrahimispace to the kernel to tell it what system call it is calling), then the name of
137*287e80b3SSadaf Ebrahimithe system call is displayed.
138*287e80b3SSadaf Ebrahimi
139*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_EXECNAME* If "common_pid" is the key (the pid of the executing task),
140*287e80b3SSadaf Ebrahimiinstead of showing the number, show the name of the running task.
141*287e80b3SSadaf Ebrahimi
142*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_LOG* will display the key in a binary logarithmic scale.
143*287e80b3SSadaf Ebrahimi
144*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_USECS* for use with "common_timestamp" or TRACEFS_HIST_TIMESTAMP,
145*287e80b3SSadaf Ebrahimiin which case it will show the timestamp in microseconds instead of nanoseconds.
146*287e80b3SSadaf Ebrahimi
147*287e80b3SSadaf EbrahimiRETURN VALUE
148*287e80b3SSadaf Ebrahimi------------
149*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd*() returns an allocated histogram descriptor which must
150*287e80b3SSadaf Ebrahimibe freed by *tracefs_hist_free*() or NULL on error.
151*287e80b3SSadaf Ebrahimi
152*287e80b3SSadaf EbrahimiAll the other functions return zero on success or -1 on error.
153*287e80b3SSadaf Ebrahimi
154*287e80b3SSadaf EbrahimiIf *tracefs_hist_start*() returns an error, a message may be displayed
155*287e80b3SSadaf Ebrahimiin the kernel that can be retrieved by *tracefs_error_last()*.
156*287e80b3SSadaf Ebrahimi
157*287e80b3SSadaf EbrahimiEXAMPLE
158*287e80b3SSadaf Ebrahimi-------
159*287e80b3SSadaf Ebrahimi[source,c]
160*287e80b3SSadaf Ebrahimi--
161*287e80b3SSadaf Ebrahimi#include <stdlib.h>
162*287e80b3SSadaf Ebrahimi#include <ctype.h>
163*287e80b3SSadaf Ebrahimi#include <unistd.h>
164*287e80b3SSadaf Ebrahimi#include <tracefs.h>
165*287e80b3SSadaf Ebrahimi
166*287e80b3SSadaf Ebrahimienum commands {
167*287e80b3SSadaf Ebrahimi	START,
168*287e80b3SSadaf Ebrahimi	PAUSE,
169*287e80b3SSadaf Ebrahimi	CONT,
170*287e80b3SSadaf Ebrahimi	RESET,
171*287e80b3SSadaf Ebrahimi	DELETE,
172*287e80b3SSadaf Ebrahimi	SHOW,
173*287e80b3SSadaf Ebrahimi};
174*287e80b3SSadaf Ebrahimi
175*287e80b3SSadaf Ebrahimistatic void parse_system_event(char *group, char **system, char **event)
176*287e80b3SSadaf Ebrahimi{
177*287e80b3SSadaf Ebrahimi	*system = strtok(group, "/");
178*287e80b3SSadaf Ebrahimi	*event = strtok(NULL, "/");
179*287e80b3SSadaf Ebrahimi	if (!*event) {
180*287e80b3SSadaf Ebrahimi		*event = *system;
181*287e80b3SSadaf Ebrahimi		*system = NULL;
182*287e80b3SSadaf Ebrahimi	}
183*287e80b3SSadaf Ebrahimi}
184*287e80b3SSadaf Ebrahimi
185*287e80b3SSadaf Ebrahimistatic int parse_keys(char *keys, struct tracefs_hist_axis_cnt **axes)
186*287e80b3SSadaf Ebrahimi{
187*287e80b3SSadaf Ebrahimi	char *sav = NULL;
188*287e80b3SSadaf Ebrahimi	char *key;
189*287e80b3SSadaf Ebrahimi	int cnt = 0;
190*287e80b3SSadaf Ebrahimi
191*287e80b3SSadaf Ebrahimi	for (key = strtok_r(keys, ",", &sav); key; key = strtok_r(NULL, ",", &sav)) {
192*287e80b3SSadaf Ebrahimi		struct tracefs_hist_axis_cnt *ax;
193*287e80b3SSadaf Ebrahimi		char *att;
194*287e80b3SSadaf Ebrahimi
195*287e80b3SSadaf Ebrahimi		ax = realloc(*axes, sizeof(*ax) * (cnt + 2));
196*287e80b3SSadaf Ebrahimi		if (!ax) {
197*287e80b3SSadaf Ebrahimi			perror("Failed to allocate axes");
198*287e80b3SSadaf Ebrahimi			exit(-1);
199*287e80b3SSadaf Ebrahimi		}
200*287e80b3SSadaf Ebrahimi		ax[cnt].key = key;
201*287e80b3SSadaf Ebrahimi		ax[cnt].type = 0;
202*287e80b3SSadaf Ebrahimi		ax[cnt + 1].key = NULL;
203*287e80b3SSadaf Ebrahimi		ax[cnt + 1].type = 0;
204*287e80b3SSadaf Ebrahimi
205*287e80b3SSadaf Ebrahimi		*axes = ax;
206*287e80b3SSadaf Ebrahimi
207*287e80b3SSadaf Ebrahimi		att = strchr(key, '.');
208*287e80b3SSadaf Ebrahimi		if (att) {
209*287e80b3SSadaf Ebrahimi			*att++ = '\0';
210*287e80b3SSadaf Ebrahimi			if (strcmp(att, "hex") == 0)
211*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_HEX;
212*287e80b3SSadaf Ebrahimi			else if (strcmp(att, "sym") == 0)
213*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_SYM;
214*287e80b3SSadaf Ebrahimi			else if (strcmp(att, "sym_offset") == 0)
215*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_SYM_OFFSET;
216*287e80b3SSadaf Ebrahimi			else if (strcmp(att, "syscall") == 0)
217*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_SYSCALL;
218*287e80b3SSadaf Ebrahimi			else if (strcmp(att, "exec") == 0)
219*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_EXECNAME;
220*287e80b3SSadaf Ebrahimi			else if (strcmp(att, "log") == 0)
221*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_LOG;
222*287e80b3SSadaf Ebrahimi			else if (strcmp(att, "usecs") == 0)
223*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_USECS;
224*287e80b3SSadaf Ebrahimi			else if (strncmp(att, "buckets", 7) == 0) {
225*287e80b3SSadaf Ebrahimi				if (att[7] != '=' && !isdigit(att[8])) {
226*287e80b3SSadaf Ebrahimi					fprintf(stderr, "'buckets' key type requires '=<size>'\n");
227*287e80b3SSadaf Ebrahimi					exit(-1);
228*287e80b3SSadaf Ebrahimi				}
229*287e80b3SSadaf Ebrahimi				ax[cnt].type = TRACEFS_HIST_KEY_BUCKETS;
230*287e80b3SSadaf Ebrahimi				ax[cnt].cnt = atoi(&att[8]);
231*287e80b3SSadaf Ebrahimi			} else {
232*287e80b3SSadaf Ebrahimi				fprintf(stderr, "Undefined attribute '%s'\n", att);
233*287e80b3SSadaf Ebrahimi				fprintf(stderr,"  Acceptable attributes:\n");
234*287e80b3SSadaf Ebrahimi				fprintf(stderr,"    hex, sym, sym_offset, syscall, exe, log, usecs\n");
235*287e80b3SSadaf Ebrahimi				exit(-1);
236*287e80b3SSadaf Ebrahimi			}
237*287e80b3SSadaf Ebrahimi		}
238*287e80b3SSadaf Ebrahimi		cnt++;
239*287e80b3SSadaf Ebrahimi	}
240*287e80b3SSadaf Ebrahimi	return cnt;
241*287e80b3SSadaf Ebrahimi}
242*287e80b3SSadaf Ebrahimi
243*287e80b3SSadaf Ebrahimistatic void process_hist(enum commands cmd, const char *instance_name,
244*287e80b3SSadaf Ebrahimi			 char *group, char *keys, char *vals, char *sort,
245*287e80b3SSadaf Ebrahimi			 char *ascend, char *desc)
246*287e80b3SSadaf Ebrahimi{
247*287e80b3SSadaf Ebrahimi	struct tracefs_instance *instance = NULL;
248*287e80b3SSadaf Ebrahimi	struct tracefs_hist *hist;
249*287e80b3SSadaf Ebrahimi	struct tep_handle *tep;
250*287e80b3SSadaf Ebrahimi	struct tracefs_hist_axis_cnt *axes = NULL;
251*287e80b3SSadaf Ebrahimi	char *system;
252*287e80b3SSadaf Ebrahimi	char *event;
253*287e80b3SSadaf Ebrahimi	char *sav;
254*287e80b3SSadaf Ebrahimi	char *val;
255*287e80b3SSadaf Ebrahimi	int ret;
256*287e80b3SSadaf Ebrahimi	int cnt;
257*287e80b3SSadaf Ebrahimi
258*287e80b3SSadaf Ebrahimi	if (instance_name) {
259*287e80b3SSadaf Ebrahimi		instance = tracefs_instance_create(instance_name);
260*287e80b3SSadaf Ebrahimi		if (!instance) {
261*287e80b3SSadaf Ebrahimi			fprintf(stderr, "Failed instance create\n");
262*287e80b3SSadaf Ebrahimi			exit(-1);
263*287e80b3SSadaf Ebrahimi		}
264*287e80b3SSadaf Ebrahimi	}
265*287e80b3SSadaf Ebrahimi
266*287e80b3SSadaf Ebrahimi	tep = tracefs_local_events(NULL);
267*287e80b3SSadaf Ebrahimi	if (!tep) {
268*287e80b3SSadaf Ebrahimi		perror("Could not read events");
269*287e80b3SSadaf Ebrahimi		exit(-1);
270*287e80b3SSadaf Ebrahimi	}
271*287e80b3SSadaf Ebrahimi
272*287e80b3SSadaf Ebrahimi	parse_system_event(group, &system, &event);
273*287e80b3SSadaf Ebrahimi
274*287e80b3SSadaf Ebrahimi	if (cmd == SHOW) {
275*287e80b3SSadaf Ebrahimi		char *content;
276*287e80b3SSadaf Ebrahimi		content = tracefs_event_file_read(instance, system, event,
277*287e80b3SSadaf Ebrahimi						  "hist", NULL);
278*287e80b3SSadaf Ebrahimi		if (!content) {
279*287e80b3SSadaf Ebrahimi			perror("Reading hist file");
280*287e80b3SSadaf Ebrahimi			exit(-1);
281*287e80b3SSadaf Ebrahimi		}
282*287e80b3SSadaf Ebrahimi		printf("%s\n", content);
283*287e80b3SSadaf Ebrahimi		free(content);
284*287e80b3SSadaf Ebrahimi		return;
285*287e80b3SSadaf Ebrahimi	}
286*287e80b3SSadaf Ebrahimi
287*287e80b3SSadaf Ebrahimi	if (!keys) {
288*287e80b3SSadaf Ebrahimi		fprintf(stderr, "Command needs -k option\n");
289*287e80b3SSadaf Ebrahimi		exit(-1);
290*287e80b3SSadaf Ebrahimi	}
291*287e80b3SSadaf Ebrahimi
292*287e80b3SSadaf Ebrahimi	cnt = parse_keys(keys, &axes);
293*287e80b3SSadaf Ebrahimi	if (!cnt) {
294*287e80b3SSadaf Ebrahimi		fprintf(stderr, "No keys??\n");
295*287e80b3SSadaf Ebrahimi		exit(-1);
296*287e80b3SSadaf Ebrahimi	}
297*287e80b3SSadaf Ebrahimi
298*287e80b3SSadaf Ebrahimi	/* buckets require the nd_cnt function */
299*287e80b3SSadaf Ebrahimi	switch (cnt) {
300*287e80b3SSadaf Ebrahimi	case 2:
301*287e80b3SSadaf Ebrahimi		if (axes[1].type == TRACEFS_HIST_KEY_BUCKETS)
302*287e80b3SSadaf Ebrahimi			cnt = -1;
303*287e80b3SSadaf Ebrahimi		/* fall through */
304*287e80b3SSadaf Ebrahimi	case 1:
305*287e80b3SSadaf Ebrahimi		if (axes[0].type == TRACEFS_HIST_KEY_BUCKETS)
306*287e80b3SSadaf Ebrahimi			cnt = -1;
307*287e80b3SSadaf Ebrahimi	}
308*287e80b3SSadaf Ebrahimi
309*287e80b3SSadaf Ebrahimi	/* Show examples of hist1d and hist2d */
310*287e80b3SSadaf Ebrahimi	switch (cnt) {
311*287e80b3SSadaf Ebrahimi	case 1:
312*287e80b3SSadaf Ebrahimi		hist = tracefs_hist_alloc(tep, system, event,
313*287e80b3SSadaf Ebrahimi					  axes[0].key, axes[0].type);
314*287e80b3SSadaf Ebrahimi		break;
315*287e80b3SSadaf Ebrahimi	case 2:
316*287e80b3SSadaf Ebrahimi		hist = tracefs_hist_alloc_2d(tep, system, event,
317*287e80b3SSadaf Ebrahimi					     axes[0].key, axes[0].type,
318*287e80b3SSadaf Ebrahimi					     axes[1].key, axes[1].type);
319*287e80b3SSadaf Ebrahimi		break;
320*287e80b3SSadaf Ebrahimi	default:
321*287e80b3SSadaf Ebrahimi		/* Really, 1 and 2 could use this too */
322*287e80b3SSadaf Ebrahimi		hist = tracefs_hist_alloc_nd_cnt(tep, system, event, axes);
323*287e80b3SSadaf Ebrahimi	}
324*287e80b3SSadaf Ebrahimi	if (!hist) {
325*287e80b3SSadaf Ebrahimi		fprintf(stderr, "Failed hist create\n");
326*287e80b3SSadaf Ebrahimi		exit(-1);
327*287e80b3SSadaf Ebrahimi	}
328*287e80b3SSadaf Ebrahimi
329*287e80b3SSadaf Ebrahimi	if (vals) {
330*287e80b3SSadaf Ebrahimi		sav = NULL;
331*287e80b3SSadaf Ebrahimi		for (val = strtok_r(vals, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) {
332*287e80b3SSadaf Ebrahimi			ret = tracefs_hist_add_value(hist, val);
333*287e80b3SSadaf Ebrahimi			if (ret) {
334*287e80b3SSadaf Ebrahimi				fprintf(stderr, "Failed to add value %s\n", val);
335*287e80b3SSadaf Ebrahimi				exit(-1);
336*287e80b3SSadaf Ebrahimi			}
337*287e80b3SSadaf Ebrahimi		}
338*287e80b3SSadaf Ebrahimi	}
339*287e80b3SSadaf Ebrahimi
340*287e80b3SSadaf Ebrahimi	if (sort) {
341*287e80b3SSadaf Ebrahimi		sav = NULL;
342*287e80b3SSadaf Ebrahimi		for (val = strtok_r(sort, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) {
343*287e80b3SSadaf Ebrahimi			ret = tracefs_hist_add_sort_key(hist, val);
344*287e80b3SSadaf Ebrahimi			if (ret) {
345*287e80b3SSadaf Ebrahimi				fprintf(stderr, "Failed to add sort key/val %s\n", val);
346*287e80b3SSadaf Ebrahimi				exit(-1);
347*287e80b3SSadaf Ebrahimi			}
348*287e80b3SSadaf Ebrahimi		}
349*287e80b3SSadaf Ebrahimi	}
350*287e80b3SSadaf Ebrahimi
351*287e80b3SSadaf Ebrahimi	if (ascend) {
352*287e80b3SSadaf Ebrahimi		sav = NULL;
353*287e80b3SSadaf Ebrahimi		for (val = strtok_r(ascend, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) {
354*287e80b3SSadaf Ebrahimi			ret = tracefs_hist_sort_key_direction(hist, val, TRACEFS_HIST_SORT_ASCENDING);
355*287e80b3SSadaf Ebrahimi			if (ret) {
356*287e80b3SSadaf Ebrahimi				fprintf(stderr, "Failed to add ascending key/val %s\n", val);
357*287e80b3SSadaf Ebrahimi				exit(-1);
358*287e80b3SSadaf Ebrahimi			}
359*287e80b3SSadaf Ebrahimi		}
360*287e80b3SSadaf Ebrahimi	}
361*287e80b3SSadaf Ebrahimi
362*287e80b3SSadaf Ebrahimi	if (desc) {
363*287e80b3SSadaf Ebrahimi		sav = NULL;
364*287e80b3SSadaf Ebrahimi		for (val = strtok_r(desc, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) {
365*287e80b3SSadaf Ebrahimi			ret = tracefs_hist_sort_key_direction(hist, val, TRACEFS_HIST_SORT_DESCENDING);
366*287e80b3SSadaf Ebrahimi			if (ret) {
367*287e80b3SSadaf Ebrahimi				fprintf(stderr, "Failed to add descending key/val %s\n", val);
368*287e80b3SSadaf Ebrahimi				exit(-1);
369*287e80b3SSadaf Ebrahimi			}
370*287e80b3SSadaf Ebrahimi		}
371*287e80b3SSadaf Ebrahimi	}
372*287e80b3SSadaf Ebrahimi
373*287e80b3SSadaf Ebrahimi	tracefs_error_clear(instance);
374*287e80b3SSadaf Ebrahimi
375*287e80b3SSadaf Ebrahimi	switch (cmd) {
376*287e80b3SSadaf Ebrahimi	case START:
377*287e80b3SSadaf Ebrahimi		ret = tracefs_hist_start(instance, hist);
378*287e80b3SSadaf Ebrahimi		if (ret) {
379*287e80b3SSadaf Ebrahimi			char *err = tracefs_error_last(instance);
380*287e80b3SSadaf Ebrahimi			if (err)
381*287e80b3SSadaf Ebrahimi				fprintf(stderr, "\n%s\n", err);
382*287e80b3SSadaf Ebrahimi		}
383*287e80b3SSadaf Ebrahimi		break;
384*287e80b3SSadaf Ebrahimi	case PAUSE:
385*287e80b3SSadaf Ebrahimi		ret = tracefs_hist_pause(instance, hist);
386*287e80b3SSadaf Ebrahimi		break;
387*287e80b3SSadaf Ebrahimi	case CONT:
388*287e80b3SSadaf Ebrahimi		ret = tracefs_hist_continue(instance, hist);
389*287e80b3SSadaf Ebrahimi		break;
390*287e80b3SSadaf Ebrahimi	case RESET:
391*287e80b3SSadaf Ebrahimi		ret = tracefs_hist_reset(instance, hist);
392*287e80b3SSadaf Ebrahimi		break;
393*287e80b3SSadaf Ebrahimi	case DELETE:
394*287e80b3SSadaf Ebrahimi		ret = tracefs_hist_destroy(instance, hist);
395*287e80b3SSadaf Ebrahimi		break;
396*287e80b3SSadaf Ebrahimi	case SHOW:
397*287e80b3SSadaf Ebrahimi		/* Show was already done */
398*287e80b3SSadaf Ebrahimi		break;
399*287e80b3SSadaf Ebrahimi	}
400*287e80b3SSadaf Ebrahimi	if (ret)
401*287e80b3SSadaf Ebrahimi		fprintf(stderr, "Failed: command\n");
402*287e80b3SSadaf Ebrahimi	exit(ret);
403*287e80b3SSadaf Ebrahimi}
404*287e80b3SSadaf Ebrahimi
405*287e80b3SSadaf Ebrahimiint main (int argc, char **argv, char **env)
406*287e80b3SSadaf Ebrahimi{
407*287e80b3SSadaf Ebrahimi	enum commands cmd;
408*287e80b3SSadaf Ebrahimi	char *instance = NULL;
409*287e80b3SSadaf Ebrahimi	char *cmd_str;
410*287e80b3SSadaf Ebrahimi	char *event = NULL;
411*287e80b3SSadaf Ebrahimi	char *keys = NULL;
412*287e80b3SSadaf Ebrahimi	char *vals = NULL;
413*287e80b3SSadaf Ebrahimi	char *sort = NULL;
414*287e80b3SSadaf Ebrahimi	char *desc = NULL;
415*287e80b3SSadaf Ebrahimi	char *ascend = NULL;
416*287e80b3SSadaf Ebrahimi
417*287e80b3SSadaf Ebrahimi	if (argc < 2) {
418*287e80b3SSadaf Ebrahimi		fprintf(stderr, "usage: %s command [-B instance][-e [system/]event][-k keys][-v vals][-s sort]\n", argv[0]);
419*287e80b3SSadaf Ebrahimi		fprintf(stderr, "      [-a ascending][-d descending]\n");
420*287e80b3SSadaf Ebrahimi		exit(-1);
421*287e80b3SSadaf Ebrahimi	}
422*287e80b3SSadaf Ebrahimi
423*287e80b3SSadaf Ebrahimi	cmd_str = argv[1];
424*287e80b3SSadaf Ebrahimi
425*287e80b3SSadaf Ebrahimi	if (!strcmp(cmd_str, "start"))
426*287e80b3SSadaf Ebrahimi		cmd = START;
427*287e80b3SSadaf Ebrahimi	else if (!strcmp(cmd_str, "pause"))
428*287e80b3SSadaf Ebrahimi		cmd = PAUSE;
429*287e80b3SSadaf Ebrahimi	else if (!strcmp(cmd_str, "cont"))
430*287e80b3SSadaf Ebrahimi		cmd = CONT;
431*287e80b3SSadaf Ebrahimi	else if (!strcmp(cmd_str, "reset"))
432*287e80b3SSadaf Ebrahimi		cmd = RESET;
433*287e80b3SSadaf Ebrahimi	else if (!strcmp(cmd_str, "delete"))
434*287e80b3SSadaf Ebrahimi		cmd = DELETE;
435*287e80b3SSadaf Ebrahimi	else if (!strcmp(cmd_str, "show"))
436*287e80b3SSadaf Ebrahimi		cmd = SHOW;
437*287e80b3SSadaf Ebrahimi	else {
438*287e80b3SSadaf Ebrahimi		fprintf(stderr, "Unknown command %s\n", cmd_str);
439*287e80b3SSadaf Ebrahimi		exit(-1);
440*287e80b3SSadaf Ebrahimi	}
441*287e80b3SSadaf Ebrahimi
442*287e80b3SSadaf Ebrahimi	for (;;) {
443*287e80b3SSadaf Ebrahimi		int c;
444*287e80b3SSadaf Ebrahimi
445*287e80b3SSadaf Ebrahimi		c = getopt(argc - 1, argv + 1, "e:k:v:B:s:d:a:");
446*287e80b3SSadaf Ebrahimi		if (c == -1)
447*287e80b3SSadaf Ebrahimi			break;
448*287e80b3SSadaf Ebrahimi
449*287e80b3SSadaf Ebrahimi		switch (c) {
450*287e80b3SSadaf Ebrahimi		case 'e':
451*287e80b3SSadaf Ebrahimi			event = optarg;
452*287e80b3SSadaf Ebrahimi			break;
453*287e80b3SSadaf Ebrahimi		case 'k':
454*287e80b3SSadaf Ebrahimi			keys = optarg;
455*287e80b3SSadaf Ebrahimi			break;
456*287e80b3SSadaf Ebrahimi		case 'v':
457*287e80b3SSadaf Ebrahimi			vals = optarg;
458*287e80b3SSadaf Ebrahimi			break;
459*287e80b3SSadaf Ebrahimi		case 'B':
460*287e80b3SSadaf Ebrahimi			instance = optarg;
461*287e80b3SSadaf Ebrahimi			break;
462*287e80b3SSadaf Ebrahimi		case 's':
463*287e80b3SSadaf Ebrahimi			sort = optarg;
464*287e80b3SSadaf Ebrahimi			break;
465*287e80b3SSadaf Ebrahimi		case 'd':
466*287e80b3SSadaf Ebrahimi			desc = optarg;
467*287e80b3SSadaf Ebrahimi			break;
468*287e80b3SSadaf Ebrahimi		case 'a':
469*287e80b3SSadaf Ebrahimi			ascend = optarg;
470*287e80b3SSadaf Ebrahimi			break;
471*287e80b3SSadaf Ebrahimi		}
472*287e80b3SSadaf Ebrahimi	}
473*287e80b3SSadaf Ebrahimi	if (!event) {
474*287e80b3SSadaf Ebrahimi		event = "kmem/kmalloc";
475*287e80b3SSadaf Ebrahimi		if (!keys)
476*287e80b3SSadaf Ebrahimi			keys = "call_site.sym,bytes_req";
477*287e80b3SSadaf Ebrahimi		if (!vals)
478*287e80b3SSadaf Ebrahimi			vals = "bytes_alloc";
479*287e80b3SSadaf Ebrahimi		if (!sort)
480*287e80b3SSadaf Ebrahimi			sort = "bytes_req,bytes_alloc";
481*287e80b3SSadaf Ebrahimi		if (!desc)
482*287e80b3SSadaf Ebrahimi			desc = "bytes_alloc";
483*287e80b3SSadaf Ebrahimi	}
484*287e80b3SSadaf Ebrahimi	process_hist(cmd, instance, event, keys, vals, sort, ascend, desc);
485*287e80b3SSadaf Ebrahimi}
486*287e80b3SSadaf Ebrahimi
487*287e80b3SSadaf Ebrahimi--
488*287e80b3SSadaf Ebrahimi
489*287e80b3SSadaf EbrahimiFILES
490*287e80b3SSadaf Ebrahimi-----
491*287e80b3SSadaf Ebrahimi[verse]
492*287e80b3SSadaf Ebrahimi--
493*287e80b3SSadaf Ebrahimi*tracefs.h*
494*287e80b3SSadaf Ebrahimi	Header file to include in order to have access to the library APIs.
495*287e80b3SSadaf Ebrahimi*-ltracefs*
496*287e80b3SSadaf Ebrahimi	Linker switch to add when building a program that uses the library.
497*287e80b3SSadaf Ebrahimi--
498*287e80b3SSadaf Ebrahimi
499*287e80b3SSadaf EbrahimiSEE ALSO
500*287e80b3SSadaf Ebrahimi--------
501*287e80b3SSadaf Ebrahimi*libtracefs*(3),
502*287e80b3SSadaf Ebrahimi*libtraceevent*(3),
503*287e80b3SSadaf Ebrahimi*trace-cmd*(1),
504*287e80b3SSadaf Ebrahimi*tracefs_hist_pause*(3),
505*287e80b3SSadaf Ebrahimi*tracefs_hist_continue*(3),
506*287e80b3SSadaf Ebrahimi*tracefs_hist_reset*(3)
507*287e80b3SSadaf Ebrahimi
508*287e80b3SSadaf EbrahimiAUTHOR
509*287e80b3SSadaf Ebrahimi------
510*287e80b3SSadaf Ebrahimi[verse]
511*287e80b3SSadaf Ebrahimi--
512*287e80b3SSadaf Ebrahimi*Steven Rostedt* <[email protected]>
513*287e80b3SSadaf Ebrahimi*Tzvetomir Stoyanov* <[email protected]>
514*287e80b3SSadaf Ebrahimi*sameeruddin shaik* <[email protected]>
515*287e80b3SSadaf Ebrahimi--
516*287e80b3SSadaf EbrahimiREPORTING BUGS
517*287e80b3SSadaf Ebrahimi--------------
518*287e80b3SSadaf EbrahimiReport bugs to  <[email protected]>
519*287e80b3SSadaf Ebrahimi
520*287e80b3SSadaf EbrahimiLICENSE
521*287e80b3SSadaf Ebrahimi-------
522*287e80b3SSadaf Ebrahimilibtracefs is Free Software licensed under the GNU LGPL 2.1
523*287e80b3SSadaf Ebrahimi
524*287e80b3SSadaf EbrahimiRESOURCES
525*287e80b3SSadaf Ebrahimi---------
526*287e80b3SSadaf Ebrahimihttps://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/
527*287e80b3SSadaf Ebrahimi
528*287e80b3SSadaf EbrahimiCOPYING
529*287e80b3SSadaf Ebrahimi-------
530*287e80b3SSadaf EbrahimiCopyright \(C) 2020 VMware, Inc. Free use of this software is granted under
531*287e80b3SSadaf Ebrahimithe terms of the GNU Public License (GPL).
532