aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r--tools/perf/builtin-record.c344
1 files changed, 226 insertions, 118 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index d7ebbd75754..a5a050af8e7 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -14,6 +14,11 @@
14#include "util/parse-events.h" 14#include "util/parse-events.h"
15#include "util/string.h" 15#include "util/string.h"
16 16
17#include "util/header.h"
18#include "util/event.h"
19#include "util/debug.h"
20#include "util/trace-event.h"
21
17#include <unistd.h> 22#include <unistd.h>
18#include <sched.h> 23#include <sched.h>
19 24
@@ -32,13 +37,19 @@ static int output;
32static const char *output_name = "perf.data"; 37static const char *output_name = "perf.data";
33static int group = 0; 38static int group = 0;
34static unsigned int realtime_prio = 0; 39static unsigned int realtime_prio = 0;
40static int raw_samples = 0;
35static int system_wide = 0; 41static int system_wide = 0;
42static int profile_cpu = -1;
36static pid_t target_pid = -1; 43static pid_t target_pid = -1;
37static int inherit = 1; 44static int inherit = 1;
38static int force = 0; 45static int force = 0;
39static int append_file = 0; 46static int append_file = 0;
40static int call_graph = 0; 47static int call_graph = 0;
41static int verbose = 0; 48static int inherit_stat = 0;
49static int no_samples = 0;
50static int sample_address = 0;
51static int multiplex = 0;
52static int multiplex_fd = -1;
42 53
43static long samples; 54static long samples;
44static struct timeval last_read; 55static struct timeval last_read;
@@ -52,25 +63,8 @@ static int nr_poll;
52static int nr_cpu; 63static int nr_cpu;
53 64
54static int file_new = 1; 65static int file_new = 1;
55static struct perf_file_header file_header;
56
57struct mmap_event {
58 struct perf_event_header header;
59 u32 pid;
60 u32 tid;
61 u64 start;
62 u64 len;
63 u64 pgoff;
64 char filename[PATH_MAX];
65};
66
67struct comm_event {
68 struct perf_event_header header;
69 u32 pid;
70 u32 tid;
71 char comm[16];
72};
73 66
67struct perf_header *header;
74 68
75struct mmap_data { 69struct mmap_data {
76 int counter; 70 int counter;
@@ -83,7 +77,7 @@ static struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
83 77
84static unsigned long mmap_read_head(struct mmap_data *md) 78static unsigned long mmap_read_head(struct mmap_data *md)
85{ 79{
86 struct perf_counter_mmap_page *pc = md->base; 80 struct perf_event_mmap_page *pc = md->base;
87 long head; 81 long head;
88 82
89 head = pc->data_head; 83 head = pc->data_head;
@@ -94,7 +88,7 @@ static unsigned long mmap_read_head(struct mmap_data *md)
94 88
95static void mmap_write_tail(struct mmap_data *md, unsigned long tail) 89static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
96{ 90{
97 struct perf_counter_mmap_page *pc = md->base; 91 struct perf_event_mmap_page *pc = md->base;
98 92
99 /* 93 /*
100 * ensure all reads are done before we write the tail out. 94 * ensure all reads are done before we write the tail out.
@@ -197,47 +191,49 @@ static void sig_atexit(void)
197 kill(getpid(), signr); 191 kill(getpid(), signr);
198} 192}
199 193
200static void pid_synthesize_comm_event(pid_t pid, int full) 194static pid_t pid_synthesize_comm_event(pid_t pid, int full)
201{ 195{
202 struct comm_event comm_ev; 196 struct comm_event comm_ev;
203 char filename[PATH_MAX]; 197 char filename[PATH_MAX];
204 char bf[BUFSIZ]; 198 char bf[BUFSIZ];
205 int fd; 199 FILE *fp;
206 size_t size; 200 size_t size = 0;
207 char *field, *sep;
208 DIR *tasks; 201 DIR *tasks;
209 struct dirent dirent, *next; 202 struct dirent dirent, *next;
203 pid_t tgid = 0;
210 204
211 snprintf(filename, sizeof(filename), "/proc/%d/stat", pid); 205 snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
212 206
213 fd = open(filename, O_RDONLY); 207 fp = fopen(filename, "r");
214 if (fd < 0) { 208 if (fp == NULL) {
215 /* 209 /*
216 * We raced with a task exiting - just return: 210 * We raced with a task exiting - just return:
217 */ 211 */
218 if (verbose) 212 if (verbose)
219 fprintf(stderr, "couldn't open %s\n", filename); 213 fprintf(stderr, "couldn't open %s\n", filename);
220 return; 214 return 0;
221 } 215 }
222 if (read(fd, bf, sizeof(bf)) < 0) {
223 fprintf(stderr, "couldn't read %s\n", filename);
224 exit(EXIT_FAILURE);
225 }
226 close(fd);
227 216
228 /* 9027 (cat) R 6747 9027 6747 34816 9027 ... */
229 memset(&comm_ev, 0, sizeof(comm_ev)); 217 memset(&comm_ev, 0, sizeof(comm_ev));
230 field = strchr(bf, '('); 218 while (!comm_ev.comm[0] || !comm_ev.pid) {
231 if (field == NULL) 219 if (fgets(bf, sizeof(bf), fp) == NULL)
232 goto out_failure; 220 goto out_failure;
233 sep = strchr(++field, ')'); 221
234 if (sep == NULL) 222 if (memcmp(bf, "Name:", 5) == 0) {
235 goto out_failure; 223 char *name = bf + 5;
236 size = sep - field; 224 while (*name && isspace(*name))
237 memcpy(comm_ev.comm, field, size++); 225 ++name;
238 226 size = strlen(name) - 1;
239 comm_ev.pid = pid; 227 memcpy(comm_ev.comm, name, size++);
240 comm_ev.header.type = PERF_EVENT_COMM; 228 } else if (memcmp(bf, "Tgid:", 5) == 0) {
229 char *tgids = bf + 5;
230 while (*tgids && isspace(*tgids))
231 ++tgids;
232 tgid = comm_ev.pid = atoi(tgids);
233 }
234 }
235
236 comm_ev.header.type = PERF_RECORD_COMM;
241 size = ALIGN(size, sizeof(u64)); 237 size = ALIGN(size, sizeof(u64));
242 comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size); 238 comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size);
243 239
@@ -245,7 +241,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
245 comm_ev.tid = pid; 241 comm_ev.tid = pid;
246 242
247 write_output(&comm_ev, comm_ev.header.size); 243 write_output(&comm_ev, comm_ev.header.size);
248 return; 244 goto out_fclose;
249 } 245 }
250 246
251 snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 247 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
@@ -262,7 +258,10 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
262 write_output(&comm_ev, comm_ev.header.size); 258 write_output(&comm_ev, comm_ev.header.size);
263 } 259 }
264 closedir(tasks); 260 closedir(tasks);
265 return; 261
262out_fclose:
263 fclose(fp);
264 return tgid;
266 265
267out_failure: 266out_failure:
268 fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n", 267 fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n",
@@ -270,7 +269,7 @@ out_failure:
270 exit(EXIT_FAILURE); 269 exit(EXIT_FAILURE);
271} 270}
272 271
273static void pid_synthesize_mmap_samples(pid_t pid) 272static void pid_synthesize_mmap_samples(pid_t pid, pid_t tgid)
274{ 273{
275 char filename[PATH_MAX]; 274 char filename[PATH_MAX];
276 FILE *fp; 275 FILE *fp;
@@ -289,7 +288,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
289 while (1) { 288 while (1) {
290 char bf[BUFSIZ], *pbf = bf; 289 char bf[BUFSIZ], *pbf = bf;
291 struct mmap_event mmap_ev = { 290 struct mmap_event mmap_ev = {
292 .header.type = PERF_EVENT_MMAP, 291 .header = { .type = PERF_RECORD_MMAP },
293 }; 292 };
294 int n; 293 int n;
295 size_t size; 294 size_t size;
@@ -306,12 +305,15 @@ static void pid_synthesize_mmap_samples(pid_t pid)
306 continue; 305 continue;
307 pbf += n + 3; 306 pbf += n + 3;
308 if (*pbf == 'x') { /* vm_exec */ 307 if (*pbf == 'x') { /* vm_exec */
309 char *execname = strrchr(bf, ' '); 308 char *execname = strchr(bf, '/');
309
310 /* Catch VDSO */
311 if (execname == NULL)
312 execname = strstr(bf, "[vdso]");
310 313
311 if (execname == NULL || execname[1] != '/') 314 if (execname == NULL)
312 continue; 315 continue;
313 316
314 execname += 1;
315 size = strlen(execname); 317 size = strlen(execname);
316 execname[size - 1] = '\0'; /* Remove \n */ 318 execname[size - 1] = '\0'; /* Remove \n */
317 memcpy(mmap_ev.filename, execname, size); 319 memcpy(mmap_ev.filename, execname, size);
@@ -319,7 +321,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
319 mmap_ev.len -= mmap_ev.start; 321 mmap_ev.len -= mmap_ev.start;
320 mmap_ev.header.size = (sizeof(mmap_ev) - 322 mmap_ev.header.size = (sizeof(mmap_ev) -
321 (sizeof(mmap_ev.filename) - size)); 323 (sizeof(mmap_ev.filename) - size));
322 mmap_ev.pid = pid; 324 mmap_ev.pid = tgid;
323 mmap_ev.tid = pid; 325 mmap_ev.tid = pid;
324 326
325 write_output(&mmap_ev, mmap_ev.header.size); 327 write_output(&mmap_ev, mmap_ev.header.size);
@@ -329,7 +331,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
329 fclose(fp); 331 fclose(fp);
330} 332}
331 333
332static void synthesize_samples(void) 334static void synthesize_all(void)
333{ 335{
334 DIR *proc; 336 DIR *proc;
335 struct dirent dirent, *next; 337 struct dirent dirent, *next;
@@ -338,14 +340,14 @@ static void synthesize_samples(void)
338 340
339 while (!readdir_r(proc, &dirent, &next) && next) { 341 while (!readdir_r(proc, &dirent, &next) && next) {
340 char *end; 342 char *end;
341 pid_t pid; 343 pid_t pid, tgid;
342 344
343 pid = strtol(dirent.d_name, &end, 10); 345 pid = strtol(dirent.d_name, &end, 10);
344 if (*end) /* only interested in proper numerical dirents */ 346 if (*end) /* only interested in proper numerical dirents */
345 continue; 347 continue;
346 348
347 pid_synthesize_comm_event(pid, 1); 349 tgid = pid_synthesize_comm_event(pid, 1);
348 pid_synthesize_mmap_samples(pid); 350 pid_synthesize_mmap_samples(pid, tgid);
349 } 351 }
350 352
351 closedir(proc); 353 closedir(proc);
@@ -353,12 +355,37 @@ static void synthesize_samples(void)
353 355
354static int group_fd; 356static int group_fd;
355 357
356static void create_counter(int counter, int cpu, pid_t pid) 358static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr)
357{ 359{
358 struct perf_counter_attr *attr = attrs + counter; 360 struct perf_header_attr *h_attr;
359 int track = 1; 361
362 if (nr < header->attrs) {
363 h_attr = header->attr[nr];
364 } else {
365 h_attr = perf_header_attr__new(a);
366 perf_header__add_attr(header, h_attr);
367 }
360 368
361 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 369 return h_attr;
370}
371
372static void create_counter(int counter, int cpu, pid_t pid)
373{
374 struct perf_event_attr *attr = attrs + counter;
375 struct perf_header_attr *h_attr;
376 int track = !counter; /* only the first counter needs these */
377 struct {
378 u64 count;
379 u64 time_enabled;
380 u64 time_running;
381 u64 id;
382 } read_data;
383
384 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
385 PERF_FORMAT_TOTAL_TIME_RUNNING |
386 PERF_FORMAT_ID;
387
388 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
362 389
363 if (freq) { 390 if (freq) {
364 attr->sample_type |= PERF_SAMPLE_PERIOD; 391 attr->sample_type |= PERF_SAMPLE_PERIOD;
@@ -366,16 +393,22 @@ static void create_counter(int counter, int cpu, pid_t pid)
366 attr->sample_freq = freq; 393 attr->sample_freq = freq;
367 } 394 }
368 395
396 if (no_samples)
397 attr->sample_freq = 0;
398
399 if (inherit_stat)
400 attr->inherit_stat = 1;
401
402 if (sample_address)
403 attr->sample_type |= PERF_SAMPLE_ADDR;
404
369 if (call_graph) 405 if (call_graph)
370 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 406 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
371 407
372 if (file_new) { 408 if (raw_samples) {
373 file_header.sample_type = attr->sample_type; 409 attr->sample_type |= PERF_SAMPLE_TIME;
374 } else { 410 attr->sample_type |= PERF_SAMPLE_RAW;
375 if (file_header.sample_type != attr->sample_type) { 411 attr->sample_type |= PERF_SAMPLE_CPU;
376 fprintf(stderr, "incompatible append\n");
377 exit(-1);
378 }
379 } 412 }
380 413
381 attr->mmap = track; 414 attr->mmap = track;
@@ -383,16 +416,16 @@ static void create_counter(int counter, int cpu, pid_t pid)
383 attr->inherit = (cpu < 0) && inherit; 416 attr->inherit = (cpu < 0) && inherit;
384 attr->disabled = 1; 417 attr->disabled = 1;
385 418
386 track = 0; /* only the first counter needs these */
387
388try_again: 419try_again:
389 fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0); 420 fd[nr_cpu][counter] = sys_perf_event_open(attr, pid, cpu, group_fd, 0);
390 421
391 if (fd[nr_cpu][counter] < 0) { 422 if (fd[nr_cpu][counter] < 0) {
392 int err = errno; 423 int err = errno;
393 424
394 if (err == EPERM) 425 if (err == EPERM)
395 die("Permission error - are you root?\n"); 426 die("Permission error - are you root?\n");
427 else if (err == ENODEV && profile_cpu != -1)
428 die("No such device - did you specify an out-of-range profile CPU?\n");
396 429
397 /* 430 /*
398 * If it's cycles then fall back to hrtimer 431 * If it's cycles then fall back to hrtimer
@@ -411,10 +444,26 @@ try_again:
411 printf("\n"); 444 printf("\n");
412 error("perfcounter syscall returned with %d (%s)\n", 445 error("perfcounter syscall returned with %d (%s)\n",
413 fd[nr_cpu][counter], strerror(err)); 446 fd[nr_cpu][counter], strerror(err));
414 die("No CONFIG_PERF_COUNTERS=y kernel support configured?\n"); 447 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
448 exit(-1);
449 }
450
451 h_attr = get_header_attr(attr, counter);
452
453 if (!file_new) {
454 if (memcmp(&h_attr->attr, attr, sizeof(*attr))) {
455 fprintf(stderr, "incompatible append\n");
456 exit(-1);
457 }
458 }
459
460 if (read(fd[nr_cpu][counter], &read_data, sizeof(read_data)) == -1) {
461 perror("Unable to read perf file descriptor\n");
415 exit(-1); 462 exit(-1);
416 } 463 }
417 464
465 perf_header_attr__add_id(h_attr, read_data.id);
466
418 assert(fd[nr_cpu][counter] >= 0); 467 assert(fd[nr_cpu][counter] >= 0);
419 fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK); 468 fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);
420 469
@@ -423,33 +472,37 @@ try_again:
423 */ 472 */
424 if (group && group_fd == -1) 473 if (group && group_fd == -1)
425 group_fd = fd[nr_cpu][counter]; 474 group_fd = fd[nr_cpu][counter];
475 if (multiplex && multiplex_fd == -1)
476 multiplex_fd = fd[nr_cpu][counter];
426 477
427 event_array[nr_poll].fd = fd[nr_cpu][counter]; 478 if (multiplex && fd[nr_cpu][counter] != multiplex_fd) {
428 event_array[nr_poll].events = POLLIN; 479 int ret;
429 nr_poll++; 480
430 481 ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd);
431 mmap_array[nr_cpu][counter].counter = counter; 482 assert(ret != -1);
432 mmap_array[nr_cpu][counter].prev = 0; 483 } else {
433 mmap_array[nr_cpu][counter].mask = mmap_pages*page_size - 1; 484 event_array[nr_poll].fd = fd[nr_cpu][counter];
434 mmap_array[nr_cpu][counter].base = mmap(NULL, (mmap_pages+1)*page_size, 485 event_array[nr_poll].events = POLLIN;
435 PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter], 0); 486 nr_poll++;
436 if (mmap_array[nr_cpu][counter].base == MAP_FAILED) { 487
437 error("failed to mmap with %d (%s)\n", errno, strerror(errno)); 488 mmap_array[nr_cpu][counter].counter = counter;
438 exit(-1); 489 mmap_array[nr_cpu][counter].prev = 0;
490 mmap_array[nr_cpu][counter].mask = mmap_pages*page_size - 1;
491 mmap_array[nr_cpu][counter].base = mmap(NULL, (mmap_pages+1)*page_size,
492 PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter], 0);
493 if (mmap_array[nr_cpu][counter].base == MAP_FAILED) {
494 error("failed to mmap with %d (%s)\n", errno, strerror(errno));
495 exit(-1);
496 }
439 } 497 }
440 498
441 ioctl(fd[nr_cpu][counter], PERF_COUNTER_IOC_ENABLE); 499 ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE);
442} 500}
443 501
444static void open_counters(int cpu, pid_t pid) 502static void open_counters(int cpu, pid_t pid)
445{ 503{
446 int counter; 504 int counter;
447 505
448 if (pid > 0) {
449 pid_synthesize_comm_event(pid, 0);
450 pid_synthesize_mmap_samples(pid);
451 }
452
453 group_fd = -1; 506 group_fd = -1;
454 for (counter = 0; counter < nr_counters; counter++) 507 for (counter = 0; counter < nr_counters; counter++)
455 create_counter(counter, cpu, pid); 508 create_counter(counter, cpu, pid);
@@ -459,19 +512,19 @@ static void open_counters(int cpu, pid_t pid)
459 512
460static void atexit_header(void) 513static void atexit_header(void)
461{ 514{
462 file_header.data_size += bytes_written; 515 header->data_size += bytes_written;
463 516
464 if (pwrite(output, &file_header, sizeof(file_header), 0) == -1) 517 perf_header__write(header, output);
465 perror("failed to write on file headers");
466} 518}
467 519
468static int __cmd_record(int argc, const char **argv) 520static int __cmd_record(int argc, const char **argv)
469{ 521{
470 int i, counter; 522 int i, counter;
471 struct stat st; 523 struct stat st;
472 pid_t pid; 524 pid_t pid = 0;
473 int flags; 525 int flags;
474 int ret; 526 int ret;
527 unsigned long waking = 0;
475 528
476 page_size = sysconf(_SC_PAGE_SIZE); 529 page_size = sysconf(_SC_PAGE_SIZE);
477 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 530 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
@@ -482,10 +535,14 @@ static int __cmd_record(int argc, const char **argv)
482 signal(SIGCHLD, sig_handler); 535 signal(SIGCHLD, sig_handler);
483 signal(SIGINT, sig_handler); 536 signal(SIGINT, sig_handler);
484 537
485 if (!stat(output_name, &st) && !force && !append_file) { 538 if (!stat(output_name, &st) && st.st_size) {
486 fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n", 539 if (!force && !append_file) {
487 output_name); 540 fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n",
488 exit(-1); 541 output_name);
542 exit(-1);
543 }
544 } else {
545 append_file = 0;
489 } 546 }
490 547
491 flags = O_CREAT|O_RDWR; 548 flags = O_CREAT|O_RDWR;
@@ -500,21 +557,47 @@ static int __cmd_record(int argc, const char **argv)
500 exit(-1); 557 exit(-1);
501 } 558 }
502 559
503 if (!file_new) { 560 if (!file_new)
504 if (read(output, &file_header, sizeof(file_header)) == -1) { 561 header = perf_header__read(output);
505 perror("failed to read file headers"); 562 else
506 exit(-1); 563 header = perf_header__new();
564
565
566 if (raw_samples) {
567 read_tracing_data(attrs, nr_counters);
568 } else {
569 for (i = 0; i < nr_counters; i++) {
570 if (attrs[i].sample_type & PERF_SAMPLE_RAW) {
571 read_tracing_data(attrs, nr_counters);
572 break;
573 }
507 } 574 }
575 }
576 atexit(atexit_header);
508 577
509 lseek(output, file_header.data_size, SEEK_CUR); 578 if (!system_wide) {
579 pid = target_pid;
580 if (pid == -1)
581 pid = getpid();
582
583 open_counters(profile_cpu, pid);
584 } else {
585 if (profile_cpu != -1) {
586 open_counters(profile_cpu, target_pid);
587 } else {
588 for (i = 0; i < nr_cpus; i++)
589 open_counters(i, target_pid);
590 }
510 } 591 }
511 592
512 atexit(atexit_header); 593 if (file_new)
594 perf_header__write(header, output);
513 595
514 if (!system_wide) { 596 if (!system_wide) {
515 open_counters(-1, target_pid != -1 ? target_pid : getpid()); 597 pid_t tgid = pid_synthesize_comm_event(pid, 0);
516 } else for (i = 0; i < nr_cpus; i++) 598 pid_synthesize_mmap_samples(pid, tgid);
517 open_counters(i, target_pid); 599 } else
600 synthesize_all();
518 601
519 if (target_pid == -1 && argc) { 602 if (target_pid == -1 && argc) {
520 pid = fork(); 603 pid = fork();
@@ -539,21 +622,33 @@ static int __cmd_record(int argc, const char **argv)
539 } 622 }
540 } 623 }
541 624
542 if (system_wide) 625 for (;;) {
543 synthesize_samples();
544
545 while (!done) {
546 int hits = samples; 626 int hits = samples;
547 627
548 for (i = 0; i < nr_cpu; i++) { 628 for (i = 0; i < nr_cpu; i++) {
549 for (counter = 0; counter < nr_counters; counter++) 629 for (counter = 0; counter < nr_counters; counter++) {
550 mmap_read(&mmap_array[i][counter]); 630 if (mmap_array[i][counter].base)
631 mmap_read(&mmap_array[i][counter]);
632 }
551 } 633 }
552 634
553 if (hits == samples) 635 if (hits == samples) {
554 ret = poll(event_array, nr_poll, 100); 636 if (done)
637 break;
638 ret = poll(event_array, nr_poll, -1);
639 waking++;
640 }
641
642 if (done) {
643 for (i = 0; i < nr_cpu; i++) {
644 for (counter = 0; counter < nr_counters; counter++)
645 ioctl(fd[i][counter], PERF_EVENT_IOC_DISABLE);
646 }
647 }
555 } 648 }
556 649
650 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
651
557 /* 652 /*
558 * Approximate RIP event size: 24 bytes. 653 * Approximate RIP event size: 24 bytes.
559 */ 654 */
@@ -580,10 +675,14 @@ static const struct option options[] = {
580 "record events on existing pid"), 675 "record events on existing pid"),
581 OPT_INTEGER('r', "realtime", &realtime_prio, 676 OPT_INTEGER('r', "realtime", &realtime_prio,
582 "collect data with this RT SCHED_FIFO priority"), 677 "collect data with this RT SCHED_FIFO priority"),
678 OPT_BOOLEAN('R', "raw-samples", &raw_samples,
679 "collect raw sample records from all opened counters"),
583 OPT_BOOLEAN('a', "all-cpus", &system_wide, 680 OPT_BOOLEAN('a', "all-cpus", &system_wide,
584 "system-wide collection from all CPUs"), 681 "system-wide collection from all CPUs"),
585 OPT_BOOLEAN('A', "append", &append_file, 682 OPT_BOOLEAN('A', "append", &append_file,
586 "append to the output file to do incremental profiling"), 683 "append to the output file to do incremental profiling"),
684 OPT_INTEGER('C', "profile_cpu", &profile_cpu,
685 "CPU to profile on"),
587 OPT_BOOLEAN('f', "force", &force, 686 OPT_BOOLEAN('f', "force", &force,
588 "overwrite existing data file"), 687 "overwrite existing data file"),
589 OPT_LONG('c', "count", &default_interval, 688 OPT_LONG('c', "count", &default_interval,
@@ -600,14 +699,23 @@ static const struct option options[] = {
600 "do call-graph (stack chain/backtrace) recording"), 699 "do call-graph (stack chain/backtrace) recording"),
601 OPT_BOOLEAN('v', "verbose", &verbose, 700 OPT_BOOLEAN('v', "verbose", &verbose,
602 "be more verbose (show counter open errors, etc)"), 701 "be more verbose (show counter open errors, etc)"),
702 OPT_BOOLEAN('s', "stat", &inherit_stat,
703 "per thread counts"),
704 OPT_BOOLEAN('d', "data", &sample_address,
705 "Sample addresses"),
706 OPT_BOOLEAN('n', "no-samples", &no_samples,
707 "don't sample"),
708 OPT_BOOLEAN('M', "multiplex", &multiplex,
709 "multiplex counter output in a single channel"),
603 OPT_END() 710 OPT_END()
604}; 711};
605 712
606int cmd_record(int argc, const char **argv, const char *prefix) 713int cmd_record(int argc, const char **argv, const char *prefix __used)
607{ 714{
608 int counter; 715 int counter;
609 716
610 argc = parse_options(argc, argv, options, record_usage, 0); 717 argc = parse_options(argc, argv, options, record_usage,
718 PARSE_OPT_STOP_AT_NON_OPTION);
611 if (!argc && target_pid == -1 && !system_wide) 719 if (!argc && target_pid == -1 && !system_wide)
612 usage_with_options(record_usage, options); 720 usage_with_options(record_usage, options);
613 721