mirror of https://gitee.com/openkylin/linux.git
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) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJXQ33GAAoJENZQFvNTUqpAbLUP/1fyH/IxpYfGBvsukbthQlxC oRSJTxAGP6cxm7n9LYIO01EIcHAx7VKVrf2WrKJp6QtQPQflpSFWdvUB3imKE6q7 /+Tcg9eVp88Oqc5MvSmV//ICjKn6Cdr86I/4PuBcLa+nAJcSP3BZK9HSVkKu5Ot7 wHfbnbHiQo3pRZAL7t/newpmO4wZ135DDlmITcfXXTozjgcxW6fjoJaWwnjycEHd sdZDMeQs1Avos5THMfyiK4b5xWUDFj/rhjGcsbrk9bfzg0iPeReDfi68uf7zqh5k pAHpdIspHp2DfBxNWKwHFD1fzngAkK9i4IRocikqtnYD06lKpFTv4rTncn0UfUra cOIaDTVNA8QIt/cOeSvKHPMWIDdLybBPva7iUHUDPh1fRHZn10TqHP3PUAlGB6QC 0PRIET1Iw0ugsDUeeA7EfUD/w30FkKrDEuSEUBCDV8k1VLPfz09QnaRiE9D/OYsf VqwRDU9/Hy4E+L/DZDEyJII6frWeuTm6N1n83273zlyyHOPoH37NwJwKIGojxu0k 9sBtd4Y7g+flNzatdtybLPiOipTpxo2tHz/GC9C8EHLchuub4CXpQzMtcffkd285 Uj55QEMwV5UCh9bJSIoS5rfM1djB3h4eMO7dE5f1qgo2JUcmHwxxbpIcbi648rR2 KDtB2LnaC24PzSGN0NMK =MhyE -----END PGP SIGNATURE----- Merge tag 'perf-core-for-mingo-20160523' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent Pull perf/core improvements from Arnaldo Carvalho de Melo: User visible changes: - Add "srcline_from" and "srcline_to" branch sort keys to 'perf top' and 'perf report' (Andi Kleen) Infrastructure changes: - 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) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
0c9f790fcb
|
@ -103,12 +103,13 @@ OPTIONS
|
||||||
|
|
||||||
If --branch-stack option is used, following sort keys are also
|
If --branch-stack option is used, following sort keys are also
|
||||||
available:
|
available:
|
||||||
dso_from, dso_to, symbol_from, symbol_to, mispredict.
|
|
||||||
|
|
||||||
- dso_from: name of library or module branched from
|
- dso_from: name of library or module branched from
|
||||||
- dso_to: name of library or module branched to
|
- dso_to: name of library or module branched to
|
||||||
- symbol_from: name of function branched from
|
- symbol_from: name of function branched from
|
||||||
- symbol_to: name of function branched to
|
- 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
|
- mispredict: "N" for predicted branch, "Y" for mispredicted branch
|
||||||
- in_tx: branch in TSX transaction
|
- in_tx: branch in TSX transaction
|
||||||
- abort: TSX transaction abort.
|
- abort: TSX transaction abort.
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <asm/bug.h>
|
||||||
|
|
||||||
|
|
||||||
struct record {
|
struct record {
|
||||||
|
@ -82,27 +83,87 @@ static int process_synthesized_event(struct perf_tool *tool,
|
||||||
return record__write(rec, event, event->header.size);
|
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)
|
static int record__mmap_read(struct record *rec, int idx)
|
||||||
{
|
{
|
||||||
struct perf_mmap *md = &rec->evlist->mmap[idx];
|
struct perf_mmap *md = &rec->evlist->mmap[idx];
|
||||||
u64 head = perf_mmap__read_head(md);
|
u64 head = perf_mmap__read_head(md);
|
||||||
u64 old = md->prev;
|
u64 old = md->prev;
|
||||||
|
u64 end = head, start = old;
|
||||||
unsigned char *data = md->base + page_size;
|
unsigned char *data = md->base + page_size;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
void *buf;
|
void *buf;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (old == head)
|
if (rb_find_range(rec->evlist, data, md->mask, head,
|
||||||
|
old, &start, &end))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (start == end)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rec->samples++;
|
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");
|
||||||
|
|
||||||
if ((old & md->mask) + size != (head & md->mask)) {
|
md->prev = head;
|
||||||
buf = &data[old & md->mask];
|
perf_evlist__mmap_consume(rec->evlist, idx);
|
||||||
size = md->mask + 1 - (old & md->mask);
|
return 0;
|
||||||
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) {
|
if (record__write(rec, buf, size) < 0) {
|
||||||
rc = -1;
|
rc = -1;
|
||||||
|
@ -110,16 +171,16 @@ static int record__mmap_read(struct record *rec, int idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = &data[old & md->mask];
|
buf = &data[start & md->mask];
|
||||||
size = head - old;
|
size = end - start;
|
||||||
old += size;
|
start += size;
|
||||||
|
|
||||||
if (record__write(rec, buf, size) < 0) {
|
if (record__write(rec, buf, size) < 0) {
|
||||||
rc = -1;
|
rc = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
md->prev = old;
|
md->prev = head;
|
||||||
perf_evlist__mmap_consume(rec->evlist, idx);
|
perf_evlist__mmap_consume(rec->evlist, idx);
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -576,84 +576,54 @@ static struct syscall_fmt {
|
||||||
bool hexret;
|
bool hexret;
|
||||||
} syscall_fmts[] = {
|
} syscall_fmts[] = {
|
||||||
{ .name = "access", .errmsg = true,
|
{ .name = "access", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
|
.arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
|
||||||
[1] = SCA_ACCMODE, /* mode */ }, },
|
|
||||||
{ .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
|
{ .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
|
||||||
{ .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
|
{ .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
|
||||||
{ .name = "brk", .hexret = true,
|
{ .name = "brk", .hexret = true,
|
||||||
.arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
|
.arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
|
||||||
{ .name = "chdir", .errmsg = true,
|
{ .name = "chdir", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
|
{ .name = "chmod", .errmsg = true, },
|
||||||
{ .name = "chmod", .errmsg = true,
|
{ .name = "chroot", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
|
|
||||||
{ .name = "chroot", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
|
|
||||||
{ .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
|
{ .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
|
||||||
{ .name = "clone", .errpid = true, },
|
{ .name = "clone", .errpid = true, },
|
||||||
{ .name = "close", .errmsg = true,
|
{ .name = "close", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
|
.arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
|
||||||
{ .name = "connect", .errmsg = true, },
|
{ .name = "connect", .errmsg = true, },
|
||||||
{ .name = "creat", .errmsg = true,
|
{ .name = "creat", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
{ .name = "dup", .errmsg = true, },
|
||||||
{ .name = "dup", .errmsg = true,
|
{ .name = "dup2", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
{ .name = "dup3", .errmsg = true, },
|
||||||
{ .name = "dup2", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
|
||||||
{ .name = "dup3", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
|
||||||
{ .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
|
{ .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
|
||||||
{ .name = "eventfd2", .errmsg = true,
|
{ .name = "eventfd2", .errmsg = true,
|
||||||
.arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
|
.arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
|
||||||
{ .name = "faccessat", .errmsg = true,
|
{ .name = "faccessat", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
|
{ .name = "fadvise64", .errmsg = true, },
|
||||||
[1] = SCA_FILENAME, /* filename */ }, },
|
{ .name = "fallocate", .errmsg = true, },
|
||||||
{ .name = "fadvise64", .errmsg = true,
|
{ .name = "fchdir", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
{ .name = "fchmod", .errmsg = true, },
|
||||||
{ .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 */ }, },
|
|
||||||
{ .name = "fchmodat", .errmsg = true,
|
{ .name = "fchmodat", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */
|
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
||||||
[1] = SCA_FILENAME, /* filename */ }, },
|
{ .name = "fchown", .errmsg = true, },
|
||||||
{ .name = "fchown", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
|
||||||
{ .name = "fchownat", .errmsg = true,
|
{ .name = "fchownat", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */
|
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
||||||
[1] = SCA_FILENAME, /* filename */ }, },
|
|
||||||
{ .name = "fcntl", .errmsg = true,
|
{ .name = "fcntl", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */
|
.arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
|
||||||
[1] = SCA_STRARRAY, /* cmd */ },
|
|
||||||
.arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
|
.arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
|
||||||
{ .name = "fdatasync", .errmsg = true,
|
{ .name = "fdatasync", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
|
||||||
{ .name = "flock", .errmsg = true,
|
{ .name = "flock", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */
|
.arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, },
|
||||||
[1] = SCA_FLOCK, /* cmd */ }, },
|
{ .name = "fsetxattr", .errmsg = true, },
|
||||||
{ .name = "fsetxattr", .errmsg = true,
|
{ .name = "fstat", .errmsg = true, .alias = "newfstat", },
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
{ .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
|
||||||
{ .name = "fstat", .errmsg = true, .alias = "newfstat",
|
{ .name = "fstatfs", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
{ .name = "fsync", .errmsg = true, },
|
||||||
{ .name = "fstatat", .errmsg = true, .alias = "newfstatat",
|
{ .name = "ftruncate", .errmsg = true, },
|
||||||
.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 */ }, },
|
|
||||||
{ .name = "futex", .errmsg = true,
|
{ .name = "futex", .errmsg = true,
|
||||||
.arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
|
.arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
|
||||||
{ .name = "futimesat", .errmsg = true,
|
{ .name = "futimesat", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */
|
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
||||||
[1] = SCA_FILENAME, /* filename */ }, },
|
{ .name = "getdents", .errmsg = true, },
|
||||||
{ .name = "getdents", .errmsg = true,
|
{ .name = "getdents64", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
|
||||||
{ .name = "getdents64", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
|
||||||
{ .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
|
{ .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
|
||||||
{ .name = "getpid", .errpid = true, },
|
{ .name = "getpid", .errpid = true, },
|
||||||
{ .name = "getpgid", .errpid = true, },
|
{ .name = "getpgid", .errpid = true, },
|
||||||
|
@ -661,12 +631,10 @@ static struct syscall_fmt {
|
||||||
{ .name = "getrandom", .errmsg = true,
|
{ .name = "getrandom", .errmsg = true,
|
||||||
.arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
|
.arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
|
||||||
{ .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
|
{ .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
|
||||||
{ .name = "getxattr", .errmsg = true,
|
{ .name = "getxattr", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
{ .name = "inotify_add_watch", .errmsg = true, },
|
||||||
{ .name = "inotify_add_watch", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, },
|
|
||||||
{ .name = "ioctl", .errmsg = true,
|
{ .name = "ioctl", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */
|
.arg_scnprintf = {
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
/*
|
/*
|
||||||
* FIXME: Make this available to all arches.
|
* FIXME: Make this available to all arches.
|
||||||
|
@ -680,41 +648,28 @@ static struct syscall_fmt {
|
||||||
{ .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
|
{ .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
|
||||||
{ .name = "kill", .errmsg = true,
|
{ .name = "kill", .errmsg = true,
|
||||||
.arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
|
.arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
|
||||||
{ .name = "lchown", .errmsg = true,
|
{ .name = "lchown", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
|
{ .name = "lgetxattr", .errmsg = true, },
|
||||||
{ .name = "lgetxattr", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
|
||||||
{ .name = "linkat", .errmsg = true,
|
{ .name = "linkat", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
||||||
{ .name = "listxattr", .errmsg = true,
|
{ .name = "listxattr", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
{ .name = "llistxattr", .errmsg = true, },
|
||||||
{ .name = "llistxattr", .errmsg = true,
|
{ .name = "lremovexattr", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
|
||||||
{ .name = "lremovexattr", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
|
||||||
{ .name = "lseek", .errmsg = true,
|
{ .name = "lseek", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */
|
.arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ },
|
||||||
[2] = SCA_STRARRAY, /* whence */ },
|
|
||||||
.arg_parm = { [2] = &strarray__whences, /* whence */ }, },
|
.arg_parm = { [2] = &strarray__whences, /* whence */ }, },
|
||||||
{ .name = "lsetxattr", .errmsg = true,
|
{ .name = "lsetxattr", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
{ .name = "lstat", .errmsg = true, .alias = "newlstat", },
|
||||||
{ .name = "lstat", .errmsg = true, .alias = "newlstat",
|
{ .name = "lsxattr", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
|
|
||||||
{ .name = "lsxattr", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
|
||||||
{ .name = "madvise", .errmsg = true,
|
{ .name = "madvise", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_HEX, /* start */
|
.arg_scnprintf = { [0] = SCA_HEX, /* start */
|
||||||
[2] = SCA_MADV_BHV, /* behavior */ }, },
|
[2] = SCA_MADV_BHV, /* behavior */ }, },
|
||||||
{ .name = "mkdir", .errmsg = true,
|
{ .name = "mkdir", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
|
||||||
{ .name = "mkdirat", .errmsg = true,
|
{ .name = "mkdirat", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */
|
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
||||||
[1] = SCA_FILENAME, /* pathname */ }, },
|
{ .name = "mknod", .errmsg = true, },
|
||||||
{ .name = "mknod", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
|
|
||||||
{ .name = "mknodat", .errmsg = true,
|
{ .name = "mknodat", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */
|
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
||||||
[1] = SCA_FILENAME, /* filename */ }, },
|
|
||||||
{ .name = "mlock", .errmsg = true,
|
{ .name = "mlock", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
|
.arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
|
||||||
{ .name = "mlockall", .errmsg = true,
|
{ .name = "mlockall", .errmsg = true,
|
||||||
|
@ -722,8 +677,7 @@ static struct syscall_fmt {
|
||||||
{ .name = "mmap", .hexret = true,
|
{ .name = "mmap", .hexret = true,
|
||||||
.arg_scnprintf = { [0] = SCA_HEX, /* addr */
|
.arg_scnprintf = { [0] = SCA_HEX, /* addr */
|
||||||
[2] = SCA_MMAP_PROT, /* prot */
|
[2] = SCA_MMAP_PROT, /* prot */
|
||||||
[3] = SCA_MMAP_FLAGS, /* flags */
|
[3] = SCA_MMAP_FLAGS, /* flags */ }, },
|
||||||
[4] = SCA_FD, /* fd */ }, },
|
|
||||||
{ .name = "mprotect", .errmsg = true,
|
{ .name = "mprotect", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_HEX, /* start */
|
.arg_scnprintf = { [0] = SCA_HEX, /* start */
|
||||||
[2] = SCA_MMAP_PROT, /* prot */ }, },
|
[2] = SCA_MMAP_PROT, /* prot */ }, },
|
||||||
|
@ -740,17 +694,14 @@ static struct syscall_fmt {
|
||||||
{ .name = "name_to_handle_at", .errmsg = true,
|
{ .name = "name_to_handle_at", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
||||||
{ .name = "newfstatat", .errmsg = true,
|
{ .name = "newfstatat", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
|
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
||||||
[1] = SCA_FILENAME, /* filename */ }, },
|
|
||||||
{ .name = "open", .errmsg = true,
|
{ .name = "open", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
|
.arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
|
||||||
[1] = SCA_OPEN_FLAGS, /* flags */ }, },
|
|
||||||
{ .name = "open_by_handle_at", .errmsg = true,
|
{ .name = "open_by_handle_at", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
|
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
|
||||||
[2] = SCA_OPEN_FLAGS, /* flags */ }, },
|
[2] = SCA_OPEN_FLAGS, /* flags */ }, },
|
||||||
{ .name = "openat", .errmsg = true,
|
{ .name = "openat", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
|
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
|
||||||
[1] = SCA_FILENAME, /* filename */
|
|
||||||
[2] = SCA_OPEN_FLAGS, /* flags */ }, },
|
[2] = SCA_OPEN_FLAGS, /* flags */ }, },
|
||||||
{ .name = "perf_event_open", .errmsg = true,
|
{ .name = "perf_event_open", .errmsg = true,
|
||||||
.arg_scnprintf = { [2] = SCA_INT, /* cpu */
|
.arg_scnprintf = { [2] = SCA_INT, /* cpu */
|
||||||
|
@ -760,39 +711,26 @@ static struct syscall_fmt {
|
||||||
.arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
|
.arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
|
||||||
{ .name = "poll", .errmsg = true, .timeout = true, },
|
{ .name = "poll", .errmsg = true, .timeout = true, },
|
||||||
{ .name = "ppoll", .errmsg = true, .timeout = true, },
|
{ .name = "ppoll", .errmsg = true, .timeout = true, },
|
||||||
{ .name = "pread", .errmsg = true, .alias = "pread64",
|
{ .name = "pread", .errmsg = true, .alias = "pread64", },
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
{ .name = "preadv", .errmsg = true, .alias = "pread", },
|
||||||
{ .name = "preadv", .errmsg = true, .alias = "pread",
|
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
|
||||||
{ .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
|
{ .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
|
||||||
{ .name = "pwrite", .errmsg = true, .alias = "pwrite64",
|
{ .name = "pwrite", .errmsg = true, .alias = "pwrite64", },
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
{ .name = "pwritev", .errmsg = true, },
|
||||||
{ .name = "pwritev", .errmsg = true,
|
{ .name = "read", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
{ .name = "readlink", .errmsg = true, },
|
||||||
{ .name = "read", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
|
||||||
{ .name = "readlink", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
|
|
||||||
{ .name = "readlinkat", .errmsg = true,
|
{ .name = "readlinkat", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
|
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
||||||
[1] = SCA_FILENAME, /* pathname */ }, },
|
{ .name = "readv", .errmsg = true, },
|
||||||
{ .name = "readv", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
|
||||||
{ .name = "recvfrom", .errmsg = true,
|
{ .name = "recvfrom", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */
|
.arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||||
[3] = SCA_MSG_FLAGS, /* flags */ }, },
|
|
||||||
{ .name = "recvmmsg", .errmsg = true,
|
{ .name = "recvmmsg", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */
|
.arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||||
[3] = SCA_MSG_FLAGS, /* flags */ }, },
|
|
||||||
{ .name = "recvmsg", .errmsg = true,
|
{ .name = "recvmsg", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */
|
.arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||||
[2] = SCA_MSG_FLAGS, /* flags */ }, },
|
{ .name = "removexattr", .errmsg = true, },
|
||||||
{ .name = "removexattr", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
|
||||||
{ .name = "renameat", .errmsg = true,
|
{ .name = "renameat", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
||||||
{ .name = "rmdir", .errmsg = true,
|
{ .name = "rmdir", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
|
||||||
{ .name = "rt_sigaction", .errmsg = true,
|
{ .name = "rt_sigaction", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
|
.arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
|
||||||
{ .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
|
{ .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
|
||||||
|
@ -807,22 +745,17 @@ static struct syscall_fmt {
|
||||||
[1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
|
[1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
|
||||||
{ .name = "select", .errmsg = true, .timeout = true, },
|
{ .name = "select", .errmsg = true, .timeout = true, },
|
||||||
{ .name = "sendmmsg", .errmsg = true,
|
{ .name = "sendmmsg", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */
|
.arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||||
[3] = SCA_MSG_FLAGS, /* flags */ }, },
|
|
||||||
{ .name = "sendmsg", .errmsg = true,
|
{ .name = "sendmsg", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */
|
.arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||||
[2] = SCA_MSG_FLAGS, /* flags */ }, },
|
|
||||||
{ .name = "sendto", .errmsg = true,
|
{ .name = "sendto", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */
|
.arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||||
[3] = SCA_MSG_FLAGS, /* flags */ }, },
|
|
||||||
{ .name = "set_tid_address", .errpid = true, },
|
{ .name = "set_tid_address", .errpid = true, },
|
||||||
{ .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
|
{ .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
|
||||||
{ .name = "setpgid", .errmsg = true, },
|
{ .name = "setpgid", .errmsg = true, },
|
||||||
{ .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
|
{ .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
|
||||||
{ .name = "setxattr", .errmsg = true,
|
{ .name = "setxattr", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
{ .name = "shutdown", .errmsg = true, },
|
||||||
{ .name = "shutdown", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
|
||||||
{ .name = "socket", .errmsg = true,
|
{ .name = "socket", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
|
.arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
|
||||||
[1] = SCA_SK_TYPE, /* type */ },
|
[1] = SCA_SK_TYPE, /* type */ },
|
||||||
|
@ -831,10 +764,8 @@ static struct syscall_fmt {
|
||||||
.arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
|
.arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
|
||||||
[1] = SCA_SK_TYPE, /* type */ },
|
[1] = SCA_SK_TYPE, /* type */ },
|
||||||
.arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
|
.arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
|
||||||
{ .name = "stat", .errmsg = true, .alias = "newstat",
|
{ .name = "stat", .errmsg = true, .alias = "newstat", },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
{ .name = "statfs", .errmsg = true, },
|
||||||
{ .name = "statfs", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
|
||||||
{ .name = "swapoff", .errmsg = true,
|
{ .name = "swapoff", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
|
.arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
|
||||||
{ .name = "swapon", .errmsg = true,
|
{ .name = "swapon", .errmsg = true,
|
||||||
|
@ -845,29 +776,21 @@ static struct syscall_fmt {
|
||||||
.arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
|
.arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
|
||||||
{ .name = "tkill", .errmsg = true,
|
{ .name = "tkill", .errmsg = true,
|
||||||
.arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
|
.arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
|
||||||
{ .name = "truncate", .errmsg = true,
|
{ .name = "truncate", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
|
|
||||||
{ .name = "uname", .errmsg = true, .alias = "newuname", },
|
{ .name = "uname", .errmsg = true, .alias = "newuname", },
|
||||||
{ .name = "unlinkat", .errmsg = true,
|
{ .name = "unlinkat", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
|
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
||||||
[1] = SCA_FILENAME, /* pathname */ }, },
|
{ .name = "utime", .errmsg = true, },
|
||||||
{ .name = "utime", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
|
|
||||||
{ .name = "utimensat", .errmsg = true,
|
{ .name = "utimensat", .errmsg = true,
|
||||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */
|
.arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
|
||||||
[1] = SCA_FILENAME, /* filename */ }, },
|
{ .name = "utimes", .errmsg = true, },
|
||||||
{ .name = "utimes", .errmsg = true,
|
{ .name = "vmsplice", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
|
|
||||||
{ .name = "vmsplice", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
|
||||||
{ .name = "wait4", .errpid = true,
|
{ .name = "wait4", .errpid = true,
|
||||||
.arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
|
.arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
|
||||||
{ .name = "waitid", .errpid = true,
|
{ .name = "waitid", .errpid = true,
|
||||||
.arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
|
.arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
|
||||||
{ .name = "write", .errmsg = true,
|
{ .name = "write", .errmsg = true, },
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
{ .name = "writev", .errmsg = true, },
|
||||||
{ .name = "writev", .errmsg = true,
|
|
||||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int syscall_fmt__cmp(const void *name, const void *fmtp)
|
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)
|
||||||
static int syscall__set_arg_fmts(struct syscall *sc)
|
static int syscall__set_arg_fmts(struct syscall *sc)
|
||||||
{
|
{
|
||||||
struct format_field *field;
|
struct format_field *field;
|
||||||
int idx = 0;
|
int idx = 0, len;
|
||||||
|
|
||||||
sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
|
sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
|
||||||
if (sc->arg_scnprintf == NULL)
|
if (sc->arg_scnprintf == NULL)
|
||||||
|
@ -1216,12 +1139,31 @@ static int syscall__set_arg_fmts(struct syscall *sc)
|
||||||
for (field = sc->args; field; field = field->next) {
|
for (field = sc->args; field; field = field->next) {
|
||||||
if (sc->fmt && sc->fmt->arg_scnprintf[idx])
|
if (sc->fmt && sc->fmt->arg_scnprintf[idx])
|
||||||
sc->arg_scnprintf[idx] = 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)
|
else if (field->flags & FIELD_IS_POINTER)
|
||||||
sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
|
sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
|
||||||
else if (strcmp(field->type, "pid_t") == 0)
|
else if (strcmp(field->type, "pid_t") == 0)
|
||||||
sc->arg_scnprintf[idx] = SCA_PID;
|
sc->arg_scnprintf[idx] = SCA_PID;
|
||||||
else if (strcmp(field->type, "umode_t") == 0)
|
else if (strcmp(field->type, "umode_t") == 0)
|
||||||
sc->arg_scnprintf[idx] = SCA_MODE_T;
|
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;
|
++idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
|
||||||
perf_evlist__set_maps(evlist, cpus, threads);
|
perf_evlist__set_maps(evlist, cpus, threads);
|
||||||
fdarray__init(&evlist->pollfd, 64);
|
fdarray__init(&evlist->pollfd, 64);
|
||||||
evlist->workload.pid = -1;
|
evlist->workload.pid = -1;
|
||||||
|
evlist->backward = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct perf_evlist *perf_evlist__new(void)
|
struct perf_evlist *perf_evlist__new(void)
|
||||||
|
@ -679,6 +680,33 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
|
||||||
return NULL;
|
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 */
|
/* When check_messup is true, 'end' must points to a good entry */
|
||||||
static union perf_event *
|
static union perf_event *
|
||||||
perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start,
|
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)
|
||||||
if (evlist->mmap[idx].base != NULL) {
|
if (evlist->mmap[idx].base != NULL) {
|
||||||
munmap(evlist->mmap[idx].base, evlist->mmap_len);
|
munmap(evlist->mmap[idx].base, evlist->mmap_len);
|
||||||
evlist->mmap[idx].base = NULL;
|
evlist->mmap[idx].base = NULL;
|
||||||
|
evlist->mmap[idx].fd = -1;
|
||||||
atomic_set(&evlist->mmap[idx].refcnt, 0);
|
atomic_set(&evlist->mmap[idx].refcnt, 0);
|
||||||
}
|
}
|
||||||
auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap);
|
auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap);
|
||||||
|
@ -901,10 +930,14 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
|
||||||
|
|
||||||
static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
|
static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
|
evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
|
||||||
if (cpu_map__empty(evlist->cpus))
|
if (cpu_map__empty(evlist->cpus))
|
||||||
evlist->nr_mmaps = thread_map__nr(evlist->threads);
|
evlist->nr_mmaps = thread_map__nr(evlist->threads);
|
||||||
evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
|
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;
|
return evlist->mmap != NULL ? 0 : -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -941,6 +974,7 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
|
||||||
evlist->mmap[idx].base = NULL;
|
evlist->mmap[idx].base = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
evlist->mmap[idx].fd = fd;
|
||||||
|
|
||||||
if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap,
|
if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap,
|
||||||
&mp->auxtrace_mp, evlist->mmap[idx].base, fd))
|
&mp->auxtrace_mp, evlist->mmap[idx].base, fd))
|
||||||
|
|
|
@ -28,6 +28,7 @@ struct record_opts;
|
||||||
struct perf_mmap {
|
struct perf_mmap {
|
||||||
void *base;
|
void *base;
|
||||||
int mask;
|
int mask;
|
||||||
|
int fd;
|
||||||
atomic_t refcnt;
|
atomic_t refcnt;
|
||||||
u64 prev;
|
u64 prev;
|
||||||
struct auxtrace_mmap auxtrace_mmap;
|
struct auxtrace_mmap auxtrace_mmap;
|
||||||
|
@ -43,6 +44,7 @@ struct perf_evlist {
|
||||||
bool overwrite;
|
bool overwrite;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
bool has_user_cpus;
|
bool has_user_cpus;
|
||||||
|
bool backward;
|
||||||
size_t mmap_len;
|
size_t mmap_len;
|
||||||
int id_pos;
|
int id_pos;
|
||||||
int is_pos;
|
int is_pos;
|
||||||
|
@ -135,6 +137,8 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
|
||||||
|
|
||||||
void perf_evlist__mmap_consume(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);
|
int perf_evlist__open(struct perf_evlist *evlist);
|
||||||
void perf_evlist__close(struct perf_evlist *evlist);
|
void perf_evlist__close(struct perf_evlist *evlist);
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ static struct {
|
||||||
bool clockid;
|
bool clockid;
|
||||||
bool clockid_wrong;
|
bool clockid_wrong;
|
||||||
bool lbr_flags;
|
bool lbr_flags;
|
||||||
|
bool write_backward;
|
||||||
} perf_missing_features;
|
} perf_missing_features;
|
||||||
|
|
||||||
static clockid_t clockid;
|
static clockid_t clockid;
|
||||||
|
@ -1376,6 +1377,8 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
|
||||||
if (perf_missing_features.lbr_flags)
|
if (perf_missing_features.lbr_flags)
|
||||||
evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
|
evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
|
||||||
PERF_SAMPLE_BRANCH_NO_CYCLES);
|
PERF_SAMPLE_BRANCH_NO_CYCLES);
|
||||||
|
if (perf_missing_features.write_backward)
|
||||||
|
evsel->attr.write_backward = false;
|
||||||
retry_sample_id:
|
retry_sample_id:
|
||||||
if (perf_missing_features.sample_id_all)
|
if (perf_missing_features.sample_id_all)
|
||||||
evsel->attr.sample_id_all = 0;
|
evsel->attr.sample_id_all = 0;
|
||||||
|
@ -1438,6 +1441,12 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (evsel->overwrite &&
|
||||||
|
perf_missing_features.write_backward) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out_close;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1500,6 +1509,10 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
|
||||||
PERF_SAMPLE_BRANCH_NO_FLAGS))) {
|
PERF_SAMPLE_BRANCH_NO_FLAGS))) {
|
||||||
perf_missing_features.lbr_flags = true;
|
perf_missing_features.lbr_flags = true;
|
||||||
goto fallback_missing_features;
|
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:
|
out_close:
|
||||||
|
|
|
@ -112,6 +112,7 @@ struct perf_evsel {
|
||||||
bool tracking;
|
bool tracking;
|
||||||
bool per_pkg;
|
bool per_pkg;
|
||||||
bool precise_max;
|
bool precise_max;
|
||||||
|
bool overwrite;
|
||||||
/* parse modifier helper */
|
/* parse modifier helper */
|
||||||
int exclude_GH;
|
int exclude_GH;
|
||||||
int nr_members;
|
int nr_members;
|
||||||
|
|
|
@ -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__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
|
||||||
hists__set_unres_dso_col_len(hists, HISTC_DSO_TO);
|
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) {
|
if (h->mem_info) {
|
||||||
|
@ -1042,6 +1049,8 @@ void hist_entry__delete(struct hist_entry *he)
|
||||||
if (he->branch_info) {
|
if (he->branch_info) {
|
||||||
map__zput(he->branch_info->from.map);
|
map__zput(he->branch_info->from.map);
|
||||||
map__zput(he->branch_info->to.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);
|
zfree(&he->branch_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,8 @@ enum hist_column {
|
||||||
HISTC_MEM_IADDR_SYMBOL,
|
HISTC_MEM_IADDR_SYMBOL,
|
||||||
HISTC_TRANSACTION,
|
HISTC_TRANSACTION,
|
||||||
HISTC_CYCLES,
|
HISTC_CYCLES,
|
||||||
|
HISTC_SRCLINE_FROM,
|
||||||
|
HISTC_SRCLINE_TO,
|
||||||
HISTC_TRACE,
|
HISTC_TRACE,
|
||||||
HISTC_NR_COLS, /* Last entry */
|
HISTC_NR_COLS, /* Last entry */
|
||||||
};
|
};
|
||||||
|
|
|
@ -353,6 +353,88 @@ struct sort_entry sort_srcline = {
|
||||||
.se_width_idx = HISTC_SRCLINE,
|
.se_width_idx = HISTC_SRCLINE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* --sort srcline_from */
|
||||||
|
|
||||||
|
static int64_t
|
||||||
|
sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||||
|
{
|
||||||
|
if (!left->branch_info->srcline_from) {
|
||||||
|
struct map *map = left->branch_info->from.map;
|
||||||
|
if (!map)
|
||||||
|
left->branch_info->srcline_from = SRCLINE_UNKNOWN;
|
||||||
|
else
|
||||||
|
left->branch_info->srcline_from = get_srcline(map->dso,
|
||||||
|
map__rip_2objdump(map,
|
||||||
|
left->branch_info->from.al_addr),
|
||||||
|
left->branch_info->from.sym, true);
|
||||||
|
}
|
||||||
|
if (!right->branch_info->srcline_from) {
|
||||||
|
struct map *map = right->branch_info->from.map;
|
||||||
|
if (!map)
|
||||||
|
right->branch_info->srcline_from = SRCLINE_UNKNOWN;
|
||||||
|
else
|
||||||
|
right->branch_info->srcline_from = get_srcline(map->dso,
|
||||||
|
map__rip_2objdump(map,
|
||||||
|
right->branch_info->from.al_addr),
|
||||||
|
right->branch_info->from.sym, true);
|
||||||
|
}
|
||||||
|
return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hist_entry__srcline_from_snprintf(struct hist_entry *he, char *bf,
|
||||||
|
size_t size, unsigned int width)
|
||||||
|
{
|
||||||
|
return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_from);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sort_entry sort_srcline_from = {
|
||||||
|
.se_header = "From Source:Line",
|
||||||
|
.se_cmp = sort__srcline_from_cmp,
|
||||||
|
.se_snprintf = hist_entry__srcline_from_snprintf,
|
||||||
|
.se_width_idx = HISTC_SRCLINE_FROM,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* --sort srcline_to */
|
||||||
|
|
||||||
|
static int64_t
|
||||||
|
sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||||
|
{
|
||||||
|
if (!left->branch_info->srcline_to) {
|
||||||
|
struct map *map = left->branch_info->to.map;
|
||||||
|
if (!map)
|
||||||
|
left->branch_info->srcline_to = SRCLINE_UNKNOWN;
|
||||||
|
else
|
||||||
|
left->branch_info->srcline_to = get_srcline(map->dso,
|
||||||
|
map__rip_2objdump(map,
|
||||||
|
left->branch_info->to.al_addr),
|
||||||
|
left->branch_info->from.sym, true);
|
||||||
|
}
|
||||||
|
if (!right->branch_info->srcline_to) {
|
||||||
|
struct map *map = right->branch_info->to.map;
|
||||||
|
if (!map)
|
||||||
|
right->branch_info->srcline_to = SRCLINE_UNKNOWN;
|
||||||
|
else
|
||||||
|
right->branch_info->srcline_to = get_srcline(map->dso,
|
||||||
|
map__rip_2objdump(map,
|
||||||
|
right->branch_info->to.al_addr),
|
||||||
|
right->branch_info->to.sym, true);
|
||||||
|
}
|
||||||
|
return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hist_entry__srcline_to_snprintf(struct hist_entry *he, char *bf,
|
||||||
|
size_t size, unsigned int width)
|
||||||
|
{
|
||||||
|
return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_to);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sort_entry sort_srcline_to = {
|
||||||
|
.se_header = "To Source:Line",
|
||||||
|
.se_cmp = sort__srcline_to_cmp,
|
||||||
|
.se_snprintf = hist_entry__srcline_to_snprintf,
|
||||||
|
.se_width_idx = HISTC_SRCLINE_TO,
|
||||||
|
};
|
||||||
|
|
||||||
/* --sort srcfile */
|
/* --sort srcfile */
|
||||||
|
|
||||||
static char no_srcfile[1];
|
static char no_srcfile[1];
|
||||||
|
@ -1347,6 +1429,8 @@ static struct sort_dimension bstack_sort_dimensions[] = {
|
||||||
DIM(SORT_IN_TX, "in_tx", sort_in_tx),
|
DIM(SORT_IN_TX, "in_tx", sort_in_tx),
|
||||||
DIM(SORT_ABORT, "abort", sort_abort),
|
DIM(SORT_ABORT, "abort", sort_abort),
|
||||||
DIM(SORT_CYCLES, "cycles", sort_cycles),
|
DIM(SORT_CYCLES, "cycles", sort_cycles),
|
||||||
|
DIM(SORT_SRCLINE_FROM, "srcline_from", sort_srcline_from),
|
||||||
|
DIM(SORT_SRCLINE_TO, "srcline_to", sort_srcline_to),
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef DIM
|
#undef DIM
|
||||||
|
|
|
@ -215,6 +215,8 @@ enum sort_type {
|
||||||
SORT_ABORT,
|
SORT_ABORT,
|
||||||
SORT_IN_TX,
|
SORT_IN_TX,
|
||||||
SORT_CYCLES,
|
SORT_CYCLES,
|
||||||
|
SORT_SRCLINE_FROM,
|
||||||
|
SORT_SRCLINE_TO,
|
||||||
|
|
||||||
/* memory mode specific sort keys */
|
/* memory mode specific sort keys */
|
||||||
__SORT_MEMORY_MODE,
|
__SORT_MEMORY_MODE,
|
||||||
|
|
|
@ -186,6 +186,8 @@ struct branch_info {
|
||||||
struct addr_map_symbol from;
|
struct addr_map_symbol from;
|
||||||
struct addr_map_symbol to;
|
struct addr_map_symbol to;
|
||||||
struct branch_flags flags;
|
struct branch_flags flags;
|
||||||
|
char *srcline_from;
|
||||||
|
char *srcline_to;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mem_info {
|
struct mem_info {
|
||||||
|
|
Loading…
Reference in New Issue