Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <inttypes.h>
0003 #include <stdio.h>
0004 #include <stdlib.h>
0005 #include <string.h>
0006 #include <errno.h>
0007 #include <linux/zalloc.h>
0008 
0009 #include "values.h"
0010 #include "debug.h"
0011 
0012 int perf_read_values_init(struct perf_read_values *values)
0013 {
0014     values->threads_max = 16;
0015     values->pid = malloc(values->threads_max * sizeof(*values->pid));
0016     values->tid = malloc(values->threads_max * sizeof(*values->tid));
0017     values->value = zalloc(values->threads_max * sizeof(*values->value));
0018     if (!values->pid || !values->tid || !values->value) {
0019         pr_debug("failed to allocate read_values threads arrays");
0020         goto out_free_pid;
0021     }
0022     values->threads = 0;
0023 
0024     values->counters_max = 16;
0025     values->counterrawid = malloc(values->counters_max
0026                       * sizeof(*values->counterrawid));
0027     values->countername = malloc(values->counters_max
0028                      * sizeof(*values->countername));
0029     if (!values->counterrawid || !values->countername) {
0030         pr_debug("failed to allocate read_values counters arrays");
0031         goto out_free_counter;
0032     }
0033     values->counters = 0;
0034 
0035     return 0;
0036 
0037 out_free_counter:
0038     zfree(&values->counterrawid);
0039     zfree(&values->countername);
0040 out_free_pid:
0041     zfree(&values->pid);
0042     zfree(&values->tid);
0043     zfree(&values->value);
0044     return -ENOMEM;
0045 }
0046 
0047 void perf_read_values_destroy(struct perf_read_values *values)
0048 {
0049     int i;
0050 
0051     if (!values->threads_max || !values->counters_max)
0052         return;
0053 
0054     for (i = 0; i < values->threads; i++)
0055         zfree(&values->value[i]);
0056     zfree(&values->value);
0057     zfree(&values->pid);
0058     zfree(&values->tid);
0059     zfree(&values->counterrawid);
0060     for (i = 0; i < values->counters; i++)
0061         zfree(&values->countername[i]);
0062     zfree(&values->countername);
0063 }
0064 
0065 static int perf_read_values__enlarge_threads(struct perf_read_values *values)
0066 {
0067     int nthreads_max = values->threads_max * 2;
0068     void *npid = realloc(values->pid, nthreads_max * sizeof(*values->pid)),
0069          *ntid = realloc(values->tid, nthreads_max * sizeof(*values->tid)),
0070          *nvalue = realloc(values->value, nthreads_max * sizeof(*values->value));
0071 
0072     if (!npid || !ntid || !nvalue)
0073         goto out_err;
0074 
0075     values->threads_max = nthreads_max;
0076     values->pid = npid;
0077     values->tid = ntid;
0078     values->value = nvalue;
0079     return 0;
0080 out_err:
0081     free(npid);
0082     free(ntid);
0083     free(nvalue);
0084     pr_debug("failed to enlarge read_values threads arrays");
0085     return -ENOMEM;
0086 }
0087 
0088 static int perf_read_values__findnew_thread(struct perf_read_values *values,
0089                         u32 pid, u32 tid)
0090 {
0091     int i;
0092 
0093     for (i = 0; i < values->threads; i++)
0094         if (values->pid[i] == pid && values->tid[i] == tid)
0095             return i;
0096 
0097     if (values->threads == values->threads_max) {
0098         i = perf_read_values__enlarge_threads(values);
0099         if (i < 0)
0100             return i;
0101     }
0102 
0103     i = values->threads;
0104 
0105     values->value[i] = zalloc(values->counters_max * sizeof(**values->value));
0106     if (!values->value[i]) {
0107         pr_debug("failed to allocate read_values counters array");
0108         return -ENOMEM;
0109     }
0110     values->pid[i] = pid;
0111     values->tid[i] = tid;
0112     values->threads = i + 1;
0113 
0114     return i;
0115 }
0116 
0117 static int perf_read_values__enlarge_counters(struct perf_read_values *values)
0118 {
0119     char **countername;
0120     int i, counters_max = values->counters_max * 2;
0121     u64 *counterrawid = realloc(values->counterrawid, counters_max * sizeof(*values->counterrawid));
0122 
0123     if (!counterrawid) {
0124         pr_debug("failed to enlarge read_values rawid array");
0125         goto out_enomem;
0126     }
0127 
0128     countername = realloc(values->countername, counters_max * sizeof(*values->countername));
0129     if (!countername) {
0130         pr_debug("failed to enlarge read_values rawid array");
0131         goto out_free_rawid;
0132     }
0133 
0134     for (i = 0; i < values->threads; i++) {
0135         u64 *value = realloc(values->value[i], counters_max * sizeof(**values->value));
0136         int j;
0137 
0138         if (!value) {
0139             pr_debug("failed to enlarge read_values ->values array");
0140             goto out_free_name;
0141         }
0142 
0143         for (j = values->counters_max; j < counters_max; j++)
0144             value[j] = 0;
0145 
0146         values->value[i] = value;
0147     }
0148 
0149     values->counters_max = counters_max;
0150     values->counterrawid = counterrawid;
0151     values->countername  = countername;
0152 
0153     return 0;
0154 out_free_name:
0155     free(countername);
0156 out_free_rawid:
0157     free(counterrawid);
0158 out_enomem:
0159     return -ENOMEM;
0160 }
0161 
0162 static int perf_read_values__findnew_counter(struct perf_read_values *values,
0163                          u64 rawid, const char *name)
0164 {
0165     int i;
0166 
0167     for (i = 0; i < values->counters; i++)
0168         if (values->counterrawid[i] == rawid)
0169             return i;
0170 
0171     if (values->counters == values->counters_max) {
0172         i = perf_read_values__enlarge_counters(values);
0173         if (i)
0174             return i;
0175     }
0176 
0177     i = values->counters++;
0178     values->counterrawid[i] = rawid;
0179     values->countername[i] = strdup(name);
0180 
0181     return i;
0182 }
0183 
0184 int perf_read_values_add_value(struct perf_read_values *values,
0185                 u32 pid, u32 tid,
0186                 u64 rawid, const char *name, u64 value)
0187 {
0188     int tindex, cindex;
0189 
0190     tindex = perf_read_values__findnew_thread(values, pid, tid);
0191     if (tindex < 0)
0192         return tindex;
0193     cindex = perf_read_values__findnew_counter(values, rawid, name);
0194     if (cindex < 0)
0195         return cindex;
0196 
0197     values->value[tindex][cindex] += value;
0198     return 0;
0199 }
0200 
0201 static void perf_read_values__display_pretty(FILE *fp,
0202                          struct perf_read_values *values)
0203 {
0204     int i, j;
0205     int pidwidth, tidwidth;
0206     int *counterwidth;
0207 
0208     counterwidth = malloc(values->counters * sizeof(*counterwidth));
0209     if (!counterwidth) {
0210         fprintf(fp, "INTERNAL ERROR: Failed to allocate counterwidth array\n");
0211         return;
0212     }
0213     tidwidth = 3;
0214     pidwidth = 3;
0215     for (j = 0; j < values->counters; j++)
0216         counterwidth[j] = strlen(values->countername[j]);
0217     for (i = 0; i < values->threads; i++) {
0218         int width;
0219 
0220         width = snprintf(NULL, 0, "%d", values->pid[i]);
0221         if (width > pidwidth)
0222             pidwidth = width;
0223         width = snprintf(NULL, 0, "%d", values->tid[i]);
0224         if (width > tidwidth)
0225             tidwidth = width;
0226         for (j = 0; j < values->counters; j++) {
0227             width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
0228             if (width > counterwidth[j])
0229                 counterwidth[j] = width;
0230         }
0231     }
0232 
0233     fprintf(fp, "# %*s  %*s", pidwidth, "PID", tidwidth, "TID");
0234     for (j = 0; j < values->counters; j++)
0235         fprintf(fp, "  %*s", counterwidth[j], values->countername[j]);
0236     fprintf(fp, "\n");
0237 
0238     for (i = 0; i < values->threads; i++) {
0239         fprintf(fp, "  %*d  %*d", pidwidth, values->pid[i],
0240             tidwidth, values->tid[i]);
0241         for (j = 0; j < values->counters; j++)
0242             fprintf(fp, "  %*" PRIu64,
0243                 counterwidth[j], values->value[i][j]);
0244         fprintf(fp, "\n");
0245     }
0246     free(counterwidth);
0247 }
0248 
0249 static void perf_read_values__display_raw(FILE *fp,
0250                       struct perf_read_values *values)
0251 {
0252     int width, pidwidth, tidwidth, namewidth, rawwidth, countwidth;
0253     int i, j;
0254 
0255     tidwidth = 3; /* TID */
0256     pidwidth = 3; /* PID */
0257     namewidth = 4; /* "Name" */
0258     rawwidth = 3; /* "Raw" */
0259     countwidth = 5; /* "Count" */
0260 
0261     for (i = 0; i < values->threads; i++) {
0262         width = snprintf(NULL, 0, "%d", values->pid[i]);
0263         if (width > pidwidth)
0264             pidwidth = width;
0265         width = snprintf(NULL, 0, "%d", values->tid[i]);
0266         if (width > tidwidth)
0267             tidwidth = width;
0268     }
0269     for (j = 0; j < values->counters; j++) {
0270         width = strlen(values->countername[j]);
0271         if (width > namewidth)
0272             namewidth = width;
0273         width = snprintf(NULL, 0, "%" PRIx64, values->counterrawid[j]);
0274         if (width > rawwidth)
0275             rawwidth = width;
0276     }
0277     for (i = 0; i < values->threads; i++) {
0278         for (j = 0; j < values->counters; j++) {
0279             width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
0280             if (width > countwidth)
0281                 countwidth = width;
0282         }
0283     }
0284 
0285     fprintf(fp, "# %*s  %*s  %*s  %*s  %*s\n",
0286         pidwidth, "PID", tidwidth, "TID",
0287         namewidth, "Name", rawwidth, "Raw",
0288         countwidth, "Count");
0289     for (i = 0; i < values->threads; i++)
0290         for (j = 0; j < values->counters; j++)
0291             fprintf(fp, "  %*d  %*d  %*s  %*" PRIx64 "  %*" PRIu64,
0292                 pidwidth, values->pid[i],
0293                 tidwidth, values->tid[i],
0294                 namewidth, values->countername[j],
0295                 rawwidth, values->counterrawid[j],
0296                 countwidth, values->value[i][j]);
0297 }
0298 
0299 void perf_read_values_display(FILE *fp, struct perf_read_values *values, int raw)
0300 {
0301     if (raw)
0302         perf_read_values__display_raw(fp, values);
0303     else
0304         perf_read_values__display_pretty(fp, values);
0305 }