root/tools/perf/util/values.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. perf_read_values_init
  2. perf_read_values_destroy
  3. perf_read_values__enlarge_threads
  4. perf_read_values__findnew_thread
  5. perf_read_values__enlarge_counters
  6. perf_read_values__findnew_counter
  7. perf_read_values_add_value
  8. perf_read_values__display_pretty
  9. perf_read_values__display_raw
  10. perf_read_values_display

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

/* [<][>][^][v][top][bottom][index][help] */