diff options
Diffstat (limited to 'tools/perf/builtin-mem.c')
-rw-r--r-- | tools/perf/builtin-mem.c | 131 |
1 files changed, 104 insertions, 27 deletions
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 24db6ffe2957..9b5663950a4d 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c | |||
@@ -7,44 +7,47 @@ | |||
7 | #include "util/session.h" | 7 | #include "util/session.h" |
8 | #include "util/data.h" | 8 | #include "util/data.h" |
9 | 9 | ||
10 | #define MEM_OPERATION_LOAD "load" | 10 | #define MEM_OPERATION_LOAD 0x1 |
11 | #define MEM_OPERATION_STORE "store" | 11 | #define MEM_OPERATION_STORE 0x2 |
12 | |||
13 | static const char *mem_operation = MEM_OPERATION_LOAD; | ||
14 | 12 | ||
15 | struct perf_mem { | 13 | struct perf_mem { |
16 | struct perf_tool tool; | 14 | struct perf_tool tool; |
17 | char const *input_name; | 15 | char const *input_name; |
18 | bool hide_unresolved; | 16 | bool hide_unresolved; |
19 | bool dump_raw; | 17 | bool dump_raw; |
18 | int operation; | ||
20 | const char *cpu_list; | 19 | const char *cpu_list; |
21 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | 20 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); |
22 | }; | 21 | }; |
23 | 22 | ||
24 | static int __cmd_record(int argc, const char **argv) | 23 | static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) |
25 | { | 24 | { |
26 | int rec_argc, i = 0, j; | 25 | int rec_argc, i = 0, j; |
27 | const char **rec_argv; | 26 | const char **rec_argv; |
28 | char event[64]; | ||
29 | int ret; | 27 | int ret; |
30 | 28 | ||
31 | rec_argc = argc + 4; | 29 | rec_argc = argc + 7; /* max number of arguments */ |
32 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); | 30 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); |
33 | if (!rec_argv) | 31 | if (!rec_argv) |
34 | return -1; | 32 | return -1; |
35 | 33 | ||
36 | rec_argv[i++] = strdup("record"); | 34 | rec_argv[i++] = "record"; |
37 | if (!strcmp(mem_operation, MEM_OPERATION_LOAD)) | ||
38 | rec_argv[i++] = strdup("-W"); | ||
39 | rec_argv[i++] = strdup("-d"); | ||
40 | rec_argv[i++] = strdup("-e"); | ||
41 | 35 | ||
42 | if (strcmp(mem_operation, MEM_OPERATION_LOAD)) | 36 | if (mem->operation & MEM_OPERATION_LOAD) |
43 | sprintf(event, "cpu/mem-stores/pp"); | 37 | rec_argv[i++] = "-W"; |
44 | else | 38 | |
45 | sprintf(event, "cpu/mem-loads/pp"); | 39 | rec_argv[i++] = "-d"; |
40 | |||
41 | if (mem->operation & MEM_OPERATION_LOAD) { | ||
42 | rec_argv[i++] = "-e"; | ||
43 | rec_argv[i++] = "cpu/mem-loads/pp"; | ||
44 | } | ||
45 | |||
46 | if (mem->operation & MEM_OPERATION_STORE) { | ||
47 | rec_argv[i++] = "-e"; | ||
48 | rec_argv[i++] = "cpu/mem-stores/pp"; | ||
49 | } | ||
46 | 50 | ||
47 | rec_argv[i++] = strdup(event); | ||
48 | for (j = 1; j < argc; j++, i++) | 51 | for (j = 1; j < argc; j++, i++) |
49 | rec_argv[i] = argv[j]; | 52 | rec_argv[i] = argv[j]; |
50 | 53 | ||
@@ -162,17 +165,17 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem) | |||
162 | if (!rep_argv) | 165 | if (!rep_argv) |
163 | return -1; | 166 | return -1; |
164 | 167 | ||
165 | rep_argv[i++] = strdup("report"); | 168 | rep_argv[i++] = "report"; |
166 | rep_argv[i++] = strdup("--mem-mode"); | 169 | rep_argv[i++] = "--mem-mode"; |
167 | rep_argv[i++] = strdup("-n"); /* display number of samples */ | 170 | rep_argv[i++] = "-n"; /* display number of samples */ |
168 | 171 | ||
169 | /* | 172 | /* |
170 | * there is no weight (cost) associated with stores, so don't print | 173 | * there is no weight (cost) associated with stores, so don't print |
171 | * the column | 174 | * the column |
172 | */ | 175 | */ |
173 | if (strcmp(mem_operation, MEM_OPERATION_LOAD)) | 176 | if (!(mem->operation & MEM_OPERATION_LOAD)) |
174 | rep_argv[i++] = strdup("--sort=mem,sym,dso,symbol_daddr," | 177 | rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr," |
175 | "dso_daddr,tlb,locked"); | 178 | "dso_daddr,tlb,locked"; |
176 | 179 | ||
177 | for (j = 1; j < argc; j++, i++) | 180 | for (j = 1; j < argc; j++, i++) |
178 | rep_argv[i] = argv[j]; | 181 | rep_argv[i] = argv[j]; |
@@ -182,6 +185,75 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem) | |||
182 | return ret; | 185 | return ret; |
183 | } | 186 | } |
184 | 187 | ||
188 | struct mem_mode { | ||
189 | const char *name; | ||
190 | int mode; | ||
191 | }; | ||
192 | |||
193 | #define MEM_OPT(n, m) \ | ||
194 | { .name = n, .mode = (m) } | ||
195 | |||
196 | #define MEM_END { .name = NULL } | ||
197 | |||
198 | static const struct mem_mode mem_modes[]={ | ||
199 | MEM_OPT("load", MEM_OPERATION_LOAD), | ||
200 | MEM_OPT("store", MEM_OPERATION_STORE), | ||
201 | MEM_END | ||
202 | }; | ||
203 | |||
204 | static int | ||
205 | parse_mem_ops(const struct option *opt, const char *str, int unset) | ||
206 | { | ||
207 | int *mode = (int *)opt->value; | ||
208 | const struct mem_mode *m; | ||
209 | char *s, *os = NULL, *p; | ||
210 | int ret = -1; | ||
211 | |||
212 | if (unset) | ||
213 | return 0; | ||
214 | |||
215 | /* str may be NULL in case no arg is passed to -t */ | ||
216 | if (str) { | ||
217 | /* because str is read-only */ | ||
218 | s = os = strdup(str); | ||
219 | if (!s) | ||
220 | return -1; | ||
221 | |||
222 | /* reset mode */ | ||
223 | *mode = 0; | ||
224 | |||
225 | for (;;) { | ||
226 | p = strchr(s, ','); | ||
227 | if (p) | ||
228 | *p = '\0'; | ||
229 | |||
230 | for (m = mem_modes; m->name; m++) { | ||
231 | if (!strcasecmp(s, m->name)) | ||
232 | break; | ||
233 | } | ||
234 | if (!m->name) { | ||
235 | fprintf(stderr, "unknown sampling op %s," | ||
236 | " check man page\n", s); | ||
237 | goto error; | ||
238 | } | ||
239 | |||
240 | *mode |= m->mode; | ||
241 | |||
242 | if (!p) | ||
243 | break; | ||
244 | |||
245 | s = p + 1; | ||
246 | } | ||
247 | } | ||
248 | ret = 0; | ||
249 | |||
250 | if (*mode == 0) | ||
251 | *mode = MEM_OPERATION_LOAD; | ||
252 | error: | ||
253 | free(os); | ||
254 | return ret; | ||
255 | } | ||
256 | |||
185 | int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) | 257 | int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) |
186 | { | 258 | { |
187 | struct stat st; | 259 | struct stat st; |
@@ -197,10 +269,15 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
197 | .ordered_events = true, | 269 | .ordered_events = true, |
198 | }, | 270 | }, |
199 | .input_name = "perf.data", | 271 | .input_name = "perf.data", |
272 | /* | ||
273 | * default to both load an store sampling | ||
274 | */ | ||
275 | .operation = MEM_OPERATION_LOAD | MEM_OPERATION_STORE, | ||
200 | }; | 276 | }; |
201 | const struct option mem_options[] = { | 277 | const struct option mem_options[] = { |
202 | OPT_STRING('t', "type", &mem_operation, | 278 | OPT_CALLBACK('t', "type", &mem.operation, |
203 | "type", "memory operations(load/store)"), | 279 | "type", "memory operations(load,store) Default load,store", |
280 | parse_mem_ops), | ||
204 | OPT_BOOLEAN('D', "dump-raw-samples", &mem.dump_raw, | 281 | OPT_BOOLEAN('D', "dump-raw-samples", &mem.dump_raw, |
205 | "dump raw samples in ASCII"), | 282 | "dump raw samples in ASCII"), |
206 | OPT_BOOLEAN('U', "hide-unresolved", &mem.hide_unresolved, | 283 | OPT_BOOLEAN('U', "hide-unresolved", &mem.hide_unresolved, |
@@ -225,7 +302,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
225 | argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands, | 302 | argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands, |
226 | mem_usage, PARSE_OPT_STOP_AT_NON_OPTION); | 303 | mem_usage, PARSE_OPT_STOP_AT_NON_OPTION); |
227 | 304 | ||
228 | if (!argc || !(strncmp(argv[0], "rec", 3) || mem_operation)) | 305 | if (!argc || !(strncmp(argv[0], "rec", 3) || mem.operation)) |
229 | usage_with_options(mem_usage, mem_options); | 306 | usage_with_options(mem_usage, mem_options); |
230 | 307 | ||
231 | if (!mem.input_name || !strlen(mem.input_name)) { | 308 | if (!mem.input_name || !strlen(mem.input_name)) { |
@@ -236,7 +313,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
236 | } | 313 | } |
237 | 314 | ||
238 | if (!strncmp(argv[0], "rec", 3)) | 315 | if (!strncmp(argv[0], "rec", 3)) |
239 | return __cmd_record(argc, argv); | 316 | return __cmd_record(argc, argv, &mem); |
240 | else if (!strncmp(argv[0], "rep", 3)) | 317 | else if (!strncmp(argv[0], "rep", 3)) |
241 | return report_events(argc, argv, &mem); | 318 | return report_events(argc, argv, &mem); |
242 | else | 319 | else |