Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c9f790f authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge tag 'perf-core-for-mingo-20160523' of...

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 408cf677 3a62a7b8
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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.
+71 −10
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <unistd.h>
#include <sched.h>
#include <sys/mman.h>
#include <asm/bug.h>


struct record {
@@ -82,27 +83,87 @@ 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];
	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 (rb_find_range(rec->evlist, data, md->mask, head,
			  old, &start, &end))
		return -1;

	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");

		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];
		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;
@@ -110,16 +171,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;
+95 −153
Original line number Diff line number Diff line
@@ -576,84 +576,54 @@ 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	    = "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	    = "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 = { [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 */ }, },
	{ .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 */ }, },
	{ .name	    = "fchown",	    .errmsg = true,
	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
	  .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 = { [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 */ }, },
	{ .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_FLOCK, /* cmd */ }, },
	{ .name	    = "fsetxattr",  .errmsg = true, },
	{ .name	    = "fstat",	    .errmsg = true, .alias = "newfstat", },
	{ .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 */ }, },
	{ .name	    = "getdents",   .errmsg = true,
	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
	{ .name	    = "getdents64", .errmsg = true,
	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
	  .arg_scnprintf = { [0] = SCA_FDAT, /* 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, },
@@ -661,12 +631,10 @@ 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 = { [0] = SCA_FD, /* fd */
	  .arg_scnprintf = {
#if defined(__i386__) || defined(__x86_64__)
/*
 * 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	    = "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 = { [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 */ }, },
	{ .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,
@@ -722,8 +677,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 */ }, },
@@ -740,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 */
@@ -760,39 +711,26 @@ 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	    = "readlink",   .errmsg = true,
	  .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
	{ .name	    = "pwrite",	    .errmsg = true, .alias = "pwrite64", },
	{ .name	    = "pwritev",    .errmsg = true, },
	{ .name	    = "read",	    .errmsg = true, },
	{ .name	    = "readlink",   .errmsg = true, },
	{ .name	    = "readlinkat", .errmsg = true,
	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
			     [1] = SCA_FILENAME, /* pathname */ }, },
	{ .name	    = "readv",	    .errmsg = true,
	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
	{ .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 */ }, },
	{ .name	    = "removexattr", .errmsg = true,
	  .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
	  .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
	{ .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), },
@@ -807,22 +745,17 @@ 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	    = "setxattr",   .errmsg = true, },
	{ .name	    = "shutdown",   .errmsg = true, },
	{ .name	    = "socket",	    .errmsg = true,
	  .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
			     [1] = SCA_SK_TYPE, /* type */ },
@@ -831,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,
@@ -845,29 +776,21 @@ 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 */ }, },
	{ .name	    = "vmsplice",  .errmsg = true,
	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
	  .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 */ }, },
	{ .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 +1127,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)
@@ -1216,12 +1139,31 @@ 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)
			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;
	}

+34 −0
Original line number Diff line number Diff line
@@ -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)
@@ -679,6 +680,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,
@@ -881,6 +909,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 +930,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 +974,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))
+4 −0
Original line number Diff line number Diff line
@@ -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;
@@ -43,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;
@@ -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);

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);

Loading