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