diff options
| -rw-r--r-- | tools/perf/Documentation/perf-report.txt | 3 | ||||
| -rw-r--r-- | tools/perf/builtin-record.c | 81 | ||||
| -rw-r--r-- | tools/perf/builtin-trace.c | 248 | ||||
| -rw-r--r-- | tools/perf/util/evlist.c | 34 | ||||
| -rw-r--r-- | tools/perf/util/evlist.h | 4 | ||||
| -rw-r--r-- | tools/perf/util/evsel.c | 13 | ||||
| -rw-r--r-- | tools/perf/util/evsel.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/hist.c | 9 | ||||
| -rw-r--r-- | tools/perf/util/hist.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/sort.c | 84 | ||||
| -rw-r--r-- | tools/perf/util/sort.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/symbol.h | 2 |
12 files changed, 319 insertions, 164 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 496d42cdf02b..9cbddc290aff 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
| @@ -103,12 +103,13 @@ OPTIONS | |||
| 103 | 103 | ||
| 104 | If --branch-stack option is used, following sort keys are also | 104 | If --branch-stack option is used, following sort keys are also |
| 105 | available: | 105 | available: |
| 106 | dso_from, dso_to, symbol_from, symbol_to, mispredict. | ||
| 107 | 106 | ||
| 108 | - dso_from: name of library or module branched from | 107 | - dso_from: name of library or module branched from |
| 109 | - dso_to: name of library or module branched to | 108 | - dso_to: name of library or module branched to |
| 110 | - symbol_from: name of function branched from | 109 | - symbol_from: name of function branched from |
| 111 | - symbol_to: name of function branched to | 110 | - symbol_to: name of function branched to |
| 111 | - srcline_from: source file and line branched from | ||
| 112 | - srcline_to: source file and line branched to | ||
| 112 | - mispredict: "N" for predicted branch, "Y" for mispredicted branch | 113 | - mispredict: "N" for predicted branch, "Y" for mispredicted branch |
| 113 | - in_tx: branch in TSX transaction | 114 | - in_tx: branch in TSX transaction |
| 114 | - abort: TSX transaction abort. | 115 | - abort: TSX transaction abort. |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index f3679c44d3f3..dc3fcb597e4c 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <unistd.h> | 40 | #include <unistd.h> |
| 41 | #include <sched.h> | 41 | #include <sched.h> |
| 42 | #include <sys/mman.h> | 42 | #include <sys/mman.h> |
| 43 | #include <asm/bug.h> | ||
| 43 | 44 | ||
| 44 | 45 | ||
| 45 | struct record { | 46 | struct record { |
| @@ -82,27 +83,87 @@ static int process_synthesized_event(struct perf_tool *tool, | |||
| 82 | return record__write(rec, event, event->header.size); | 83 | return record__write(rec, event, event->header.size); |
| 83 | } | 84 | } |
| 84 | 85 | ||
| 86 | static int | ||
| 87 | backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end) | ||
| 88 | { | ||
| 89 | struct perf_event_header *pheader; | ||
| 90 | u64 evt_head = head; | ||
| 91 | int size = mask + 1; | ||
| 92 | |||
| 93 | pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head); | ||
| 94 | pheader = (struct perf_event_header *)(buf + (head & mask)); | ||
| 95 | *start = head; | ||
| 96 | while (true) { | ||
| 97 | if (evt_head - head >= (unsigned int)size) { | ||
| 98 | pr_debug("Finshed reading backward ring buffer: rewind\n"); | ||
| 99 | if (evt_head - head > (unsigned int)size) | ||
| 100 | evt_head -= pheader->size; | ||
| 101 | *end = evt_head; | ||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | pheader = (struct perf_event_header *)(buf + (evt_head & mask)); | ||
| 106 | |||
| 107 | if (pheader->size == 0) { | ||
| 108 | pr_debug("Finshed reading backward ring buffer: get start\n"); | ||
| 109 | *end = evt_head; | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | evt_head += pheader->size; | ||
| 114 | pr_debug3("move evt_head: %"PRIx64"\n", evt_head); | ||
| 115 | } | ||
| 116 | WARN_ONCE(1, "Shouldn't get here\n"); | ||
| 117 | return -1; | ||
| 118 | } | ||
| 119 | |||
| 120 | static int | ||
| 121 | rb_find_range(struct perf_evlist *evlist, | ||
| 122 | void *data, int mask, u64 head, u64 old, | ||
| 123 | u64 *start, u64 *end) | ||
| 124 | { | ||
| 125 | if (!evlist->backward) { | ||
| 126 | *start = old; | ||
| 127 | *end = head; | ||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | return backward_rb_find_range(data, mask, head, start, end); | ||
| 132 | } | ||
| 133 | |||
| 85 | static int record__mmap_read(struct record *rec, int idx) | 134 | static int record__mmap_read(struct record *rec, int idx) |
| 86 | { | 135 | { |
| 87 | struct perf_mmap *md = &rec->evlist->mmap[idx]; | 136 | struct perf_mmap *md = &rec->evlist->mmap[idx]; |
| 88 | u64 head = perf_mmap__read_head(md); | 137 | u64 head = perf_mmap__read_head(md); |
| 89 | u64 old = md->prev; | 138 | u64 old = md->prev; |
| 139 | u64 end = head, start = old; | ||
| 90 | unsigned char *data = md->base + page_size; | 140 | unsigned char *data = md->base + page_size; |
| 91 | unsigned long size; | 141 | unsigned long size; |
| 92 | void *buf; | 142 | void *buf; |
| 93 | int rc = 0; | 143 | int rc = 0; |
| 94 | 144 | ||
| 95 | if (old == head) | 145 | if (rb_find_range(rec->evlist, data, md->mask, head, |
| 146 | old, &start, &end)) | ||
| 147 | return -1; | ||
| 148 | |||
| 149 | if (start == end) | ||
| 96 | return 0; | 150 | return 0; |
| 97 | 151 | ||
| 98 | rec->samples++; | 152 | rec->samples++; |
| 99 | 153 | ||
| 100 | size = head - old; | 154 | size = end - start; |
| 155 | if (size > (unsigned long)(md->mask) + 1) { | ||
| 156 | WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); | ||
| 157 | |||
| 158 | md->prev = head; | ||
| 159 | perf_evlist__mmap_consume(rec->evlist, idx); | ||
| 160 | return 0; | ||
| 161 | } | ||
| 101 | 162 | ||
| 102 | if ((old & md->mask) + size != (head & md->mask)) { | 163 | if ((start & md->mask) + size != (end & md->mask)) { |
| 103 | buf = &data[old & md->mask]; | 164 | buf = &data[start & md->mask]; |
| 104 | size = md->mask + 1 - (old & md->mask); | 165 | size = md->mask + 1 - (start & md->mask); |
| 105 | old += size; | 166 | start += size; |
| 106 | 167 | ||
| 107 | if (record__write(rec, buf, size) < 0) { | 168 | if (record__write(rec, buf, size) < 0) { |
| 108 | rc = -1; | 169 | rc = -1; |
| @@ -110,16 +171,16 @@ static int record__mmap_read(struct record *rec, int idx) | |||
| 110 | } | 171 | } |
| 111 | } | 172 | } |
| 112 | 173 | ||
| 113 | buf = &data[old & md->mask]; | 174 | buf = &data[start & md->mask]; |
| 114 | size = head - old; | 175 | size = end - start; |
| 115 | old += size; | 176 | start += size; |
| 116 | 177 | ||
| 117 | if (record__write(rec, buf, size) < 0) { | 178 | if (record__write(rec, buf, size) < 0) { |
| 118 | rc = -1; | 179 | rc = -1; |
| 119 | goto out; | 180 | goto out; |
| 120 | } | 181 | } |
| 121 | 182 | ||
| 122 | md->prev = old; | 183 | md->prev = head; |
| 123 | perf_evlist__mmap_consume(rec->evlist, idx); | 184 | perf_evlist__mmap_consume(rec->evlist, idx); |
| 124 | out: | 185 | out: |
| 125 | return rc; | 186 | return rc; |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 487c10401d46..5c50fe70d6b3 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
| @@ -576,84 +576,54 @@ static struct syscall_fmt { | |||
| 576 | bool hexret; | 576 | bool hexret; |
| 577 | } syscall_fmts[] = { | 577 | } syscall_fmts[] = { |
| 578 | { .name = "access", .errmsg = true, | 578 | { .name = "access", .errmsg = true, |
| 579 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ | 579 | .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, }, |
| 580 | [1] = SCA_ACCMODE, /* mode */ }, }, | ||
| 581 | { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, | 580 | { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, |
| 582 | { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), }, | 581 | { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), }, |
| 583 | { .name = "brk", .hexret = true, | 582 | { .name = "brk", .hexret = true, |
| 584 | .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, | 583 | .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, |
| 585 | { .name = "chdir", .errmsg = true, | 584 | { .name = "chdir", .errmsg = true, }, |
| 586 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | 585 | { .name = "chmod", .errmsg = true, }, |
| 587 | { .name = "chmod", .errmsg = true, | 586 | { .name = "chroot", .errmsg = true, }, |
| 588 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
| 589 | { .name = "chroot", .errmsg = true, | ||
| 590 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
| 591 | { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, | 587 | { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, |
| 592 | { .name = "clone", .errpid = true, }, | 588 | { .name = "clone", .errpid = true, }, |
| 593 | { .name = "close", .errmsg = true, | 589 | { .name = "close", .errmsg = true, |
| 594 | .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, | 590 | .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, |
| 595 | { .name = "connect", .errmsg = true, }, | 591 | { .name = "connect", .errmsg = true, }, |
| 596 | { .name = "creat", .errmsg = true, | 592 | { .name = "creat", .errmsg = true, }, |
| 597 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | 593 | { .name = "dup", .errmsg = true, }, |
| 598 | { .name = "dup", .errmsg = true, | 594 | { .name = "dup2", .errmsg = true, }, |
| 599 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 595 | { .name = "dup3", .errmsg = true, }, |
| 600 | { .name = "dup2", .errmsg = true, | ||
| 601 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 602 | { .name = "dup3", .errmsg = true, | ||
| 603 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 604 | { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), }, | 596 | { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), }, |
| 605 | { .name = "eventfd2", .errmsg = true, | 597 | { .name = "eventfd2", .errmsg = true, |
| 606 | .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, | 598 | .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, |
| 607 | { .name = "faccessat", .errmsg = true, | 599 | { .name = "faccessat", .errmsg = true, }, |
| 608 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 600 | { .name = "fadvise64", .errmsg = true, }, |
| 609 | [1] = SCA_FILENAME, /* filename */ }, }, | 601 | { .name = "fallocate", .errmsg = true, }, |
| 610 | { .name = "fadvise64", .errmsg = true, | 602 | { .name = "fchdir", .errmsg = true, }, |
| 611 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 603 | { .name = "fchmod", .errmsg = true, }, |
| 612 | { .name = "fallocate", .errmsg = true, | ||
| 613 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 614 | { .name = "fchdir", .errmsg = true, | ||
| 615 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 616 | { .name = "fchmod", .errmsg = true, | ||
| 617 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 618 | { .name = "fchmodat", .errmsg = true, | 604 | { .name = "fchmodat", .errmsg = true, |
| 619 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ | 605 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
| 620 | [1] = SCA_FILENAME, /* filename */ }, }, | 606 | { .name = "fchown", .errmsg = true, }, |
| 621 | { .name = "fchown", .errmsg = true, | ||
| 622 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 623 | { .name = "fchownat", .errmsg = true, | 607 | { .name = "fchownat", .errmsg = true, |
| 624 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ | 608 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
| 625 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
| 626 | { .name = "fcntl", .errmsg = true, | 609 | { .name = "fcntl", .errmsg = true, |
| 627 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 610 | .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ }, |
| 628 | [1] = SCA_STRARRAY, /* cmd */ }, | ||
| 629 | .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, }, | 611 | .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, }, |
| 630 | { .name = "fdatasync", .errmsg = true, | 612 | { .name = "fdatasync", .errmsg = true, }, |
| 631 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 632 | { .name = "flock", .errmsg = true, | 613 | { .name = "flock", .errmsg = true, |
| 633 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 614 | .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, }, |
| 634 | [1] = SCA_FLOCK, /* cmd */ }, }, | 615 | { .name = "fsetxattr", .errmsg = true, }, |
| 635 | { .name = "fsetxattr", .errmsg = true, | 616 | { .name = "fstat", .errmsg = true, .alias = "newfstat", }, |
| 636 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 617 | { .name = "fstatat", .errmsg = true, .alias = "newfstatat", }, |
| 637 | { .name = "fstat", .errmsg = true, .alias = "newfstat", | 618 | { .name = "fstatfs", .errmsg = true, }, |
| 638 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 619 | { .name = "fsync", .errmsg = true, }, |
| 639 | { .name = "fstatat", .errmsg = true, .alias = "newfstatat", | 620 | { .name = "ftruncate", .errmsg = true, }, |
| 640 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | ||
| 641 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
| 642 | { .name = "fstatfs", .errmsg = true, | ||
| 643 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 644 | { .name = "fsync", .errmsg = true, | ||
| 645 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 646 | { .name = "ftruncate", .errmsg = true, | ||
| 647 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 648 | { .name = "futex", .errmsg = true, | 621 | { .name = "futex", .errmsg = true, |
| 649 | .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, | 622 | .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, |
| 650 | { .name = "futimesat", .errmsg = true, | 623 | { .name = "futimesat", .errmsg = true, |
| 651 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ | 624 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
| 652 | [1] = SCA_FILENAME, /* filename */ }, }, | 625 | { .name = "getdents", .errmsg = true, }, |
| 653 | { .name = "getdents", .errmsg = true, | 626 | { .name = "getdents64", .errmsg = true, }, |
| 654 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 655 | { .name = "getdents64", .errmsg = true, | ||
| 656 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 657 | { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, | 627 | { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, |
| 658 | { .name = "getpid", .errpid = true, }, | 628 | { .name = "getpid", .errpid = true, }, |
| 659 | { .name = "getpgid", .errpid = true, }, | 629 | { .name = "getpgid", .errpid = true, }, |
| @@ -661,12 +631,10 @@ static struct syscall_fmt { | |||
| 661 | { .name = "getrandom", .errmsg = true, | 631 | { .name = "getrandom", .errmsg = true, |
| 662 | .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, }, | 632 | .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, }, |
| 663 | { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, | 633 | { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, |
| 664 | { .name = "getxattr", .errmsg = true, | 634 | { .name = "getxattr", .errmsg = true, }, |
| 665 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | 635 | { .name = "inotify_add_watch", .errmsg = true, }, |
| 666 | { .name = "inotify_add_watch", .errmsg = true, | ||
| 667 | .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, }, | ||
| 668 | { .name = "ioctl", .errmsg = true, | 636 | { .name = "ioctl", .errmsg = true, |
| 669 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 637 | .arg_scnprintf = { |
| 670 | #if defined(__i386__) || defined(__x86_64__) | 638 | #if defined(__i386__) || defined(__x86_64__) |
| 671 | /* | 639 | /* |
| 672 | * FIXME: Make this available to all arches. | 640 | * FIXME: Make this available to all arches. |
| @@ -680,41 +648,28 @@ static struct syscall_fmt { | |||
| 680 | { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), }, | 648 | { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), }, |
| 681 | { .name = "kill", .errmsg = true, | 649 | { .name = "kill", .errmsg = true, |
| 682 | .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, | 650 | .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, |
| 683 | { .name = "lchown", .errmsg = true, | 651 | { .name = "lchown", .errmsg = true, }, |
| 684 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | 652 | { .name = "lgetxattr", .errmsg = true, }, |
| 685 | { .name = "lgetxattr", .errmsg = true, | ||
| 686 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
| 687 | { .name = "linkat", .errmsg = true, | 653 | { .name = "linkat", .errmsg = true, |
| 688 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, | 654 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
| 689 | { .name = "listxattr", .errmsg = true, | 655 | { .name = "listxattr", .errmsg = true, }, |
| 690 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | 656 | { .name = "llistxattr", .errmsg = true, }, |
| 691 | { .name = "llistxattr", .errmsg = true, | 657 | { .name = "lremovexattr", .errmsg = true, }, |
| 692 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
| 693 | { .name = "lremovexattr", .errmsg = true, | ||
| 694 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
| 695 | { .name = "lseek", .errmsg = true, | 658 | { .name = "lseek", .errmsg = true, |
| 696 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 659 | .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ }, |
| 697 | [2] = SCA_STRARRAY, /* whence */ }, | ||
| 698 | .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, | 660 | .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, |
| 699 | { .name = "lsetxattr", .errmsg = true, | 661 | { .name = "lsetxattr", .errmsg = true, }, |
| 700 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | 662 | { .name = "lstat", .errmsg = true, .alias = "newlstat", }, |
| 701 | { .name = "lstat", .errmsg = true, .alias = "newlstat", | 663 | { .name = "lsxattr", .errmsg = true, }, |
| 702 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
| 703 | { .name = "lsxattr", .errmsg = true, | ||
| 704 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
| 705 | { .name = "madvise", .errmsg = true, | 664 | { .name = "madvise", .errmsg = true, |
| 706 | .arg_scnprintf = { [0] = SCA_HEX, /* start */ | 665 | .arg_scnprintf = { [0] = SCA_HEX, /* start */ |
| 707 | [2] = SCA_MADV_BHV, /* behavior */ }, }, | 666 | [2] = SCA_MADV_BHV, /* behavior */ }, }, |
| 708 | { .name = "mkdir", .errmsg = true, | 667 | { .name = "mkdir", .errmsg = true, }, |
| 709 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
| 710 | { .name = "mkdirat", .errmsg = true, | 668 | { .name = "mkdirat", .errmsg = true, |
| 711 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ | 669 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
| 712 | [1] = SCA_FILENAME, /* pathname */ }, }, | 670 | { .name = "mknod", .errmsg = true, }, |
| 713 | { .name = "mknod", .errmsg = true, | ||
| 714 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
| 715 | { .name = "mknodat", .errmsg = true, | 671 | { .name = "mknodat", .errmsg = true, |
| 716 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ | 672 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
| 717 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
| 718 | { .name = "mlock", .errmsg = true, | 673 | { .name = "mlock", .errmsg = true, |
| 719 | .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, | 674 | .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, |
| 720 | { .name = "mlockall", .errmsg = true, | 675 | { .name = "mlockall", .errmsg = true, |
| @@ -722,8 +677,7 @@ static struct syscall_fmt { | |||
| 722 | { .name = "mmap", .hexret = true, | 677 | { .name = "mmap", .hexret = true, |
| 723 | .arg_scnprintf = { [0] = SCA_HEX, /* addr */ | 678 | .arg_scnprintf = { [0] = SCA_HEX, /* addr */ |
| 724 | [2] = SCA_MMAP_PROT, /* prot */ | 679 | [2] = SCA_MMAP_PROT, /* prot */ |
| 725 | [3] = SCA_MMAP_FLAGS, /* flags */ | 680 | [3] = SCA_MMAP_FLAGS, /* flags */ }, }, |
| 726 | [4] = SCA_FD, /* fd */ }, }, | ||
| 727 | { .name = "mprotect", .errmsg = true, | 681 | { .name = "mprotect", .errmsg = true, |
| 728 | .arg_scnprintf = { [0] = SCA_HEX, /* start */ | 682 | .arg_scnprintf = { [0] = SCA_HEX, /* start */ |
| 729 | [2] = SCA_MMAP_PROT, /* prot */ }, }, | 683 | [2] = SCA_MMAP_PROT, /* prot */ }, }, |
| @@ -740,17 +694,14 @@ static struct syscall_fmt { | |||
| 740 | { .name = "name_to_handle_at", .errmsg = true, | 694 | { .name = "name_to_handle_at", .errmsg = true, |
| 741 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, | 695 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
| 742 | { .name = "newfstatat", .errmsg = true, | 696 | { .name = "newfstatat", .errmsg = true, |
| 743 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 697 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
| 744 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
| 745 | { .name = "open", .errmsg = true, | 698 | { .name = "open", .errmsg = true, |
| 746 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ | 699 | .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, }, |
| 747 | [1] = SCA_OPEN_FLAGS, /* flags */ }, }, | ||
| 748 | { .name = "open_by_handle_at", .errmsg = true, | 700 | { .name = "open_by_handle_at", .errmsg = true, |
| 749 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 701 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ |
| 750 | [2] = SCA_OPEN_FLAGS, /* flags */ }, }, | 702 | [2] = SCA_OPEN_FLAGS, /* flags */ }, }, |
| 751 | { .name = "openat", .errmsg = true, | 703 | { .name = "openat", .errmsg = true, |
| 752 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 704 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ |
| 753 | [1] = SCA_FILENAME, /* filename */ | ||
| 754 | [2] = SCA_OPEN_FLAGS, /* flags */ }, }, | 705 | [2] = SCA_OPEN_FLAGS, /* flags */ }, }, |
| 755 | { .name = "perf_event_open", .errmsg = true, | 706 | { .name = "perf_event_open", .errmsg = true, |
| 756 | .arg_scnprintf = { [2] = SCA_INT, /* cpu */ | 707 | .arg_scnprintf = { [2] = SCA_INT, /* cpu */ |
| @@ -760,39 +711,26 @@ static struct syscall_fmt { | |||
| 760 | .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, }, | 711 | .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, }, |
| 761 | { .name = "poll", .errmsg = true, .timeout = true, }, | 712 | { .name = "poll", .errmsg = true, .timeout = true, }, |
| 762 | { .name = "ppoll", .errmsg = true, .timeout = true, }, | 713 | { .name = "ppoll", .errmsg = true, .timeout = true, }, |
| 763 | { .name = "pread", .errmsg = true, .alias = "pread64", | 714 | { .name = "pread", .errmsg = true, .alias = "pread64", }, |
| 764 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 715 | { .name = "preadv", .errmsg = true, .alias = "pread", }, |
| 765 | { .name = "preadv", .errmsg = true, .alias = "pread", | ||
| 766 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 767 | { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), }, | 716 | { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), }, |
| 768 | { .name = "pwrite", .errmsg = true, .alias = "pwrite64", | 717 | { .name = "pwrite", .errmsg = true, .alias = "pwrite64", }, |
| 769 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 718 | { .name = "pwritev", .errmsg = true, }, |
| 770 | { .name = "pwritev", .errmsg = true, | 719 | { .name = "read", .errmsg = true, }, |
| 771 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 720 | { .name = "readlink", .errmsg = true, }, |
| 772 | { .name = "read", .errmsg = true, | ||
| 773 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 774 | { .name = "readlink", .errmsg = true, | ||
| 775 | .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, }, | ||
| 776 | { .name = "readlinkat", .errmsg = true, | 721 | { .name = "readlinkat", .errmsg = true, |
| 777 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 722 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
| 778 | [1] = SCA_FILENAME, /* pathname */ }, }, | 723 | { .name = "readv", .errmsg = true, }, |
| 779 | { .name = "readv", .errmsg = true, | ||
| 780 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 781 | { .name = "recvfrom", .errmsg = true, | 724 | { .name = "recvfrom", .errmsg = true, |
| 782 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 725 | .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, |
| 783 | [3] = SCA_MSG_FLAGS, /* flags */ }, }, | ||
| 784 | { .name = "recvmmsg", .errmsg = true, | 726 | { .name = "recvmmsg", .errmsg = true, |
| 785 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 727 | .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, |
| 786 | [3] = SCA_MSG_FLAGS, /* flags */ }, }, | ||
| 787 | { .name = "recvmsg", .errmsg = true, | 728 | { .name = "recvmsg", .errmsg = true, |
| 788 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 729 | .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, |
| 789 | [2] = SCA_MSG_FLAGS, /* flags */ }, }, | 730 | { .name = "removexattr", .errmsg = true, }, |
| 790 | { .name = "removexattr", .errmsg = true, | ||
| 791 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
| 792 | { .name = "renameat", .errmsg = true, | 731 | { .name = "renameat", .errmsg = true, |
| 793 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, | 732 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
| 794 | { .name = "rmdir", .errmsg = true, | 733 | { .name = "rmdir", .errmsg = true, }, |
| 795 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
| 796 | { .name = "rt_sigaction", .errmsg = true, | 734 | { .name = "rt_sigaction", .errmsg = true, |
| 797 | .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, | 735 | .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, |
| 798 | { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), }, | 736 | { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), }, |
| @@ -807,22 +745,17 @@ static struct syscall_fmt { | |||
| 807 | [1] = SCA_SECCOMP_FLAGS, /* flags */ }, }, | 745 | [1] = SCA_SECCOMP_FLAGS, /* flags */ }, }, |
| 808 | { .name = "select", .errmsg = true, .timeout = true, }, | 746 | { .name = "select", .errmsg = true, .timeout = true, }, |
| 809 | { .name = "sendmmsg", .errmsg = true, | 747 | { .name = "sendmmsg", .errmsg = true, |
| 810 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 748 | .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, |
| 811 | [3] = SCA_MSG_FLAGS, /* flags */ }, }, | ||
| 812 | { .name = "sendmsg", .errmsg = true, | 749 | { .name = "sendmsg", .errmsg = true, |
| 813 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 750 | .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, |
| 814 | [2] = SCA_MSG_FLAGS, /* flags */ }, }, | ||
| 815 | { .name = "sendto", .errmsg = true, | 751 | { .name = "sendto", .errmsg = true, |
| 816 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 752 | .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, |
| 817 | [3] = SCA_MSG_FLAGS, /* flags */ }, }, | ||
| 818 | { .name = "set_tid_address", .errpid = true, }, | 753 | { .name = "set_tid_address", .errpid = true, }, |
| 819 | { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, | 754 | { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, |
| 820 | { .name = "setpgid", .errmsg = true, }, | 755 | { .name = "setpgid", .errmsg = true, }, |
| 821 | { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, | 756 | { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, |
| 822 | { .name = "setxattr", .errmsg = true, | 757 | { .name = "setxattr", .errmsg = true, }, |
| 823 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | 758 | { .name = "shutdown", .errmsg = true, }, |
| 824 | { .name = "shutdown", .errmsg = true, | ||
| 825 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 826 | { .name = "socket", .errmsg = true, | 759 | { .name = "socket", .errmsg = true, |
| 827 | .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ | 760 | .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ |
| 828 | [1] = SCA_SK_TYPE, /* type */ }, | 761 | [1] = SCA_SK_TYPE, /* type */ }, |
| @@ -831,10 +764,8 @@ static struct syscall_fmt { | |||
| 831 | .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ | 764 | .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ |
| 832 | [1] = SCA_SK_TYPE, /* type */ }, | 765 | [1] = SCA_SK_TYPE, /* type */ }, |
| 833 | .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, | 766 | .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, |
| 834 | { .name = "stat", .errmsg = true, .alias = "newstat", | 767 | { .name = "stat", .errmsg = true, .alias = "newstat", }, |
| 835 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | 768 | { .name = "statfs", .errmsg = true, }, |
| 836 | { .name = "statfs", .errmsg = true, | ||
| 837 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
| 838 | { .name = "swapoff", .errmsg = true, | 769 | { .name = "swapoff", .errmsg = true, |
| 839 | .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, | 770 | .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, |
| 840 | { .name = "swapon", .errmsg = true, | 771 | { .name = "swapon", .errmsg = true, |
| @@ -845,29 +776,21 @@ static struct syscall_fmt { | |||
| 845 | .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, | 776 | .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, |
| 846 | { .name = "tkill", .errmsg = true, | 777 | { .name = "tkill", .errmsg = true, |
| 847 | .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, | 778 | .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, |
| 848 | { .name = "truncate", .errmsg = true, | 779 | { .name = "truncate", .errmsg = true, }, |
| 849 | .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, }, | ||
| 850 | { .name = "uname", .errmsg = true, .alias = "newuname", }, | 780 | { .name = "uname", .errmsg = true, .alias = "newuname", }, |
| 851 | { .name = "unlinkat", .errmsg = true, | 781 | { .name = "unlinkat", .errmsg = true, |
| 852 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 782 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
| 853 | [1] = SCA_FILENAME, /* pathname */ }, }, | 783 | { .name = "utime", .errmsg = true, }, |
| 854 | { .name = "utime", .errmsg = true, | ||
| 855 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
| 856 | { .name = "utimensat", .errmsg = true, | 784 | { .name = "utimensat", .errmsg = true, |
| 857 | .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ | 785 | .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, }, |
| 858 | [1] = SCA_FILENAME, /* filename */ }, }, | 786 | { .name = "utimes", .errmsg = true, }, |
| 859 | { .name = "utimes", .errmsg = true, | 787 | { .name = "vmsplice", .errmsg = true, }, |
| 860 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
| 861 | { .name = "vmsplice", .errmsg = true, | ||
| 862 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 863 | { .name = "wait4", .errpid = true, | 788 | { .name = "wait4", .errpid = true, |
| 864 | .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, }, | 789 | .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, }, |
| 865 | { .name = "waitid", .errpid = true, | 790 | { .name = "waitid", .errpid = true, |
| 866 | .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, }, | 791 | .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, }, |
| 867 | { .name = "write", .errmsg = true, | 792 | { .name = "write", .errmsg = true, }, |
| 868 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 793 | { .name = "writev", .errmsg = true, }, |
| 869 | { .name = "writev", .errmsg = true, | ||
| 870 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | ||
| 871 | }; | 794 | }; |
| 872 | 795 | ||
| 873 | static int syscall_fmt__cmp(const void *name, const void *fmtp) | 796 | static int syscall_fmt__cmp(const void *name, const void *fmtp) |
| @@ -1204,7 +1127,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) | |||
| 1204 | static int syscall__set_arg_fmts(struct syscall *sc) | 1127 | static int syscall__set_arg_fmts(struct syscall *sc) |
| 1205 | { | 1128 | { |
| 1206 | struct format_field *field; | 1129 | struct format_field *field; |
| 1207 | int idx = 0; | 1130 | int idx = 0, len; |
| 1208 | 1131 | ||
| 1209 | sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *)); | 1132 | sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *)); |
| 1210 | if (sc->arg_scnprintf == NULL) | 1133 | if (sc->arg_scnprintf == NULL) |
| @@ -1216,12 +1139,31 @@ static int syscall__set_arg_fmts(struct syscall *sc) | |||
| 1216 | for (field = sc->args; field; field = field->next) { | 1139 | for (field = sc->args; field; field = field->next) { |
| 1217 | if (sc->fmt && sc->fmt->arg_scnprintf[idx]) | 1140 | if (sc->fmt && sc->fmt->arg_scnprintf[idx]) |
| 1218 | sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; | 1141 | sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; |
| 1142 | else if (strcmp(field->type, "const char *") == 0 && | ||
| 1143 | (strcmp(field->name, "filename") == 0 || | ||
| 1144 | strcmp(field->name, "path") == 0 || | ||
| 1145 | strcmp(field->name, "pathname") == 0)) | ||
| 1146 | sc->arg_scnprintf[idx] = SCA_FILENAME; | ||
| 1219 | else if (field->flags & FIELD_IS_POINTER) | 1147 | else if (field->flags & FIELD_IS_POINTER) |
| 1220 | sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex; | 1148 | sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex; |
| 1221 | else if (strcmp(field->type, "pid_t") == 0) | 1149 | else if (strcmp(field->type, "pid_t") == 0) |
| 1222 | sc->arg_scnprintf[idx] = SCA_PID; | 1150 | sc->arg_scnprintf[idx] = SCA_PID; |
| 1223 | else if (strcmp(field->type, "umode_t") == 0) | 1151 | else if (strcmp(field->type, "umode_t") == 0) |
| 1224 | sc->arg_scnprintf[idx] = SCA_MODE_T; | 1152 | sc->arg_scnprintf[idx] = SCA_MODE_T; |
| 1153 | else if ((strcmp(field->type, "int") == 0 || | ||
| 1154 | strcmp(field->type, "unsigned int") == 0 || | ||
| 1155 | strcmp(field->type, "long") == 0) && | ||
| 1156 | (len = strlen(field->name)) >= 2 && | ||
| 1157 | strcmp(field->name + len - 2, "fd") == 0) { | ||
| 1158 | /* | ||
| 1159 | * /sys/kernel/tracing/events/syscalls/sys_enter* | ||
| 1160 | * egrep 'field:.*fd;' .../format|sed -r 's/.*field:([a-z ]+) [a-z_]*fd.+/\1/g'|sort|uniq -c | ||
| 1161 | * 65 int | ||
| 1162 | * 23 unsigned int | ||
| 1163 | * 7 unsigned long | ||
| 1164 | */ | ||
| 1165 | sc->arg_scnprintf[idx] = SCA_FD; | ||
| 1166 | } | ||
| 1225 | ++idx; | 1167 | ++idx; |
| 1226 | } | 1168 | } |
| 1227 | 1169 | ||
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index c4bfe11479a0..e82ba90cc969 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
| @@ -44,6 +44,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, | |||
| 44 | perf_evlist__set_maps(evlist, cpus, threads); | 44 | perf_evlist__set_maps(evlist, cpus, threads); |
| 45 | fdarray__init(&evlist->pollfd, 64); | 45 | fdarray__init(&evlist->pollfd, 64); |
| 46 | evlist->workload.pid = -1; | 46 | evlist->workload.pid = -1; |
| 47 | evlist->backward = false; | ||
| 47 | } | 48 | } |
| 48 | 49 | ||
| 49 | struct perf_evlist *perf_evlist__new(void) | 50 | struct perf_evlist *perf_evlist__new(void) |
| @@ -679,6 +680,33 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, | |||
| 679 | return NULL; | 680 | return NULL; |
| 680 | } | 681 | } |
| 681 | 682 | ||
| 683 | static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value) | ||
| 684 | { | ||
| 685 | int i; | ||
| 686 | |||
| 687 | for (i = 0; i < evlist->nr_mmaps; i++) { | ||
| 688 | int fd = evlist->mmap[i].fd; | ||
| 689 | int err; | ||
| 690 | |||
| 691 | if (fd < 0) | ||
| 692 | continue; | ||
| 693 | err = ioctl(fd, PERF_EVENT_IOC_PAUSE_OUTPUT, value ? 1 : 0); | ||
| 694 | if (err) | ||
| 695 | return err; | ||
| 696 | } | ||
| 697 | return 0; | ||
| 698 | } | ||
| 699 | |||
| 700 | int perf_evlist__pause(struct perf_evlist *evlist) | ||
| 701 | { | ||
| 702 | return perf_evlist__set_paused(evlist, true); | ||
| 703 | } | ||
| 704 | |||
| 705 | int perf_evlist__resume(struct perf_evlist *evlist) | ||
| 706 | { | ||
| 707 | return perf_evlist__set_paused(evlist, false); | ||
| 708 | } | ||
| 709 | |||
| 682 | /* When check_messup is true, 'end' must points to a good entry */ | 710 | /* When check_messup is true, 'end' must points to a good entry */ |
| 683 | static union perf_event * | 711 | static union perf_event * |
| 684 | perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start, | 712 | perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start, |
| @@ -881,6 +909,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) | |||
| 881 | if (evlist->mmap[idx].base != NULL) { | 909 | if (evlist->mmap[idx].base != NULL) { |
| 882 | munmap(evlist->mmap[idx].base, evlist->mmap_len); | 910 | munmap(evlist->mmap[idx].base, evlist->mmap_len); |
| 883 | evlist->mmap[idx].base = NULL; | 911 | evlist->mmap[idx].base = NULL; |
| 912 | evlist->mmap[idx].fd = -1; | ||
| 884 | atomic_set(&evlist->mmap[idx].refcnt, 0); | 913 | atomic_set(&evlist->mmap[idx].refcnt, 0); |
| 885 | } | 914 | } |
| 886 | auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap); | 915 | auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap); |
| @@ -901,10 +930,14 @@ void perf_evlist__munmap(struct perf_evlist *evlist) | |||
| 901 | 930 | ||
| 902 | static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) | 931 | static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) |
| 903 | { | 932 | { |
| 933 | int i; | ||
| 934 | |||
| 904 | evlist->nr_mmaps = cpu_map__nr(evlist->cpus); | 935 | evlist->nr_mmaps = cpu_map__nr(evlist->cpus); |
| 905 | if (cpu_map__empty(evlist->cpus)) | 936 | if (cpu_map__empty(evlist->cpus)) |
| 906 | evlist->nr_mmaps = thread_map__nr(evlist->threads); | 937 | evlist->nr_mmaps = thread_map__nr(evlist->threads); |
| 907 | evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); | 938 | evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); |
| 939 | for (i = 0; i < evlist->nr_mmaps; i++) | ||
| 940 | evlist->mmap[i].fd = -1; | ||
| 908 | return evlist->mmap != NULL ? 0 : -ENOMEM; | 941 | return evlist->mmap != NULL ? 0 : -ENOMEM; |
| 909 | } | 942 | } |
| 910 | 943 | ||
| @@ -941,6 +974,7 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, | |||
| 941 | evlist->mmap[idx].base = NULL; | 974 | evlist->mmap[idx].base = NULL; |
| 942 | return -1; | 975 | return -1; |
| 943 | } | 976 | } |
| 977 | evlist->mmap[idx].fd = fd; | ||
| 944 | 978 | ||
| 945 | if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap, | 979 | if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap, |
| 946 | &mp->auxtrace_mp, evlist->mmap[idx].base, fd)) | 980 | &mp->auxtrace_mp, evlist->mmap[idx].base, fd)) |
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 85d1b59802e8..d740fb877ab6 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
| @@ -28,6 +28,7 @@ struct record_opts; | |||
| 28 | struct perf_mmap { | 28 | struct perf_mmap { |
| 29 | void *base; | 29 | void *base; |
| 30 | int mask; | 30 | int mask; |
| 31 | int fd; | ||
| 31 | atomic_t refcnt; | 32 | atomic_t refcnt; |
| 32 | u64 prev; | 33 | u64 prev; |
| 33 | struct auxtrace_mmap auxtrace_mmap; | 34 | struct auxtrace_mmap auxtrace_mmap; |
| @@ -43,6 +44,7 @@ struct perf_evlist { | |||
| 43 | bool overwrite; | 44 | bool overwrite; |
| 44 | bool enabled; | 45 | bool enabled; |
| 45 | bool has_user_cpus; | 46 | bool has_user_cpus; |
| 47 | bool backward; | ||
| 46 | size_t mmap_len; | 48 | size_t mmap_len; |
| 47 | int id_pos; | 49 | int id_pos; |
| 48 | int is_pos; | 50 | int is_pos; |
| @@ -135,6 +137,8 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx); | |||
| 135 | 137 | ||
| 136 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); | 138 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); |
| 137 | 139 | ||
| 140 | int perf_evlist__pause(struct perf_evlist *evlist); | ||
| 141 | int perf_evlist__resume(struct perf_evlist *evlist); | ||
| 138 | int perf_evlist__open(struct perf_evlist *evlist); | 142 | int perf_evlist__open(struct perf_evlist *evlist); |
| 139 | void perf_evlist__close(struct perf_evlist *evlist); | 143 | void perf_evlist__close(struct perf_evlist *evlist); |
| 140 | 144 | ||
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 964c7c3602c0..02c177d14c8d 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -37,6 +37,7 @@ static struct { | |||
| 37 | bool clockid; | 37 | bool clockid; |
| 38 | bool clockid_wrong; | 38 | bool clockid_wrong; |
| 39 | bool lbr_flags; | 39 | bool lbr_flags; |
| 40 | bool write_backward; | ||
| 40 | } perf_missing_features; | 41 | } perf_missing_features; |
| 41 | 42 | ||
| 42 | static clockid_t clockid; | 43 | static clockid_t clockid; |
| @@ -1376,6 +1377,8 @@ fallback_missing_features: | |||
| 1376 | if (perf_missing_features.lbr_flags) | 1377 | if (perf_missing_features.lbr_flags) |
| 1377 | evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | | 1378 | evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | |
| 1378 | PERF_SAMPLE_BRANCH_NO_CYCLES); | 1379 | PERF_SAMPLE_BRANCH_NO_CYCLES); |
| 1380 | if (perf_missing_features.write_backward) | ||
| 1381 | evsel->attr.write_backward = false; | ||
| 1379 | retry_sample_id: | 1382 | retry_sample_id: |
| 1380 | if (perf_missing_features.sample_id_all) | 1383 | if (perf_missing_features.sample_id_all) |
| 1381 | evsel->attr.sample_id_all = 0; | 1384 | evsel->attr.sample_id_all = 0; |
| @@ -1438,6 +1441,12 @@ retry_open: | |||
| 1438 | err = -EINVAL; | 1441 | err = -EINVAL; |
| 1439 | goto out_close; | 1442 | goto out_close; |
| 1440 | } | 1443 | } |
| 1444 | |||
| 1445 | if (evsel->overwrite && | ||
| 1446 | perf_missing_features.write_backward) { | ||
| 1447 | err = -EINVAL; | ||
| 1448 | goto out_close; | ||
| 1449 | } | ||
| 1441 | } | 1450 | } |
| 1442 | } | 1451 | } |
| 1443 | 1452 | ||
| @@ -1500,6 +1509,10 @@ try_fallback: | |||
| 1500 | PERF_SAMPLE_BRANCH_NO_FLAGS))) { | 1509 | PERF_SAMPLE_BRANCH_NO_FLAGS))) { |
| 1501 | perf_missing_features.lbr_flags = true; | 1510 | perf_missing_features.lbr_flags = true; |
| 1502 | goto fallback_missing_features; | 1511 | goto fallback_missing_features; |
| 1512 | } else if (!perf_missing_features.write_backward && | ||
| 1513 | evsel->attr.write_backward) { | ||
| 1514 | perf_missing_features.write_backward = true; | ||
| 1515 | goto fallback_missing_features; | ||
| 1503 | } | 1516 | } |
| 1504 | 1517 | ||
| 1505 | out_close: | 1518 | out_close: |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 8a644fef452c..c1f10159804c 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
| @@ -112,6 +112,7 @@ struct perf_evsel { | |||
| 112 | bool tracking; | 112 | bool tracking; |
| 113 | bool per_pkg; | 113 | bool per_pkg; |
| 114 | bool precise_max; | 114 | bool precise_max; |
| 115 | bool overwrite; | ||
| 115 | /* parse modifier helper */ | 116 | /* parse modifier helper */ |
| 116 | int exclude_GH; | 117 | int exclude_GH; |
| 117 | int nr_members; | 118 | int nr_members; |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index cfab531437c7..d1f19e0012d4 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
| @@ -117,6 +117,13 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) | |||
| 117 | hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen); | 117 | hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen); |
| 118 | hists__set_unres_dso_col_len(hists, HISTC_DSO_TO); | 118 | hists__set_unres_dso_col_len(hists, HISTC_DSO_TO); |
| 119 | } | 119 | } |
| 120 | |||
| 121 | if (h->branch_info->srcline_from) | ||
| 122 | hists__new_col_len(hists, HISTC_SRCLINE_FROM, | ||
| 123 | strlen(h->branch_info->srcline_from)); | ||
| 124 | if (h->branch_info->srcline_to) | ||
| 125 | hists__new_col_len(hists, HISTC_SRCLINE_TO, | ||
| 126 | strlen(h->branch_info->srcline_to)); | ||
| 120 | } | 127 | } |
| 121 | 128 | ||
| 122 | if (h->mem_info) { | 129 | if (h->mem_info) { |
| @@ -1042,6 +1049,8 @@ void hist_entry__delete(struct hist_entry *he) | |||
| 1042 | if (he->branch_info) { | 1049 | if (he->branch_info) { |
| 1043 | map__zput(he->branch_info->from.map); | 1050 | map__zput(he->branch_info->from.map); |
| 1044 | map__zput(he->branch_info->to.map); | 1051 | map__zput(he->branch_info->to.map); |
| 1052 | free_srcline(he->branch_info->srcline_from); | ||
| 1053 | free_srcline(he->branch_info->srcline_to); | ||
| 1045 | zfree(&he->branch_info); | 1054 | zfree(&he->branch_info); |
| 1046 | } | 1055 | } |
| 1047 | 1056 | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 0f84bfb42bb1..7b54ccf1b737 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
| @@ -52,6 +52,8 @@ enum hist_column { | |||
| 52 | HISTC_MEM_IADDR_SYMBOL, | 52 | HISTC_MEM_IADDR_SYMBOL, |
| 53 | HISTC_TRANSACTION, | 53 | HISTC_TRANSACTION, |
| 54 | HISTC_CYCLES, | 54 | HISTC_CYCLES, |
| 55 | HISTC_SRCLINE_FROM, | ||
| 56 | HISTC_SRCLINE_TO, | ||
| 55 | HISTC_TRACE, | 57 | HISTC_TRACE, |
| 56 | HISTC_NR_COLS, /* Last entry */ | 58 | HISTC_NR_COLS, /* Last entry */ |
| 57 | }; | 59 | }; |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 20e69edd5006..c4e9bd70723c 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
| @@ -353,6 +353,88 @@ struct sort_entry sort_srcline = { | |||
| 353 | .se_width_idx = HISTC_SRCLINE, | 353 | .se_width_idx = HISTC_SRCLINE, |
| 354 | }; | 354 | }; |
| 355 | 355 | ||
| 356 | /* --sort srcline_from */ | ||
| 357 | |||
| 358 | static int64_t | ||
| 359 | sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right) | ||
| 360 | { | ||
| 361 | if (!left->branch_info->srcline_from) { | ||
| 362 | struct map *map = left->branch_info->from.map; | ||
| 363 | if (!map) | ||
| 364 | left->branch_info->srcline_from = SRCLINE_UNKNOWN; | ||
| 365 | else | ||
| 366 | left->branch_info->srcline_from = get_srcline(map->dso, | ||
| 367 | map__rip_2objdump(map, | ||
| 368 | left->branch_info->from.al_addr), | ||
| 369 | left->branch_info->from.sym, true); | ||
| 370 | } | ||
| 371 | if (!right->branch_info->srcline_from) { | ||
| 372 | struct map *map = right->branch_info->from.map; | ||
| 373 | if (!map) | ||
| 374 | right->branch_info->srcline_from = SRCLINE_UNKNOWN; | ||
| 375 | else | ||
| 376 | right->branch_info->srcline_from = get_srcline(map->dso, | ||
| 377 | map__rip_2objdump(map, | ||
| 378 | right->branch_info->from.al_addr), | ||
| 379 | right->branch_info->from.sym, true); | ||
| 380 | } | ||
| 381 | return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from); | ||
| 382 | } | ||
| 383 | |||
| 384 | static int hist_entry__srcline_from_snprintf(struct hist_entry *he, char *bf, | ||
| 385 | size_t size, unsigned int width) | ||
| 386 | { | ||
| 387 | return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_from); | ||
| 388 | } | ||
| 389 | |||
| 390 | struct sort_entry sort_srcline_from = { | ||
| 391 | .se_header = "From Source:Line", | ||
| 392 | .se_cmp = sort__srcline_from_cmp, | ||
| 393 | .se_snprintf = hist_entry__srcline_from_snprintf, | ||
| 394 | .se_width_idx = HISTC_SRCLINE_FROM, | ||
| 395 | }; | ||
| 396 | |||
| 397 | /* --sort srcline_to */ | ||
| 398 | |||
| 399 | static int64_t | ||
| 400 | sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right) | ||
| 401 | { | ||
| 402 | if (!left->branch_info->srcline_to) { | ||
| 403 | struct map *map = left->branch_info->to.map; | ||
| 404 | if (!map) | ||
| 405 | left->branch_info->srcline_to = SRCLINE_UNKNOWN; | ||
| 406 | else | ||
| 407 | left->branch_info->srcline_to = get_srcline(map->dso, | ||
| 408 | map__rip_2objdump(map, | ||
| 409 | left->branch_info->to.al_addr), | ||
| 410 | left->branch_info->from.sym, true); | ||
| 411 | } | ||
| 412 | if (!right->branch_info->srcline_to) { | ||
| 413 | struct map *map = right->branch_info->to.map; | ||
| 414 | if (!map) | ||
| 415 | right->branch_info->srcline_to = SRCLINE_UNKNOWN; | ||
| 416 | else | ||
| 417 | right->branch_info->srcline_to = get_srcline(map->dso, | ||
| 418 | map__rip_2objdump(map, | ||
| 419 | right->branch_info->to.al_addr), | ||
| 420 | right->branch_info->to.sym, true); | ||
| 421 | } | ||
| 422 | return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to); | ||
| 423 | } | ||
| 424 | |||
| 425 | static int hist_entry__srcline_to_snprintf(struct hist_entry *he, char *bf, | ||
| 426 | size_t size, unsigned int width) | ||
| 427 | { | ||
| 428 | return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_to); | ||
| 429 | } | ||
| 430 | |||
| 431 | struct sort_entry sort_srcline_to = { | ||
| 432 | .se_header = "To Source:Line", | ||
| 433 | .se_cmp = sort__srcline_to_cmp, | ||
| 434 | .se_snprintf = hist_entry__srcline_to_snprintf, | ||
| 435 | .se_width_idx = HISTC_SRCLINE_TO, | ||
| 436 | }; | ||
| 437 | |||
| 356 | /* --sort srcfile */ | 438 | /* --sort srcfile */ |
| 357 | 439 | ||
| 358 | static char no_srcfile[1]; | 440 | static char no_srcfile[1]; |
| @@ -1347,6 +1429,8 @@ static struct sort_dimension bstack_sort_dimensions[] = { | |||
| 1347 | DIM(SORT_IN_TX, "in_tx", sort_in_tx), | 1429 | DIM(SORT_IN_TX, "in_tx", sort_in_tx), |
| 1348 | DIM(SORT_ABORT, "abort", sort_abort), | 1430 | DIM(SORT_ABORT, "abort", sort_abort), |
| 1349 | DIM(SORT_CYCLES, "cycles", sort_cycles), | 1431 | DIM(SORT_CYCLES, "cycles", sort_cycles), |
| 1432 | DIM(SORT_SRCLINE_FROM, "srcline_from", sort_srcline_from), | ||
| 1433 | DIM(SORT_SRCLINE_TO, "srcline_to", sort_srcline_to), | ||
| 1350 | }; | 1434 | }; |
| 1351 | 1435 | ||
| 1352 | #undef DIM | 1436 | #undef DIM |
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 42927f448bcb..ebb59cacd092 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
| @@ -215,6 +215,8 @@ enum sort_type { | |||
| 215 | SORT_ABORT, | 215 | SORT_ABORT, |
| 216 | SORT_IN_TX, | 216 | SORT_IN_TX, |
| 217 | SORT_CYCLES, | 217 | SORT_CYCLES, |
| 218 | SORT_SRCLINE_FROM, | ||
| 219 | SORT_SRCLINE_TO, | ||
| 218 | 220 | ||
| 219 | /* memory mode specific sort keys */ | 221 | /* memory mode specific sort keys */ |
| 220 | __SORT_MEMORY_MODE, | 222 | __SORT_MEMORY_MODE, |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index fa415347dbf9..b10d558a8803 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
| @@ -186,6 +186,8 @@ struct branch_info { | |||
| 186 | struct addr_map_symbol from; | 186 | struct addr_map_symbol from; |
| 187 | struct addr_map_symbol to; | 187 | struct addr_map_symbol to; |
| 188 | struct branch_flags flags; | 188 | struct branch_flags flags; |
| 189 | char *srcline_from; | ||
| 190 | char *srcline_to; | ||
| 189 | }; | 191 | }; |
| 190 | 192 | ||
| 191 | struct mem_info { | 193 | struct mem_info { |
