perf/core improvements
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit 408cf677073a5d1a7343bc6430a7297ba7b280d4:
Merge tag 'perf-core-for-mingo-20160520' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent (2016-05-20 19:37:43 +0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-20160523
for you to fetch changes up to 3a62a7b8200a177ad96161e4f2678514e6ee301e:
perf record: Read from backward ring buffer (2016-05-23 18:22:48 -0300)
----------------------------------------------------------------
perf/core improvements:
User visible:
- Add "srcline_from" and "srcline_to" branch sort keys to 'perf top' and 'perf report' (Andi Kleen)
Infrastructure:
- Make 'perf trace' auto-attach fd->name and ptr->name beautifiers based on the name of syscall arguments, this way new syscalls that have 'const char * (path,pathname,filename)' will use the fd->name beautifier (vfs_getname perf probe, if in place) and the 'fd->name' (vfs_getname or via /proc/PID/fd/) (Arnaldo Carvalho de Melo)
- Infrastructure to read from a ring buffer in backward write mode (Wang Nan)
----------------------------------------------------------------
Andi Kleen (1):
perf report: Add srcline_from/to branch sort keys
Arnaldo Carvalho de Melo (2):
perf trace: Use the fd->name beautifier as default for "fd" args
perf trace: Use the ptr->name beautifier as default for "filename" argsWang Nan (6):
perf evsel: Add overwrite attribute and check write_backward perf evsel: Record fd into perf_mmap
perf evlist: Add API to pause/resume
perf record: Prevent reading invalid data in record__mmap_read perf record: Rename variable to make code clear perf record: Read from backward ring buffer
tools/perf/Documentation/perf-report.txt | 3 +- tools/perf/builtin-record.c | 81 ++++++++-- tools/perf/builtin-trace.c | 248 ++++++++++++------------------- tools/perf/util/evlist.c | 34 +++++ tools/perf/util/evlist.h | 4 + tools/perf/util/evsel.c | 13 ++ tools/perf/util/evsel.h | 1 + tools/perf/util/hist.c | 9 ++ tools/perf/util/hist.h | 2 + tools/perf/util/sort.c | 84 +++++++++++ tools/perf/util/sort.h | 2 + tools/perf/util/symbol.h | 2 + 12 files changed, 319 insertions(+), 164 deletions(-)
Arnaldo Carvalho de Melo
maintainerPATCH 1/9 perf evsel: Add overwrite attribute and check write_backward
From: Wang Nan <[email protected]>
Add 'overwrite' attribute to evsel to mark whether this event is overwritable. The following commits will support syntax like:
# perf record -e cycles/overwrite/ ...
An overwritable evsel requires kernel support for the perf_event_attr.write_backward ring buffer feature.
Add it to perf_missing_feature.
--- tools/perf/util/evsel.c | 13 +++++++++++++ tools/perf/util/evsel.h | 1 + 2 files changed, 14 insertions(+)
tools/perf/util/evsel.c +13 -0
@@ -37,6 +37,7 @@ static struct {bool clockid;bool clockid_wrong;bool lbr_flags; +bool write_backward; } perf_missing_features;static clockid_t clockid;
@@ -1376,6 +1377,8 @@ fallback_missing_features:if (perf_missing_features.lbr_flags) evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |PERF_SAMPLE_BRANCH_NO_CYCLES ); +if (perf_missing_features.write_backward) + evsel->attr.write_backward = false; retry_sample_id:if (perf_missing_features.sample_id_all) evsel->attr.sample_id_all =0 ;
@@ -1438,6 +1441,12 @@ retry_open: err = -EINVAL ; goto out_close; } + +if (evsel->overwrite && + perf_missing_features.write_backward) { + err = -EINVAL ; + goto out_close; + } } }
@@ -1500,6 +1509,10 @@ try_fallback: PERF_SAMPLE_BRANCH_NO_FLAGS))) { perf_missing_features.lbr_flags = true; goto fallback_missing_features; + } else if (!perf_missing_features.write_backward && + evsel->attr.write_backward) { + perf_missing_features.write_backward = true; + goto fallback_missing_features; } out_close:
tools/perf/util/evsel.h +1 -0
@@ -112,6 +112,7 @@ struct perf_evsel {bool tracking;bool per_pkg;bool precise_max; +bool overwrite;/* parse modifier helper */ int exclude_GH;int nr_members;
Signature · 1 line
2.5.5
Arnaldo Carvalho de Melo
maintainerPATCH 2/9 perf evsel: Record fd into perf_mmap
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
Add a fd field into struct perf_mmap so that perf can track the mmap fd.
This feature will be used for toggling overwrite ring buffers.
--- tools/perf/util/evlist.c | 6 ++++++ tools/perf/util/evlist.h | 1 + 2 files changed, 7 insertions(+)
tools/perf/util/evlist.c +6 -0
@@ -881,6 +881,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)if (evlist->mmap[idx].base !=NULL ) {munmap (evlist->mmap[idx].base, evlist->mmap_len); evlist->mmap[idx].base =NULL ; + evlist->mmap[idx].fd =-1 ;atomic_set (&evlist->mmap[idx].refcnt,0 ); }auxtrace_mmap__munmap (&evlist->mmap[idx].auxtrace_mmap);
@@ -901,10 +902,14 @@ void perf_evlist__munmap(struct perf_evlist *evlist)static int perf_evlist__alloc_mmap (struct perf_evlist *evlist) { +int i; + evlist->nr_mmaps =cpu_map__nr (evlist->cpus);if (cpu_map__empty (evlist->cpus)) evlist->nr_mmaps =thread_map__nr (evlist->threads); evlist->mmap =zalloc (evlist->nr_mmaps *sizeof (struct perf_mmap )); +for (i =0 ; i < evlist->nr_mmaps; i++) + evlist->mmap[i].fd =-1 ;return evlist->mmap !=NULL ?0 : -ENOMEM ; }
@@ -941,6 +946,7 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, evlist->mmap[idx].base =NULL ;return -1 ; } + evlist->mmap[idx].fd = fd;if (auxtrace_mmap__mmap (&evlist->mmap[idx].auxtrace_mmap, &mp->auxtrace_mp, evlist->mmap[idx].base, fd))
tools/perf/util/evlist.h +1 -0
@@ -28,6 +28,7 @@ struct record_opts;struct perf_mmap {void *base;int mask; +int fd;atomic_t refcnt;u64 prev;struct auxtrace_mmap auxtrace_mmap;
Signature · 1 line
2.5.5
Arnaldo Carvalho de Melo
maintainerPATCH 3/9 perf report: Add srcline_from/to branch sort keys
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Add "srcline_from" and "srcline_to" branch sort keys that allow to show the source lines of a branch.
That makes it much easier to track down where particular branches happen in the program, for example to examine branch mispredictions, or to associate it with cycle counts:
% perf record -b -e cycles:p ./tcall
% perf report --sort srcline_from,srcline_to,mispredict
...
15.10% tcall.c:18 tcall.c:10 N
14.83% tcall.c:11 tcall.c:5 N
14.12% tcall.c:7 tcall.c:12 N
14.04% tcall.c:12 tcall.c:5 N
12.42% tcall.c:17 tcall.c:18 N
12.39% tcall.c:7 tcall.c:13 N
12.27% tcall.c:13 tcall.c:17 N
...
% perf report --sort srcline_from,srcline_to,cycles
...
17.12% tcall.c:18 tcall.c:11 1
17.01% tcall.c:12 tcall.c:6 1
16.98% tcall.c:11 tcall.c:6 1
15.91% tcall.c:17 tcall.c:18 1
6.38% tcall.c:7 tcall.c:17 7
4.80% tcall.c:7 tcall.c:12 8
4.21% tcall.c:7 tcall.c:17 8
2.67% tcall.c:7 tcall.c:12 7
2.62% tcall.c:7 tcall.c:12 10
2.10% tcall.c:7 tcall.c:17 9
1.58% tcall.c:7 tcall.c:12 6
1.44% tcall.c:7 tcall.c:12 5
1.38% tcall.c:7 tcall.c:12 9
1.06% tcall.c:7 tcall.c:17 13
1.05% tcall.c:7 tcall.c:12 4
1.01% tcall.c:7 tcall.c:17 6Open issues:
- Some kernel symbols get misresolved.
--- tools/perf/Documentation/perf-report.txt | 3 +- tools/perf/util/hist.c | 9 ++++ tools/perf/util/hist.h | 2 + tools/perf/util/sort.c | 84 ++++++++++++++++++++++++++++++++ tools/perf/util/sort.h | 2 + tools/perf/util/symbol.h | 2 + 6 files changed, 101 insertions(+), 1 deletion(-)
tools/perf/Documentation/perf-report.txt +2 -1
@@ -103,12 +103,13 @@ OPTIONS If --branch-stack option is used, following sort keys are also available: - dso_from, dso_to, symbol_from, symbol_to, mispredict. - dso_from: name of library or module branched from - dso_to: name of library or module branched to - symbol_from: name of function branched from - symbol_to: name of function branched to + - srcline_from: source file and line branched from + - srcline_to: source file and line branched to - mispredict: "N" for predicted branch, "Y" for mispredicted branch - in_tx: branch in TSX transaction - abort: TSX transaction abort.
tools/perf/util/hist.c +9 -0
@@ -117,6 +117,13 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)hists__new_col_len (hists,HISTC_SYMBOL_TO , symlen);hists__set_unres_dso_col_len (hists,HISTC_DSO_TO ); } + +if (h->branch_info->srcline_from) +hists__new_col_len (hists,HISTC_SRCLINE_FROM , +strlen (h->branch_info->srcline_from)); +if (h->branch_info->srcline_to) +hists__new_col_len (hists,HISTC_SRCLINE_TO , +strlen (h->branch_info->srcline_to)); }if (h->mem_info) {
@@ -1042,6 +1049,8 @@ void hist_entry__delete(struct hist_entry *he)if (he->branch_info) {map__zput (he->branch_info->from.map);map__zput (he->branch_info->to.map); +free_srcline (he->branch_info->srcline_from); +free_srcline (he->branch_info->srcline_to);zfree (&he->branch_info); }
tools/perf/util/hist.h +2 -0
@@ -52,6 +52,8 @@ enum hist_column {HISTC_MEM_IADDR_SYMBOL ,HISTC_TRANSACTION ,HISTC_CYCLES , +HISTC_SRCLINE_FROM , +HISTC_SRCLINE_TO ,HISTC_TRACE , HISTC_NR_COLS, /* Last entry */ };
tools/perf/util/sort.c +84 -0
96 lines not on this page · raw message
tools/perf/util/sort.h +2 -0
@@ -215,6 +215,8 @@ enum sort_type {SORT_ABORT ,SORT_IN_TX ,SORT_CYCLES , +SORT_SRCLINE_FROM , +SORT_SRCLINE_TO ,/* memory mode specific sort keys */ __SORT_MEMORY_MODE,
tools/perf/util/symbol.h +2 -0
@@ -186,6 +186,8 @@ struct branch_info {struct addr_map_symbol from;struct addr_map_symbol to;struct branch_flags flags; +char *srcline_from; +char *srcline_to; };struct mem_info {
Signature · 1 line
2.5.5
Arnaldo Carvalho de Melo
maintainerPATCH 4/9 perf trace: Use the fd->name beautifier as default for "fd" args
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Noticed when the 'setsockopt' 'fd' arg wasn't being formatted via the SCA_FD beautifier, so just remove the setting of "fd" args to SCA_FD and do it when reading the syscall info, like we do for args of type "pid_t", i.e. "fd" as the name should be enough as the decision to use the SFA_FD beautifier. For odd cases we can just do it explicitely.
--- tools/perf/builtin-trace.c | 132 +++++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 78 deletions(-)
tools/perf/builtin-trace.c +54 -78
@@ -595,65 +595,45 @@ static struct syscall_fmt { { .name = "connect", .errmsg = true, }, { .name = "creat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, - { .name = "dup", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "dup2", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "dup3", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + { .name = "dup", .errmsg = true, }, + { .name = "dup2", .errmsg = true, }, + { .name = "dup3", .errmsg = true, }, { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), }, { .name = "eventfd2", .errmsg = true, .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, { .name = "faccessat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ - [1] = SCA_FILENAME, /* filename */ }, }, - { .name = "fadvise64", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "fallocate", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "fchdir", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "fchmod", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + .arg_scnprintf = { [1] = SCA_FILENAME, /* filename */ }, }, + { .name = "fadvise64", .errmsg = true, }, + { .name = "fallocate", .errmsg = true, }, + { .name = "fchdir", .errmsg = true, }, + { .name = "fchmod", .errmsg = true, }, { .name = "fchmodat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ [1] = SCA_FILENAME, /* filename */ }, }, - { .name = "fchown", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + { .name = "fchown", .errmsg = true, }, { .name = "fchownat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ [1] = SCA_FILENAME, /* filename */ }, }, { .name = "fcntl", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ - [1] = SCA_STRARRAY, /* cmd */ }, + .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ }, .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, }, - { .name = "fdatasync", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + { .name = "fdatasync", .errmsg = true, }, { .name = "flock", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ - [1] = SCA_FLOCK, /* cmd */ }, }, - { .name = "fsetxattr", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "fstat", .errmsg = true, .alias = "newfstat", - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, }, + { .name = "fsetxattr", .errmsg = true, }, + { .name = "fstat", .errmsg = true, .alias = "newfstat", }, { .name = "fstatat", .errmsg = true, .alias = "newfstatat", - .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ - [1] = SCA_FILENAME, /* filename */ }, }, - { .name = "fstatfs", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "fsync", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "ftruncate", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + .arg_scnprintf = { [1] = SCA_FILENAME, /* filename */ }, }, + { .name = "fstatfs", .errmsg = true, }, + { .name = "fsync", .errmsg = true, }, + { .name = "ftruncate", .errmsg = true, }, { .name = "futex", .errmsg = true, .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, { .name = "futimesat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ [1] = SCA_FILENAME, /* filename */ }, }, - { .name = "getdents", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "getdents64", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + { .name = "getdents", .errmsg = true, }, + { .name = "getdents64", .errmsg = true, }, { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, { .name = "getpid", .errpid = true, }, { .name = "getpgid", .errpid = true, },
@@ -666,7 +646,7 @@ static struct syscall_fmt { { .name = "inotify_add_watch", .errmsg = true, .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, }, { .name = "ioctl", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ + .arg_scnprintf = {#if defined(__i386__) || defined(__x86_64__)/* * FIXME: Make this available to all arches.
@@ -693,8 +673,7 @@ static struct syscall_fmt { { .name = "lremovexattr", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, { .name = "lseek", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ - [2] = SCA_STRARRAY, /* whence */ }, + .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ }, .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, { .name = "lsetxattr", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
@@ -722,8 +701,7 @@ static struct syscall_fmt { { .name = "mmap", .hexret = true, .arg_scnprintf = { [0] = SCA_HEX, /* addr */ [2] = SCA_MMAP_PROT, /* prot */ - [3] = SCA_MMAP_FLAGS, /* flags */ - [4] = SCA_FD, /* fd */ }, }, + [3] = SCA_MMAP_FLAGS, /* flags */ }, }, { .name = "mprotect", .errmsg = true, .arg_scnprintf = { [0] = SCA_HEX, /* start */ [2] = SCA_MMAP_PROT, /* prot */ }, },
@@ -760,33 +738,24 @@ static struct syscall_fmt { .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, }, { .name = "poll", .errmsg = true, .timeout = true, }, { .name = "ppoll", .errmsg = true, .timeout = true, }, - { .name = "pread", .errmsg = true, .alias = "pread64", - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "preadv", .errmsg = true, .alias = "pread", - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + { .name = "pread", .errmsg = true, .alias = "pread64", }, + { .name = "preadv", .errmsg = true, .alias = "pread", }, { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), }, - { .name = "pwrite", .errmsg = true, .alias = "pwrite64", - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "pwritev", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "read", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + { .name = "pwrite", .errmsg = true, .alias = "pwrite64", }, + { .name = "pwritev", .errmsg = true, }, + { .name = "read", .errmsg = true, }, { .name = "readlink", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, }, { .name = "readlinkat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ [1] = SCA_FILENAME, /* pathname */ }, }, - { .name = "readv", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + { .name = "readv", .errmsg = true, }, { .name = "recvfrom", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ - [3] = SCA_MSG_FLAGS, /* flags */ }, }, + .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, { .name = "recvmmsg", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ - [3] = SCA_MSG_FLAGS, /* flags */ }, }, + .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, { .name = "recvmsg", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ - [2] = SCA_MSG_FLAGS, /* flags */ }, }, + .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, { .name = "removexattr", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, { .name = "renameat", .errmsg = true,
@@ -807,22 +776,18 @@ static struct syscall_fmt { [1] = SCA_SECCOMP_FLAGS, /* flags */ }, }, { .name = "select", .errmsg = true, .timeout = true, }, { .name = "sendmmsg", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ - [3] = SCA_MSG_FLAGS, /* flags */ }, }, + .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, { .name = "sendmsg", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ - [2] = SCA_MSG_FLAGS, /* flags */ }, }, + .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, { .name = "sendto", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ - [3] = SCA_MSG_FLAGS, /* flags */ }, }, + .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, { .name = "set_tid_address", .errpid = true, }, { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, { .name = "setpgid", .errmsg = true, }, { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, { .name = "setxattr", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, - { .name = "shutdown", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + { .name = "shutdown", .errmsg = true, }, { .name = "socket", .errmsg = true, .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ [1] = SCA_SK_TYPE, /* type */ },
@@ -858,16 +823,13 @@ static struct syscall_fmt { [1] = SCA_FILENAME, /* filename */ }, }, { .name = "utimes", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, - { .name = "vmsplice", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + { .name = "vmsplice", .errmsg = true, }, { .name = "wait4", .errpid = true, .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, }, { .name = "waitid", .errpid = true, .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, }, - { .name = "write", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, - { .name = "writev", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + { .name = "write", .errmsg = true, }, + { .name = "writev", .errmsg = true, }, }; static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -1204,7 +1166,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)static int syscall__set_arg_fmts (struct syscall *sc) {struct format_field *field; -int idx =0 ; +int idx =0 , len; sc->arg_scnprintf =calloc (sc->nr_args,sizeof (void *));if (sc->arg_scnprintf ==NULL )
@@ -1222,6 +1184,20 @@ static int syscall__set_arg_fmts(struct syscall *sc) sc->arg_scnprintf[idx] =SCA_PID ; else if (strcmp(field->type, "umode_t") == 0) sc->arg_scnprintf[idx] = SCA_MODE_T; + else if ((strcmp(field->type, "int") == 0 || + strcmp(field->type, "unsigned int") == 0 || + strcmp(field->type, "long") == 0) && + (len = strlen(field->name)) >= 2 && + strcmp(field->name + len - 2, "fd") == 0) { +/* +* /sys/kernel/tracing/events/syscalls/sys_enter* +* egrep 'field:.*fd;' .../format|sed -r 's/.*field:([a-z ]+) [a-z_]*fd.+/\1/g'|sort|uniq -c +* 65 int +* 23 unsigned int +* 7 unsigned long +*/ + sc->arg_scnprintf[idx] =SCA_FD ; + } ++idx; }
Signature · 1 line
2.5.5
Arnaldo Carvalho de Melo
maintainerPATCH 5/9 perf trace: Use the ptr->name beautifier as default for "filename" args
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Auto-attach the ptr->name beautifier to syscall args "filename", "path" and "pathname" if they are of type "const char *".
--- tools/perf/builtin-trace.c | 120 ++++++++++++++++----------------------------- 1 file changed, 43 insertions(+), 77 deletions(-)
tools/perf/builtin-trace.c +43 -77
@@ -576,44 +576,36 @@ static struct syscall_fmt { bool hexret; } syscall_fmts[] = { { .name = "access", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ - [1] = SCA_ACCMODE, /* mode */ }, }, + .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, }, { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), }, { .name = "brk", .hexret = true, .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, - { .name = "chdir", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, - { .name = "chmod", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, - { .name = "chroot", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, + { .name = "chdir", .errmsg = true, }, + { .name = "chmod", .errmsg = true, }, + { .name = "chroot", .errmsg = true, }, { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, { .name = "clone", .errpid = true, }, { .name = "close", .errmsg = true, .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, { .name = "connect", .errmsg = true, }, - { .name = "creat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, + { .name = "creat", .errmsg = true, }, { .name = "dup", .errmsg = true, }, { .name = "dup2", .errmsg = true, }, { .name = "dup3", .errmsg = true, }, { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), }, { .name = "eventfd2", .errmsg = true, .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, - { .name = "faccessat", .errmsg = true, - .arg_scnprintf = { [1] = SCA_FILENAME, /* filename */ }, }, + { .name = "faccessat", .errmsg = true, }, { .name = "fadvise64", .errmsg = true, }, { .name = "fallocate", .errmsg = true, }, { .name = "fchdir", .errmsg = true, }, { .name = "fchmod", .errmsg = true, }, { .name = "fchmodat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ - [1] = SCA_FILENAME, /* filename */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, { .name = "fchown", .errmsg = true, }, { .name = "fchownat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ - [1] = SCA_FILENAME, /* filename */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, { .name = "fcntl", .errmsg = true, .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ }, .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
@@ -622,16 +614,14 @@ static struct syscall_fmt { .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, }, { .name = "fsetxattr", .errmsg = true, }, { .name = "fstat", .errmsg = true, .alias = "newfstat", }, - { .name = "fstatat", .errmsg = true, .alias = "newfstatat", - .arg_scnprintf = { [1] = SCA_FILENAME, /* filename */ }, }, + { .name = "fstatat", .errmsg = true, .alias = "newfstatat", }, { .name = "fstatfs", .errmsg = true, }, { .name = "fsync", .errmsg = true, }, { .name = "ftruncate", .errmsg = true, }, { .name = "futex", .errmsg = true, .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, { .name = "futimesat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ - [1] = SCA_FILENAME, /* filename */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, { .name = "getdents", .errmsg = true, }, { .name = "getdents64", .errmsg = true, }, { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
@@ -641,10 +631,8 @@ static struct syscall_fmt { { .name = "getrandom", .errmsg = true, .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, }, { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, - { .name = "getxattr", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, - { .name = "inotify_add_watch", .errmsg = true, - .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, }, + { .name = "getxattr", .errmsg = true, }, + { .name = "inotify_add_watch", .errmsg = true, }, { .name = "ioctl", .errmsg = true, .arg_scnprintf = { #if defined(__i386__) || defined(__x86_64__)
@@ -660,40 +648,28 @@ static struct syscall_fmt { { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), }, { .name = "kill", .errmsg = true, .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, - { .name = "lchown", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, - { .name = "lgetxattr", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, + { .name = "lchown", .errmsg = true, }, + { .name = "lgetxattr", .errmsg = true, }, { .name = "linkat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, - { .name = "listxattr", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, - { .name = "llistxattr", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, - { .name = "lremovexattr", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, + { .name = "listxattr", .errmsg = true, }, + { .name = "llistxattr", .errmsg = true, }, + { .name = "lremovexattr", .errmsg = true, }, { .name = "lseek", .errmsg = true, .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ }, .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, - { .name = "lsetxattr", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, - { .name = "lstat", .errmsg = true, .alias = "newlstat", - .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, - { .name = "lsxattr", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, + { .name = "lsetxattr", .errmsg = true, }, + { .name = "lstat", .errmsg = true, .alias = "newlstat", }, + { .name = "lsxattr", .errmsg = true, }, { .name = "madvise", .errmsg = true, .arg_scnprintf = { [0] = SCA_HEX, /* start */ [2] = SCA_MADV_BHV, /* behavior */ }, }, - { .name = "mkdir", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, + { .name = "mkdir", .errmsg = true, }, { .name = "mkdirat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ - [1] = SCA_FILENAME, /* pathname */ }, }, - { .name = "mknod", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, + { .name = "mknod", .errmsg = true, }, { .name = "mknodat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ - [1] = SCA_FILENAME, /* filename */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, { .name = "mlock", .errmsg = true, .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, { .name = "mlockall", .errmsg = true,
@@ -718,17 +694,14 @@ static struct syscall_fmt { { .name = "name_to_handle_at", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, { .name = "newfstatat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ - [1] = SCA_FILENAME, /* filename */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, { .name = "open", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ - [1] = SCA_OPEN_FLAGS, /* flags */ }, }, + .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, }, { .name = "open_by_handle_at", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ [2] = SCA_OPEN_FLAGS, /* flags */ }, }, { .name = "openat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ - [1] = SCA_FILENAME, /* filename */ [2] = SCA_OPEN_FLAGS, /* flags */ }, }, { .name = "perf_event_open", .errmsg = true, .arg_scnprintf = { [2] = SCA_INT, /* cpu */
@@ -744,11 +717,9 @@ static struct syscall_fmt { { .name = "pwrite", .errmsg = true, .alias = "pwrite64", }, { .name = "pwritev", .errmsg = true, }, { .name = "read", .errmsg = true, }, - { .name = "readlink", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, }, + { .name = "readlink", .errmsg = true, }, { .name = "readlinkat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ - [1] = SCA_FILENAME, /* pathname */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, { .name = "readv", .errmsg = true, }, { .name = "recvfrom", .errmsg = true, .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
@@ -756,12 +727,10 @@ static struct syscall_fmt { .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, { .name = "recvmsg", .errmsg = true, .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, - { .name = "removexattr", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, + { .name = "removexattr", .errmsg = true, }, { .name = "renameat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, - { .name = "rmdir", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, + { .name = "rmdir", .errmsg = true, }, { .name = "rt_sigaction", .errmsg = true, .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
@@ -785,8 +754,7 @@ static struct syscall_fmt { { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, { .name = "setpgid", .errmsg = true, }, { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, - { .name = "setxattr", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, + { .name = "setxattr", .errmsg = true, }, { .name = "shutdown", .errmsg = true, }, { .name = "socket", .errmsg = true, .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
@@ -796,10 +764,8 @@ static struct syscall_fmt { .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ [1] = SCA_SK_TYPE, /* type */ }, .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, - { .name = "stat", .errmsg = true, .alias = "newstat", - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, - { .name = "statfs", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, + { .name = "stat", .errmsg = true, .alias = "newstat", }, + { .name = "statfs", .errmsg = true, }, { .name = "swapoff", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, { .name = "swapon", .errmsg = true,
@@ -810,19 +776,14 @@ static struct syscall_fmt { .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, { .name = "tkill", .errmsg = true, .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, - { .name = "truncate", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, }, + { .name = "truncate", .errmsg = true, }, { .name = "uname", .errmsg = true, .alias = "newuname", }, { .name = "unlinkat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ - [1] = SCA_FILENAME, /* pathname */ }, }, - { .name = "utime", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, + { .name = "utime", .errmsg = true, }, { .name = "utimensat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ - [1] = SCA_FILENAME, /* filename */ }, }, - { .name = "utimes", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, }, + { .name = "utimes", .errmsg = true, }, { .name = "vmsplice", .errmsg = true, }, { .name = "wait4", .errpid = true, .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
@@ -1178,6 +1139,11 @@ static int syscall__set_arg_fmts(struct syscall *sc)for (field = sc->args; field; field = field->next) {if (sc->fmt && sc->fmt->arg_scnprintf[idx]) sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; +else if (strcmp (field->type,"const char *" ) ==0 && + (strcmp (field->name,"filename" ) ==0 || +strcmp (field->name,"path" ) ==0 || +strcmp (field->name,"pathname" ) ==0 )) + sc->arg_scnprintf[idx] =SCA_FILENAME ;else if (field->flags &FIELD_IS_POINTER ) sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;else if (strcmp (field->type,"pid_t" ) ==0 )
Signature · 1 line
2.5.5
Arnaldo Carvalho de Melo
maintainerPATCH 6/9 perf evlist: Add API to pause/resume
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
perf_evlist__toggle_{pause,resume}() are introduced to pause/resume events in an evlist. Utilize PERF_EVENT_IOC_PAUSE_OUTPUT ioctl.
Following commits use them to ensure overwrite ring buffer is paused before reading.
[ Return -1, like all other ioctl() usage in evlist.c, rename 'pause'
arg to avoid breaking the build on ubuntu 12.04 and other old systems ]
--- tools/perf/util/evlist.c | 27 +++++++++++++++++++++++++++ tools/perf/util/evlist.h | 2 ++ 2 files changed, 29 insertions(+)
tools/perf/util/evlist.c +27 -0
@@ -679,6 +679,33 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,return NULL ; } +static int perf_evlist__set_paused (struct perf_evlist *evlist,bool value) +{ +int i; + +for (i =0 ; i < evlist->nr_mmaps; i++) { +int fd = evlist->mmap[i].fd; +int err; + +if (fd <0 ) +continue ; + err =ioctl (fd,PERF_EVENT_IOC_PAUSE_OUTPUT , value ?1 :0 ); +if (err) +return err; + } +return 0 ; +} + +int perf_evlist__pause (struct perf_evlist *evlist) +{ +return perf_evlist__set_paused (evlist, true); +} + +int perf_evlist__resume (struct perf_evlist *evlist) +{ +return perf_evlist__set_paused (evlist, false); +} +/* When check_messup is true, 'end' must points to a good entry */ static union perf_event * perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start,
tools/perf/util/evlist.h +2 -0
@@ -136,6 +136,8 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);void perf_evlist__mmap_consume (struct perf_evlist *evlist,int idx); +int perf_evlist__pause (struct perf_evlist *evlist); +int perf_evlist__resume (struct perf_evlist *evlist);int perf_evlist__open (struct perf_evlist *evlist);void perf_evlist__close (struct perf_evlist *evlist);
Signature · 1 line
2.5.5
Arnaldo Carvalho de Melo
maintainerPATCH 7/9 perf record: Prevent reading invalid data in record__mmap_read
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
When record__mmap_read() requires data more than the size of ring buffer, drop those data to avoid accessing invalid memory.
This can happen when reading from overwritable ring buffer, which should be avoided. However, check this for robustness.
--- tools/perf/builtin-record.c | 8 ++++++++ 1 file changed, 8 insertions(+)
tools/perf/builtin-record.c +8 -0
@@ -40,6 +40,7 @@#include <unistd.h> #include <sched.h> #include <sys/mman.h> +#include <asm/bug.h> struct record {
@@ -98,6 +99,13 @@ static int record__mmap_read(struct record *rec, int idx) rec->samples++; size = head - old; +if (size > (unsigned long )(md->mask) +1 ) { +WARN_ONCE (1 ,"failed to keep up with mmap data. (warn only once)\n" ); + + md->prev = head; +perf_evlist__mmap_consume (rec->evlist, idx); +return 0 ; + }if ((old & md->mask) + size != (head & md->mask)) { buf = &data[old & md->mask];
Signature · 1 line
2.5.5
Arnaldo Carvalho de Melo
maintainerPATCH 8/9 perf record: Rename variable to make code clear
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
record__mmap_read() writes data from ring buffer into perf.data. 'head' is maintained by the kernel, points to the last written record. 'old' is maintained by perf, points to the record read in previous round. record__mmap_read() saves data from 'old' to 'head' to perf.data.
The names of these variables are not very intutive. In addition, when dealing with backward writing ring buffer, the md->prev pointer should point to 'head' instead of the last byte it got.
Add 'start' and 'end' pointer to make code clear and set md->prev to 'head' instead of the moved 'old' pointer. This patch doesn't change behavior since:
buf = &data[old & md->mask];
size = head - old;
old += size; <--- Here, old == head--- tools/perf/builtin-record.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
tools/perf/builtin-record.c +11 -10
@@ -88,17 +88,18 @@ static int record__mmap_read(struct record *rec, int idx)struct perf_mmap *md = &rec->evlist->mmap[idx];u64 head =perf_mmap__read_head (md);u64 old = md->prev; +u64 end = head, start = old;unsigned char *data = md->base + page_size;unsigned long size;void *buf;int rc =0 ; -if (old == head) +if (start == end)return 0 ; rec->samples++; - size = head - old; + size = end - start;if (size > (unsigned long )(md->mask) +1 ) {WARN_ONCE (1 ,"failed to keep up with mmap data. (warn only once)\n" );
@@ -107,10 +108,10 @@ static int record__mmap_read(struct record *rec, int idx)return 0 ; } -if ((old & md->mask) + size != (head & md->mask)) { - buf = &data[old & md->mask]; - size = md->mask +1 - (old & md->mask); - old += size; +if ((start & md->mask) + size != (end & md->mask)) { + buf = &data[start & md->mask]; + size = md->mask +1 - (start & md->mask); + start += size;if (record__write (rec, buf, size) <0 ) { rc =-1 ;
@@ -118,16 +119,16 @@ static int record__mmap_read(struct record *rec, int idx) } } - buf = &data[old & md->mask]; - size = head - old; - old += size; + buf = &data[start & md->mask]; + size = end - start; + start += size;if (record__write (rec, buf, size) <0 ) { rc =-1 ; goto out; } - md->prev = old; + md->prev = head;perf_evlist__mmap_consume (rec->evlist, idx); out:return rc;
Signature · 1 line
2.5.5
Arnaldo Carvalho de Melo
maintainerPATCH 9/9 perf record: Read from backward ring buffer
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
Introduce rb_find_range() to find start and end position from a backward ring buffer.
--- tools/perf/builtin-record.c | 52 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/evlist.c | 1 + tools/perf/util/evlist.h | 1 + 3 files changed, 54 insertions(+)
tools/perf/builtin-record.c +52 -0
@@ -83,6 +83,54 @@ static int process_synthesized_event(struct perf_tool *tool,return record__write (rec, event, event->header.size); } +static int +backward_rb_find_range (void *buf,int mask,u64 head,u64 *start,u64 *end) +{ +struct perf_event_header *pheader; +u64 evt_head = head; +int size = mask +1 ; + +pr_debug2 ("backward_rb_find_range: buf=%p, head=%" PRIx64"\n" , buf, head); + pheader = (struct perf_event_header *)(buf + (head & mask)); + *start = head; +while (true) { +if (evt_head - head >= (unsigned int )size) { +pr_debug ("Finshed reading backward ring buffer: rewind\n" ); +if (evt_head - head > (unsigned int )size) + evt_head -= pheader->size; + *end = evt_head; +return 0 ; + } + + pheader = (struct perf_event_header *)(buf + (evt_head & mask)); + +if (pheader->size ==0 ) { +pr_debug ("Finshed reading backward ring buffer: get start\n" ); + *end = evt_head; +return 0 ; + } + + evt_head += pheader->size; +pr_debug3 ("move evt_head: %" PRIx64"\n" , evt_head); + } +WARN_ONCE (1 ,"Shouldn't get here\n" ); +return -1 ; +} + +static int +rb_find_range (struct perf_evlist *evlist, +void *data,int mask,u64 head,u64 old, +u64 *start,u64 *end) +{ +if (!evlist->backward) { + *start = old; + *end = head; +return 0 ; + } + +return backward_rb_find_range (data, mask, head, start, end); +} +static int record__mmap_read (struct record *rec,int idx) {struct perf_mmap *md = &rec->evlist->mmap[idx];
@@ -94,6 +142,10 @@ static int record__mmap_read(struct record *rec, int idx)void *buf;int rc =0 ; +if (rb_find_range (rec->evlist, data, md->mask, head, + old, &start, &end)) +return -1 ; +if (start == end)return 0 ;
tools/perf/util/evlist.c +1 -0
@@ -44,6 +44,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,perf_evlist__set_maps (evlist, cpus, threads);fdarray__init (&evlist->pollfd,64 ); evlist->workload.pid =-1 ; + evlist->backward = false; }struct perf_evlist *perf_evlist__new (void )
tools/perf/util/evlist.h +1 -0
@@ -44,6 +44,7 @@ struct perf_evlist {bool overwrite;bool enabled;bool has_user_cpus; +bool backward;size_t mmap_len;int id_pos;int is_pos;
Signature · 1 line
2.5.5
Quoted 54 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit
408cf677073a5d1a7343bc6430a7297ba7b280d4:Merge tag 'perf-core-for-mingo-20160520' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxinto perf/urgent (2016-05-20 19:37:43 +0200)are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingo-20160523for you to fetch changes up to
3a62a7b8200a177ad96161e4f2678514e6ee301e:perf record: Read from backward ring buffer (2016-05-23 18:22:48 -0300)
----------------------------------------------------------------
perf/core improvements:User visible:
- Add "
srcline_from" and "srcline_to" branch sort keys to 'perf top' and 'perf report' (Andi Kleen)Infrastructure:
- Make 'perf trace' auto-attach
fd->nameandptr->namebeautifiers based on the name of syscall arguments, this way new syscalls that have 'const char * (path,pathname,filename)' will use thefd->namebeautifier (vfs_getnameperf probe, if in place) and the 'fd->name' (vfs_getnameor via/proc/PID/fd/) (Arnaldo Carvalho de Melo)- Infrastructure to read from a ring buffer in backward write mode (Wang Nan)
Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Andi Kleen (1):
perf report: Add srcline_from/to branch sort keysArnaldo Carvalho de Melo (2):
perf trace: Use the fd->name beautifier as default for "fd" args perf trace: Use the ptr->name beautifier as default for "filename" argsWang Nan (6):
perf evsel: Add overwrite attribute and checkwrite_backwardperf evsel: Record fd intoperf_mmap
perf evlist: Add API to pause/resume
perf record: Prevent reading invalid data inrecord__mmap_readperf record: Rename variable to make code clear perf record: Read from backward ring buffer
Quoted 13 lines
tools/perf/Documentation/perf-report.txt | 3 +- tools/perf/builtin-record.c | 81 ++++++++-- tools/perf/builtin-trace.c | 248 ++++++++++++------------------- tools/perf/util/evlist.c | 34 +++++ tools/perf/util/evlist.h | 4 + tools/perf/util/evsel.c | 13 ++ tools/perf/util/evsel.h | 1 + tools/perf/util/hist.c | 9 ++ tools/perf/util/hist.h | 2 + tools/perf/util/sort.c | 84 +++++++++++ tools/perf/util/sort.h | 2 + tools/perf/util/symbol.h | 2 + 12 files changed, 319 insertions(+), 164 deletions(-)
Pulled, thanks a lot Arnaldo!
Ingo