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