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