aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-05-05 11:50:27 -0400
committerIngo Molnar <mingo@elte.hu>2009-05-05 14:18:33 -0400
commit16c8a10932aef971292c9570eb5f60b5d4e83ed2 (patch)
treeee9f6860cad353bb7a5219468ffdc4e4fc700792 /Documentation
parent2023b359214bbc5bad31571cf50d7fb83b535c0a (diff)
perf_counter: tools: update the tools to support process and inherited counters
"perf record": - per task counter - inherit switch - nmi switch "perf report": - userspace/kernel filter "perf stat": - userspace/kernel filter Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> LKML-Reference: <20090505155437.389163017@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/perf_counter/builtin-record.c155
-rw-r--r--Documentation/perf_counter/builtin-stat.c24
-rw-r--r--Documentation/perf_counter/perf-report.cc27
3 files changed, 140 insertions, 66 deletions
diff --git a/Documentation/perf_counter/builtin-record.c b/Documentation/perf_counter/builtin-record.c
index ddfdcf86fb20..5f5e6df0260d 100644
--- a/Documentation/perf_counter/builtin-record.c
+++ b/Documentation/perf_counter/builtin-record.c
@@ -45,7 +45,10 @@ static unsigned int mmap_pages = 16;
45static int output; 45static int output;
46static char *output_name = "output.perf"; 46static char *output_name = "output.perf";
47static int group = 0; 47static int group = 0;
48static unsigned int realtime_prio = 0; 48static unsigned int realtime_prio = 0;
49static int system_wide = 0;
50static int inherit = 1;
51static int nmi = 1;
49 52
50const unsigned int default_count[] = { 53const unsigned int default_count[] = {
51 1000000, 54 1000000,
@@ -167,7 +170,7 @@ static void display_events_help(void)
167static void display_help(void) 170static void display_help(void)
168{ 171{
169 printf( 172 printf(
170 "Usage: perf-record [<options>]\n" 173 "Usage: perf-record [<options>] <cmd>\n"
171 "perf-record Options (up to %d event types can be specified at once):\n\n", 174 "perf-record Options (up to %d event types can be specified at once):\n\n",
172 MAX_COUNTERS); 175 MAX_COUNTERS);
173 176
@@ -178,12 +181,13 @@ static void display_help(void)
178 " -m pages --mmap_pages=<pages> # number of mmap data pages\n" 181 " -m pages --mmap_pages=<pages> # number of mmap data pages\n"
179 " -o file --output=<file> # output file\n" 182 " -o file --output=<file> # output file\n"
180 " -r prio --realtime=<prio> # use RT prio\n" 183 " -r prio --realtime=<prio> # use RT prio\n"
184 " -s --system # system wide profiling\n"
181 ); 185 );
182 186
183 exit(0); 187 exit(0);
184} 188}
185 189
186static void process_options(int argc, char *argv[]) 190static void process_options(int argc, const char *argv[])
187{ 191{
188 int error = 0, counter; 192 int error = 0, counter;
189 193
@@ -196,9 +200,12 @@ static void process_options(int argc, char *argv[])
196 {"mmap_pages", required_argument, NULL, 'm'}, 200 {"mmap_pages", required_argument, NULL, 'm'},
197 {"output", required_argument, NULL, 'o'}, 201 {"output", required_argument, NULL, 'o'},
198 {"realtime", required_argument, NULL, 'r'}, 202 {"realtime", required_argument, NULL, 'r'},
203 {"system", no_argument, NULL, 's'},
204 {"inherit", no_argument, NULL, 'i'},
205 {"nmi", no_argument, NULL, 'n'},
199 {NULL, 0, NULL, 0 } 206 {NULL, 0, NULL, 0 }
200 }; 207 };
201 int c = getopt_long(argc, argv, "+:c:e:m:o:r:", 208 int c = getopt_long(argc, argv, "+:c:e:m:o:r:sin",
202 long_options, &option_index); 209 long_options, &option_index);
203 if (c == -1) 210 if (c == -1)
204 break; 211 break;
@@ -209,9 +216,16 @@ static void process_options(int argc, char *argv[])
209 case 'm': mmap_pages = atoi(optarg); break; 216 case 'm': mmap_pages = atoi(optarg); break;
210 case 'o': output_name = strdup(optarg); break; 217 case 'o': output_name = strdup(optarg); break;
211 case 'r': realtime_prio = atoi(optarg); break; 218 case 'r': realtime_prio = atoi(optarg); break;
219 case 's': system_wide ^= 1; break;
220 case 'i': inherit ^= 1; break;
221 case 'n': nmi ^= 1; break;
212 default: error = 1; break; 222 default: error = 1; break;
213 } 223 }
214 } 224 }
225
226 if (argc - optind == 0)
227 error = 1;
228
215 if (error) 229 if (error)
216 display_help(); 230 display_help();
217 231
@@ -325,18 +339,82 @@ static void mmap_read(struct mmap_data *md)
325 339
326static volatile int done = 0; 340static volatile int done = 0;
327 341
328static void sigchld_handler(int sig) 342static void sig_handler(int sig)
329{ 343{
330 if (sig == SIGCHLD) 344 done = 1;
331 done = 1;
332} 345}
333 346
334int cmd_record(int argc, char **argv) 347static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
348static struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
349
350static int nr_poll;
351static int nr_cpu;
352
353static void open_counters(int cpu)
335{ 354{
336 struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
337 struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
338 struct perf_counter_hw_event hw_event; 355 struct perf_counter_hw_event hw_event;
339 int i, counter, group_fd, nr_poll = 0; 356 int counter, group_fd;
357 int track = 1;
358 pid_t pid = -1;
359
360 if (cpu < 0)
361 pid = 0;
362
363 group_fd = -1;
364 for (counter = 0; counter < nr_counters; counter++) {
365
366 memset(&hw_event, 0, sizeof(hw_event));
367 hw_event.config = event_id[counter];
368 hw_event.irq_period = event_count[counter];
369 hw_event.record_type = PERF_RECORD_IP | PERF_RECORD_TID;
370 hw_event.nmi = nmi;
371 hw_event.mmap = track;
372 hw_event.comm = track;
373 hw_event.inherit = (cpu < 0) && inherit;
374
375 track = 0; // only the first counter needs these
376
377 fd[nr_cpu][counter] =
378 sys_perf_counter_open(&hw_event, pid, cpu, group_fd, 0);
379
380 if (fd[nr_cpu][counter] < 0) {
381 int err = errno;
382 printf("kerneltop error: syscall returned with %d (%s)\n",
383 fd[nr_cpu][counter], strerror(err));
384 if (err == EPERM)
385 printf("Are you root?\n");
386 exit(-1);
387 }
388 assert(fd[nr_cpu][counter] >= 0);
389 fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);
390
391 /*
392 * First counter acts as the group leader:
393 */
394 if (group && group_fd == -1)
395 group_fd = fd[nr_cpu][counter];
396
397 event_array[nr_poll].fd = fd[nr_cpu][counter];
398 event_array[nr_poll].events = POLLIN;
399 nr_poll++;
400
401 mmap_array[nr_cpu][counter].counter = counter;
402 mmap_array[nr_cpu][counter].prev = 0;
403 mmap_array[nr_cpu][counter].mask = mmap_pages*page_size - 1;
404 mmap_array[nr_cpu][counter].base = mmap(NULL, (mmap_pages+1)*page_size,
405 PROT_READ, MAP_SHARED, fd[nr_cpu][counter], 0);
406 if (mmap_array[nr_cpu][counter].base == MAP_FAILED) {
407 printf("kerneltop error: failed to mmap with %d (%s)\n",
408 errno, strerror(errno));
409 exit(-1);
410 }
411 }
412 nr_cpu++;
413}
414
415int cmd_record(int argc, const char **argv)
416{
417 int i, counter;
340 pid_t pid; 418 pid_t pid;
341 int ret; 419 int ret;
342 420
@@ -357,54 +435,13 @@ int cmd_record(int argc, char **argv)
357 argc -= optind; 435 argc -= optind;
358 argv += optind; 436 argv += optind;
359 437
360 for (i = 0; i < nr_cpus; i++) { 438 if (!system_wide)
361 group_fd = -1; 439 open_counters(-1);
362 for (counter = 0; counter < nr_counters; counter++) { 440 else for (i = 0; i < nr_cpus; i++)
363 441 open_counters(i);
364 memset(&hw_event, 0, sizeof(hw_event));
365 hw_event.config = event_id[counter];
366 hw_event.irq_period = event_count[counter];
367 hw_event.record_type = PERF_RECORD_IP | PERF_RECORD_TID;
368 hw_event.nmi = 1;
369 hw_event.mmap = 1;
370 hw_event.comm = 1;
371
372 fd[i][counter] = sys_perf_counter_open(&hw_event, -1, i, group_fd, 0);
373 if (fd[i][counter] < 0) {
374 int err = errno;
375 printf("kerneltop error: syscall returned with %d (%s)\n",
376 fd[i][counter], strerror(err));
377 if (err == EPERM)
378 printf("Are you root?\n");
379 exit(-1);
380 }
381 assert(fd[i][counter] >= 0);
382 fcntl(fd[i][counter], F_SETFL, O_NONBLOCK);
383
384 /*
385 * First counter acts as the group leader:
386 */
387 if (group && group_fd == -1)
388 group_fd = fd[i][counter];
389
390 event_array[nr_poll].fd = fd[i][counter];
391 event_array[nr_poll].events = POLLIN;
392 nr_poll++;
393
394 mmap_array[i][counter].counter = counter;
395 mmap_array[i][counter].prev = 0;
396 mmap_array[i][counter].mask = mmap_pages*page_size - 1;
397 mmap_array[i][counter].base = mmap(NULL, (mmap_pages+1)*page_size,
398 PROT_READ, MAP_SHARED, fd[i][counter], 0);
399 if (mmap_array[i][counter].base == MAP_FAILED) {
400 printf("kerneltop error: failed to mmap with %d (%s)\n",
401 errno, strerror(errno));
402 exit(-1);
403 }
404 }
405 }
406 442
407 signal(SIGCHLD, sigchld_handler); 443 signal(SIGCHLD, sig_handler);
444 signal(SIGINT, sig_handler);
408 445
409 pid = fork(); 446 pid = fork();
410 if (pid < 0) 447 if (pid < 0)
@@ -434,7 +471,7 @@ int cmd_record(int argc, char **argv)
434 while (!done) { 471 while (!done) {
435 int hits = events; 472 int hits = events;
436 473
437 for (i = 0; i < nr_cpus; i++) { 474 for (i = 0; i < nr_cpu; i++) {
438 for (counter = 0; counter < nr_counters; counter++) 475 for (counter = 0; counter < nr_counters; counter++)
439 mmap_read(&mmap_array[i][counter]); 476 mmap_read(&mmap_array[i][counter]);
440 } 477 }
diff --git a/Documentation/perf_counter/builtin-stat.c b/Documentation/perf_counter/builtin-stat.c
index 6de38d256883..e2fa117eab58 100644
--- a/Documentation/perf_counter/builtin-stat.c
+++ b/Documentation/perf_counter/builtin-stat.c
@@ -87,6 +87,9 @@
87 87
88#include "perf.h" 88#include "perf.h"
89 89
90#define EVENT_MASK_KERNEL 1
91#define EVENT_MASK_USER 2
92
90static int system_wide = 0; 93static int system_wide = 0;
91 94
92static int nr_counters = 0; 95static int nr_counters = 0;
@@ -104,6 +107,7 @@ static __u64 event_id[MAX_COUNTERS] = {
104static int default_interval = 100000; 107static int default_interval = 100000;
105static int event_count[MAX_COUNTERS]; 108static int event_count[MAX_COUNTERS];
106static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 109static int fd[MAX_NR_CPUS][MAX_COUNTERS];
110static int event_mask[MAX_COUNTERS];
107 111
108static int tid = -1; 112static int tid = -1;
109static int profile_cpu = -1; 113static int profile_cpu = -1;
@@ -258,12 +262,23 @@ static __u64 match_event_symbols(char *str)
258 __u64 config, id; 262 __u64 config, id;
259 int type; 263 int type;
260 unsigned int i; 264 unsigned int i;
265 char mask_str[4];
261 266
262 if (sscanf(str, "r%llx", &config) == 1) 267 if (sscanf(str, "r%llx", &config) == 1)
263 return config | PERF_COUNTER_RAW_MASK; 268 return config | PERF_COUNTER_RAW_MASK;
264 269
265 if (sscanf(str, "%d:%llu", &type, &id) == 2) 270 switch (sscanf(str, "%d:%llu:%2s", &type, &id, mask_str)) {
266 return EID(type, id); 271 case 3:
272 if (strchr(mask_str, 'u'))
273 event_mask[nr_counters] |= EVENT_MASK_USER;
274 if (strchr(mask_str, 'k'))
275 event_mask[nr_counters] |= EVENT_MASK_KERNEL;
276 case 2:
277 return EID(type, id);
278
279 default:
280 break;
281 }
267 282
268 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 283 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
269 if (!strncmp(str, event_symbols[i].symbol, 284 if (!strncmp(str, event_symbols[i].symbol,
@@ -313,6 +328,11 @@ static void create_perfstat_counter(int counter)
313 hw_event.config = event_id[counter]; 328 hw_event.config = event_id[counter];
314 hw_event.record_type = 0; 329 hw_event.record_type = 0;
315 hw_event.nmi = 0; 330 hw_event.nmi = 0;
331 hw_event.exclude_kernel = event_mask[counter] & EVENT_MASK_KERNEL;
332 hw_event.exclude_user = event_mask[counter] & EVENT_MASK_USER;
333
334printf("exclude: %d\n", event_mask[counter]);
335
316 if (scale) 336 if (scale)
317 hw_event.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 337 hw_event.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
318 PERF_FORMAT_TOTAL_TIME_RUNNING; 338 PERF_FORMAT_TOTAL_TIME_RUNNING;
diff --git a/Documentation/perf_counter/perf-report.cc b/Documentation/perf_counter/perf-report.cc
index 911d7f3e7a65..8855107fe6b3 100644
--- a/Documentation/perf_counter/perf-report.cc
+++ b/Documentation/perf_counter/perf-report.cc
@@ -33,8 +33,13 @@
33#include <string> 33#include <string>
34 34
35 35
36#define SHOW_KERNEL 1
37#define SHOW_USER 2
38#define SHOW_HV 4
39
36static char const *input_name = "output.perf"; 40static char const *input_name = "output.perf";
37static int input; 41static int input;
42static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
38 43
39static unsigned long page_size; 44static unsigned long page_size;
40static unsigned long mmap_window = 32; 45static unsigned long mmap_window = 32;
@@ -359,15 +364,21 @@ static void process_options(int argc, char *argv[])
359 /** Options for getopt */ 364 /** Options for getopt */
360 static struct option long_options[] = { 365 static struct option long_options[] = {
361 {"input", required_argument, NULL, 'i'}, 366 {"input", required_argument, NULL, 'i'},
367 {"no-user", no_argument, NULL, 'u'},
368 {"no-kernel", no_argument, NULL, 'k'},
369 {"no-hv", no_argument, NULL, 'h'},
362 {NULL, 0, NULL, 0 } 370 {NULL, 0, NULL, 0 }
363 }; 371 };
364 int c = getopt_long(argc, argv, "+:i:", 372 int c = getopt_long(argc, argv, "+:i:kuh",
365 long_options, &option_index); 373 long_options, &option_index);
366 if (c == -1) 374 if (c == -1)
367 break; 375 break;
368 376
369 switch (c) { 377 switch (c) {
370 case 'i': input_name = strdup(optarg); break; 378 case 'i': input_name = strdup(optarg); break;
379 case 'k': show_mask &= ~SHOW_KERNEL; break;
380 case 'u': show_mask &= ~SHOW_USER; break;
381 case 'h': show_mask &= ~SHOW_HV; break;
371 default: error = 1; break; 382 default: error = 1; break;
372 } 383 }
373 } 384 }
@@ -443,22 +454,28 @@ more:
443 454
444 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) { 455 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) {
445 std::string comm, sym, level; 456 std::string comm, sym, level;
457 int show = 0;
446 char output[1024]; 458 char output[1024];
447 459
448 if (event->header.misc & PERF_EVENT_MISC_KERNEL) { 460 if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
461 show |= SHOW_KERNEL;
449 level = " [k] "; 462 level = " [k] ";
450 sym = resolve_kernel_symbol(event->ip.ip); 463 sym = resolve_kernel_symbol(event->ip.ip);
451 } else if (event->header.misc & PERF_EVENT_MISC_USER) { 464 } else if (event->header.misc & PERF_EVENT_MISC_USER) {
465 show |= SHOW_USER;
452 level = " [.] "; 466 level = " [.] ";
453 sym = resolve_user_symbol(event->ip.pid, event->ip.ip); 467 sym = resolve_user_symbol(event->ip.pid, event->ip.ip);
454 } else { 468 } else {
469 show |= SHOW_HV;
455 level = " [H] "; 470 level = " [H] ";
456 } 471 }
457 comm = resolve_comm(event->ip.pid);
458 472
459 snprintf(output, sizeof(output), "%16s %s %s", 473 if (show & show_mask) {
460 comm.c_str(), level.c_str(), sym.c_str()); 474 comm = resolve_comm(event->ip.pid);
461 hist[output]++; 475 snprintf(output, sizeof(output), "%16s %s %s",
476 comm.c_str(), level.c_str(), sym.c_str());
477 hist[output]++;
478 }
462 479
463 total++; 480 total++;
464 481