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