1 #include <stdlib.h>
2 
3 #include "util.h"
4 #include "values.h"
5 
perf_read_values_init(struct perf_read_values * values)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 
perf_read_values_destroy(struct perf_read_values * values)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 
perf_read_values__enlarge_threads(struct perf_read_values * values)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 
perf_read_values__findnew_thread(struct perf_read_values * values,u32 pid,u32 tid)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 
perf_read_values__enlarge_counters(struct perf_read_values * values)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 
perf_read_values__findnew_counter(struct perf_read_values * values,u64 rawid,const char * name)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 
perf_read_values_add_value(struct perf_read_values * values,u32 pid,u32 tid,u64 rawid,const char * name,u64 value)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 
perf_read_values__display_pretty(FILE * fp,struct perf_read_values * values)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, "%" PRIu64, 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, "  %*" PRIu64,
169 				counterwidth[j], values->value[i][j]);
170 		fprintf(fp, "\n");
171 	}
172 	free(counterwidth);
173 }
174 
perf_read_values__display_raw(FILE * fp,struct perf_read_values * values)175 static void perf_read_values__display_raw(FILE *fp,
176 					  struct perf_read_values *values)
177 {
178 	int width, pidwidth, tidwidth, namewidth, rawwidth, countwidth;
179 	int i, j;
180 
181 	tidwidth = 3; /* TID */
182 	pidwidth = 3; /* PID */
183 	namewidth = 4; /* "Name" */
184 	rawwidth = 3; /* "Raw" */
185 	countwidth = 5; /* "Count" */
186 
187 	for (i = 0; i < values->threads; i++) {
188 		width = snprintf(NULL, 0, "%d", values->pid[i]);
189 		if (width > pidwidth)
190 			pidwidth = width;
191 		width = snprintf(NULL, 0, "%d", values->tid[i]);
192 		if (width > tidwidth)
193 			tidwidth = width;
194 	}
195 	for (j = 0; j < values->counters; j++) {
196 		width = strlen(values->countername[j]);
197 		if (width > namewidth)
198 			namewidth = width;
199 		width = snprintf(NULL, 0, "%" PRIx64, values->counterrawid[j]);
200 		if (width > rawwidth)
201 			rawwidth = width;
202 	}
203 	for (i = 0; i < values->threads; i++) {
204 		for (j = 0; j < values->counters; j++) {
205 			width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
206 			if (width > countwidth)
207 				countwidth = width;
208 		}
209 	}
210 
211 	fprintf(fp, "# %*s  %*s  %*s  %*s  %*s\n",
212 		pidwidth, "PID", tidwidth, "TID",
213 		namewidth, "Name", rawwidth, "Raw",
214 		countwidth, "Count");
215 	for (i = 0; i < values->threads; i++)
216 		for (j = 0; j < values->counters; j++)
217 			fprintf(fp, "  %*d  %*d  %*s  %*" PRIx64 "  %*" PRIu64,
218 				pidwidth, values->pid[i],
219 				tidwidth, values->tid[i],
220 				namewidth, values->countername[j],
221 				rawwidth, values->counterrawid[j],
222 				countwidth, values->value[i][j]);
223 }
224 
perf_read_values_display(FILE * fp,struct perf_read_values * values,int raw)225 void perf_read_values_display(FILE *fp, struct perf_read_values *values, int raw)
226 {
227 	if (raw)
228 		perf_read_values__display_raw(fp, values);
229 	else
230 		perf_read_values__display_pretty(fp, values);
231 }
232