1 // SPDX-License-Identifier: GPL-2.0
7 #include <linux/zalloc.h>
12 int perf_read_values_init(struct perf_read_values
*values
)
14 values
->threads_max
= 16;
15 values
->pid
= malloc(values
->threads_max
* sizeof(*values
->pid
));
16 values
->tid
= malloc(values
->threads_max
* sizeof(*values
->tid
));
17 values
->value
= zalloc(values
->threads_max
* sizeof(*values
->value
));
18 if (!values
->pid
|| !values
->tid
|| !values
->value
) {
19 pr_debug("failed to allocate read_values threads arrays");
24 values
->counters_max
= 16;
25 values
->counterrawid
= malloc(values
->counters_max
26 * sizeof(*values
->counterrawid
));
27 values
->countername
= malloc(values
->counters_max
28 * sizeof(*values
->countername
));
29 if (!values
->counterrawid
|| !values
->countername
) {
30 pr_debug("failed to allocate read_values counters arrays");
31 goto out_free_counter
;
38 zfree(&values
->counterrawid
);
39 zfree(&values
->countername
);
43 zfree(&values
->value
);
47 void perf_read_values_destroy(struct perf_read_values
*values
)
51 if (!values
->threads_max
|| !values
->counters_max
)
54 for (i
= 0; i
< values
->threads
; i
++)
55 zfree(&values
->value
[i
]);
56 zfree(&values
->value
);
59 zfree(&values
->counterrawid
);
60 for (i
= 0; i
< values
->counters
; i
++)
61 zfree(&values
->countername
[i
]);
62 zfree(&values
->countername
);
65 static int perf_read_values__enlarge_threads(struct perf_read_values
*values
)
67 int nthreads_max
= values
->threads_max
* 2;
68 void *npid
= realloc(values
->pid
, nthreads_max
* sizeof(*values
->pid
)),
69 *ntid
= realloc(values
->tid
, nthreads_max
* sizeof(*values
->tid
)),
70 *nvalue
= realloc(values
->value
, nthreads_max
* sizeof(*values
->value
));
72 if (!npid
|| !ntid
|| !nvalue
)
75 values
->threads_max
= nthreads_max
;
78 values
->value
= nvalue
;
84 pr_debug("failed to enlarge read_values threads arrays");
88 static int perf_read_values__findnew_thread(struct perf_read_values
*values
,
93 for (i
= 0; i
< values
->threads
; i
++)
94 if (values
->pid
[i
] == pid
&& values
->tid
[i
] == tid
)
97 if (values
->threads
== values
->threads_max
) {
98 i
= perf_read_values__enlarge_threads(values
);
105 values
->value
[i
] = zalloc(values
->counters_max
* sizeof(**values
->value
));
106 if (!values
->value
[i
]) {
107 pr_debug("failed to allocate read_values counters array");
110 values
->pid
[i
] = pid
;
111 values
->tid
[i
] = tid
;
112 values
->threads
= i
+ 1;
117 static int perf_read_values__enlarge_counters(struct perf_read_values
*values
)
120 int i
, counters_max
= values
->counters_max
* 2;
121 u64
*counterrawid
= realloc(values
->counterrawid
, counters_max
* sizeof(*values
->counterrawid
));
124 pr_debug("failed to enlarge read_values rawid array");
128 countername
= realloc(values
->countername
, counters_max
* sizeof(*values
->countername
));
130 pr_debug("failed to enlarge read_values rawid array");
134 for (i
= 0; i
< values
->threads
; i
++) {
135 u64
*value
= realloc(values
->value
[i
], counters_max
* sizeof(**values
->value
));
139 pr_debug("failed to enlarge read_values ->values array");
143 for (j
= values
->counters_max
; j
< counters_max
; j
++)
146 values
->value
[i
] = value
;
149 values
->counters_max
= counters_max
;
150 values
->counterrawid
= counterrawid
;
151 values
->countername
= countername
;
162 static int perf_read_values__findnew_counter(struct perf_read_values
*values
,
163 u64 rawid
, const char *name
)
167 for (i
= 0; i
< values
->counters
; i
++)
168 if (values
->counterrawid
[i
] == rawid
)
171 if (values
->counters
== values
->counters_max
) {
172 i
= perf_read_values__enlarge_counters(values
);
177 i
= values
->counters
++;
178 values
->counterrawid
[i
] = rawid
;
179 values
->countername
[i
] = strdup(name
);
184 int perf_read_values_add_value(struct perf_read_values
*values
,
186 u64 rawid
, const char *name
, u64 value
)
190 tindex
= perf_read_values__findnew_thread(values
, pid
, tid
);
193 cindex
= perf_read_values__findnew_counter(values
, rawid
, name
);
197 values
->value
[tindex
][cindex
] += value
;
201 static void perf_read_values__display_pretty(FILE *fp
,
202 struct perf_read_values
*values
)
205 int pidwidth
, tidwidth
;
208 counterwidth
= malloc(values
->counters
* sizeof(*counterwidth
));
210 fprintf(fp
, "INTERNAL ERROR: Failed to allocate counterwidth array\n");
215 for (j
= 0; j
< values
->counters
; j
++)
216 counterwidth
[j
] = strlen(values
->countername
[j
]);
217 for (i
= 0; i
< values
->threads
; i
++) {
220 width
= snprintf(NULL
, 0, "%d", values
->pid
[i
]);
221 if (width
> pidwidth
)
223 width
= snprintf(NULL
, 0, "%d", values
->tid
[i
]);
224 if (width
> tidwidth
)
226 for (j
= 0; j
< values
->counters
; j
++) {
227 width
= snprintf(NULL
, 0, "%" PRIu64
, values
->value
[i
][j
]);
228 if (width
> counterwidth
[j
])
229 counterwidth
[j
] = width
;
233 fprintf(fp
, "# %*s %*s", pidwidth
, "PID", tidwidth
, "TID");
234 for (j
= 0; j
< values
->counters
; j
++)
235 fprintf(fp
, " %*s", counterwidth
[j
], values
->countername
[j
]);
238 for (i
= 0; i
< values
->threads
; i
++) {
239 fprintf(fp
, " %*d %*d", pidwidth
, values
->pid
[i
],
240 tidwidth
, values
->tid
[i
]);
241 for (j
= 0; j
< values
->counters
; j
++)
242 fprintf(fp
, " %*" PRIu64
,
243 counterwidth
[j
], values
->value
[i
][j
]);
249 static void perf_read_values__display_raw(FILE *fp
,
250 struct perf_read_values
*values
)
252 int width
, pidwidth
, tidwidth
, namewidth
, rawwidth
, countwidth
;
255 tidwidth
= 3; /* TID */
256 pidwidth
= 3; /* PID */
257 namewidth
= 4; /* "Name" */
258 rawwidth
= 3; /* "Raw" */
259 countwidth
= 5; /* "Count" */
261 for (i
= 0; i
< values
->threads
; i
++) {
262 width
= snprintf(NULL
, 0, "%d", values
->pid
[i
]);
263 if (width
> pidwidth
)
265 width
= snprintf(NULL
, 0, "%d", values
->tid
[i
]);
266 if (width
> tidwidth
)
269 for (j
= 0; j
< values
->counters
; j
++) {
270 width
= strlen(values
->countername
[j
]);
271 if (width
> namewidth
)
273 width
= snprintf(NULL
, 0, "%" PRIx64
, values
->counterrawid
[j
]);
274 if (width
> rawwidth
)
277 for (i
= 0; i
< values
->threads
; i
++) {
278 for (j
= 0; j
< values
->counters
; j
++) {
279 width
= snprintf(NULL
, 0, "%" PRIu64
, values
->value
[i
][j
]);
280 if (width
> countwidth
)
285 fprintf(fp
, "# %*s %*s %*s %*s %*s\n",
286 pidwidth
, "PID", tidwidth
, "TID",
287 namewidth
, "Name", rawwidth
, "Raw",
288 countwidth
, "Count");
289 for (i
= 0; i
< values
->threads
; i
++)
290 for (j
= 0; j
< values
->counters
; j
++)
291 fprintf(fp
, " %*d %*d %*s %*" PRIx64
" %*" PRIu64
,
292 pidwidth
, values
->pid
[i
],
293 tidwidth
, values
->tid
[i
],
294 namewidth
, values
->countername
[j
],
295 rawwidth
, values
->counterrawid
[j
],
296 countwidth
, values
->value
[i
][j
]);
299 void perf_read_values_display(FILE *fp
, struct perf_read_values
*values
, int raw
)
302 perf_read_values__display_raw(fp
, values
);
304 perf_read_values__display_pretty(fp
, values
);