xref: /openbmc/linux/tools/perf/util/values.c (revision d78c317f)
1 #include <stdlib.h>
2 
3 #include "util.h"
4 #include "values.h"
5 
6 void perf_read_values_init(struct perf_read_values *values)
7 {
8 	values->threads_max = 16;
9 	values->pid = malloc(values->threads_max * sizeof(*values->pid));
10 	values->tid = malloc(values->threads_max * sizeof(*values->tid));
11 	values->value = malloc(values->threads_max * sizeof(*values->value));
12 	if (!values->pid || !values->tid || !values->value)
13 		die("failed to allocate read_values threads arrays");
14 	values->threads = 0;
15 
16 	values->counters_max = 16;
17 	values->counterrawid = malloc(values->counters_max
18 				      * sizeof(*values->counterrawid));
19 	values->countername = malloc(values->counters_max
20 				     * sizeof(*values->countername));
21 	if (!values->counterrawid || !values->countername)
22 		die("failed to allocate read_values counters arrays");
23 	values->counters = 0;
24 }
25 
26 void perf_read_values_destroy(struct perf_read_values *values)
27 {
28 	int i;
29 
30 	if (!values->threads_max || !values->counters_max)
31 		return;
32 
33 	for (i = 0; i < values->threads; i++)
34 		free(values->value[i]);
35 	free(values->value);
36 	free(values->pid);
37 	free(values->tid);
38 	free(values->counterrawid);
39 	for (i = 0; i < values->counters; i++)
40 		free(values->countername[i]);
41 	free(values->countername);
42 }
43 
44 static void perf_read_values__enlarge_threads(struct perf_read_values *values)
45 {
46 	values->threads_max *= 2;
47 	values->pid = realloc(values->pid,
48 			      values->threads_max * sizeof(*values->pid));
49 	values->tid = realloc(values->tid,
50 			      values->threads_max * sizeof(*values->tid));
51 	values->value = realloc(values->value,
52 				values->threads_max * sizeof(*values->value));
53 	if (!values->pid || !values->tid || !values->value)
54 		die("failed to enlarge read_values threads arrays");
55 }
56 
57 static int perf_read_values__findnew_thread(struct perf_read_values *values,
58 					    u32 pid, u32 tid)
59 {
60 	int i;
61 
62 	for (i = 0; i < values->threads; i++)
63 		if (values->pid[i] == pid && values->tid[i] == tid)
64 			return i;
65 
66 	if (values->threads == values->threads_max)
67 		perf_read_values__enlarge_threads(values);
68 
69 	i = values->threads++;
70 	values->pid[i] = pid;
71 	values->tid[i] = tid;
72 	values->value[i] = malloc(values->counters_max * sizeof(**values->value));
73 	if (!values->value[i])
74 		die("failed to allocate read_values counters array");
75 
76 	return i;
77 }
78 
79 static void perf_read_values__enlarge_counters(struct perf_read_values *values)
80 {
81 	int i;
82 
83 	values->counters_max *= 2;
84 	values->counterrawid = realloc(values->counterrawid,
85 				       values->counters_max * sizeof(*values->counterrawid));
86 	values->countername = realloc(values->countername,
87 				      values->counters_max * sizeof(*values->countername));
88 	if (!values->counterrawid || !values->countername)
89 		die("failed to enlarge read_values counters arrays");
90 
91 	for (i = 0; i < values->threads; i++) {
92 		values->value[i] = realloc(values->value[i],
93 					   values->counters_max * sizeof(**values->value));
94 		if (!values->value[i])
95 			die("failed to enlarge read_values counters arrays");
96 	}
97 }
98 
99 static int perf_read_values__findnew_counter(struct perf_read_values *values,
100 					     u64 rawid, const char *name)
101 {
102 	int i;
103 
104 	for (i = 0; i < values->counters; i++)
105 		if (values->counterrawid[i] == rawid)
106 			return i;
107 
108 	if (values->counters == values->counters_max)
109 		perf_read_values__enlarge_counters(values);
110 
111 	i = values->counters++;
112 	values->counterrawid[i] = rawid;
113 	values->countername[i] = strdup(name);
114 
115 	return i;
116 }
117 
118 void perf_read_values_add_value(struct perf_read_values *values,
119 				u32 pid, u32 tid,
120 				u64 rawid, const char *name, u64 value)
121 {
122 	int tindex, cindex;
123 
124 	tindex = perf_read_values__findnew_thread(values, pid, tid);
125 	cindex = perf_read_values__findnew_counter(values, rawid, name);
126 
127 	values->value[tindex][cindex] = value;
128 }
129 
130 static void perf_read_values__display_pretty(FILE *fp,
131 					     struct perf_read_values *values)
132 {
133 	int i, j;
134 	int pidwidth, tidwidth;
135 	int *counterwidth;
136 
137 	counterwidth = malloc(values->counters * sizeof(*counterwidth));
138 	if (!counterwidth)
139 		die("failed to allocate counterwidth array");
140 	tidwidth = 3;
141 	pidwidth = 3;
142 	for (j = 0; j < values->counters; j++)
143 		counterwidth[j] = strlen(values->countername[j]);
144 	for (i = 0; i < values->threads; i++) {
145 		int width;
146 
147 		width = snprintf(NULL, 0, "%d", values->pid[i]);
148 		if (width > pidwidth)
149 			pidwidth = width;
150 		width = snprintf(NULL, 0, "%d", values->tid[i]);
151 		if (width > tidwidth)
152 			tidwidth = width;
153 		for (j = 0; j < values->counters; j++) {
154 			width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
155 			if (width > counterwidth[j])
156 				counterwidth[j] = width;
157 		}
158 	}
159 
160 	fprintf(fp, "# %*s  %*s", pidwidth, "PID", tidwidth, "TID");
161 	for (j = 0; j < values->counters; j++)
162 		fprintf(fp, "  %*s", counterwidth[j], values->countername[j]);
163 	fprintf(fp, "\n");
164 
165 	for (i = 0; i < values->threads; i++) {
166 		fprintf(fp, "  %*d  %*d", pidwidth, values->pid[i],
167 			tidwidth, values->tid[i]);
168 		for (j = 0; j < values->counters; j++)
169 			fprintf(fp, "  %*" PRIu64,
170 				counterwidth[j], values->value[i][j]);
171 		fprintf(fp, "\n");
172 	}
173 	free(counterwidth);
174 }
175 
176 static void perf_read_values__display_raw(FILE *fp,
177 					  struct perf_read_values *values)
178 {
179 	int width, pidwidth, tidwidth, namewidth, rawwidth, countwidth;
180 	int i, j;
181 
182 	tidwidth = 3; /* TID */
183 	pidwidth = 3; /* PID */
184 	namewidth = 4; /* "Name" */
185 	rawwidth = 3; /* "Raw" */
186 	countwidth = 5; /* "Count" */
187 
188 	for (i = 0; i < values->threads; i++) {
189 		width = snprintf(NULL, 0, "%d", values->pid[i]);
190 		if (width > pidwidth)
191 			pidwidth = width;
192 		width = snprintf(NULL, 0, "%d", values->tid[i]);
193 		if (width > tidwidth)
194 			tidwidth = width;
195 	}
196 	for (j = 0; j < values->counters; j++) {
197 		width = strlen(values->countername[j]);
198 		if (width > namewidth)
199 			namewidth = width;
200 		width = snprintf(NULL, 0, "%" PRIx64, values->counterrawid[j]);
201 		if (width > rawwidth)
202 			rawwidth = width;
203 	}
204 	for (i = 0; i < values->threads; i++) {
205 		for (j = 0; j < values->counters; j++) {
206 			width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
207 			if (width > countwidth)
208 				countwidth = width;
209 		}
210 	}
211 
212 	fprintf(fp, "# %*s  %*s  %*s  %*s  %*s\n",
213 		pidwidth, "PID", tidwidth, "TID",
214 		namewidth, "Name", rawwidth, "Raw",
215 		countwidth, "Count");
216 	for (i = 0; i < values->threads; i++)
217 		for (j = 0; j < values->counters; j++)
218 			fprintf(fp, "  %*d  %*d  %*s  %*" PRIx64 "  %*" PRIu64,
219 				pidwidth, values->pid[i],
220 				tidwidth, values->tid[i],
221 				namewidth, values->countername[j],
222 				rawwidth, values->counterrawid[j],
223 				countwidth, values->value[i][j]);
224 }
225 
226 void perf_read_values_display(FILE *fp, struct perf_read_values *values, int raw)
227 {
228 	if (raw)
229 		perf_read_values__display_raw(fp, values);
230 	else
231 		perf_read_values__display_pretty(fp, values);
232 }
233