Skip to contentSkip to conversation

perf/core improvements and fixes

GIT PULL New Arnaldo Carvalho de Melo 3 participants 38 messages May 8, 2015 – May 18, 2015

Subsystems (2)
lore
Share & tools
lore

Arnaldo Carvalho de Melo

author maintainer
#0 lore raw

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit cb307113746b4d184155d2c412e8069aeaa60d42:

perf_event: Don't allow vmalloc() backed perf on powerpc (2015-05-08 12:26:01 +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

for you to fetch changes up to 76d408498b08447e0f61dfdd611aeb6e8e61ce80:

perf build: Disable libdw DWARF unwind when built with NO_DWARF (2015-05-08 16:43:14 -0300)

----------------------------------------------------------------
perf/core improvements and fixes:

User visible:

- 'perf probe' improvements (Masami Hiramatsu)

- Support glob wildcards for function name
- Support $params special probe argument: Collect all function arguments
- Make --line checks validate C-style function name.
- Add --no-inlines option to avoid searching inline functions

- Introduce new 'perf bench futex' benchmark: 'wake-parallel', to measure parallel waker threads generating contention for kerne locks (hb->lock) (Davidlohr Bueso)

Bug fixes:

- 'perf top' survives much longer on high core count machines, more work needed to refcount more data structures besides 'struct thread' and fix more races (Arnaldo Carvalho de Melo)

Infrastructure:

- Move barrier.h mb/rmb/wmb API from tools/perf/ to kernel like tools/arch/ hierarchy (Arnaldo Carvalho de Melo)

- Borrow atomic.h from the kernel, initially the x86 implementations with a fallback to gcc intrinsics for the other arches, all the kernel like framework in place for doing arch specific implementations, preferrably cloning what is in the kernel to the greater extent possible (Arnaldo Carvalho de Melo)

- Protect the 'struct thread' lifetime with a reference counter, and protect data structures that contains its instances with a mutex (Arnaldo Carvalho de Melo

- Disable libdw DWARF unwind when built with NO_DWARF (Naveen N. Rao)

----------------------------------------------------------------
Arnaldo Carvalho de Melo (17):
perf tools: Move x86 barrier.h stuff to tools/arch/x86/include/asm/barrier.h perf tools: Move powerpc barrier.h stuff to tools/arch/powerpc/include/asm/barrier.h perf tools: Move s390 barrier.h stuff to tools/arch/s390/include/asm/barrier.h perf tools: Move barrier() definition to tools/include/linux/compiler.h
tools: Adopt asm-generic/barrier.h
perf tools: Move sh barrier.h stuff to tools/arch/sh/include/asm/barrier.h perf tools: Move sparc barrier.h stuff to tools/arch/sparc/include/asm/barrier.h perf tools: Move alpha barrier.h stuff to tools/arch/alpha/include/asm/barrier.h perf tools: Move ia64 barrier.h stuff to tools/arch/ia64/include/asm/barrier.h perf tools: Move arm(64) barrier.h stuff to tools/arch/arm*/include/asm/barrier.h perf tools: Move xtensa barrier.h stuff to tools/arch/xtensa/include/asm/barrier.h perf tools: Move mips barrier.h stuff to tools/arch/mips/include/asm/barrier.h perf tools: Move tile barrier.h stuff to tools/arch/tile/include/asm/barrier.h perf tools: Move generic barriers out of perf-sys.h
tools include: Add basic atomic.h implementation from the kernel sources perf tools: Use atomic_t to implement thread__{get,put} refcnt
perf machine: Protect the machine->threads with a rwlock

Davidlohr Bueso (2):
perf bench futex: Support parallel waker threads perf bench futex: Handle spurious wakeups

Masami Hiramatsu (10):
perf probe: Fix to close probe_events file in error
perf probe: Fix a typo for the flags of open
perf probe: Fix to return 0 when positive value returned perf probe: Make --line checks validate C-style function name perf probe: Skip kernel symbols which is out of .text
perf probe: Support $params special probe argument
perf probe: Use perf_probe_event.target instead of passing as an argument perf probe: Introduce probe_conf global configs
perf probe: Add --no-inlines option to avoid searching inline functions perf probe: Support glob wildcards for function name

Naveen N. Rao (1):
perf build: Disable libdw DWARF unwind when built with NO_DWARF

 tools/arch/alpha/include/asm/barrier.h    |   8 +
 tools/arch/arm/include/asm/barrier.h      |  12 ++
 tools/arch/arm64/include/asm/barrier.h    |  16 ++
 tools/arch/ia64/include/asm/barrier.h     |  48 +++++
 tools/arch/mips/include/asm/barrier.h     |  20 ++
 tools/arch/powerpc/include/asm/barrier.h  |  29 +++
 tools/arch/s390/include/asm/barrier.h     |  30 +++
 tools/arch/sh/include/asm/barrier.h       |  32 ++++
 tools/arch/sparc/include/asm/barrier.h    |   8 +
 tools/arch/sparc/include/asm/barrier_32.h |   6 +
 tools/arch/sparc/include/asm/barrier_64.h |  42 +++++
 tools/arch/tile/include/asm/barrier.h     |  15 ++
 tools/arch/x86/include/asm/atomic.h       |  65 +++++++
 tools/arch/x86/include/asm/barrier.h      |  28 +++
 tools/arch/x86/include/asm/rmwcc.h        |  41 +++++
 tools/arch/xtensa/include/asm/barrier.h   |  18 ++
 tools/include/asm-generic/atomic-gcc.h    |  63 +++++++
 tools/include/asm-generic/barrier.h       |  44 +++++
 tools/include/asm/atomic.h                |  10 +
 tools/include/asm/barrier.h               |  27 +++
 tools/include/linux/atomic.h              |   6 +
 tools/include/linux/compiler.h            |   4 +
 tools/include/linux/types.h               |   4 +
 tools/perf/Documentation/perf-bench.txt   |   3 +
 tools/perf/Documentation/perf-probe.txt   |   6 +-
 tools/perf/MANIFEST                       |  19 ++
 tools/perf/bench/Build                    |   1 +
 tools/perf/bench/bench.h                  |   2 +
 tools/perf/bench/futex-wake-parallel.c    | 294 ++++++++++++++++++++++++++++++
 tools/perf/bench/futex-wake.c             |   7 +-
 tools/perf/builtin-annotate.c             |  10 +-
 tools/perf/builtin-bench.c                |   1 +
 tools/perf/builtin-diff.c                 |   9 +-
 tools/perf/builtin-inject.c               |   1 +
 tools/perf/builtin-kmem.c                 |   7 +-
 tools/perf/builtin-kvm.c                  |   6 +-
 tools/perf/builtin-lock.c                 |   8 +-
 tools/perf/builtin-mem.c                  |   5 +-
 tools/perf/builtin-probe.c                |  26 +--
 tools/perf/builtin-report.c               |   9 +-
 tools/perf/builtin-sched.c                |  82 ++++++---
 tools/perf/builtin-script.c               |  20 +-
 tools/perf/builtin-timechart.c            |   5 +-
 tools/perf/builtin-top.c                  |   2 +-
 tools/perf/builtin-trace.c                |  36 ++--
 tools/perf/config/Makefile                |   4 +
 tools/perf/perf-sys.h                     |  73 +-------
 tools/perf/tests/code-reading.c           |  22 ++-
 tools/perf/tests/dwarf-unwind.c           |   1 +
 tools/perf/tests/hists_common.c           |   1 +
 tools/perf/tests/hists_cumulate.c         |   4 +-
 tools/perf/tests/hists_filter.c           |   4 +-
 tools/perf/tests/hists_link.c             |   8 +-
 tools/perf/tests/hists_output.c           |   4 +-
 tools/perf/tests/mmap-thread-lookup.c     |   2 +
 tools/perf/tests/thread-mg-share.c        |  12 +-
 tools/perf/util/build-id.c                |   5 +-
 tools/perf/util/db-export.c               |  14 +-
 tools/perf/util/dwarf-aux.c               |  16 ++
 tools/perf/util/dwarf-aux.h               |   3 +
 tools/perf/util/event.c                   |  15 ++
 tools/perf/util/event.h                   |   2 +
 tools/perf/util/machine.c                 |  89 +++++++--
 tools/perf/util/machine.h                 |   5 +-
 tools/perf/util/probe-event.c             | 177 ++++++++++--------
 tools/perf/util/probe-event.h             |  15 +-
 tools/perf/util/probe-finder.c            |  73 +++++---
 tools/perf/util/probe-finder.h            |  10 +-
 tools/perf/util/thread.c                  |  14 +-
 tools/perf/util/thread.h                  |   3 +-
 tools/perf/util/util.h                    |   4 +
 71 files changed, 1392 insertions(+), 323 deletions(-)
 create mode 100644 tools/arch/alpha/include/asm/barrier.h
 create mode 100644 tools/arch/arm/include/asm/barrier.h
 create mode 100644 tools/arch/arm64/include/asm/barrier.h
 create mode 100644 tools/arch/ia64/include/asm/barrier.h
 create mode 100644 tools/arch/mips/include/asm/barrier.h
 create mode 100644 tools/arch/powerpc/include/asm/barrier.h
 create mode 100644 tools/arch/s390/include/asm/barrier.h
 create mode 100644 tools/arch/sh/include/asm/barrier.h
 create mode 100644 tools/arch/sparc/include/asm/barrier.h
 create mode 100644 tools/arch/sparc/include/asm/barrier_32.h
 create mode 100644 tools/arch/sparc/include/asm/barrier_64.h
 create mode 100644 tools/arch/tile/include/asm/barrier.h
 create mode 100644 tools/arch/x86/include/asm/atomic.h
 create mode 100644 tools/arch/x86/include/asm/barrier.h
 create mode 100644 tools/arch/x86/include/asm/rmwcc.h
 create mode 100644 tools/arch/xtensa/include/asm/barrier.h
 create mode 100644 tools/include/asm-generic/atomic-gcc.h
 create mode 100644 tools/include/asm-generic/barrier.h
 create mode 100644 tools/include/asm/atomic.h
 create mode 100644 tools/include/asm/barrier.h
 create mode 100644 tools/include/linux/atomic.h
 create mode 100644 tools/perf/bench/futex-wake-parallel.c
author maintainer
#1 lore raw

PATCH 1/30 perf probe: Fix to close probe_events file in error

From: Masami Hiramatsu <[email protected]>

Fix perf-probe to close probe_events file if it failed to get existing probe's name. This also fix the return error code to -ENOMEM.

---
 tools/perf/util/probe-event.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/util/probe-event.c +3 -1
index abf5845..230353f 100644
@@ -2384,7 +2384,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 	namelist = get_probe_trace_event_names(fd, false);
 	if (!namelist) {
 		pr_debug("Failed to get current event list.\n");
-		return -EIO;
+		ret = -ENOMEM;
+		goto close_out;
 	}
 	/* Get kprobe blacklist if exists */
 	if (!pev->uprobes) {
@@ -2467,6 +2468,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 
 	kprobe_blacklist__delete(&blacklist);
 	strlist__delete(namelist);
+close_out:
 	close(fd);
 	return ret;
 }
Signature · 1 line
2.1.0
author maintainer
#2 lore raw

PATCH 2/30 perf probe: Fix a typo for the flags of open

In reply to Arnaldo Carvalho de Melo

From: Masami Hiramatsu <[email protected]>

Fix to pass O_APPEND by using bit-or with other flags, instead of passing it as mode.

---
 tools/perf/util/probe-event.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/probe-event.c +1 -1
index 230353f..63cb7c5 100644
@@ -1969,7 +1969,7 @@ static int open_probe_events(const char *trace_file, bool readwrite)
 	if (ret >= 0) {
 		pr_debug("Opening %s write=%d\n", buf, readwrite);
 		if (readwrite && !probe_event_dry_run)
-			ret = open(buf, O_RDWR, O_APPEND);
+			ret = open(buf, O_RDWR | O_APPEND, 0);
 		else
 			ret = open(buf, O_RDONLY, 0);
 
Signature · 1 line
2.1.0
author maintainer
#3 lore raw

PATCH 3/30 perf probe: Fix to return 0 when positive value returned

In reply to Arnaldo Carvalho de Melo

From: Masami Hiramatsu <[email protected]>

Fix to return 0 when positive value returned from probe command.

At least --vars can returns a positive value if it found a point.
----

  # perf probe --vars vfs_read && echo succeeded! || echo failed!
  Available variables at vfs_read
          @<vfs_read+0>
                  char*   buf
                  loff_t* pos
                  size_t  count
                  struct file*    file
  failed!
  ----

This fixes above problem.
----

  # perf probe --vars vfs_read && echo succeeded! || echo failed!
  Available variables at vfs_read
          @<vfs_read+0>
                  char*   buf
                  loff_t* pos
                  size_t  count
                  struct file*    file
  succeeded!
  ----
---
 tools/perf/builtin-probe.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/builtin-probe.c +1 -1
index 53d475b..9c4cf5e 100644
@@ -523,5 +523,5 @@ int cmd_probe(int argc, const char **argv, const char *prefix)
 		cleanup_params();
 	}
 
-	return ret;
+	return ret < 0 ? ret : 0;
 }
Signature · 1 line
2.1.0
author maintainer
#4 lore raw

PATCH 4/30 perf probe: Make --line checks validate C-style function name

In reply to Arnaldo Carvalho de Melo

From: Masami Hiramatsu <[email protected]>

Fix --line to check valid C-style function name and returns a semantic error if it is not.

For example, previously, --line doesn't support lazy pattern but it doesn't recognized as a semantic error.

----

  # perf probe -L 'func;return*:0-10'
  Specified source line is not found.
    Error: Failed to show lines.
  ----

With this patch, it is correctly handled as a semantic error.
----

  # perf probe -L 'func;return*:0-10'
  Semantic error :'func;return*' is not a valid function name.
  ...
  ----
---
 tools/perf/util/probe-event.c | 35 ++++++++++++++++++++---------------
 1 file changed, 20 insertions(+), 15 deletions(-)
tools/perf/util/probe-event.c +20 -15
index 63cb7c5..4265f2e 100644
@@ -980,6 +980,18 @@ static int parse_line_num(char **ptr, int *val, const char *what)
 	return 0;
 }
 
+/* Check the name is good for event, group or function */
+static bool is_c_func_name(const char *name)
+{
+	if (!isalpha(*name) && *name != '_')
+		return false;
+	while (*++name != '\0') {
+		if (!isalpha(*name) && !isdigit(*name) && *name != '_')
+			return false;
+	}
+	return true;
+}
+
 /*
  * Stuff 'lr' according to the line range described by 'arg'.
  * The line range syntax is described by:
@@ -1048,10 +1060,15 @@ int parse_line_range_desc(const char *arg, struct line_range *lr)
 			goto err;
 		}
 		lr->function = name;
-	} else if (strchr(name, '.'))
+	} else if (strchr(name, '/') || strchr(name, '.'))
 		lr->file = name;
-	else
+	else if (is_c_func_name(name))/* We reuse it for checking funcname */
 		lr->function = name;
+	else {	/* Invalid name */
+		semantic_error("'%s' is not a valid function name.\n", name);
+		err = -EINVAL;
+		goto err;
+	}
 
 	return 0;
 err:
@@ -1059,18 +1076,6 @@ err:
 	return err;
 }
 
-/* Check the name is good for event/group */
-static bool check_event_name(const char *name)
-{
-	if (!isalpha(*name) && *name != '_')
-		return false;
-	while (*++name != '\0') {
-		if (!isalpha(*name) && !isdigit(*name) && *name != '_')
-			return false;
-	}
-	return true;
-}
-
 /* Parse probepoint definition. */
 static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 {
@@ -1094,7 +1099,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 			semantic_error("Group name is not supported yet.\n");
 			return -ENOTSUP;
 		}
-		if (!check_event_name(arg)) {
+		if (!is_c_func_name(arg)) {
 			semantic_error("%s is bad for event name -it must "
 				       "follow C symbol-naming rule.\n", arg);
 			return -EINVAL;
Signature · 1 line
2.1.0
author maintainer
#5 lore raw

PATCH 5/30 perf probe: Skip kernel symbols which is out of .text

In reply to Arnaldo Carvalho de Melo

From: Masami Hiramatsu <[email protected]>

Skip the kernel symbols which is out of .text, e.g. the functions in .inittext. Those are found in debuginfo/kallsyms, but already freed from memory.

e.g.
----

  # perf probe vfs_caches_init
  vfs_caches_init+0 is out of .text, skip it.
  Probe point 'vfs_caches_init' not found.
    Error: Failed to add events.
  ----
---
 tools/perf/util/probe-event.c | 31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)
tools/perf/util/probe-event.c +24 -7
index 4265f2e..37a3a8b 100644
@@ -557,8 +557,9 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
 					   bool uprobe)
 {
 	struct ref_reloc_sym *reloc_sym;
+	u64 etext_addr;
 	char *tmp;
-	int i;
+	int i, skipped = 0;
 
 	if (uprobe)
 		return add_exec_to_probe_trace_events(tevs, ntevs, module);
@@ -572,19 +573,29 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
 		pr_warning("Relocated base symbol is not found!\n");
 		return -EINVAL;
 	}
+	/* Get the address of _etext for checking non-probable text symbol */
+	etext_addr = kernel_get_symbol_address_by_name("_etext", false);
 
 	for (i = 0; i < ntevs; i++) {
 		if (tevs[i].point.address && !tevs[i].point.retprobe) {
-			tmp = strdup(reloc_sym->name);
-			if (!tmp)
-				return -ENOMEM;
+			/* If we found a wrong one, mark it by NULL symbol */
+			if (etext_addr < tevs[i].point.address) {
+				pr_warning("%s+%lu is out of .text, skip it.\n",
+				   tevs[i].point.symbol, tevs[i].point.offset);
+				tmp = NULL;
+				skipped++;
+			} else {
+				tmp = strdup(reloc_sym->name);
+				if (!tmp)
+					return -ENOMEM;
+			}
 			free(tevs[i].point.symbol);
 			tevs[i].point.symbol = tmp;
 			tevs[i].point.offset = tevs[i].point.address -
 					       reloc_sym->unrelocated_addr;
 		}
 	}
-	return 0;
+	return skipped;
 }
 
 /* Try to find perf_probe_event with debuginfo */
@@ -630,11 +641,14 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
 		pr_debug("Found %d probe_trace_events.\n", ntevs);
 		ret = post_process_probe_trace_events(*tevs, ntevs,
 							target, pev->uprobes);
-		if (ret < 0) {
+		if (ret < 0 || ret == ntevs) {
 			clear_probe_trace_events(*tevs, ntevs);
 			zfree(tevs);
 		}
-		return ret < 0 ? ret : ntevs;
+		if (ret != ntevs)
+			return ret < 0 ? ret : ntevs;
+		ntevs = 0;
+		/* Fall through */
 	}
 
 	if (ntevs == 0)	{	/* No error but failed to find probe point. */
@@ -2403,6 +2417,9 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 	pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
 	for (i = 0; i < ntevs; i++) {
 		tev = &tevs[i];
+		/* Skip if the symbol is out of .text (marked previously) */
+		if (!tev->point.symbol)
+			continue;
 		/* Ensure that the address is NOT blacklisted */
 		node = kprobe_blacklist__find_by_address(&blacklist,
 							 tev->point.address);
Signature · 1 line
2.1.0
author maintainer
#6 lore raw

PATCH 6/30 perf probe: Support $params special probe argument

In reply to Arnaldo Carvalho de Melo

From: Masami Hiramatsu <[email protected]>

$params is similar to $vars but matches only function parameters not local variables.

Thus, this is useful for tracing function parameter changing or tracing function call with parameters.

Testing it:

 # perf probe tcp_sendmsg '$params'
 Added new event:
  probe:tcp_sendmsg    (on tcp_sendmsg with $params)

You can now use it in all perf tools, such as:

perf record -e probe:tcp_sendmsg -aR sleep 1

 # perf probe -l
  probe:tcp_sendmsg    (on tcp_sendmsg@acme/git/linux/net/ipv4/tcp.c with iocb sk msg size)
 # perf record -a -e probe:*
 press some random letters to generate TCP (sshd) traffic...

^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.223 MB perf.data (6 samples) ]

 # perf script
   sshd 6385 [2] 3.907529: probe:tcp_sendmsg: iocb=0xffff8800ac4cfe70 sk=0xffff88042196c140 msg=0xffff8800ac4cfda8 size=0x24
   sshd 6385 [2] 4.138973: probe:tcp_sendmsg: iocb=0xffff8800ac4cfe70 sk=0xffff88042196c140 msg=0xffff8800ac4cfda8 size=0x24
   sshd 6385 [2] 4.378966: probe:tcp_sendmsg: iocb=0xffff8800ac4cfe70 sk=0xffff88042196c140 msg=0xffff8800ac4cfda8 size=0x24
   sshd 6385 [2] 4.603681: probe:tcp_sendmsg: iocb=0xffff8800ac4cfe70 sk=0xffff88042196c140 msg=0xffff8800ac4cfda8 size=0x24
   sshd 6385 [2] 4.818455: probe:tcp_sendmsg: iocb=0xffff8800ac4cfe70 sk=0xffff88042196c140 msg=0xffff8800ac4cfda8 size=0x24
   sshd 6385 [2] 5.043603: probe:tcp_sendmsg: iocb=0xffff8800ac4cfe70 sk=0xffff88042196c140 msg=0xffff8800ac4cfda8 size=0x24
 # cat /sys/kernel/debug/tracing/events/probe/tcp_sendmsg/format
 name: tcp_sendmsg
 ID: 1927
 format:
   field:unsigned short common_type;	offset:0;	size:2;	signed:0;
   field:unsigned char common_flags;	offset:2;	size:1;	signed:0;
   field:unsigned char common_preempt_count;	offset:3;	size:1;	signed:0;
   field:int common_pid;	offset:4;	size:4;	signed:1;

field:unsigned long __probe_ip; offset:8; size:8; signed:0;
field:u64 iocb; offset:16; size:8; signed:0;
field:u64 sk; offset:24; size:8; signed:0;
field:u64 msg; offset:32; size:8; signed:0;
field:u64 size; offset:40; size:8; signed:0;

print fmt: "(%lx) iocb=0x%Lx sk=0x%Lx msg=0x%Lx size=0x%Lx", REC->__probe_ip, REC->iocb, REC->sk, REC->msg, REC->size #

Do some system wide tracing of this probe + write syscalls:

 # perf trace -e write --ev probe:* --filter-pids 6385
  462.612 (0.010 ms): bash/19153 write(fd: 1</dev/pts/1>, buf: 0x7f7556c78000, count: 29               ) = 29
  462.701 (0.027 ms): sshd/19152 write(fd: 3<socket:[63117]>, buf: 0x7f78dd12e160, count: 68           ) ...
  462.701 (        ): probe:tcp_sendmsg:(ffffffff8163db30) iocb=0xffff8803ebec7e70 sk=0xffff88042196ab80 msg=0xffff8803ebec7da8 size=0x44)
  462.710 (0.035 ms): sshd/19152  ... [continued]: write()) = 68
  462.787 (0.009 ms): bash/19153 write(fd: 2</dev/pts/1>, buf: 0x7f7556c77000, count: 22               ) = 22
  462.865 (0.002 ms): sshd/19152 write(fd: 3<socket:[63117]>, buf: 0x7f78dd12e160, count: 68           ) ...
  462.865 (        ): probe:tcp_sendmsg:(ffffffff8163db30) iocb=0xffff8803ebec7e70 sk=0xffff88042196ab80 msg=0xffff8803ebec7da8 size=0x44)
  462.873 (0.010 ms): sshd/19152  ... [continued]: write()) = 68
Cc Ananth N Mavinakayanahalli <[email protected]>
Cc David Ahern <[email protected]>
Cc Hemant Kumar <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Peter Zijlstra <[email protected]>
[ Add some examples to the changelog message showing how to use it ]
---
 tools/perf/Documentation/perf-probe.txt |  2 +-
 tools/perf/util/probe-finder.c          | 29 ++++++++++++++++-------------
 tools/perf/util/probe-finder.h          |  3 +++
 3 files changed, 20 insertions(+), 14 deletions(-)
tools/perf/Documentation/perf-probe.txt +1 -1
index a272f2e..ad3e355 100644
@@ -151,7 +151,7 @@ Each probe argument follows below syntax.
  [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE]
 
 'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
-'$vars' special argument is also available for NAME, it is expanded to the local variables which can access at given probe point.
+'$vars' and '$params' special arguments are also available for NAME, '$vars' is expanded to the local variables (including function parameters) which can access at given probe point. '$params' is expanded to only the function parameters.
 'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type.
 
 On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid.
tools/perf/util/probe-finder.c +16 -13
index b5bf9d5..63d3389 100644
@@ -1087,6 +1087,7 @@ found:
 struct local_vars_finder {
 	struct probe_finder *pf;
 	struct perf_probe_arg *args;
+	bool vars;
 	int max_args;
 	int nargs;
 	int ret;
@@ -1101,7 +1102,7 @@ static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
 
 	tag = dwarf_tag(die_mem);
 	if (tag == DW_TAG_formal_parameter ||
-	    tag == DW_TAG_variable) {
+	    (tag == DW_TAG_variable && vf->vars)) {
 		if (convert_variable_location(die_mem, vf->pf->addr,
 					      vf->pf->fb_ops, &pf->sp_die,
 					      NULL) == 0) {
@@ -1127,26 +1128,28 @@ static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf,
 	Dwarf_Die die_mem;
 	int i;
 	int n = 0;
-	struct local_vars_finder vf = {.pf = pf, .args = args,
+	struct local_vars_finder vf = {.pf = pf, .args = args, .vars = false,
 				.max_args = MAX_PROBE_ARGS, .ret = 0};
 
 	for (i = 0; i < pf->pev->nargs; i++) {
 		/* var never be NULL */
-		if (strcmp(pf->pev->args[i].var, "$vars") == 0) {
-			pr_debug("Expanding $vars into:");
-			vf.nargs = n;
-			/* Special local variables */
-			die_find_child(sc_die, copy_variables_cb, (void *)&vf,
-				       &die_mem);
-			pr_debug(" (%d)\n", vf.nargs - n);
-			if (vf.ret < 0)
-				return vf.ret;
-			n = vf.nargs;
-		} else {
+		if (strcmp(pf->pev->args[i].var, PROBE_ARG_VARS) == 0)
+			vf.vars = true;
+		else if (strcmp(pf->pev->args[i].var, PROBE_ARG_PARAMS) != 0) {
 			/* Copy normal argument */
 			args[n] = pf->pev->args[i];
 			n++;
+			continue;
 		}
+		pr_debug("Expanding %s into:", pf->pev->args[i].var);
+		vf.nargs = n;
+		/* Special local variables */
+		die_find_child(sc_die, copy_variables_cb, (void *)&vf,
+			       &die_mem);
+		pr_debug(" (%d)\n", vf.nargs - n);
+		if (vf.ret < 0)
+			return vf.ret;
+		n = vf.nargs;
 	}
 	return n;
 }
tools/perf/util/probe-finder.h +3 -0
index ebf8c8c..f53553d 100644
@@ -10,6 +10,9 @@
 #define MAX_PROBES		 128
 #define MAX_PROBE_ARGS		 128
 
+#define PROBE_ARG_VARS		"$vars"
+#define PROBE_ARG_PARAMS	"$params"
+
 static inline int is_c_varname(const char *name)
 {
 	/* TODO */
Signature · 1 line
2.1.0
author maintainer
#7 lore raw

PATCH 7/30 perf tools: Move x86 barrier.h stuff to tools/arch/x86/include/asm/barrier.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We will need it for atomic.h, so move it from the ad-hoc tools/perf/ place to a tools/ subset of the kernel arch/ hierarchy.

Other aches will follow, each in a cset.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/arch/x86/include/asm/barrier.h | 28 ++++++++++++++++++++++++++++
 tools/include/asm/barrier.h          |  3 +++
 tools/perf/MANIFEST                  |  2 ++
 tools/perf/perf-sys.h                |  7 +------
 4 files changed, 34 insertions(+), 6 deletions(-)
 create mode 100644 tools/arch/x86/include/asm/barrier.h
 create mode 100644 tools/include/asm/barrier.h
tools/arch/x86/include/asm/barrier.h new file +28 -0
new file mode 100644
index 0000000..f366d8e
@@ -0,0 +1,28 @@
+#ifndef _TOOLS_LINUX_ASM_X86_BARRIER_H
+#define _TOOLS_LINUX_ASM_X86_BARRIER_H
+
+/*
+ * Copied from the Linux kernel sources, and also moving code
+ * out from tools/perf/perf-sys.h so as to make it be located
+ * in a place similar as in the kernel sources.
+ *
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ */
+
+#if defined(__i386__)
+/*
+ * Some non-Intel clones support out of order store. wmb() ceases to be a
+ * nop for these.
+ */
+#define mb()	asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
+#define rmb()	asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
+#define wmb()	asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
+#elif defined(__x86_64__)
+#define mb() 	asm volatile("mfence":::"memory")
+#define rmb()	asm volatile("lfence":::"memory")
+#define wmb()	asm volatile("sfence" ::: "memory")
+#endif
+
+#endif /* _TOOLS_LINUX_ASM_X86_BARRIER_H */
tools/include/asm/barrier.h new file +3 -0
new file mode 100644
index 0000000..9a55c12
@@ -0,0 +1,3 @@
+#if defined(__i386__) || defined(__x86_64__)
+#include "../../arch/x86/include/asm/barrier.h"
+#endif
tools/perf/MANIFEST +2 -0
index 11ccbb2..594737a 100644
@@ -1,4 +1,5 @@
 tools/perf
+tools/arch/x86/include/asm/barrier.h
 tools/scripts
 tools/build
 tools/lib/traceevent
@@ -6,6 +7,7 @@ tools/lib/api
 tools/lib/symbol/kallsyms.c
 tools/lib/symbol/kallsyms.h
 tools/lib/util/find_next_bit.c
+tools/include/asm/barrier.h
 tools/include/asm/bug.h
 tools/include/asm-generic/bitops/arch_hweight.h
 tools/include/asm-generic/bitops/atomic.h
tools/perf/perf-sys.h +1 -6
index 6ef6816..781d441 100644
@@ -6,11 +6,9 @@
 #include <sys/syscall.h>
 #include <linux/types.h>
 #include <linux/perf_event.h>
+#include <asm/barrier.h>
 
 #if defined(__i386__)
-#define mb()		asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
-#define wmb()		asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
-#define rmb()		asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
 #define cpu_relax()	asm volatile("rep; nop" ::: "memory");
 #define CPUINFO_PROC	{"model name"}
 #ifndef __NR_perf_event_open
@@ -25,9 +23,6 @@
 #endif
 
 #if defined(__x86_64__)
-#define mb()		asm volatile("mfence" ::: "memory")
-#define wmb()		asm volatile("sfence" ::: "memory")
-#define rmb()		asm volatile("lfence" ::: "memory")
 #define cpu_relax()	asm volatile("rep; nop" ::: "memory");
 #define CPUINFO_PROC	{"model name"}
 #ifndef __NR_perf_event_open
Signature · 1 line
2.1.0
author maintainer
#8 lore raw

PATCH 8/30 perf tools: Move powerpc barrier.h stuff to tools/arch/powerpc/include/asm/barrier.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We will need it for atomic.h, so move it from the ad-hoc tools/perf/ place to a tools/ subset of the kernel arch/ hierarchy.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/arch/powerpc/include/asm/barrier.h | 29 +++++++++++++++++++++++++++++
 tools/include/asm/barrier.h              |  2 ++
 tools/perf/MANIFEST                      |  1 +
 tools/perf/perf-sys.h                    |  3 ---
 4 files changed, 32 insertions(+), 3 deletions(-)
 create mode 100644 tools/arch/powerpc/include/asm/barrier.h
tools/arch/powerpc/include/asm/barrier.h new file +29 -0
new file mode 100644
index 0000000..b23aee8
@@ -0,0 +1,29 @@
+/*
+ * Copied from the kernel sources:
+ *
+ * Copyright (C) 1999 Cort Dougan <[email protected]>
+ */
+#ifndef _TOOLS_LINUX_ASM_POWERPC_BARRIER_H
+#define _TOOLS_LINUX_ASM_POWERPC_BARRIER_H
+
+/*
+ * Memory barrier.
+ * The sync instruction guarantees that all memory accesses initiated
+ * by this processor have been performed (with respect to all other
+ * mechanisms that access memory).  The eieio instruction is a barrier
+ * providing an ordering (separately) for (a) cacheable stores and (b)
+ * loads and stores to non-cacheable memory (e.g. I/O devices).
+ *
+ * mb() prevents loads and stores being reordered across this point.
+ * rmb() prevents loads being reordered across this point.
+ * wmb() prevents stores being reordered across this point.
+ *
+ * *mb() variants without smp_ prefix must order all types of memory
+ * operations with one another. sync is the only instruction sufficient
+ * to do this.
+ */
+#define mb()   __asm__ __volatile__ ("sync" : : : "memory")
+#define rmb()  __asm__ __volatile__ ("sync" : : : "memory")
+#define wmb()  __asm__ __volatile__ ("sync" : : : "memory")
+
+#endif /* _TOOLS_LINUX_ASM_POWERPC_BARRIER_H */
tools/include/asm/barrier.h +2 -0
index 9a55c12..249f672 100644
@@ -1,3 +1,5 @@
 #if defined(__i386__) || defined(__x86_64__)
 #include "../../arch/x86/include/asm/barrier.h"
+#elif defined(__powerpc__)
+#include "../../arch/powerpc/include/asm/barrier.h"
 #endif
tools/perf/MANIFEST +1 -0
index 594737a..4b3346e 100644
@@ -1,4 +1,5 @@
 tools/perf
+tools/arch/powerpc/include/asm/barrier.h
 tools/arch/x86/include/asm/barrier.h
 tools/scripts
 tools/build
tools/perf/perf-sys.h +0 -3
index 781d441..01c0695 100644
@@ -38,9 +38,6 @@
 
 #ifdef __powerpc__
 #include "../../arch/powerpc/include/uapi/asm/unistd.h"
-#define mb()		asm volatile ("sync" ::: "memory")
-#define wmb()		asm volatile ("sync" ::: "memory")
-#define rmb()		asm volatile ("sync" ::: "memory")
 #define CPUINFO_PROC	{"cpu"}
 #endif
 
Signature · 1 line
2.1.0
author maintainer
#9 lore raw

PATCH 9/30 perf tools: Move s390 barrier.h stuff to tools/arch/s390/include/asm/barrier.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We will need it for atomic.h, so move it from the ad-hoc tools/perf/ place to a tools/ subset of the kernel arch/ hierarchy.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/arch/s390/include/asm/barrier.h | 30 ++++++++++++++++++++++++++++++
 tools/include/asm/barrier.h           |  2 ++
 tools/perf/MANIFEST                   |  1 +
 tools/perf/perf-sys.h                 |  3 ---
 4 files changed, 33 insertions(+), 3 deletions(-)
 create mode 100644 tools/arch/s390/include/asm/barrier.h
tools/arch/s390/include/asm/barrier.h new file +30 -0
new file mode 100644
index 0000000..f851412
@@ -0,0 +1,30 @@
+/*
+ * Copied from the kernel sources:
+ *
+ * Copyright IBM Corp. 1999, 2009
+ *
+ * Author(s): Martin Schwidefsky <[email protected]>
+ */
+
+#ifndef __TOOLS_LINUX_ASM_BARRIER_H
+#define __TOOLS_LINUX_ASM_BARRIER_H
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ */
+
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+/* Fast-BCR without checkpoint synchronization */
+#define __ASM_BARRIER "bcr 14,0\n"
+#else
+#define __ASM_BARRIER "bcr 15,0\n"
+#endif
+
+#define mb() do {  asm volatile(__ASM_BARRIER : : : "memory"); } while (0)
+
+#define rmb()				mb()
+#define wmb()				mb()
+
+#endif /* __TOOLS_LIB_ASM_BARRIER_H */
tools/include/asm/barrier.h +2 -0
index 249f672..7eb8894 100644
@@ -2,4 +2,6 @@
 #include "../../arch/x86/include/asm/barrier.h"
 #elif defined(__powerpc__)
 #include "../../arch/powerpc/include/asm/barrier.h"
+#elif defined(__s390__)
+#include "../../arch/s390/include/asm/barrier.h"
 #endif
tools/perf/MANIFEST +1 -0
index 4b3346e..00754af 100644
@@ -1,5 +1,6 @@
 tools/perf
 tools/arch/powerpc/include/asm/barrier.h
+tools/arch/s390/include/asm/barrier.h
 tools/arch/x86/include/asm/barrier.h
 tools/scripts
 tools/build
tools/perf/perf-sys.h +0 -3
index 01c0695..bf349ea 100644
@@ -42,9 +42,6 @@
 #endif
 
 #ifdef __s390__
-#define mb()		asm volatile("bcr 15,0" ::: "memory")
-#define wmb()		asm volatile("bcr 15,0" ::: "memory")
-#define rmb()		asm volatile("bcr 15,0" ::: "memory")
 #define CPUINFO_PROC	{"vendor_id"}
 #endif
 
Signature · 1 line
2.1.0
author maintainer
#10 lore raw

PATCH 10/30 perf tools: Move barrier() definition to tools/include/linux/compiler.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

To make it generally accessible by other tools/ projects, also will be used in the tools/arch/*/include/asm/barrier.h files that are being introduced now.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/include/linux/compiler.h | 4 ++++
 tools/perf/perf-sys.h          | 2 --
 2 files changed, 4 insertions(+), 2 deletions(-)
tools/include/linux/compiler.h +4 -0
index 88461f0..f0e7267 100644
@@ -1,6 +1,10 @@
 #ifndef _TOOLS_LINUX_COMPILER_H_
 #define _TOOLS_LINUX_COMPILER_H_
 
+/* Optimization barrier */
+/* The "volatile" is due to gcc bugs */
+#define barrier() __asm__ __volatile__("": : :"memory")
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
tools/perf/perf-sys.h +0 -2
index bf349ea..f44e53e 100644
@@ -153,8 +153,6 @@
 #define CPUINFO_PROC    {"model name"}
 #endif
 
-#define barrier() asm volatile ("" ::: "memory")
-
 #ifndef cpu_relax
 #define cpu_relax() barrier()
 #endif
Signature · 1 line
2.1.0
author maintainer
#11 lore raw

PATCH 11/30 tools: Adopt asm-generic/barrier.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

Quoted 1 line

From the kernel's include/asm-generic/barrier.h, will be used by the

sh barrier.h implementation.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/include/asm-generic/barrier.h | 44 +++++++++++++++++++++++++++++++++++++
 tools/perf/MANIFEST                 |  1 +
 2 files changed, 45 insertions(+)
 create mode 100644 tools/include/asm-generic/barrier.h
tools/include/asm-generic/barrier.h new file +44 -0
new file mode 100644
index 0000000..47b9339
@@ -0,0 +1,44 @@
+/*
+ * Copied from the kernel sources to tools/perf/:
+ *
+ * Generic barrier definitions, originally based on MN10300 definitions.
+ *
+ * It should be possible to use these on really simple architectures,
+ * but it serves more as a starting point for new ports.
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells ([email protected])
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef __TOOLS_LINUX_ASM_GENERIC_BARRIER_H
+#define __TOOLS_LINUX_ASM_GENERIC_BARRIER_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/compiler.h>
+
+/*
+ * Force strict CPU ordering. And yes, this is required on UP too when we're
+ * talking to devices.
+ *
+ * Fall back to compiler barriers if nothing better is provided.
+ */
+
+#ifndef mb
+#define mb()	barrier()
+#endif
+
+#ifndef rmb
+#define rmb()	mb()
+#endif
+
+#ifndef wmb
+#define wmb()	mb()
+#endif
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __TOOLS_LINUX_ASM_GENERIC_BARRIER_H */
tools/perf/MANIFEST +1 -0
index 00754af..ac62caf 100644
@@ -11,6 +11,7 @@ tools/lib/symbol/kallsyms.h
 tools/lib/util/find_next_bit.c
 tools/include/asm/barrier.h
 tools/include/asm/bug.h
+tools/include/asm-generic/barrier.h
 tools/include/asm-generic/bitops/arch_hweight.h
 tools/include/asm-generic/bitops/atomic.h
 tools/include/asm-generic/bitops/const_hweight.h
Signature · 1 line
2.1.0
author maintainer
#12 lore raw

PATCH 12/30 perf tools: Move sh barrier.h stuff to tools/arch/sh/include/asm/barrier.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We will need it for atomic.h, so move it from the ad-hoc tools/perf/ place to a tools/ subset of the kernel arch/ hierarchy.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/arch/sh/include/asm/barrier.h | 32 ++++++++++++++++++++++++++++++++
 tools/include/asm/barrier.h         |  2 ++
 tools/perf/MANIFEST                 |  1 +
 tools/perf/perf-sys.h               |  9 ---------
 4 files changed, 35 insertions(+), 9 deletions(-)
 create mode 100644 tools/arch/sh/include/asm/barrier.h
tools/arch/sh/include/asm/barrier.h new file +32 -0
new file mode 100644
index 0000000..c18fd75
@@ -0,0 +1,32 @@
+/*
+ * Copied from the kernel sources:
+ *
+ * Copyright (C) 1999, 2000  Niibe Yutaka  &  Kaz Kojima
+ * Copyright (C) 2002 Paul Mundt
+ */
+#ifndef __TOOLS_LINUX_ASM_SH_BARRIER_H
+#define __TOOLS_LINUX_ASM_SH_BARRIER_H
+
+/*
+ * A brief note on ctrl_barrier(), the control register write barrier.
+ *
+ * Legacy SH cores typically require a sequence of 8 nops after
+ * modification of a control register in order for the changes to take
+ * effect. On newer cores (like the sh4a and sh5) this is accomplished
+ * with icbi.
+ *
+ * Also note that on sh4a in the icbi case we can forego a synco for the
+ * write barrier, as it's not necessary for control registers.
+ *
+ * Historically we have only done this type of barrier for the MMUCR, but
+ * it's also necessary for the CCR, so we make it generic here instead.
+ */
+#if defined(__SH4A__) || defined(__SH5__)
+#define mb()		__asm__ __volatile__ ("synco": : :"memory")
+#define rmb()		mb()
+#define wmb()		mb()
+#endif
+
+#include <asm-generic/barrier.h>
+
+#endif /* __TOOLS_LINUX_ASM_SH_BARRIER_H */
tools/include/asm/barrier.h +2 -0
index 7eb8894..1338c8a 100644
@@ -4,4 +4,6 @@
 #include "../../arch/powerpc/include/asm/barrier.h"
 #elif defined(__s390__)
 #include "../../arch/s390/include/asm/barrier.h"
+#elif defined(__sh__)
+#include "../../arch/sh/include/asm/barrier.h"
 #endif
tools/perf/MANIFEST +1 -0
index ac62caf..2ceb1b2 100644
@@ -1,6 +1,7 @@
 tools/perf
 tools/arch/powerpc/include/asm/barrier.h
 tools/arch/s390/include/asm/barrier.h
+tools/arch/sh/include/asm/barrier.h
 tools/arch/x86/include/asm/barrier.h
 tools/scripts
 tools/build
tools/perf/perf-sys.h +0 -9
index f44e53e..7ef5e82 100644
@@ -46,15 +46,6 @@
 #endif
 
 #ifdef __sh__
-#if defined(__SH4A__) || defined(__SH5__)
-# define mb()		asm volatile("synco" ::: "memory")
-# define wmb()		asm volatile("synco" ::: "memory")
-# define rmb()		asm volatile("synco" ::: "memory")
-#else
-# define mb()		asm volatile("" ::: "memory")
-# define wmb()		asm volatile("" ::: "memory")
-# define rmb()		asm volatile("" ::: "memory")
-#endif
 #define CPUINFO_PROC	{"cpu type"}
 #endif
 
Signature · 1 line
2.1.0
author maintainer
#13 lore raw

PATCH 13/30 perf tools: Move sparc barrier.h stuff to tools/arch/sparc/include/asm/barrier.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We will need it for atomic.h, so move it from the ad-hoc tools/perf/ place to a tools/ subset of the kernel arch/ hierarchy.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/arch/sparc/include/asm/barrier.h    |  8 ++++++
 tools/arch/sparc/include/asm/barrier_32.h |  6 +++++
 tools/arch/sparc/include/asm/barrier_64.h | 42 +++++++++++++++++++++++++++++++
 tools/include/asm/barrier.h               |  2 ++
 tools/perf/MANIFEST                       |  3 +++
 tools/perf/perf-sys.h                     |  9 -------
 6 files changed, 61 insertions(+), 9 deletions(-)
 create mode 100644 tools/arch/sparc/include/asm/barrier.h
 create mode 100644 tools/arch/sparc/include/asm/barrier_32.h
 create mode 100644 tools/arch/sparc/include/asm/barrier_64.h
tools/arch/sparc/include/asm/barrier.h new file +8 -0
new file mode 100644
index 0000000..8c017b3
@@ -0,0 +1,8 @@
+#ifndef ___TOOLS_LINUX_ASM_SPARC_BARRIER_H
+#define ___TOOLS_LINUX_ASM_SPARC_BARRIER_H
+#if defined(__sparc__) && defined(__arch64__)
+#include "barrier_64.h"
+#else
+#include "barrier_32.h"
+#endif
+#endif
tools/arch/sparc/include/asm/barrier_32.h new file +6 -0
new file mode 100644
index 0000000..c5eadd0
@@ -0,0 +1,6 @@
+#ifndef __TOOLS_PERF_SPARC_BARRIER_H
+#define __TOOLS_PERF_SPARC_BARRIER_H
+
+#include <asm-generic/barrier.h>
+
+#endif /* !(__TOOLS_PERF_SPARC_BARRIER_H) */
tools/arch/sparc/include/asm/barrier_64.h new file +42 -0

42 lines not on this page · raw message

tools/include/asm/barrier.h +2 -0
index 1338c8a..87f6309 100644
@@ -6,4 +6,6 @@
 #include "../../arch/s390/include/asm/barrier.h"
 #elif defined(__sh__)
 #include "../../arch/sh/include/asm/barrier.h"
+#elif defined(__sparc__)
+#include "../../arch/sparc/include/asm/barrier.h"
 #endif
tools/perf/MANIFEST +3 -0
index 2ceb1b2..ee69240 100644
@@ -2,6 +2,9 @@ tools/perf
 tools/arch/powerpc/include/asm/barrier.h
 tools/arch/s390/include/asm/barrier.h
 tools/arch/sh/include/asm/barrier.h
+tools/arch/sparc/include/asm/barrier.h
+tools/arch/sparc/include/asm/barrier_32.h
+tools/arch/sparc/include/asm/barrier_64.h
 tools/arch/x86/include/asm/barrier.h
 tools/scripts
 tools/build
tools/perf/perf-sys.h +0 -9
index 7ef5e82..b3e911a 100644
@@ -57,15 +57,6 @@
 #endif
 
 #ifdef __sparc__
-#ifdef __LP64__
-#define mb()		asm volatile("ba,pt %%xcc, 1f\n"	\
-				     "membar #StoreLoad\n"	\
-				     "1:\n":::"memory")
-#else
-#define mb()		asm volatile("":::"memory")
-#endif
-#define wmb()		asm volatile("":::"memory")
-#define rmb()		asm volatile("":::"memory")
 #define CPUINFO_PROC	{"cpu"}
 #endif
 
Signature · 1 line
2.1.0
author maintainer
#14 lore raw

PATCH 14/30 perf tools: Move alpha barrier.h stuff to tools/arch/alpha/include/asm/barrier.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We will need it for atomic.h, so move it from the ad-hoc tools/perf/ place to a tools/ subset of the kernel arch/ hierarchy.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/arch/alpha/include/asm/barrier.h | 8 ++++++++
 tools/include/asm/barrier.h            | 2 ++
 tools/perf/MANIFEST                    | 1 +
 tools/perf/perf-sys.h                  | 3 ---
 4 files changed, 11 insertions(+), 3 deletions(-)
 create mode 100644 tools/arch/alpha/include/asm/barrier.h
tools/arch/alpha/include/asm/barrier.h new file +8 -0
new file mode 100644
index 0000000..95df19c
@@ -0,0 +1,8 @@
+#ifndef __TOOLS_LINUX_ASM_ALPHA_BARRIER_H
+#define __TOOLS_LINUX_ASM_ALPHA_BARRIER_H
+
+#define mb()	__asm__ __volatile__("mb": : :"memory")
+#define rmb()	__asm__ __volatile__("mb": : :"memory")
+#define wmb()	__asm__ __volatile__("wmb": : :"memory")
+
+#endif		/* __TOOLS_LINUX_ASM_ALPHA_BARRIER_H */
tools/include/asm/barrier.h +2 -0
index 87f6309..a579a2e 100644
@@ -8,4 +8,6 @@
 #include "../../arch/sh/include/asm/barrier.h"
 #elif defined(__sparc__)
 #include "../../arch/sparc/include/asm/barrier.h"
+#elif defined(__alpha__)
+#include "../../arch/alpha/include/asm/barrier.h"
 #endif
tools/perf/MANIFEST +1 -0
index ee69240..9919ee3 100644
@@ -1,4 +1,5 @@
 tools/perf
+tools/arch/alpha/include/asm/barrier.h
 tools/arch/powerpc/include/asm/barrier.h
 tools/arch/s390/include/asm/barrier.h
 tools/arch/sh/include/asm/barrier.h
tools/perf/perf-sys.h +0 -3
index b3e911a..4710f057 100644
@@ -61,9 +61,6 @@
 #endif
 
 #ifdef __alpha__
-#define mb()		asm volatile("mb" ::: "memory")
-#define wmb()		asm volatile("wmb" ::: "memory")
-#define rmb()		asm volatile("mb" ::: "memory")
 #define CPUINFO_PROC	{"cpu model"}
 #endif
 
Signature · 1 line
2.1.0
author maintainer
#15 lore raw

PATCH 15/30 perf tools: Move ia64 barrier.h stuff to tools/arch/ia64/include/asm/barrier.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We will need it for atomic.h, so move it from the ad-hoc tools/perf/ place to a tools/ subset of the kernel arch/ hierarchy.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/arch/ia64/include/asm/barrier.h | 48 +++++++++++++++++++++++++++++++++++
 tools/include/asm/barrier.h           |  2 ++
 tools/perf/MANIFEST                   |  1 +
 tools/perf/perf-sys.h                 |  3 ---
 4 files changed, 51 insertions(+), 3 deletions(-)
 create mode 100644 tools/arch/ia64/include/asm/barrier.h
tools/arch/ia64/include/asm/barrier.h new file +48 -0
new file mode 100644
index 0000000..e4422b4
@@ -0,0 +1,48 @@
+/*
+ * Copied from the kernel sources to tools/:
+ *
+ * Memory barrier definitions.  This is based on information published
+ * in the Processor Abstraction Layer and the System Abstraction Layer
+ * manual.
+ *
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <[email protected]>
+ * Copyright (C) 1999 Asit Mallick <[email protected]>
+ * Copyright (C) 1999 Don Dugger <[email protected]>
+ */
+#ifndef _TOOLS_LINUX_ASM_IA64_BARRIER_H
+#define _TOOLS_LINUX_ASM_IA64_BARRIER_H
+
+#include <linux/compiler.h>
+
+/*
+ * Macros to force memory ordering.  In these descriptions, "previous"
+ * and "subsequent" refer to program order; "visible" means that all
+ * architecturally visible effects of a memory access have occurred
+ * (at a minimum, this means the memory has been read or written).
+ *
+ *   wmb():	Guarantees that all preceding stores to memory-
+ *		like regions are visible before any subsequent
+ *		stores and that all following stores will be
+ *		visible only after all previous stores.
+ *   rmb():	Like wmb(), but for reads.
+ *   mb():	wmb()/rmb() combo, i.e., all previous memory
+ *		accesses are visible before all subsequent
+ *		accesses and vice versa.  This is also known as
+ *		a "fence."
+ *
+ * Note: "mb()" and its variants cannot be used as a fence to order
+ * accesses to memory mapped I/O registers.  For that, mf.a needs to
+ * be used.  However, we don't want to always use mf.a because (a)
+ * it's (presumably) much slower than mf and (b) mf.a is supported for
+ * sequential memory pages only.
+ */
+
+/* XXX From arch/ia64/include/uapi/asm/gcc_intrin.h */
+#define ia64_mf()       asm volatile ("mf" ::: "memory")
+
+#define mb()		ia64_mf()
+#define rmb()		mb()
+#define wmb()		mb()
+
+#endif /* _TOOLS_LINUX_ASM_IA64_BARRIER_H */
tools/include/asm/barrier.h +2 -0
index a579a2e..659aa60 100644
@@ -10,4 +10,6 @@
 #include "../../arch/sparc/include/asm/barrier.h"
 #elif defined(__alpha__)
 #include "../../arch/alpha/include/asm/barrier.h"
+#elif defined(__ia64__)
+#include "../../arch/ia64/include/asm/barrier.h"
 #endif
tools/perf/MANIFEST +1 -0
index 9919ee3..74981a6 100644
@@ -1,5 +1,6 @@
 tools/perf
 tools/arch/alpha/include/asm/barrier.h
+tools/arch/ia64/include/asm/barrier.h
 tools/arch/powerpc/include/asm/barrier.h
 tools/arch/s390/include/asm/barrier.h
 tools/arch/sh/include/asm/barrier.h
tools/perf/perf-sys.h +0 -3
index 4710f057..79052fd 100644
@@ -65,9 +65,6 @@
 #endif
 
 #ifdef __ia64__
-#define mb()		asm volatile ("mf" ::: "memory")
-#define wmb()		asm volatile ("mf" ::: "memory")
-#define rmb()		asm volatile ("mf" ::: "memory")
 #define cpu_relax()	asm volatile ("hint @pause" ::: "memory")
 #define CPUINFO_PROC	{"model name"}
 #endif
Signature · 1 line
2.1.0
author maintainer
#16 lore raw

PATCH 16/30 perf tools: Move arm(64) barrier.h stuff to tools/arch/arm*/include/asm/barrier.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We will need it for atomic.h, so move it from the ad-hoc tools/perf/ place to a tools/ subset of the kernel arch/ hierarchy.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/arch/arm/include/asm/barrier.h   | 12 ++++++++++++
 tools/arch/arm64/include/asm/barrier.h | 16 ++++++++++++++++
 tools/include/asm/barrier.h            |  4 ++++
 tools/perf/MANIFEST                    |  1 +
 tools/perf/perf-sys.h                  | 10 ----------
 5 files changed, 33 insertions(+), 10 deletions(-)
 create mode 100644 tools/arch/arm/include/asm/barrier.h
 create mode 100644 tools/arch/arm64/include/asm/barrier.h
tools/arch/arm/include/asm/barrier.h new file +12 -0
new file mode 100644
index 0000000..005c618
@@ -0,0 +1,12 @@
+#ifndef _TOOLS_LINUX_ASM_ARM_BARRIER_H
+#define _TOOLS_LINUX_ASM_ARM_BARRIER_H
+
+/*
+ * Use the __kuser_memory_barrier helper in the CPU helper page. See
+ * arch/arm/kernel/entry-armv.S in the kernel source for details.
+ */
+#define mb()		((void(*)(void))0xffff0fa0)()
+#define wmb()		((void(*)(void))0xffff0fa0)()
+#define rmb()		((void(*)(void))0xffff0fa0)()
+
+#endif /* _TOOLS_LINUX_ASM_ARM_BARRIER_H */
tools/arch/arm64/include/asm/barrier.h new file +16 -0
new file mode 100644
index 0000000..a0483c8
@@ -0,0 +1,16 @@
+#ifndef _TOOLS_LINUX_ASM_AARCH64_BARRIER_H
+#define _TOOLS_LINUX_ASM_AARCH64_BARRIER_H
+
+/*
+ * From tools/perf/perf-sys.h, last modified in:
+ * f428ebd184c82a7914b2aa7e9f868918aaf7ea78 perf tools: Fix AAAAARGH64 memory barriers
+ *
+ * XXX: arch/arm64/include/asm/barrier.h in the kernel sources use dsb, is this
+ * a case like for arm32 where we do things differently in userspace?
+ */
+
+#define mb()		asm volatile("dmb ish" ::: "memory")
+#define wmb()		asm volatile("dmb ishst" ::: "memory")
+#define rmb()		asm volatile("dmb ishld" ::: "memory")
+
+#endif /* _TOOLS_LINUX_ASM_AARCH64_BARRIER_H */
tools/include/asm/barrier.h +4 -0
index 659aa60..d2ddca50 100644
@@ -1,5 +1,9 @@
 #if defined(__i386__) || defined(__x86_64__)
 #include "../../arch/x86/include/asm/barrier.h"
+#elif defined(__arm__)
+#include "../../arch/arm/include/asm/barrier.h"
+#elif defined(__aarch64__)
+#include "../../arch/arm64/include/asm/barrier.h"
 #elif defined(__powerpc__)
 #include "../../arch/powerpc/include/asm/barrier.h"
 #elif defined(__s390__)
tools/perf/MANIFEST +1 -0
index 74981a6..1b330dd 100644
@@ -1,5 +1,6 @@
 tools/perf
 tools/arch/alpha/include/asm/barrier.h
+tools/arch/arm/include/asm/barrier.h
 tools/arch/ia64/include/asm/barrier.h
 tools/arch/powerpc/include/asm/barrier.h
 tools/arch/s390/include/asm/barrier.h
tools/perf/perf-sys.h +0 -10
index 79052fd..56edbe1 100644
@@ -70,20 +70,10 @@
 #endif
 
 #ifdef __arm__
-/*
- * Use the __kuser_memory_barrier helper in the CPU helper page. See
- * arch/arm/kernel/entry-armv.S in the kernel source for details.
- */
-#define mb()		((void(*)(void))0xffff0fa0)()
-#define wmb()		((void(*)(void))0xffff0fa0)()
-#define rmb()		((void(*)(void))0xffff0fa0)()
 #define CPUINFO_PROC	{"model name", "Processor"}
 #endif
 
 #ifdef __aarch64__
-#define mb()		asm volatile("dmb ish" ::: "memory")
-#define wmb()		asm volatile("dmb ishst" ::: "memory")
-#define rmb()		asm volatile("dmb ishld" ::: "memory")
 #define cpu_relax()	asm volatile("yield" ::: "memory")
 #endif
 
Signature · 1 line
2.1.0
author maintainer
#17 lore raw

PATCH 17/30 perf tools: Move xtensa barrier.h stuff to tools/arch/xtensa/include/asm/barrier.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We will need it for atomic.h, so move it from the ad-hoc tools/perf/ place to a tools/ subset of the kernel arch/ hierarchy.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/arch/xtensa/include/asm/barrier.h | 18 ++++++++++++++++++
 tools/include/asm/barrier.h             |  2 ++
 tools/perf/MANIFEST                     |  1 +
 tools/perf/perf-sys.h                   |  3 ---
 4 files changed, 21 insertions(+), 3 deletions(-)
 create mode 100644 tools/arch/xtensa/include/asm/barrier.h
tools/arch/xtensa/include/asm/barrier.h new file +18 -0
new file mode 100644
index 0000000..583800b
@@ -0,0 +1,18 @@
+/*
+ * Copied from the kernel sources to tools/:
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2012 Tensilica Inc.
+ */
+
+#ifndef _TOOLS_LINUX_XTENSA_SYSTEM_H
+#define _TOOLS_LINUX_XTENSA_SYSTEM_H
+
+#define mb()  ({ __asm__ __volatile__("memw" : : : "memory"); })
+#define rmb() barrier()
+#define wmb() mb()
+
+#endif /* _TOOLS_LINUX_XTENSA_SYSTEM_H */
tools/include/asm/barrier.h +2 -0
index d2ddca50..ccb2244 100644
@@ -16,4 +16,6 @@
 #include "../../arch/alpha/include/asm/barrier.h"
 #elif defined(__ia64__)
 #include "../../arch/ia64/include/asm/barrier.h"
+#elif defined(__xtensa__)
+#include "../../arch/xtensa/include/asm/barrier.h"
 #endif
tools/perf/MANIFEST +1 -0
index 1b330dd..6d3c398 100644
@@ -9,6 +9,7 @@ tools/arch/sparc/include/asm/barrier.h
 tools/arch/sparc/include/asm/barrier_32.h
 tools/arch/sparc/include/asm/barrier_64.h
 tools/arch/x86/include/asm/barrier.h
+tools/arch/xtensa/include/asm/barrier.h
 tools/scripts
 tools/build
 tools/lib/traceevent
tools/perf/perf-sys.h +0 -3
index 56edbe1..ebe228f 100644
@@ -105,9 +105,6 @@
 #endif
 
 #ifdef __xtensa__
-#define mb()		asm volatile("memw" ::: "memory")
-#define wmb()		asm volatile("memw" ::: "memory")
-#define rmb()		asm volatile("" ::: "memory")
 #define CPUINFO_PROC	{"core ID"}
 #endif
 
Signature · 1 line
2.1.0
author maintainer
#18 lore raw

PATCH 18/30 perf tools: Move mips barrier.h stuff to tools/arch/mips/include/asm/barrier.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We will need it for atomic.h, so move it from the ad-hoc tools/perf/ place to a tools/ subset of the kernel arch/ hierarchy.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Deng-Cheng Zhu <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Ralf Baechle <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/arch/mips/include/asm/barrier.h | 20 ++++++++++++++++++++
 tools/include/asm/barrier.h           |  2 ++
 tools/perf/MANIFEST                   |  1 +
 tools/perf/perf-sys.h                 |  9 ---------
 4 files changed, 23 insertions(+), 9 deletions(-)
 create mode 100644 tools/arch/mips/include/asm/barrier.h
tools/arch/mips/include/asm/barrier.h new file +20 -0
new file mode 100644
index 0000000..80f96f7
@@ -0,0 +1,20 @@
+#ifndef _TOOLS_LINUX_ASM_MIPS_BARRIER_H
+#define _TOOLS_LINUX_ASM_MIPS_BARRIER_H
+/*
+ * FIXME: This came from tools/perf/perf-sys.h, where it was first introduced
+ * in c1e028ef40b8d6943b767028ba17d4f2ba020edb, more work needed to make it
+ * more closely follow the Linux kernel arch/mips/include/asm/barrier.h file.
+ * Probably when we continue work on tools/ Kconfig support to have all the
+ * CONFIG_ needed for properly doing that.
+ */
+#define mb()		asm volatile(					\
+				".set	mips2\n\t"			\
+				"sync\n\t"				\
+				".set	mips0"				\
+				: /* no output */			\
+				: /* no input */			\
+				: "memory")
+#define wmb()	mb()
+#define rmb()	mb()
+
+#endif /* _TOOLS_LINUX_ASM_MIPS_BARRIER_H */
tools/include/asm/barrier.h +2 -0
index ccb2244..a00b948 100644
@@ -14,6 +14,8 @@
 #include "../../arch/sparc/include/asm/barrier.h"
 #elif defined(__alpha__)
 #include "../../arch/alpha/include/asm/barrier.h"
+#elif defined(__mips__)
+#include "../../arch/mips/include/asm/barrier.h"
 #elif defined(__ia64__)
 #include "../../arch/ia64/include/asm/barrier.h"
 #elif defined(__xtensa__)
tools/perf/MANIFEST +1 -0
index 6d3c398..e4a7220 100644
@@ -2,6 +2,7 @@ tools/perf
 tools/arch/alpha/include/asm/barrier.h
 tools/arch/arm/include/asm/barrier.h
 tools/arch/ia64/include/asm/barrier.h
+tools/arch/mips/include/asm/barrier.h
 tools/arch/powerpc/include/asm/barrier.h
 tools/arch/s390/include/asm/barrier.h
 tools/arch/sh/include/asm/barrier.h
tools/perf/perf-sys.h +0 -9
index ebe228f..876001e 100644
@@ -78,15 +78,6 @@
 #endif
 
 #ifdef __mips__
-#define mb()		asm volatile(					\
-				".set	mips2\n\t"			\
-				"sync\n\t"				\
-				".set	mips0"				\
-				: /* no output */			\
-				: /* no input */			\
-				: "memory")
-#define wmb()	mb()
-#define rmb()	mb()
 #define CPUINFO_PROC	{"cpu model"}
 #endif
 
Signature · 1 line
2.1.0
author maintainer
#19 lore raw

PATCH 19/30 perf tools: Move tile barrier.h stuff to tools/arch/tile/include/asm/barrier.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We will need it for atomic.h, so move it from the ad-hoc tools/perf/ place to a tools/ subset of the kernel arch/ hierarchy.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/arch/tile/include/asm/barrier.h | 15 +++++++++++++++
 tools/include/asm/barrier.h           |  2 ++
 tools/perf/MANIFEST                   |  1 +
 tools/perf/perf-sys.h                 |  3 ---
 4 files changed, 18 insertions(+), 3 deletions(-)
 create mode 100644 tools/arch/tile/include/asm/barrier.h
tools/arch/tile/include/asm/barrier.h new file +15 -0
new file mode 100644
index 0000000..7d3692c
@@ -0,0 +1,15 @@
+#ifndef _TOOLS_LINUX_ASM_TILE_BARRIER_H
+#define _TOOLS_LINUX_ASM_TILE_BARRIER_H
+/*
+ * FIXME: This came from tools/perf/perf-sys.h, where it was first introduced
+ * in 620830b6954913647b7c7f68920cf48eddf6ad92, more work needed to make it
+ * more closely follow the Linux kernel arch/tile/include/asm/barrier.h file.
+ * Probably when we continue work on tools/ Kconfig support to have all the
+ * CONFIG_ needed for properly doing that.
+ */
+
+#define mb()		asm volatile ("mf" ::: "memory")
+#define wmb()		mb()
+#define rmb()		mb()
+
+#endif /* _TOOLS_LINUX_ASM_TILE_BARRIER_H */
tools/include/asm/barrier.h +2 -0
index a00b948..c23fff3b 100644
@@ -12,6 +12,8 @@
 #include "../../arch/sh/include/asm/barrier.h"
 #elif defined(__sparc__)
 #include "../../arch/sparc/include/asm/barrier.h"
+#elif defined(__tile__)
+#include "../../arch/tile/include/asm/barrier.h"
 #elif defined(__alpha__)
 #include "../../arch/alpha/include/asm/barrier.h"
 #elif defined(__mips__)
tools/perf/MANIFEST +1 -0
index e4a7220..7ef14d4 100644
@@ -9,6 +9,7 @@ tools/arch/sh/include/asm/barrier.h
 tools/arch/sparc/include/asm/barrier.h
 tools/arch/sparc/include/asm/barrier_32.h
 tools/arch/sparc/include/asm/barrier_64.h
+tools/arch/tile/include/asm/barrier.h
 tools/arch/x86/include/asm/barrier.h
 tools/arch/xtensa/include/asm/barrier.h
 tools/scripts
tools/perf/perf-sys.h +0 -3
index 876001e..e5be325 100644
@@ -100,9 +100,6 @@
 #endif
 
 #ifdef __tile__
-#define mb()		asm volatile ("mf" ::: "memory")
-#define wmb()		asm volatile ("mf" ::: "memory")
-#define rmb()		asm volatile ("mf" ::: "memory")
 #define cpu_relax()	asm volatile ("mfspr zero, PASS" ::: "memory")
 #define CPUINFO_PROC    {"model name"}
 #endif
Signature · 1 line
2.1.0
author maintainer
#20 lore raw

PATCH 20/30 perf tools: Move generic barriers out of perf-sys.h

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We will need it for atomic.h, so move it from the ad-hoc tools/perf/ place to a tools/ subset of the kernel arch/ hierarchy.

The parisc stuff was just using the asm-generic/barrier.h, no need to introduce a tools/arch/parisc/ tree just yet.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc David Ahern <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/include/asm/barrier.h | 2 ++
 tools/perf/perf-sys.h       | 9 ---------
 2 files changed, 2 insertions(+), 9 deletions(-)
tools/include/asm/barrier.h +2 -0
index c23fff3b..ac66ac5 100644
@@ -22,4 +22,6 @@
 #include "../../arch/ia64/include/asm/barrier.h"
 #elif defined(__xtensa__)
 #include "../../arch/xtensa/include/asm/barrier.h"
+#else
+#include <asm-generic/barrier.h>
 #endif
tools/perf/perf-sys.h +0 -9
index e5be325..83a25ce 100644
@@ -50,9 +50,6 @@
 #endif
 
 #ifdef __hppa__
-#define mb()		asm volatile("" ::: "memory")
-#define wmb()		asm volatile("" ::: "memory")
-#define rmb()		asm volatile("" ::: "memory")
 #define CPUINFO_PROC	{"cpu"}
 #endif
 
@@ -82,16 +79,10 @@
 #endif
 
 #ifdef __arc__
-#define mb()		asm volatile("" ::: "memory")
-#define wmb()		asm volatile("" ::: "memory")
-#define rmb()		asm volatile("" ::: "memory")
 #define CPUINFO_PROC	{"Processor"}
 #endif
 
 #ifdef __metag__
-#define mb()		asm volatile("" ::: "memory")
-#define wmb()		asm volatile("" ::: "memory")
-#define rmb()		asm volatile("" ::: "memory")
 #define CPUINFO_PROC	{"CPU"}
 #endif
 
Signature · 1 line
2.1.0
author maintainer
#21 lore raw

PATCH 21/30 tools include: Add basic atomic.h implementation from the kernel sources

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

Uses the arch/x86/ kernel code for x86_64/i386, fallbacking to a gcc intrinsics implementation that has been tested in at least sparc64.

Will be used for reference counting in tools/perf.

Cc Adrian Hunter <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Don Zickus <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Stephane Eranian <[email protected]>
---
 tools/arch/x86/include/asm/atomic.h    | 65 ++++++++++++++++++++++++++++++++++
 tools/arch/x86/include/asm/rmwcc.h     | 41 +++++++++++++++++++++
 tools/include/asm-generic/atomic-gcc.h | 63 ++++++++++++++++++++++++++++++++
 tools/include/asm/atomic.h             | 10 ++++++
 tools/include/linux/atomic.h           |  6 ++++
 tools/include/linux/types.h            |  4 +++
 tools/perf/MANIFEST                    |  4 +++
 7 files changed, 193 insertions(+)
 create mode 100644 tools/arch/x86/include/asm/atomic.h
 create mode 100644 tools/arch/x86/include/asm/rmwcc.h
 create mode 100644 tools/include/asm-generic/atomic-gcc.h
 create mode 100644 tools/include/asm/atomic.h
 create mode 100644 tools/include/linux/atomic.h
tools/arch/x86/include/asm/atomic.h new file +65 -0
new file mode 100644
index 0000000..059e33e
@@ -0,0 +1,65 @@
+#ifndef _TOOLS_LINUX_ASM_X86_ATOMIC_H
+#define _TOOLS_LINUX_ASM_X86_ATOMIC_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include "rmwcc.h"
+
+#define LOCK_PREFIX "\n\tlock; "
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ */
+
+#define ATOMIC_INIT(i)	{ (i) }
+
+/**
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically reads the value of @v.
+ */
+static inline int atomic_read(const atomic_t *v)
+{
+	return ACCESS_ONCE((v)->counter);
+}
+
+/**
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+static inline void atomic_set(atomic_t *v, int i)
+{
+	v->counter = i;
+}
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1.
+ */
+static inline void atomic_inc(atomic_t *v)
+{
+	asm volatile(LOCK_PREFIX "incl %0"
+		     : "+m" (v->counter));
+}
+
+/**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+static inline int atomic_dec_and_test(atomic_t *v)
+{
+	GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e");
+}
+
+#endif /* _TOOLS_LINUX_ASM_X86_ATOMIC_H */
tools/arch/x86/include/asm/rmwcc.h new file +41 -0

41 lines not on this page · raw message

tools/include/asm-generic/atomic-gcc.h new file +63 -0

63 lines not on this page · raw message

tools/include/asm/atomic.h new file +10 -0
new file mode 100644
index 0000000..70794f5
@@ -0,0 +1,10 @@
+#ifndef __TOOLS_LINUX_ASM_ATOMIC_H
+#define __TOOLS_LINUX_ASM_ATOMIC_H
+
+#if defined(__i386__) || defined(__x86_64__)
+#include "../../arch/x86/include/asm/atomic.h"
+#else
+#include <asm-generic/atomic-gcc.h>
+#endif
+
+#endif /* __TOOLS_LINUX_ASM_ATOMIC_H */
tools/include/linux/atomic.h new file +6 -0
new file mode 100644
index 0000000..4e3d3d1
@@ -0,0 +1,6 @@
+#ifndef __TOOLS_LINUX_ATOMIC_H
+#define __TOOLS_LINUX_ATOMIC_H
+
+#include <asm/atomic.h>
+
+#endif /* __TOOLS_LINUX_ATOMIC_H */
tools/include/linux/types.h +4 -0
index b5cf25e..0bdeda6 100644
@@ -60,6 +60,10 @@ typedef __u32 __bitwise __be32;
 typedef __u64 __bitwise __le64;
 typedef __u64 __bitwise __be64;
 
+typedef struct {
+	int counter;
+} atomic_t;
+
 struct list_head {
 	struct list_head *next, *prev;
 };
tools/perf/MANIFEST +4 -0
index 7ef14d4..a83cf75 100644
@@ -14,11 +14,14 @@ tools/arch/x86/include/asm/barrier.h
 tools/arch/xtensa/include/asm/barrier.h
 tools/scripts
 tools/build
+tools/arch/x86/include/asm/atomic.h
+tools/arch/x86/include/asm/rmwcc.h
 tools/lib/traceevent
 tools/lib/api
 tools/lib/symbol/kallsyms.c
 tools/lib/symbol/kallsyms.h
 tools/lib/util/find_next_bit.c
+tools/include/asm/atomic.h
 tools/include/asm/barrier.h
 tools/include/asm/bug.h
 tools/include/asm-generic/barrier.h
@@ -32,6 +35,7 @@ tools/include/asm-generic/bitops/fls64.h
 tools/include/asm-generic/bitops/fls.h
 tools/include/asm-generic/bitops/hweight.h
 tools/include/asm-generic/bitops.h
+tools/include/linux/atomic.h
 tools/include/linux/bitops.h
 tools/include/linux/compiler.h
 tools/include/linux/export.h
Signature · 1 line
2.1.0
author maintainer
#22 lore raw

PATCH 22/30 perf tools: Use atomic_t to implement thread__{get,put} refcnt

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

Fixing bugs in 'perf top' where the used thread unsafe 'struct thread' refcount implementation was falling apart because we really use two threads.

---
 tools/perf/util/thread.c | 6 +++---
 tools/perf/util/thread.h | 3 ++-
 2 files changed, 5 insertions(+), 4 deletions(-)
tools/perf/util/thread.c +3 -3
index 1c8fbc9..1b26552 100644
@@ -53,7 +53,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
 			goto err_thread;
 
 		list_add(&comm->list, &thread->comm_list);
-
+		atomic_set(&thread->refcnt, 0);
 	}
 
 	return thread;
@@ -84,13 +84,13 @@ void thread__delete(struct thread *thread)
 
 struct thread *thread__get(struct thread *thread)
 {
-	++thread->refcnt;
+	atomic_inc(&thread->refcnt);
 	return thread;
 }
 
 void thread__put(struct thread *thread)
 {
-	if (thread && --thread->refcnt == 0) {
+	if (thread && atomic_dec_and_test(&thread->refcnt)) {
 		list_del_init(&thread->node);
 		thread__delete(thread);
 	}
tools/perf/util/thread.h +2 -1
index 9b8a54d..f33c48c 100644
@@ -1,6 +1,7 @@
 #ifndef __PERF_THREAD_H
 #define __PERF_THREAD_H
 
+#include <linux/atomic.h>
 #include <linux/rbtree.h>
 #include <linux/list.h>
 #include <unistd.h>
@@ -21,7 +22,7 @@ struct thread {
 	pid_t			tid;
 	pid_t			ppid;
 	int			cpu;
-	int			refcnt;
+	atomic_t		refcnt;
 	char			shortname[3];
 	bool			comm_set;
 	bool			dead; /* if set thread has exited */
Signature · 1 line
2.1.0
author maintainer
#23 lore raw

PATCH 23/30 perf machine: Protect the machine->threads with a rwlock

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

In addition to using refcounts for the struct thread lifetime management, we need to protect access to machine->threads from concurrent access.

That happens in 'perf top', where a thread processes events, inserting and deleting entries from that rb_tree while another thread decays hist_entries, that end up dropping references and ultimately deleting threads from the rb_tree and releasing its resources when no further hist_entry (or other data structures, like in 'perf sched') references it.

So the rule is the same for refcounts + protected trees in the kernel, get the tree lock, find object, bump the refcount, drop the tree lock, return, use object, drop the refcount if no more use of it is needed, keep it if storing it in some other data structure, drop when releasing that data structure.

I.e. pair "t = machine__find(new)_thread()" with a "thread__put(t)", and "perf_event__preprocess_sample(&al)" with "addr_location__put(&al)".

The addr_location__put() one is because as we return references to several data structures, we may end up adding more reference counting for the other data structures and then we'll drop it at addr_location__put() time.

---
 tools/perf/builtin-annotate.c         | 10 ++--
 tools/perf/builtin-diff.c             |  9 ++--
 tools/perf/builtin-inject.c           |  1 +
 tools/perf/builtin-kmem.c             |  7 ++-
 tools/perf/builtin-kvm.c              |  6 ++-
 tools/perf/builtin-lock.c             |  8 +++-
 tools/perf/builtin-mem.c              |  5 +-
 tools/perf/builtin-report.c           |  9 ++--
 tools/perf/builtin-sched.c            | 82 ++++++++++++++++++++++----------
 tools/perf/builtin-script.c           | 20 ++++----
 tools/perf/builtin-timechart.c        |  5 +-
 tools/perf/builtin-top.c              |  2 +-
 tools/perf/builtin-trace.c            | 36 +++++++++-----
 tools/perf/tests/code-reading.c       | 22 +++++----
 tools/perf/tests/dwarf-unwind.c       |  1 +
 tools/perf/tests/hists_common.c       |  1 +
 tools/perf/tests/hists_cumulate.c     |  4 +-
 tools/perf/tests/hists_filter.c       |  4 +-
 tools/perf/tests/hists_link.c         |  8 +++-
 tools/perf/tests/hists_output.c       |  4 +-
 tools/perf/tests/mmap-thread-lookup.c |  2 +
 tools/perf/tests/thread-mg-share.c    | 12 ++---
 tools/perf/util/build-id.c            |  5 +-
 tools/perf/util/db-export.c           | 14 ++++--
 tools/perf/util/event.c               | 15 ++++++
 tools/perf/util/event.h               |  2 +
 tools/perf/util/machine.c             | 89 ++++++++++++++++++++++++++++-------
 tools/perf/util/machine.h             |  5 +-
 tools/perf/util/thread.c              | 10 +++-
 29 files changed, 284 insertions(+), 114 deletions(-)
tools/perf/builtin-annotate.c +6 -4
index 71bf745..b57a027 100644
@@ -84,6 +84,7 @@ static int process_sample_event(struct perf_tool *tool,
 {
 	struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool);
 	struct addr_location al;
+	int ret = 0;
 
 	if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
 		pr_warning("problem processing %d event, skipping it.\n",
@@ -92,15 +93,16 @@ static int process_sample_event(struct perf_tool *tool,
 	}
 
 	if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
-		return 0;
+		goto out_put;
 
 	if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) {
 		pr_warning("problem incrementing symbol count, "
 			   "skipping event\n");
-		return -1;
+		ret = -1;
 	}
-
-	return 0;
+out_put:
+	addr_location__put(&al);
+	return ret;
 }
 
 static int hist_entry__tty_annotate(struct hist_entry *he,
tools/perf/builtin-diff.c +6 -3
index df6307b..daaa7dc 100644
@@ -328,6 +328,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
 {
 	struct addr_location al;
 	struct hists *hists = evsel__hists(evsel);
+	int ret = -1;
 
 	if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
 		pr_warning("problem processing %d event, skipping it.\n",
@@ -338,7 +339,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
 	if (hists__add_entry(hists, &al, sample->period,
 			     sample->weight, sample->transaction)) {
 		pr_warning("problem incrementing symbol period, skipping event\n");
-		return -1;
+		goto out_put;
 	}
 
 	/*
@@ -350,8 +351,10 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
 	hists->stats.total_period += sample->period;
 	if (!al.filtered)
 		hists->stats.total_non_filtered_period += sample->period;
-
-	return 0;
+	ret = 0;
+out_put:
+	addr_location__put(&al);
+	return ret;
 }
 
 static struct perf_tool tool = {
tools/perf/builtin-inject.c +1 -0
index d6a47e8..52ec66b 100644
@@ -365,6 +365,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
 		}
 	}
 
+	thread__put(thread);
 repipe:
 	perf_event__repipe(tool, event, sample, machine);
 	return 0;
tools/perf/builtin-kmem.c +5 -2
index e628bf1..fe3fcb7 100644
@@ -906,6 +906,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 				struct perf_evsel *evsel,
 				struct machine *machine)
 {
+	int err = 0;
 	struct thread *thread = machine__findnew_thread(machine, sample->pid,
 							sample->tid);
 
@@ -919,10 +920,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 
 	if (evsel->handler != NULL) {
 		tracepoint_handler f = evsel->handler;
-		return f(evsel, sample);
+		err = f(evsel, sample);
 	}
 
-	return 0;
+	thread__put(thread);
+
+	return err;
 }
 
 static struct perf_tool perf_kmem = {
tools/perf/builtin-kvm.c +4 -2
index 1f9338f..15fecd3 100644
@@ -651,6 +651,7 @@ static int process_sample_event(struct perf_tool *tool,
 				struct perf_evsel *evsel,
 				struct machine *machine)
 {
+	int err = 0;
 	struct thread *thread;
 	struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat,
 						 tool);
@@ -666,9 +667,10 @@ static int process_sample_event(struct perf_tool *tool,
 	}
 
 	if (!handle_kvm_event(kvm, thread, evsel, sample))
-		return -1;
+		err = -1;
 
-	return 0;
+	thread__put(thread);
+	return err;
 }
 
 static int cpu_isa_config(struct perf_kvm_stat *kvm)
tools/perf/builtin-lock.c +6 -2
index d49c2ab..de16aae 100644
@@ -769,6 +769,7 @@ static void dump_threads(void)
 		t = perf_session__findnew(session, st->tid);
 		pr_info("%10d: %s\n", st->tid, thread__comm_str(t));
 		node = rb_next(node);
+		thread__put(t);
 	};
 }
 
@@ -810,6 +811,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 				struct perf_evsel *evsel,
 				struct machine *machine)
 {
+	int err = 0;
 	struct thread *thread = machine__findnew_thread(machine, sample->pid,
 							sample->tid);
 
@@ -821,10 +823,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 
 	if (evsel->handler != NULL) {
 		tracepoint_handler f = evsel->handler;
-		return f(evsel, sample);
+		err = f(evsel, sample);
 	}
 
-	return 0;
+	thread__put(thread);
+
+	return err;
 }
 
 static void sort_result(void)
tools/perf/builtin-mem.c +3 -2
index 675216e..da2ec06 100644
@@ -74,7 +74,7 @@ dump_raw_samples(struct perf_tool *tool,
 	}
 
 	if (al.filtered || (mem->hide_unresolved && al.sym == NULL))
-		return 0;
+		goto out_put;
 
 	if (al.map != NULL)
 		al.map->dso->hit = 1;
@@ -103,7 +103,8 @@ dump_raw_samples(struct perf_tool *tool,
 		symbol_conf.field_sep,
 		al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???",
 		al.sym ? al.sym->name : "???");
-
+out_put:
+	addr_location__put(&al);
 	return 0;
 }
 
tools/perf/builtin-report.c +5 -4
index 18cb0ff..8d5118f 100644
@@ -142,7 +142,7 @@ static int process_sample_event(struct perf_tool *tool,
 		.hide_unresolved = rep->hide_unresolved,
 		.add_entry_cb = hist_iter__report_callback,
 	};
-	int ret;
+	int ret = 0;
 
 	if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
 		pr_debug("problem processing %d event, skipping it.\n",
@@ -151,10 +151,10 @@ static int process_sample_event(struct perf_tool *tool,
 	}
 
 	if (rep->hide_unresolved && al.sym == NULL)
-		return 0;
+		goto out_put;
 
 	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
-		return 0;
+		goto out_put;
 
 	if (sort__mode == SORT_MODE__BRANCH)
 		iter.ops = &hist_iter_branch;
@@ -172,7 +172,8 @@ static int process_sample_event(struct perf_tool *tool,
 				   rep);
 	if (ret < 0)
 		pr_debug("problem adding hist entry, skipping event\n");
-
+out_put:
+	addr_location__put(&al);
 	return ret;
 }
 
tools/perf/builtin-sched.c +56 -26

218 lines not on this page · raw message

tools/perf/builtin-script.c +12 -8
index 6805098..24809787 100644
@@ -607,13 +607,14 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 	}
 
 	if (al.filtered)
-		return 0;
+		goto out_put;
 
 	if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
-		return 0;
+		goto out_put;
 
 	scripting_ops->process_event(event, sample, evsel, &al);
-
+out_put:
+	addr_location__put(&al);
 	return 0;
 }
 
@@ -681,8 +682,8 @@ static int process_comm_event(struct perf_tool *tool,
 	print_sample_start(sample, thread, evsel);
 	perf_event__fprintf(event, stdout);
 	ret = 0;
-
 out:
+	thread__put(thread);
 	return ret;
 }
 
@@ -713,6 +714,7 @@ static int process_fork_event(struct perf_tool *tool,
 	}
 	print_sample_start(sample, thread, evsel);
 	perf_event__fprintf(event, stdout);
+	thread__put(thread);
 
 	return 0;
 }
@@ -721,6 +723,7 @@ static int process_exit_event(struct perf_tool *tool,
 			      struct perf_sample *sample,
 			      struct machine *machine)
 {
+	int err = 0;
 	struct thread *thread;
 	struct perf_script *script = container_of(tool, struct perf_script, tool);
 	struct perf_session *session = script->session;
@@ -742,9 +745,10 @@ static int process_exit_event(struct perf_tool *tool,
 	perf_event__fprintf(event, stdout);
 
 	if (perf_event__process_exit(tool, event, sample, machine) < 0)
-		return -1;
+		err = -1;
 
-	return 0;
+	thread__put(thread);
+	return err;
 }
 
 static int process_mmap_event(struct perf_tool *tool,
@@ -774,7 +778,7 @@ static int process_mmap_event(struct perf_tool *tool,
 	}
 	print_sample_start(sample, thread, evsel);
 	perf_event__fprintf(event, stdout);
-
+	thread__put(thread);
 	return 0;
 }
 
@@ -805,7 +809,7 @@ static int process_mmap2_event(struct perf_tool *tool,
 	}
 	print_sample_start(sample, thread, evsel);
 	perf_event__fprintf(event, stdout);
-
+	thread__put(thread);
 	return 0;
 }
 
tools/perf/builtin-timechart.c +3 -2
index e50fe11..3b884e3 100644
@@ -523,7 +523,7 @@ static const char *cat_backtrace(union perf_event *event,
 				 * Discard all.
 				 */
 				zfree(&p);
-				goto exit;
+				goto exit_put;
 			}
 			continue;
 		}
@@ -538,7 +538,8 @@ static const char *cat_backtrace(union perf_event *event,
 		else
 			fprintf(f, "..... %016" PRIx64 "\n", ip);
 	}
-
+exit_put:
+	addr_location__put(&al);
 exit:
 	fclose(f);
 
tools/perf/builtin-top.c +1 -1
index 1cb3436..2326583 100644
@@ -793,7 +793,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
 		pthread_mutex_unlock(&hists->lock);
 	}
 
-	return;
+	addr_location__put(&al);
 }
 
 static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
tools/perf/builtin-trace.c +23 -13
index d1139b6..bb05e44 100644
@@ -1712,7 +1712,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
 	void *args;
 	size_t printed = 0;
 	struct thread *thread;
-	int id = perf_evsel__sc_tp_uint(evsel, id, sample);
+	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
 	struct syscall *sc = trace__syscall_info(trace, evsel, id);
 	struct thread_trace *ttrace;
 
@@ -1725,14 +1725,14 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
 	ttrace = thread__trace(thread, trace->output);
 	if (ttrace == NULL)
-		return -1;
+		goto out_put;
 
 	args = perf_evsel__sc_tp_ptr(evsel, args, sample);
 
 	if (ttrace->entry_str == NULL) {
 		ttrace->entry_str = malloc(1024);
 		if (!ttrace->entry_str)
-			return -1;
+			goto out_put;
 	}
 
 	if (!trace->summary_only)
@@ -1757,8 +1757,10 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
 		thread__put(trace->current);
 		trace->current = thread__get(thread);
 	}
-
-	return 0;
+	err = 0;
+out_put:
+	thread__put(thread);
+	return err;
 }
 
 static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
@@ -1768,7 +1770,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
 	long ret;
 	u64 duration = 0;
 	struct thread *thread;
-	int id = perf_evsel__sc_tp_uint(evsel, id, sample);
+	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
 	struct syscall *sc = trace__syscall_info(trace, evsel, id);
 	struct thread_trace *ttrace;
 
@@ -1781,7 +1783,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
 	ttrace = thread__trace(thread, trace->output);
 	if (ttrace == NULL)
-		return -1;
+		goto out_put;
 
 	if (trace->summary)
 		thread__update_stats(ttrace, id, sample);
@@ -1835,8 +1837,10 @@ signed_print:
 	fputc('\n', trace->output);
 out:
 	ttrace->entry_pending = false;
-
-	return 0;
+	err = 0;
+out_put:
+	thread__put(thread);
+	return err;
 }
 
 static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
@@ -1863,6 +1867,7 @@ static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evs
 
 	ttrace->runtime_ms += runtime_ms;
 	trace->runtime_ms += runtime_ms;
+	thread__put(thread);
 	return 0;
 
 out_dump:
@@ -1872,6 +1877,7 @@ out_dump:
 	       (pid_t)perf_evsel__intval(evsel, sample, "pid"),
 	       runtime,
 	       perf_evsel__intval(evsel, sample, "vruntime"));
+	thread__put(thread);
 	return 0;
 }
 
@@ -1924,11 +1930,12 @@ static int trace__pgfault(struct trace *trace,
 	struct addr_location al;
 	char map_type = 'd';
 	struct thread_trace *ttrace;
+	int err = -1;
 
 	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
 	ttrace = thread__trace(thread, trace->output);
 	if (ttrace == NULL)
-		return -1;
+		goto out_put;
 
 	if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
 		ttrace->pfmaj++;
@@ -1936,7 +1943,7 @@ static int trace__pgfault(struct trace *trace,
 		ttrace->pfmin++;
 
 	if (trace->summary_only)
-		return 0;
+		goto out;
 
 	thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
 			      sample->ip, &al);
@@ -1967,8 +1974,11 @@ static int trace__pgfault(struct trace *trace,
 	print_location(trace->output, sample, &al, true, false);
 
 	fprintf(trace->output, " (%c%c)\n", map_type, al.level);
-
-	return 0;
+out:
+	err = 0;
+out_put:
+	thread__put(thread);
+	return err;
 }
 
 static bool skip_sample(struct trace *trace, struct perf_sample *sample)
tools/perf/tests/code-reading.c +14 -8
index ca0e480..e2a432b 100644
@@ -248,6 +248,7 @@ static int process_sample_event(struct machine *machine,
 	struct perf_sample sample;
 	struct thread *thread;
 	u8 cpumode;
+	int ret;
 
 	if (perf_evlist__parse_sample(evlist, event, &sample)) {
 		pr_debug("perf_evlist__parse_sample failed\n");
@@ -262,7 +263,9 @@ static int process_sample_event(struct machine *machine,
 
 	cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
-	return read_object_code(sample.ip, READLEN, cpumode, thread, state);
+	ret = read_object_code(sample.ip, READLEN, cpumode, thread, state);
+	thread__put(thread);
+	return ret;
 }
 
 static int process_event(struct machine *machine, struct perf_evlist *evlist,
@@ -457,13 +460,13 @@ static int do_test_code_reading(bool try_kcore)
 	thread = machine__findnew_thread(machine, pid, pid);
 	if (!thread) {
 		pr_debug("machine__findnew_thread failed\n");
-		goto out_err;
+		goto out_put;
 	}
 
 	cpus = cpu_map__new(NULL);
 	if (!cpus) {
 		pr_debug("cpu_map__new failed\n");
-		goto out_err;
+		goto out_put;
 	}
 
 	while (1) {
@@ -472,7 +475,7 @@ static int do_test_code_reading(bool try_kcore)
 		evlist = perf_evlist__new();
 		if (!evlist) {
 			pr_debug("perf_evlist__new failed\n");
-			goto out_err;
+			goto out_put;
 		}
 
 		perf_evlist__set_maps(evlist, cpus, threads);
@@ -485,7 +488,7 @@ static int do_test_code_reading(bool try_kcore)
 		ret = parse_events(evlist, str, NULL);
 		if (ret < 0) {
 			pr_debug("parse_events failed\n");
-			goto out_err;
+			goto out_put;
 		}
 
 		perf_evlist__config(evlist, &opts);
@@ -506,7 +509,7 @@ static int do_test_code_reading(bool try_kcore)
 				continue;
 			}
 			pr_debug("perf_evlist__open failed\n");
-			goto out_err;
+			goto out_put;
 		}
 		break;
 	}
@@ -514,7 +517,7 @@ static int do_test_code_reading(bool try_kcore)
 	ret = perf_evlist__mmap(evlist, UINT_MAX, false);
 	if (ret < 0) {
 		pr_debug("perf_evlist__mmap failed\n");
-		goto out_err;
+		goto out_put;
 	}
 
 	perf_evlist__enable(evlist);
@@ -525,7 +528,7 @@ static int do_test_code_reading(bool try_kcore)
 
 	ret = process_events(machine, evlist, &state);
 	if (ret < 0)
-		goto out_err;
+		goto out_put;
 
 	if (!have_vmlinux && !have_kcore && !try_kcore)
 		err = TEST_CODE_READING_NO_KERNEL_OBJ;
@@ -535,7 +538,10 @@ static int do_test_code_reading(bool try_kcore)
 		err = TEST_CODE_READING_NO_ACCESS;
 	else
 		err = TEST_CODE_READING_OK;
+out_put:
+	thread__put(thread);
 out_err:
+
 	if (evlist) {
 		perf_evlist__delete(evlist);
 	} else {
tools/perf/tests/dwarf-unwind.c +1 -0
index 0bf06be..9b748e1 100644
@@ -170,6 +170,7 @@ int test__dwarf_unwind(void)
 	}
 
 	err = krava_1(thread);
+	thread__put(thread);
 
  out:
 	machine__delete_threads(machine);
tools/perf/tests/hists_common.c +1 -0
index a62c091..456f884 100644
@@ -96,6 +96,7 @@ struct machine *setup_fake_machine(struct machines *machines)
 			goto out;
 
 		thread__set_comm(thread, fake_threads[i].comm, 0);
+		thread__put(thread);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) {
tools/perf/tests/hists_cumulate.c +3 -1
index b08a95a..620f626 100644
@@ -105,8 +105,10 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
 			goto out;
 
 		if (hist_entry_iter__add(&iter, &al, evsel, &sample,
-					 PERF_MAX_STACK_DEPTH, NULL) < 0)
+					 PERF_MAX_STACK_DEPTH, NULL) < 0) {
+			addr_location__put(&al);
 			goto out;
+		}
 
 		fake_samples[i].thread = al.thread;
 		fake_samples[i].map = al.map;
tools/perf/tests/hists_filter.c +3 -1
index 108488c..82e1ee5 100644
@@ -82,8 +82,10 @@ static int add_hist_entries(struct perf_evlist *evlist,
 				goto out;
 
 			if (hist_entry_iter__add(&iter, &al, evsel, &sample,
-						 PERF_MAX_STACK_DEPTH, NULL) < 0)
+						 PERF_MAX_STACK_DEPTH, NULL) < 0) {
+				addr_location__put(&al);
 				goto out;
+			}
 
 			fake_samples[i].thread = al.thread;
 			fake_samples[i].map = al.map;
tools/perf/tests/hists_link.c +6 -2
index 34c61e4..8c102b0 100644
@@ -91,8 +91,10 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
 
 			he = __hists__add_entry(hists, &al, NULL,
 						NULL, NULL, 1, 1, 0, true);
-			if (he == NULL)
+			if (he == NULL) {
+				addr_location__put(&al);
 				goto out;
+			}
 
 			fake_common_samples[k].thread = al.thread;
 			fake_common_samples[k].map = al.map;
@@ -115,8 +117,10 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
 
 			he = __hists__add_entry(hists, &al, NULL,
 						NULL, NULL, 1, 1, 0, true);
-			if (he == NULL)
+			if (he == NULL) {
+				addr_location__put(&al);
 				goto out;
+			}
 
 			fake_samples[i][k].thread = al.thread;
 			fake_samples[i][k].map = al.map;
tools/perf/tests/hists_output.c +3 -1
index d8a23db..fd7ec4f 100644
@@ -71,8 +71,10 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
 			goto out;
 
 		if (hist_entry_iter__add(&iter, &al, evsel, &sample,
-					 PERF_MAX_STACK_DEPTH, NULL) < 0)
+					 PERF_MAX_STACK_DEPTH, NULL) < 0) {
+			addr_location__put(&al);
 			goto out;
+		}
 
 		fake_samples[i].thread = al.thread;
 		fake_samples[i].map = al.map;
tools/perf/tests/mmap-thread-lookup.c +2 -0
index 2113f1c..264e215 100644
@@ -191,6 +191,8 @@ static int mmap_events(synth_cb synth)
 				      PERF_RECORD_MISC_USER, MAP__FUNCTION,
 				      (unsigned long) (td->map + 1), &al);
 
+		thread__put(thread);
+
 		if (!al.map) {
 			pr_debug("failed, couldn't find map\n");
 			err = -1;
tools/perf/tests/thread-mg-share.c +6 -6
index b028499..dc05bd6 100644
@@ -64,22 +64,22 @@ int test__thread_mg_share(void)
 	TEST_ASSERT_VAL("map groups don't match", other_mg == other_leader->mg);
 
 	/* release thread group */
-	thread__delete(leader);
+	thread__put(leader);
 	TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 3);
 
-	thread__delete(t1);
+	thread__put(t1);
 	TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 2);
 
-	thread__delete(t2);
+	thread__put(t2);
 	TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 1);
 
-	thread__delete(t3);
+	thread__put(t3);
 
 	/* release other group  */
-	thread__delete(other_leader);
+	thread__put(other_leader);
 	TEST_ASSERT_VAL("wrong refcnt", other_mg->refcnt == 1);
 
-	thread__delete(other);
+	thread__put(other);
 
 	/*
 	 * Cannot call machine__delete_threads(machine) now,
tools/perf/util/build-id.c +4 -1
index 61867df..ad8cfcb 100644
@@ -43,6 +43,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
 	if (al.map != NULL)
 		al.map->dso->hit = 1;
 
+	thread__put(thread);
 	return 0;
 }
 
@@ -59,8 +60,10 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
 	dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
 		    event->fork.ppid, event->fork.ptid);
 
-	if (thread)
+	if (thread) {
 		machine__remove_thread(machine, thread);
+		thread__put(thread);
+	}
 
 	return 0;
 }
tools/perf/util/db-export.c +10 -4
index bb39a3f..eb7a2ac 100644
@@ -122,6 +122,7 @@ int db_export__machine(struct db_export *dbe, struct machine *machine)
 int db_export__thread(struct db_export *dbe, struct thread *thread,
 		      struct machine *machine, struct comm *comm)
 {
+	struct thread *main_thread;
 	u64 main_thread_db_id = 0;
 	int err;
 
@@ -131,8 +132,6 @@ int db_export__thread(struct db_export *dbe, struct thread *thread,
 	thread->db_id = ++dbe->thread_last_db_id;
 
 	if (thread->pid_ != -1) {
-		struct thread *main_thread;
-
 		if (thread->pid_ == thread->tid) {
 			main_thread = thread;
 		} else {
@@ -144,14 +143,16 @@ int db_export__thread(struct db_export *dbe, struct thread *thread,
 			err = db_export__thread(dbe, main_thread, machine,
 						comm);
 			if (err)
-				return err;
+				goto out_put;
 			if (comm) {
 				err = db_export__comm_thread(dbe, comm, thread);
 				if (err)
-					return err;
+					goto out_put;
 			}
 		}
 		main_thread_db_id = main_thread->db_id;
+		if (main_thread != thread)
+			thread__put(main_thread);
 	}
 
 	if (dbe->export_thread)
@@ -159,6 +160,10 @@ int db_export__thread(struct db_export *dbe, struct thread *thread,
 					  machine);
 
 	return 0;
+
+out_put:
+	thread__put(main_thread);
+	return err;
 }
 
 int db_export__comm(struct db_export *dbe, struct comm *comm,
@@ -303,6 +308,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
 	if (err)
 		return err;
 
+	/* FIXME: check refcounting for get_main_thread, that calls machine__find_thread... */
 	main_thread = get_main_thread(al->machine, thread);
 	if (main_thread)
 		comm = machine__thread_exec_comm(al->machine, main_thread);
tools/perf/util/event.c +15 -0
index db52609..a513a51 100644
@@ -919,6 +919,10 @@ void thread__find_addr_location(struct thread *thread,
 		al->sym = NULL;
 }
 
+/*
+ * Callers need to drop the reference to al->thread, obtained in
+ * machine__findnew_thread()
+ */
 int perf_event__preprocess_sample(const union perf_event *event,
 				  struct machine *machine,
 				  struct addr_location *al,
@@ -979,6 +983,17 @@ int perf_event__preprocess_sample(const union perf_event *event,
 	return 0;
 }
 
+/*
+ * The preprocess_sample method will return with reference counts for the
+ * in it, when done using (and perhaps getting ref counts if needing to
+ * keep a pointer to one of those entries) it must be paired with
+ * addr_location__put(), so that the refcounts can be decremented.
+ */
+void addr_location__put(struct addr_location *al)
+{
+	thread__zput(al->thread);
+}
+
 bool is_bts_event(struct perf_event_attr *attr)
 {
 	return attr->type == PERF_TYPE_HARDWARE &&
tools/perf/util/event.h +2 -0
index 7eecd5e..97179ab 100644
@@ -426,6 +426,8 @@ int perf_event__preprocess_sample(const union perf_event *event,
 				  struct addr_location *al,
 				  struct perf_sample *sample);
 
+void addr_location__put(struct addr_location *al);
+
 struct thread;
 
 bool is_bts_event(struct perf_event_attr *attr);
tools/perf/util/machine.c +72 -17

252 lines not on this page · raw message

tools/perf/util/machine.h +3 -2
index 1d99296..c7963c6 100644
@@ -30,6 +30,7 @@ struct machine {
 	bool		  comm_exec;
 	char		  *root_dir;
 	struct rb_root	  threads;
+	pthread_rwlock_t  threads_lock;
 	struct list_head  dead_threads;
 	struct thread	  *last_match;
 	struct vdso_info  *vdso_info;
@@ -151,8 +152,8 @@ static inline bool machine__is_host(struct machine *machine)
 	return machine ? machine->pid == HOST_KERNEL_ID : false;
 }
 
-struct thread *machine__findnew_thread(struct machine *machine, pid_t pid,
-				       pid_t tid);
+struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid);
+struct thread *machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid);
 
 size_t machine__fprintf(struct machine *machine, FILE *fp);
 
tools/perf/util/thread.c +8 -2
index 1b26552..16c28a3 100644
@@ -18,7 +18,7 @@ int thread__init_map_groups(struct thread *thread, struct machine *machine)
 	if (pid == thread->tid || pid == -1) {
 		thread->mg = map_groups__new(machine);
 	} else {
-		leader = machine__findnew_thread(machine, pid, pid);
+		leader = __machine__findnew_thread(machine, pid, pid);
 		if (leader)
 			thread->mg = map_groups__get(leader->mg);
 	}
@@ -54,6 +54,8 @@ struct thread *thread__new(pid_t pid, pid_t tid)
 
 		list_add(&comm->list, &thread->comm_list);
 		atomic_set(&thread->refcnt, 0);
+		INIT_LIST_HEAD(&thread->node);
+		RB_CLEAR_NODE(&thread->rb_node);
 	}
 
 	return thread;
@@ -67,6 +69,9 @@ void thread__delete(struct thread *thread)
 {
 	struct comm *comm, *tmp;
 
+	BUG_ON(!RB_EMPTY_NODE(&thread->rb_node));
+	BUG_ON(!list_empty(&thread->node));
+
 	thread_stack__free(thread);
 
 	if (thread->mg) {
@@ -84,7 +89,8 @@ void thread__delete(struct thread *thread)
 
 struct thread *thread__get(struct thread *thread)
 {
-	atomic_inc(&thread->refcnt);
+	if (thread)
+		atomic_inc(&thread->refcnt);
 	return thread;
 }
 
Signature · 1 line
2.1.0
author maintainer
#24 lore raw

PATCH 24/30 perf bench futex: Support parallel waker threads

In reply to Arnaldo Carvalho de Melo

From: Davidlohr Bueso <[email protected]>

The futex-wake benchmark only measures wakeups done within a single process. While this has value in its own, it does not really generate any hb->lock contention.

A new benchmark 'wake-parallel' is added, by extending the futex-wake code such that we can measure parallel waker threads. The program output shows the avg per-thread latency in order to complete its share of wakeups:

Run summary [PID 13474]: blocking on 512 threads (at [private] futex 0xa88668), 8 threads waking up 64 at a time.

[Run 1]: Avg per-thread latency (waking 64/512 threads) in 0.6230 ms (+-15.31%) [Run 2]: Avg per-thread latency (waking 64/512 threads) in 0.5175 ms (+-29.95%) [Run 3]: Avg per-thread latency (waking 64/512 threads) in 0.7578 ms (+-18.03%) [Run 4]: Avg per-thread latency (waking 64/512 threads) in 0.8944 ms (+-12.54%) [Run 5]: Avg per-thread latency (waking 64/512 threads) in 1.1204 ms (+-23.85%) Avg per-thread latency (waking 64/512 threads) in 0.7826 ms (+-9.91%)

Naturally, different combinations of numbers of blocking and waker threads will exhibit different information.

---
 tools/perf/Documentation/perf-bench.txt |   3 +
 tools/perf/bench/Build                  |   1 +
 tools/perf/bench/bench.h                |   2 +
 tools/perf/bench/futex-wake-parallel.c  | 294 ++++++++++++++++++++++++++++++++
 tools/perf/builtin-bench.c              |   1 +
 5 files changed, 301 insertions(+)
 create mode 100644 tools/perf/bench/futex-wake-parallel.c
tools/perf/Documentation/perf-bench.txt +3 -0
index f6480cb..bf3d064 100644
@@ -210,6 +210,9 @@ Suite for evaluating hash tables.
 *wake*::
 Suite for evaluating wake calls.
 
+*wake-parallel*::
+Suite for evaluating parallel wake calls.
+
 *requeue*::
 Suite for evaluating requeue calls.
 
tools/perf/bench/Build +1 -0
index 5ce9802..c3ab760 100644
@@ -3,6 +3,7 @@ perf-y += sched-pipe.o
 perf-y += mem-memcpy.o
 perf-y += futex-hash.o
 perf-y += futex-wake.o
+perf-y += futex-wake-parallel.o
 perf-y += futex-requeue.o
 
 perf-$(CONFIG_X86_64) += mem-memcpy-x86-64-asm.o
tools/perf/bench/bench.h +2 -0
index 3c4dd44..70b2f71 100644
@@ -33,6 +33,8 @@ extern int bench_mem_memcpy(int argc, const char **argv,
 extern int bench_mem_memset(int argc, const char **argv, const char *prefix);
 extern int bench_futex_hash(int argc, const char **argv, const char *prefix);
 extern int bench_futex_wake(int argc, const char **argv, const char *prefix);
+extern int bench_futex_wake_parallel(int argc, const char **argv,
+				     const char *prefix);
 extern int bench_futex_requeue(int argc, const char **argv, const char *prefix);
 
 #define BENCH_FORMAT_DEFAULT_STR	"default"
tools/perf/bench/futex-wake-parallel.c new file +294 -0

294 lines not on this page · raw message

tools/perf/builtin-bench.c +1 -0
index b9a56fa..b5314e4 100644
@@ -58,6 +58,7 @@ static struct bench mem_benchmarks[] = {
 static struct bench futex_benchmarks[] = {
 	{ "hash",	"Benchmark for futex hash table",               bench_futex_hash	},
 	{ "wake",	"Benchmark for futex wake calls",               bench_futex_wake	},
+	{ "wake-parallel", "Benchmark for parallel futex wake calls",   bench_futex_wake_parallel },
 	{ "requeue",	"Benchmark for futex requeue calls",            bench_futex_requeue	},
 	{ "all",	"Test all futex benchmarks",			NULL			},
 	{ NULL,		NULL,						NULL			}
Signature · 1 line
2.1.0
author maintainer
#25 lore raw

PATCH 25/30 perf bench futex: Handle spurious wakeups

In reply to Arnaldo Carvalho de Melo

From: Davidlohr Bueso <[email protected]>

Wrap futex_wait around a loop and catch for EINTR.

Either a spurious wakeup occurred or a signal interrupted is, either way we need to block again.

---
 tools/perf/bench/futex-wake.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
tools/perf/bench/futex-wake.c +6 -1
index 929f762..e5e41d3 100644
@@ -60,7 +60,12 @@ static void *workerfn(void *arg __maybe_unused)
 	pthread_cond_wait(&thread_worker, &thread_lock);
 	pthread_mutex_unlock(&thread_lock);
 
-	futex_wait(&futex1, 0, NULL, futex_flag);
+	while (1) {
+		if (futex_wait(&futex1, 0, NULL, futex_flag) != EINTR)
+			break;
+	}
+
+	pthread_exit(NULL);
 	return NULL;
 }
 
Signature · 1 line
2.1.0
author maintainer
#26 lore raw

PATCH 26/30 perf probe: Use perf_probe_event.target instead of passing as an argument

In reply to Arnaldo Carvalho de Melo

From: Masami Hiramatsu <[email protected]>

Use perf_probe_event.target field for the target binary instead of passing it as an argument.

---
 tools/perf/builtin-probe.c    |  1 -
 tools/perf/util/probe-event.c | 55 ++++++++++++++++++++-----------------------
 tools/perf/util/probe-event.h |  4 ++--
 3 files changed, 27 insertions(+), 33 deletions(-)
tools/perf/builtin-probe.c +0 -1
index 9c4cf5e..233f941 100644
@@ -478,7 +478,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 
 		ret = show_available_vars(params.events, params.nevents,
 					  params.max_probe_points,
-					  params.target,
 					  params.filter,
 					  params.show_ext_vars);
 		if (ret < 0)
tools/perf/util/probe-event.c +25 -30

192 lines not on this page · raw message

tools/perf/util/probe-event.h +2 -2
index e10aedc..e3d9bb1 100644
@@ -131,8 +131,8 @@ extern int show_perf_probe_events(struct strfilter *filter);
 extern int show_line_range(struct line_range *lr, const char *module,
 			   bool user);
 extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
-			       int max_probe_points, const char *module,
-			       struct strfilter *filter, bool externs);
+			       int max_probe_points, struct strfilter *filter,
+			       bool externs);
 extern int show_available_funcs(const char *module, struct strfilter *filter,
 				bool user);
 bool arch__prefers_symtab(void);
Signature · 1 line
2.1.0
author maintainer
#27 lore raw

PATCH 27/30 perf probe: Introduce probe_conf global configs

In reply to Arnaldo Carvalho de Melo

From: Masami Hiramatsu <[email protected]>

Introduce probe_conf global configuration parameters for probe-event and probe-finder, and removes related parameters from APIs.

---
 tools/perf/builtin-probe.c     | 21 ++++++-----------
 tools/perf/util/probe-event.c  | 53 ++++++++++++++++++------------------------
 tools/perf/util/probe-event.h  | 13 +++++++----
 tools/perf/util/probe-finder.c | 17 +++++++-------
 tools/perf/util/probe-finder.h |  7 ++----
 5 files changed, 48 insertions(+), 63 deletions(-)
tools/perf/builtin-probe.c +7 -14
index 233f941..dbc998f 100644
@@ -50,8 +50,6 @@
 static struct {
 	int command;	/* Command short_name */
 	bool list_events;
-	bool force_add;
-	bool show_ext_vars;
 	bool uprobes;
 	bool quiet;
 	bool target_used;
@@ -59,7 +57,6 @@ static struct {
 	struct perf_probe_event events[MAX_PROBES];
 	struct line_range line_range;
 	char *target;
-	int max_probe_points;
 	struct strfilter *filter;
 } params;
 
@@ -364,7 +361,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 		"\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
 #endif
 		opt_add_probe_event),
-	OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events"
+	OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
 		    " with existing name"),
 #ifdef HAVE_DWARF_SUPPORT
 	OPT_CALLBACK('L', "line", NULL,
@@ -373,7 +370,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_CALLBACK('V', "vars", NULL,
 		     "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
 		     "Show accessible variables on PROBEDEF", opt_show_vars),
-	OPT_BOOLEAN('\0', "externs", &params.show_ext_vars,
+	OPT_BOOLEAN('\0', "externs", &probe_conf.show_ext_vars,
 		    "Show external variables too (with --vars only)"),
 	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
 		   "file", "vmlinux pathname"),
@@ -384,7 +381,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 		opt_set_target),
 #endif
 	OPT__DRY_RUN(&probe_event_dry_run),
-	OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
+	OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
 		 "Set how many probe points can be found for a probe."),
 	OPT_CALLBACK_DEFAULT('F', "funcs", NULL, "[FILTER]",
 			     "Show potential probe-able functions.",
@@ -440,8 +437,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 		verbose = -1;
 	}
 
-	if (params.max_probe_points == 0)
-		params.max_probe_points = MAX_PROBES;
+	if (probe_conf.max_probes == 0)
+		probe_conf.max_probes = MAX_PROBES;
 
 	/*
 	 * Only consider the user's kernel image path if given.
@@ -477,9 +474,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 						       NULL);
 
 		ret = show_available_vars(params.events, params.nevents,
-					  params.max_probe_points,
-					  params.filter,
-					  params.show_ext_vars);
+					  params.filter);
 		if (ret < 0)
 			pr_err_with_code("  Error: Failed to show vars.", ret);
 		return ret;
@@ -498,9 +493,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 			usage_with_options(probe_usage, options);
 		}
 
-		ret = add_perf_probe_events(params.events, params.nevents,
-					    params.max_probe_points,
-					    params.force_add);
+		ret = add_perf_probe_events(params.events, params.nevents);
 		if (ret < 0) {
 			pr_err_with_code("  Error: Failed to add events.", ret);
 			return ret;
tools/perf/util/probe-event.c +22 -31

165 lines not on this page · raw message

tools/perf/util/probe-event.h +9 -4
index e3d9bb1..db9a9cb2 100644
@@ -6,6 +6,13 @@
 #include "strlist.h"
 #include "strfilter.h"
 
+/* Probe related configurations */
+struct probe_conf {
+	bool	show_ext_vars;
+	bool	force_add;
+	int	max_probes;
+};
+extern struct probe_conf probe_conf;
 extern bool probe_event_dry_run;
 
 /* kprobe-tracer and uprobe-tracer tracing point */
@@ -124,15 +131,13 @@ extern int line_range__init(struct line_range *lr);
 /* Internal use: Return kernel/module path */
 extern const char *kernel_get_module_path(const char *module);
 
-extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
-				 int max_probe_points, bool force_add);
+extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
 extern int del_perf_probe_events(struct strfilter *filter);
 extern int show_perf_probe_events(struct strfilter *filter);
 extern int show_line_range(struct line_range *lr, const char *module,
 			   bool user);
 extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
-			       int max_probe_points, struct strfilter *filter,
-			       bool externs);
+			       struct strfilter *filter);
 extern int show_available_funcs(const char *module, struct strfilter *filter,
 				bool user);
 bool arch__prefers_symtab(void);
tools/perf/util/probe-finder.c +8 -9
index 63d3389..f4f5eed 100644
@@ -1214,15 +1214,15 @@ end:
 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
 int debuginfo__find_trace_events(struct debuginfo *dbg,
 				 struct perf_probe_event *pev,
-				 struct probe_trace_event **tevs, int max_tevs)
+				 struct probe_trace_event **tevs)
 {
 	struct trace_event_finder tf = {
 			.pf = {.pev = pev, .callback = add_probe_trace_event},
-			.mod = dbg->mod, .max_tevs = max_tevs};
+			.max_tevs = probe_conf.max_probes, .mod = dbg->mod};
 	int ret;
 
 	/* Allocate result tevs array */
-	*tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs);
+	*tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs);
 	if (*tevs == NULL)
 		return -ENOMEM;
 
@@ -1303,9 +1303,9 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
 	die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);
 
 	/* Find external variables */
-	if (!af->externs)
+	if (!probe_conf.show_ext_vars)
 		goto out;
-	/* Don't need to search child DIE for externs. */
+	/* Don't need to search child DIE for external vars. */
 	af->child = false;
 	die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
 
@@ -1325,17 +1325,16 @@ out:
  */
 int debuginfo__find_available_vars_at(struct debuginfo *dbg,
 				      struct perf_probe_event *pev,
-				      struct variable_list **vls,
-				      int max_vls, bool externs)
+				      struct variable_list **vls)
 {
 	struct available_var_finder af = {
 			.pf = {.pev = pev, .callback = add_available_vars},
 			.mod = dbg->mod,
-			.max_vls = max_vls, .externs = externs};
+			.max_vls = probe_conf.max_probes};
 	int ret;
 
 	/* Allocate result vls array */
-	*vls = zalloc(sizeof(struct variable_list) * max_vls);
+	*vls = zalloc(sizeof(struct variable_list) * af.max_vls);
 	if (*vls == NULL)
 		return -ENOMEM;
 
tools/perf/util/probe-finder.h +2 -5
index f53553d..bed8271 100644
@@ -40,8 +40,7 @@ extern void debuginfo__delete(struct debuginfo *dbg);
 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
 extern int debuginfo__find_trace_events(struct debuginfo *dbg,
 					struct perf_probe_event *pev,
-					struct probe_trace_event **tevs,
-					int max_tevs);
+					struct probe_trace_event **tevs);
 
 /* Find a perf_probe_point from debuginfo */
 extern int debuginfo__find_probe_point(struct debuginfo *dbg,
@@ -55,8 +54,7 @@ extern int debuginfo__find_line_range(struct debuginfo *dbg,
 /* Find available variables */
 extern int debuginfo__find_available_vars_at(struct debuginfo *dbg,
 					     struct perf_probe_event *pev,
-					     struct variable_list **vls,
-					     int max_points, bool externs);
+					     struct variable_list **vls);
 
 /* Find a src file from a DWARF tag path */
 int get_real_path(const char *raw_path, const char *comp_dir,
@@ -99,7 +97,6 @@ struct available_var_finder {
 	struct variable_list	*vls;		/* Found variable lists */
 	int			nvls;		/* Number of variable lists */
 	int			max_vls;	/* Max no. of variable lists */
-	bool			externs;	/* Find external vars too */
 	bool			child;		/* Search child scopes */
 };
 
Signature · 1 line
2.1.0
author maintainer
#28 lore raw

PATCH 28/30 perf probe: Add --no-inlines option to avoid searching inline functions

In reply to Arnaldo Carvalho de Melo

From: Masami Hiramatsu <[email protected]>

Add --no-inlines(--inlines) option to avoid searching inline functions.

Searching all functions which matches glob pattern can take a long time and find a lot of inline functions.

With this option perf-probe searches target on the non-inlined functions.

---
 tools/perf/Documentation/perf-probe.txt | 4 ++++
 tools/perf/builtin-probe.c              | 2 ++
 tools/perf/util/probe-event.h           | 1 +
 tools/perf/util/probe-finder.c          | 2 +-
 4 files changed, 8 insertions(+), 1 deletion(-)
tools/perf/Documentation/perf-probe.txt +4 -0
index ad3e355..3a8a9ba 100644
@@ -83,6 +83,10 @@ OPTIONS
 	(Only for --vars) Show external defined variables in addition to local
 	variables.
 
+--no-inlines::
+	(Only for --add) Search only for non-inlined functions. The functions
+	which do not have instances are ignored.
+
 -F::
 --funcs[=FILTER]::
 	Show available functions in given module or kernel. With -x/--exec,
tools/perf/builtin-probe.c +2 -0
index dbc998f..7fa2c7a 100644
@@ -379,6 +379,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_CALLBACK('m', "module", NULL, "modname|path",
 		"target module name (for online) or path (for offline)",
 		opt_set_target),
+	OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
+		"Don't search inlined functions"),
 #endif
 	OPT__DRY_RUN(&probe_event_dry_run),
 	OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
tools/perf/util/probe-event.h +1 -0
index db9a9cb2..633aba7 100644
@@ -10,6 +10,7 @@
 struct probe_conf {
 	bool	show_ext_vars;
 	bool	force_add;
+	bool	no_inlines;
 	int	max_probes;
 };
 extern struct probe_conf probe_conf;
tools/perf/util/probe-finder.c +1 -1
index f4f5eed..1713421 100644
@@ -943,7 +943,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
 			/* TODO: Check the address in this function */
 			param->retval = call_probe_finder(sp_die, pf);
 		}
-	} else
+	} else if (!probe_conf.no_inlines)
 		/* Inlined function: search instances */
 		param->retval = die_walk_instances(sp_die,
 					probe_point_inline_cb, (void *)pf);
Signature · 1 line
2.1.0
author maintainer
#29 lore raw

PATCH 29/30 perf probe: Support glob wildcards for function name

In reply to Arnaldo Carvalho de Melo

From: Masami Hiramatsu <[email protected]>

Support glob wildcards for function name when adding new probes. This will allow us to build caches of function-entry level information with $params.

e.g.
----

  # perf probe --no-inlines --add 'kmalloc* $params'
  Added new events:
    probe:kmalloc_slab   (on kmalloc* with $params)
    probe:kmalloc_large_node (on kmalloc* with $params)
    probe:kmalloc_order_trace (on kmalloc* with $params)

You can now use it in all perf tools, such as:

perf record -e probe:kmalloc_order_trace -aR sleep 1

  # perf probe --list
    probe:kmalloc_large_node (on kmalloc_large_node@mm/slub.c with size flags node)
    probe:kmalloc_order_trace (on kmalloc_order_trace@mm/slub.c with size flags order)
    probe:kmalloc_slab   (on kmalloc_slab@mm/slab_common.c with size flags)
  ----
---
 tools/perf/util/dwarf-aux.c    | 16 ++++++++++++++++
 tools/perf/util/dwarf-aux.h    |  3 +++
 tools/perf/util/probe-event.c  | 19 ++++++++++++++-----
 tools/perf/util/probe-event.h  |  1 +
 tools/perf/util/probe-finder.c | 27 +++++++++++++++++++++------
 tools/perf/util/util.h         |  4 ++++
 6 files changed, 59 insertions(+), 11 deletions(-)
tools/perf/util/dwarf-aux.c +16 -0
index c34e024..16d46e2 100644
@@ -139,11 +139,27 @@ int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
 bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
 {
 	const char *name;
+
 	name = dwarf_diename(dw_die);
 	return name ? (strcmp(tname, name) == 0) : false;
 }
 
 /**
+ * die_match_name - Match diename and glob
+ * @dw_die: a DIE
+ * @glob: a string of target glob pattern
+ *
+ * Glob matching the name of @dw_die and @glob. Return false if matching fail.
+ */
+bool die_match_name(Dwarf_Die *dw_die, const char *glob)
+{
+	const char *name;
+
+	name = dwarf_diename(dw_die);
+	return name ? strglobmatch(name, glob) : false;
+}
+
+/**
  * die_get_call_lineno - Get callsite line number of inline-function instance
  * @in_die: a DIE of an inlined function instance
  *
tools/perf/util/dwarf-aux.h +3 -0
index af7dbcd..50a3cdc 100644
@@ -47,6 +47,9 @@ extern bool die_is_func_instance(Dwarf_Die *dw_die);
 /* Compare diename and tname */
 extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
 
+/* Matching diename with glob pattern */
+extern bool die_match_name(Dwarf_Die *dw_die, const char *glob);
+
 /* Get callsite line number of inline-function instance */
 extern int die_get_call_lineno(Dwarf_Die *in_die);
 
tools/perf/util/probe-event.c +14 -5
index a7deda4..a2d8cef 100644
@@ -589,7 +589,11 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
 				if (!tmp)
 					return -ENOMEM;
 			}
-			free(tevs[i].point.symbol);
+			/* If we have no realname, use symbol for it */
+			if (!tevs[i].point.realname)
+				tevs[i].point.realname = tevs[i].point.symbol;
+			else
+				free(tevs[i].point.symbol);
 			tevs[i].point.symbol = tmp;
 			tevs[i].point.offset = tevs[i].point.address -
 					       reloc_sym->unrelocated_addr;
@@ -1900,6 +1904,7 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
 	free(tev->event);
 	free(tev->group);
 	free(tev->point.symbol);
+	free(tev->point.realname);
 	free(tev->point.module);
 	for (i = 0; i < tev->nargs; i++) {
 		free(tev->args[i].name);
@@ -2377,6 +2382,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 	struct strlist *namelist;
 	LIST_HEAD(blacklist);
 	struct kprobe_blacklist_node *node;
+	bool safename;
 
 	if (pev->uprobes)
 		fd = open_uprobe_events(true);
@@ -2402,6 +2408,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 			pr_debug("No kprobe blacklist support, ignored\n");
 	}
 
+	safename = (pev->point.function && !strisglob(pev->point.function));
 	ret = 0;
 	pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
 	for (i = 0; i < ntevs; i++) {
@@ -2420,10 +2427,10 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 		if (pev->event)
 			event = pev->event;
 		else
-			if (pev->point.function)
+			if (safename)
 				event = pev->point.function;
 			else
-				event = tev->point.symbol;
+				event = tev->point.realname;
 		if (pev->group)
 			group = pev->group;
 		else
@@ -2488,9 +2495,11 @@ static int find_probe_functions(struct map *map, char *name)
 {
 	int found = 0;
 	struct symbol *sym;
+	struct rb_node *tmp;
 
-	map__for_each_symbol_by_name(map, name, sym) {
-		found++;
+	map__for_each_symbol(map, sym, tmp) {
+		if (strglobmatch(sym->name, name))
+			found++;
 	}
 
 	return found;
tools/perf/util/probe-event.h +1 -0
index 633aba7..1e2faa3 100644
@@ -18,6 +18,7 @@ extern bool probe_event_dry_run;
 
 /* kprobe-tracer and uprobe-tracer tracing point */
 struct probe_trace_point {
+	char		*realname;	/* function real name (if needed) */
 	char		*symbol;	/* Base symbol */
 	char		*module;	/* Module name */
 	unsigned long	offset;		/* Offset from symbol */
tools/perf/util/probe-finder.c +21 -6
index 1713421..d5f60c0 100644
@@ -717,7 +717,7 @@ static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
 	}
 	/* If the function name is given, that's what user expects */
 	if (fsp->function) {
-		if (die_compare_name(fn_die, fsp->function)) {
+		if (die_match_name(fn_die, fsp->function)) {
 			memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
 			fsp->found = true;
 			return 1;
@@ -920,13 +920,14 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
 
 	/* Check tag and diename */
 	if (!die_is_func_def(sp_die) ||
-	    !die_compare_name(sp_die, pp->function))
+	    !die_match_name(sp_die, pp->function))
 		return DWARF_CB_OK;
 
 	/* Check declared file */
 	if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
 		return DWARF_CB_OK;
 
+	pr_debug("Matched function: %s\n", dwarf_diename(sp_die));
 	pf->fname = dwarf_decl_file(sp_die);
 	if (pp->line) { /* Function relative line */
 		dwarf_decl_line(sp_die, &pf->lno);
@@ -943,10 +944,20 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
 			/* TODO: Check the address in this function */
 			param->retval = call_probe_finder(sp_die, pf);
 		}
-	} else if (!probe_conf.no_inlines)
+	} else if (!probe_conf.no_inlines) {
 		/* Inlined function: search instances */
 		param->retval = die_walk_instances(sp_die,
 					probe_point_inline_cb, (void *)pf);
+		/* This could be a non-existed inline definition */
+		if (param->retval == -ENOENT && strisglob(pp->function))
+			param->retval = 0;
+	}
+
+	/* We need to find other candidates */
+	if (strisglob(pp->function) && param->retval >= 0) {
+		param->retval = 0;	/* We have to clear the result */
+		return DWARF_CB_OK;
+	}
 
 	return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
 }
@@ -975,7 +986,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
 		if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
 			return DWARF_CB_OK;
 
-		if (die_compare_name(param->sp_die, param->function)) {
+		if (die_match_name(param->sp_die, param->function)) {
 			if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
 				return DWARF_CB_OK;
 
@@ -1028,7 +1039,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
 		return -ENOMEM;
 
 	/* Fastpath: lookup by function name from .debug_pubnames section */
-	if (pp->function) {
+	if (pp->function && !strisglob(pp->function)) {
 		struct pubname_callback_param pubname_param = {
 			.function = pp->function,
 			.file	  = pp->file,
@@ -1177,6 +1188,10 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
 	if (ret < 0)
 		return ret;
 
+	tev->point.realname = strdup(dwarf_diename(sc_die));
+	if (!tev->point.realname)
+		return -ENOMEM;
+
 	pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
 		 tev->point.offset);
 
@@ -1535,7 +1550,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
 		return DWARF_CB_OK;
 
 	if (die_is_func_def(sp_die) &&
-	    die_compare_name(sp_die, lr->function)) {
+	    die_match_name(sp_die, lr->function)) {
 		lf->fname = dwarf_decl_file(sp_die);
 		dwarf_decl_line(sp_die, &lr->offset);
 		pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
tools/perf/util/util.h +4 -0
index 1ff23e0..3601ffd 100644
@@ -257,6 +257,10 @@ char **argv_split(const char *str, int *argcp);
 void argv_free(char **argv);
 bool strglobmatch(const char *str, const char *pat);
 bool strlazymatch(const char *str, const char *pat);
+static inline bool strisglob(const char *str)
+{
+	return strpbrk(str, "*?[") != NULL;
+}
 int strtailcmp(const char *s1, const char *s2);
 char *strxfrchar(char *s, char from, char to);
 unsigned long convert_unit(unsigned long value, char *unit);
Signature · 1 line
2.1.0
author maintainer
#30 lore raw

PATCH 30/30 perf build: Disable libdw DWARF unwind when built with NO_DWARF

In reply to Arnaldo Carvalho de Melo

From: "Naveen N. Rao" <[email protected]>

We get a linker error if we try to build with NO_DWARF since we build util/unwind-libdw.c, but do not include -ldw

---
 tools/perf/config/Makefile | 4 ++++
 1 file changed, 4 insertions(+)
tools/perf/config/Makefile +4 -0
index 435b6ca..1b957a1 100644
@@ -268,6 +268,10 @@ else
   endif # libelf support
 endif # NO_LIBELF
 
+ifdef NO_DWARF
+  NO_LIBDW_DWARF_UNWIND := 1
+endif
+
 ifndef NO_LIBELF
   CFLAGS += -DHAVE_LIBELF_SUPPORT
   EXTLIBS += -lelf
Signature · 1 line
2.1.0
#31 lore raw
In reply to Arnaldo Carvalho de Melo
Quoted 186 lines · Arnaldo Carvalho de Melo

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit cb307113746b4d184155d2c412e8069aeaa60d42:

perf_event: Don't allow vmalloc() backed perf on powerpc (2015-05-08 12:26:01 +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

for you to fetch changes up to 76d408498b08447e0f61dfdd611aeb6e8e61ce80:

perf build: Disable libdw DWARF unwind when built with NO_DWARF (2015-05-08 16:43:14 -0300)

----------------------------------------------------------------
perf/core improvements and fixes:

User visible:

- 'perf probe' improvements (Masami Hiramatsu)

- Support glob wildcards for function name
- Support $params special probe argument: Collect all function arguments
- Make --line checks validate C-style function name.
- Add --no-inlines option to avoid searching inline functions

- Introduce new 'perf bench futex' benchmark: 'wake-parallel', to measure parallel waker threads generating contention for kerne locks (hb->lock) (Davidlohr Bueso)

Bug fixes:

- 'perf top' survives much longer on high core count machines, more work needed to refcount more data structures besides 'struct thread' and fix more races (Arnaldo Carvalho de Melo)

Infrastructure:

- Move barrier.h mb/rmb/wmb API from tools/perf/ to kernel like tools/arch/ hierarchy (Arnaldo Carvalho de Melo)

- Borrow atomic.h from the kernel, initially the x86 implementations with a fallback to gcc intrinsics for the other arches, all the kernel like framework in place for doing arch specific implementations, preferrably cloning what is in the kernel to the greater extent possible (Arnaldo Carvalho de Melo)

- Protect the 'struct thread' lifetime with a reference counter, and protect data structures that contains its instances with a mutex (Arnaldo Carvalho de Melo

- Disable libdw DWARF unwind when built with NO_DWARF (Naveen N. Rao)

----------------------------------------------------------------
Arnaldo Carvalho de Melo (17):
perf tools: Move x86 barrier.h stuff to tools/arch/x86/include/asm/barrier.h perf tools: Move powerpc barrier.h stuff to tools/arch/powerpc/include/asm/barrier.h perf tools: Move s390 barrier.h stuff to tools/arch/s390/include/asm/barrier.h perf tools: Move barrier() definition to tools/include/linux/compiler.h
tools: Adopt asm-generic/barrier.h
perf tools: Move sh barrier.h stuff to tools/arch/sh/include/asm/barrier.h perf tools: Move sparc barrier.h stuff to tools/arch/sparc/include/asm/barrier.h perf tools: Move alpha barrier.h stuff to tools/arch/alpha/include/asm/barrier.h perf tools: Move ia64 barrier.h stuff to tools/arch/ia64/include/asm/barrier.h perf tools: Move arm(64) barrier.h stuff to tools/arch/arm*/include/asm/barrier.h perf tools: Move xtensa barrier.h stuff to tools/arch/xtensa/include/asm/barrier.h perf tools: Move mips barrier.h stuff to tools/arch/mips/include/asm/barrier.h perf tools: Move tile barrier.h stuff to tools/arch/tile/include/asm/barrier.h perf tools: Move generic barriers out of perf-sys.h
tools include: Add basic atomic.h implementation from the kernel sources perf tools: Use atomic_t to implement thread__{get,put} refcnt
perf machine: Protect the machine->threads with a rwlock

Davidlohr Bueso (2):
perf bench futex: Support parallel waker threads perf bench futex: Handle spurious wakeups

Masami Hiramatsu (10):
perf probe: Fix to close probe_events file in error
perf probe: Fix a typo for the flags of open
perf probe: Fix to return 0 when positive value returned perf probe: Make --line checks validate C-style function name perf probe: Skip kernel symbols which is out of .text
perf probe: Support $params special probe argument
perf probe: Use perf_probe_event.target instead of passing as an argument perf probe: Introduce probe_conf global configs
perf probe: Add --no-inlines option to avoid searching inline functions perf probe: Support glob wildcards for function name

Naveen N. Rao (1):
perf build: Disable libdw DWARF unwind when built with NO_DWARF

 tools/arch/alpha/include/asm/barrier.h    |   8 +
 tools/arch/arm/include/asm/barrier.h      |  12 ++
 tools/arch/arm64/include/asm/barrier.h    |  16 ++
 tools/arch/ia64/include/asm/barrier.h     |  48 +++++
 tools/arch/mips/include/asm/barrier.h     |  20 ++
 tools/arch/powerpc/include/asm/barrier.h  |  29 +++
 tools/arch/s390/include/asm/barrier.h     |  30 +++
 tools/arch/sh/include/asm/barrier.h       |  32 ++++
 tools/arch/sparc/include/asm/barrier.h    |   8 +
 tools/arch/sparc/include/asm/barrier_32.h |   6 +
 tools/arch/sparc/include/asm/barrier_64.h |  42 +++++
 tools/arch/tile/include/asm/barrier.h     |  15 ++
 tools/arch/x86/include/asm/atomic.h       |  65 +++++++
 tools/arch/x86/include/asm/barrier.h      |  28 +++
 tools/arch/x86/include/asm/rmwcc.h        |  41 +++++
 tools/arch/xtensa/include/asm/barrier.h   |  18 ++
 tools/include/asm-generic/atomic-gcc.h    |  63 +++++++
 tools/include/asm-generic/barrier.h       |  44 +++++
 tools/include/asm/atomic.h                |  10 +
 tools/include/asm/barrier.h               |  27 +++
 tools/include/linux/atomic.h              |   6 +
 tools/include/linux/compiler.h            |   4 +
 tools/include/linux/types.h               |   4 +
 tools/perf/Documentation/perf-bench.txt   |   3 +
 tools/perf/Documentation/perf-probe.txt   |   6 +-
 tools/perf/MANIFEST                       |  19 ++
 tools/perf/bench/Build                    |   1 +
 tools/perf/bench/bench.h                  |   2 +
 tools/perf/bench/futex-wake-parallel.c    | 294 ++++++++++++++++++++++++++++++
 tools/perf/bench/futex-wake.c             |   7 +-
 tools/perf/builtin-annotate.c             |  10 +-
 tools/perf/builtin-bench.c                |   1 +
 tools/perf/builtin-diff.c                 |   9 +-
 tools/perf/builtin-inject.c               |   1 +
 tools/perf/builtin-kmem.c                 |   7 +-
 tools/perf/builtin-kvm.c                  |   6 +-
 tools/perf/builtin-lock.c                 |   8 +-
 tools/perf/builtin-mem.c                  |   5 +-
 tools/perf/builtin-probe.c                |  26 +--
 tools/perf/builtin-report.c               |   9 +-
 tools/perf/builtin-sched.c                |  82 ++++++---
 tools/perf/builtin-script.c               |  20 +-
 tools/perf/builtin-timechart.c            |   5 +-
 tools/perf/builtin-top.c                  |   2 +-
 tools/perf/builtin-trace.c                |  36 ++--
 tools/perf/config/Makefile                |   4 +
 tools/perf/perf-sys.h                     |  73 +-------
 tools/perf/tests/code-reading.c           |  22 ++-
 tools/perf/tests/dwarf-unwind.c           |   1 +
 tools/perf/tests/hists_common.c           |   1 +
 tools/perf/tests/hists_cumulate.c         |   4 +-
 tools/perf/tests/hists_filter.c           |   4 +-
 tools/perf/tests/hists_link.c             |   8 +-
 tools/perf/tests/hists_output.c           |   4 +-
 tools/perf/tests/mmap-thread-lookup.c     |   2 +
 tools/perf/tests/thread-mg-share.c        |  12 +-
 tools/perf/util/build-id.c                |   5 +-
 tools/perf/util/db-export.c               |  14 +-
 tools/perf/util/dwarf-aux.c               |  16 ++
 tools/perf/util/dwarf-aux.h               |   3 +
 tools/perf/util/event.c                   |  15 ++
 tools/perf/util/event.h                   |   2 +
 tools/perf/util/machine.c                 |  89 +++++++--
 tools/perf/util/machine.h                 |   5 +-
 tools/perf/util/probe-event.c             | 177 ++++++++++--------
 tools/perf/util/probe-event.h             |  15 +-
 tools/perf/util/probe-finder.c            |  73 +++++---
 tools/perf/util/probe-finder.h            |  10 +-
 tools/perf/util/thread.c                  |  14 +-
 tools/perf/util/thread.h                  |   3 +-
 tools/perf/util/util.h                    |   4 +
 71 files changed, 1392 insertions(+), 323 deletions(-)
 create mode 100644 tools/arch/alpha/include/asm/barrier.h
 create mode 100644 tools/arch/arm/include/asm/barrier.h
 create mode 100644 tools/arch/arm64/include/asm/barrier.h
 create mode 100644 tools/arch/ia64/include/asm/barrier.h
 create mode 100644 tools/arch/mips/include/asm/barrier.h
 create mode 100644 tools/arch/powerpc/include/asm/barrier.h
 create mode 100644 tools/arch/s390/include/asm/barrier.h
 create mode 100644 tools/arch/sh/include/asm/barrier.h
 create mode 100644 tools/arch/sparc/include/asm/barrier.h
 create mode 100644 tools/arch/sparc/include/asm/barrier_32.h
 create mode 100644 tools/arch/sparc/include/asm/barrier_64.h
 create mode 100644 tools/arch/tile/include/asm/barrier.h
 create mode 100644 tools/arch/x86/include/asm/atomic.h
 create mode 100644 tools/arch/x86/include/asm/barrier.h
Quoted 8 lines
 create mode 100644 tools/arch/x86/include/asm/rmwcc.h
 create mode 100644 tools/arch/xtensa/include/asm/barrier.h
 create mode 100644 tools/include/asm-generic/atomic-gcc.h
 create mode 100644 tools/include/asm-generic/barrier.h
 create mode 100644 tools/include/asm/atomic.h
 create mode 100644 tools/include/asm/barrier.h
 create mode 100644 tools/include/linux/atomic.h
 create mode 100644 tools/perf/bench/futex-wake-parallel.c

Pulled, thanks a lot Arnaldo!

Ingo

maintainer
#32 lore raw
In reply to Arnaldo Carvalho de Melo

Hi Arnaldo,

Quoted 36 lines · Arnaldo Carvalho de Melo

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit cb307113746b4d184155d2c412e8069aeaa60d42:

perf_event: Don't allow vmalloc() backed perf on powerpc (2015-05-08 12:26:01 +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

for you to fetch changes up to 76d408498b08447e0f61dfdd611aeb6e8e61ce80:

perf build: Disable libdw DWARF unwind when built with NO_DWARF (2015-05-08 16:43:14 -0300)

----------------------------------------------------------------
perf/core improvements and fixes:

User visible:

- 'perf probe' improvements (Masami Hiramatsu)

- Support glob wildcards for function name
- Support $params special probe argument: Collect all function arguments
- Make --line checks validate C-style function name.
- Add --no-inlines option to avoid searching inline functions

- Introduce new 'perf bench futex' benchmark: 'wake-parallel', to measure parallel waker threads generating contention for kerne locks (hb->lock) (Davidlohr Bueso)

Quoted 5 lines

Bug fixes:

- 'perf top' survives much longer on high core count machines, more work needed to refcount more data structures besides 'struct thread' and fix more races (Arnaldo Carvalho de Melo)

I'm seeing a segfault on 'perf report' with a large data file after applying thread refcount change - it happens regardless of the atomic operation.

Thanks,
Namhyung

author maintainer
#33 lore raw

Em Mon, May 11, 2015 at 02:09:39PM +0900, Namhyung Kim escreveu:

Quoted 5 lines

Hi Arnaldo,

I'm seeing a segfault on 'perf report' with a large data file after applying thread refcount change - it happens regardless of the atomic operation.

Any specific 'perf record' command line? Does it take a long time to reproduce? Any backtraces? I'll try to repro, its possible that we're doing one too many thread__put()...

- Arnaldo

maintainer
#34 lore raw
Quoted 10 lines · Arnaldo Carvalho de Melo

Em Mon, May 11, 2015 at 02:09:39PM +0900, Namhyung Kim escreveu:

Quoted 5 lines

Hi Arnaldo,

I'm seeing a segfault on 'perf report' with a large data file after applying thread refcount change - it happens regardless of the atomic operation.

Any specific 'perf record' command line? Does it take a long time to reproduce? Any backtraces? I'll try to repro, its possible that we're doing one too many thread__put()...

It's a kernel build with '-j 20' and recorded data size is ~2.1GB. It takes ~30 sec to reproduce.

  $ perf report -i threaded/kbuild7.data --header-only
  # ========
  # captured on: Thu Dec 18 12:06:35 2014
  # hostname : sejong
  # os release : 3.17.4-1-ARCH
  # perf version : 3.18.rc3.gcb4774b
  # arch : x86_64
  # nrcpus online : 12
  # nrcpus avail : 12
  # cpudesc : Intel(R) Core(TM) i7-3930K CPU @ 3.20GHz
  # cpuid : GenuineIntel,6,45,7
  # total memory : 24646828 kB
  # cmdline : /home/namhyung/project/linux/tools/perf/perf record -ag -o /home/namhyung/tmp/perf/threaded/kbuild7.data -- make -j20
  # event : name = cycles, , size = 104, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|CALLCHAIN|CPU|PERIOD, disabled = 1, inherit
  # HEADER_CPU_TOPOLOGY info available, use -I to display
  # HEADER_NUMA_TOPOLOGY info available, use -I to display
  # pmu mappings: cpu = 4, software = 1, power = 24, uncore_pcu = 13, tracepoint = 2, uncore_imc_0 = 15, uncore_imc_1 = 16, uncore_imc_2 = 17, uncore_
  # ========
  #
  $ perf data stat -i threaded/kbuild7.data

Total event stats for 'threaded/kbuild7.data' file:

             TOTAL events:   25126492
              MMAP events:        114
              COMM events:     117957
              EXIT events:     240544
          THROTTLE events:         16
        UNTHROTTLE events:         16
              FORK events:     120488
            SAMPLE events:   23878219
             MMAP2 events:     745325
    FINISHED_ROUND events:      23813

Sample event stats:

20,579,564,471,104 cycles

          23,878,219      samples                   #   sampling ratio  99.745% (3989/4000)

       498.736917889 second time sampled
  $ perf report -i threaded/kbuild7.data
  perf: Segmentation fault
  -------- backtrace --------
  perf[0x51c7cb]
  /usr/lib/libc.so.6(+0x33540)[0x7f37eb37e540]
  /usr/lib/libc.so.6(+0x9029e)[0x7f37eb3db29e]
  perf[0x4dd9c8]
  perf(__hists__add_entry+0x188)[0x4e2258]
  perf[0x4e2580]
  perf(hist_entry_iter__add+0x9d)[0x4e2a7d]
  perf[0x437fda]
  perf[0x4c4c8e]
  perf[0x4c5176]
  perf[0x4c8bab]
  perf[0x4c53c2]
  perf[0x4c5f0c]
  perf(perf_session__process_events+0xb3)[0x4c6b23]
  perf(cmd_report+0x12a0)[0x439310]
  perf[0x483ec3]
  perf(main+0x60a)[0x42979a]
  /usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7f37eb36b800]
  perf(_start+0x29)[0x4298b9]
  [0x0]

It seems like some memory area was corrupted..

Thanks,
Namhyung

author maintainer
#35 lore raw

Em Thu, May 14, 2015 at 05:23:30PM +0900, Namhyung Kim escreveu:

Quoted 51 lines · Arnaldo Carvalho de Melo
Quoted 8 lines

Em Mon, May 11, 2015 at 02:09:39PM +0900, Namhyung Kim escreveu:

Quoted 3 lines

I'm seeing a segfault on 'perf report' with a large data file after applying thread refcount change - it happens regardless of the atomic operation.

Any specific 'perf record' command line? Does it take a long time to reproduce? Any backtraces? I'll try to repro, its possible that we're doing one too many thread__put()...

It's a kernel build with '-j 20' and recorded data size is ~2.1GB. It takes ~30 sec to reproduce.

  $ perf report -i threaded/kbuild7.data --header-only
  # ========
  # captured on: Thu Dec 18 12:06:35 2014
  # hostname : sejong
  # os release : 3.17.4-1-ARCH
  # perf version : 3.18.rc3.gcb4774b
  # arch : x86_64
  # nrcpus online : 12
  # nrcpus avail : 12
  # cpudesc : Intel(R) Core(TM) i7-3930K CPU @ 3.20GHz
  # cpuid : GenuineIntel,6,45,7
  # total memory : 24646828 kB
  # cmdline : /home/namhyung/project/linux/tools/perf/perf record -ag -o /home/namhyung/tmp/perf/threaded/kbuild7.data -- make -j20
  # event : name = cycles, , size = 104, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|CALLCHAIN|CPU|PERIOD, disabled = 1, inherit
  # HEADER_CPU_TOPOLOGY info available, use -I to display
  # HEADER_NUMA_TOPOLOGY info available, use -I to display
  # pmu mappings: cpu = 4, software = 1, power = 24, uncore_pcu = 13, tracepoint = 2, uncore_imc_0 = 15, uncore_imc_1 = 16, uncore_imc_2 = 17, uncore_
  # ========
  #
  $ perf data stat -i threaded/kbuild7.data

Total event stats for 'threaded/kbuild7.data' file:

             TOTAL events:   25126492
              MMAP events:        114
              COMM events:     117957
              EXIT events:     240544
          THROTTLE events:         16
        UNTHROTTLE events:         16
              FORK events:     120488
            SAMPLE events:   23878219
             MMAP2 events:     745325
    FINISHED_ROUND events:      23813

Sample event stats:

Quoted 7 lines

20,579,564,471,104 cycles

          23,878,219      samples                   #   sampling ratio  99.745% (3989/4000)

       498.736917889 second time sampled
  $ perf report -i threaded/kbuild7.data

We need to improve this segfault backtrace, I have to always use addr2line to resolve those missing entries, i.e. if you try:

addr2line -fe /path/to/your/perf 0x4dd9c8
addr2line -fe /path/to/your/perf 0x4e2580

We would have resolved those lines :-/

But I think this is a longstanding bug in handling hist_entries, i.e. probably we have more than one pointer to a hist_entry and are accessing it in two places at the same time, with one of them deleting it and possibly reusing the data.

Quoted 23 lines

perf: Segmentation fault
-------- backtrace --------
perf[0x51c7cb] /usr/lib/libc.so.6(+0x33540)[0x7f37eb37e540] /usr/lib/libc.so.6(+0x9029e)[0x7f37eb3db29e] perf[0x4dd9c8] perf(__hists__add_entry+0x188)[0x4e2258] perf[0x4e2580] perf(hist_entry_iter__add+0x9d)[0x4e2a7d] perf[0x437fda]
perf[0x4c4c8e]
perf[0x4c5176]
perf[0x4c8bab]
perf[0x4c53c2]
perf[0x4c5f0c] perf(perf_session__process_events+0xb3)[0x4c6b23] perf(cmd_report+0x12a0)[0x439310]
perf[0x483ec3]
perf(main+0x60a)[0x42979a] /usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7f37eb36b800] perf(_start+0x29)[0x4298b9]
[0x0]

Quoted 1 line

It seems like some memory area was corrupted..

Right, looks like use after free, for instance, freeing something still on a list or rbtree :-/

- Arnaldo

maintainer
#36 lore raw

Hi Arnaldo,

Quoted 60 lines · Arnaldo Carvalho de Melo

Em Thu, May 14, 2015 at 05:23:30PM +0900, Namhyung Kim escreveu:

Quoted 51 lines · Arnaldo Carvalho de Melo
Quoted 8 lines

Em Mon, May 11, 2015 at 02:09:39PM +0900, Namhyung Kim escreveu:

Quoted 3 lines

I'm seeing a segfault on 'perf report' with a large data file after applying thread refcount change - it happens regardless of the atomic operation.

Any specific 'perf record' command line? Does it take a long time to reproduce? Any backtraces? I'll try to repro, its possible that we're doing one too many thread__put()...

It's a kernel build with '-j 20' and recorded data size is ~2.1GB. It takes ~30 sec to reproduce.

  $ perf report -i threaded/kbuild7.data --header-only
  # ========
  # captured on: Thu Dec 18 12:06:35 2014
  # hostname : sejong
  # os release : 3.17.4-1-ARCH
  # perf version : 3.18.rc3.gcb4774b
  # arch : x86_64
  # nrcpus online : 12
  # nrcpus avail : 12
  # cpudesc : Intel(R) Core(TM) i7-3930K CPU @ 3.20GHz
  # cpuid : GenuineIntel,6,45,7
  # total memory : 24646828 kB
  # cmdline : /home/namhyung/project/linux/tools/perf/perf record -ag -o /home/namhyung/tmp/perf/threaded/kbuild7.data -- make -j20
  # event : name = cycles, , size = 104, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|CALLCHAIN|CPU|PERIOD, disabled = 1, inherit
  # HEADER_CPU_TOPOLOGY info available, use -I to display
  # HEADER_NUMA_TOPOLOGY info available, use -I to display
  # pmu mappings: cpu = 4, software = 1, power = 24, uncore_pcu = 13, tracepoint = 2, uncore_imc_0 = 15, uncore_imc_1 = 16, uncore_imc_2 = 17, uncore_
  # ========
  #
  $ perf data stat -i threaded/kbuild7.data

Total event stats for 'threaded/kbuild7.data' file:

             TOTAL events:   25126492
              MMAP events:        114
              COMM events:     117957
              EXIT events:     240544
          THROTTLE events:         16
        UNTHROTTLE events:         16
              FORK events:     120488
            SAMPLE events:   23878219
             MMAP2 events:     745325
    FINISHED_ROUND events:      23813

Sample event stats:

Quoted 7 lines

20,579,564,471,104 cycles

          23,878,219      samples                   #   sampling ratio  99.745% (3989/4000)

       498.736917889 second time sampled
  $ perf report -i threaded/kbuild7.data
Quoted 7 lines

We need to improve this segfault backtrace, I have to always use addr2line to resolve those missing entries, i.e. if you try:

addr2line -fe /path/to/your/perf 0x4dd9c8
addr2line -fe /path/to/your/perf 0x4e2580

We would have resolved those lines :-/

Right, I'll add it to my TODO list.

Anyway, this is a backtrace using gdb..

Thanks,
Namhyung

Program received signal SIGSEGV, Segmentation fault. 0x00007ffff5fb229e in __strcmp_sse2_unaligned () from /usr/lib/libc.so.6 (gdb) bt

#0  0x00007ffff5fb229e in __strcmp_sse2_unaligned () from /usr/lib/libc.so.6
#1  0x00000000004d3948 in _sort__dso_cmp (map_r=<optimized out>, map_l=<optimized out>) at util/sort.c:142
#2  sort__dso_cmp (left=<optimized out>, right=<optimized out>) at util/sort.c:148
#3  0x00000000004d7f08 in hist_entry__cmp (right=0x7fffffffc530, left=0x323a27f0) at util/hist.c:911
#4  add_hist_entry (sample_self=true, al=0x7fffffffc710, entry=0x7fffffffc530, hists=0x18f6690) at util/hist.c:389
#5  __hists__add_entry (hists=0x18f6690, al=0x7fffffffc710, sym_parent=<optimized out>, bi=bi@entry=0x0, mi=mi@entry=0x0, period=<optimized out>,
    weight=0, transaction=0, sample_self=true) at util/hist.c:471
#6  0x00000000004d8234 in iter_add_single_normal_entry (iter=0x7fffffffc740, al=<optimized out>) at util/hist.c:662
#7  0x00000000004d8765 in hist_entry_iter__add (iter=0x7fffffffc740, al=0x7fffffffc710, evsel=0x18f6550, sample=<optimized out>,
    max_stack_depth=<optimized out>, arg=0x7fffffffd0a0) at util/hist.c:871
#8  0x0000000000436353 in process_sample_event (tool=0x7fffffffd0a0, event=<optimized out>, sample=0x7fffffffc870, evsel=0x18f6550,
    machine=<optimized out>) at builtin-report.c:171
#9  0x00000000004bbe23 in perf_evlist__deliver_sample (machine=0x18f4cc0, evsel=0x18f6550, sample=0x7fffffffc870, event=0x7fffe0bd3220,
    tool=0x7fffffffd0a0, evlist=0x18f5b50) at util/session.c:972
#10 machines__deliver_event (machines=machines@entry=0x18f4cc0, evlist=<optimized out>, event=event@entry=0x7fffe0bd3220,
    sample=sample@entry=0x7fffffffc870, tool=tool@entry=0x7fffffffd0a0, file_offset=file_offset@entry=1821434400) at util/session.c:1009

#11 0x00000000004bc681 in perf_session__deliver_event (file_offset=1821434400, tool=0x7fffffffd0a0, sample=0x7fffffffc870, event=0x7fffe0bd3220,
session=<optimized out>) at util/session.c:1050
#12 ordered_events__deliver_event (oe=0x18f4e00, event=<optimized out>) at util/session.c:109
#13 0x00000000004bf12b in __ordered_events__flush (oe=0x18f4e00) at util/ordered-events.c:207
#14 ordered_events__flush (oe=0x18f4e00, how=OE_FLUSH__ROUND) at util/ordered-events.c:271
#15 0x00000000004bc8aa in perf_session__process_user_event (file_offset=1821919744, event=0x7fffe0c49a00, session=0x18f4c00) at util/session.c:1087 #16 perf_session__process_event (session=session@entry=0x18f4c00, event=event@entry=0x7fffe0c49a00, file_offset=file_offset@entry=1821919744)

    at util/session.c:1200
#17 0x00000000004bdcd0 in __perf_session__process_events (file_size=2160054608, data_size=<optimized out>, data_offset=<optimized out>,
    session=0x18f4c00) at util/session.c:1501

#18 perf_session__process_events (session=session@entry=0x18f4c00) at util/session.c:1548
#19 0x0000000000437609 in __cmd_report (rep=0x7fffffffd0a0) at builtin-report.c:487
#20 cmd_report (argc=0, argv=0x7fffffffe8d0, prefix=<optimized out>) at builtin-report.c:878
#21 0x000000000047de33 in run_builtin (p=p@entry=0x85a6e8 <commands+168>, argc=argc@entry=6, argv=argv@entry=0x7fffffffe8d0) at perf.c:370 #22 0x000000000042893a in handle_internal_command (argv=0x7fffffffe8d0, argc=6) at perf.c:429
#23 run_argv (argv=0x7fffffffe660, argcp=0x7fffffffe66c) at perf.c:473
#24 main (argc=6, argv=0x7fffffffe8d0) at perf.c:588

Quoted 40 lines

But I think this is a longstanding bug in handling hist_entries, i.e. probably we have more than one pointer to a hist_entry and are accessing it in two places at the same time, with one of them deleting it and possibly reusing the data.

Quoted 23 lines

perf: Segmentation fault
-------- backtrace --------
perf[0x51c7cb] /usr/lib/libc.so.6(+0x33540)[0x7f37eb37e540] /usr/lib/libc.so.6(+0x9029e)[0x7f37eb3db29e] perf[0x4dd9c8] perf(__hists__add_entry+0x188)[0x4e2258] perf[0x4e2580] perf(hist_entry_iter__add+0x9d)[0x4e2a7d] perf[0x437fda]
perf[0x4c4c8e]
perf[0x4c5176]
perf[0x4c8bab]
perf[0x4c53c2]
perf[0x4c5f0c] perf(perf_session__process_events+0xb3)[0x4c6b23] perf(cmd_report+0x12a0)[0x439310]
perf[0x483ec3]
perf(main+0x60a)[0x42979a] /usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7f37eb36b800] perf(_start+0x29)[0x4298b9]
[0x0]

Quoted 1 line

It seems like some memory area was corrupted..

Right, looks like use after free, for instance, freeing something still on a list or rbtree :-/

- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

author maintainer
#37 lore raw

Em Fri, May 15, 2015 at 11:08:04AM +0900, Namhyung Kim escreveu:

Quoted 8 lines

Hi Arnaldo,

Quoted 5 lines · Arnaldo Carvalho de Melo

Em Thu, May 14, 2015 at 05:23:30PM +0900, Namhyung Kim escreveu:

Quoted 1 line · Arnaldo Carvalho de Melo

We need to improve this segfault backtrace, I have to always use addr2line to resolve those missing entries, i.e. if you try:

Quoted 8 lines
Quoted 4 lines

addr2line -fe /path/to/your/perf 0x4dd9c8
addr2line -fe /path/to/your/perf 0x4e2580

We would have resolved those lines :-/

Right, I'll add it to my TODO list.

Anyway, this is a backtrace using gdb..

Ok, reproduced here:

[acme@ibm-x3650m4-01 linux]$ fg
gdb perf
list
134 if (verbose) {
135 dso_name_l = dso_l->long_name;
136 dso_name_r = dso_r->long_name;
137 } else {
138 dso_name_l = dso_l->short_name;
139 dso_name_r = dso_r->short_name;
140 }
141
142 return strcmp(dso_name_l, dso_name_r);
143 }
(gdb) p dso_l
$2 = (struct dso *) 0x1924ba0
(gdb)
$3 = (struct dso *) 0x1924ba0
(gdb) p dso_r
$4 = (struct dso *) 0x1
(gdb) bt

#0  0x00000000004f557b in _sort__dso_cmp (map_l=0x182ab3120, map_r=0xd5325b0) at util/sort.c:139
#1  0x00000000004f55f1 in sort__dso_cmp (left=0x606c7f0, right=0x7fffffffb850) at util/sort.c:148
#2  0x00000000004f8470 in __sort__hpp_cmp (fmt=0x1922fb0, a=0x606c7f0, b=0x7fffffffb850) at util/sort.c:1313
#3  0x00000000004fc3b8 in hist_entry__cmp (left=0x606c7f0, right=0x7fffffffb850) at util/hist.c:911
#4  0x00000000004fafcc in add_hist_entry (hists=0x1922d80, entry=0x7fffffffb850, al=0x7fffffffbbe0, sample_self=false) at util/hist.c:389
#5  0x00000000004fb350 in __hists__add_entry (hists=0x1922d80, al=0x7fffffffbbe0, sym_parent=0x0, bi=0x0, mi=0x0, period=557536, weight=0, transaction=0, sample_self=false)
    at util/hist.c:471
#6  0x00000000004fc03c in iter_add_next_cumulative_entry (iter=0x7fffffffbc10, al=0x7fffffffbbe0) at util/hist.c:797
#7  0x00000000004fc291 in hist_entry_iter__add (iter=0x7fffffffbc10, al=0x7fffffffbbe0, evsel=0x1922c50, sample=0x7fffffffbdf0, max_stack_depth=127, arg=0x7fffffffc810) at util/hist.c:882
#8  0x000000000042f1b7 in process_sample_event (tool=0x7fffffffc810, event=0x7ffed74b41e0, sample=0x7fffffffbdf0, evsel=0x1922c50, machine=0x19213d0) at builtin-report.c:171
#9  0x00000000004da272 in perf_evlist__deliver_sample (evlist=0x1922260, tool=0x7fffffffc810, event=0x7ffed74b41e0, sample=0x7fffffffbdf0, evsel=0x1922c50, machine=0x19213d0)
    at util/session.c:1000
#10 0x00000000004da40c in machines__deliver_event (machines=0x19213d0, evlist=0x1922260, event=0x7ffed74b41e0, sample=0x7fffffffbdf0, tool=0x7fffffffc810, file_offset=1097646560)
    at util/session.c:1037

#11 0x00000000004da659 in perf_session__deliver_event (session=0x1921310, event=0x7ffed74b41e0, sample=0x7fffffffbdf0, tool=0x7fffffffc810, file_offset=1097646560) at util/session.c:1082 #12 0x00000000004d7d7b in ordered_events__deliver_event (oe=0x1921558, event=0x2050430) at util/session.c:109
#13 0x00000000004dd65b in __ordered_events__flush (oe=0x1921558) at util/ordered-events.c:207
#14 0x00000000004dd92f in ordered_events__flush (oe=0x1921558, how=OE_FLUSH__ROUND) at util/ordered-events.c:271
#15 0x00000000004d94c8 in process_finished_round (tool=0x7fffffffc810, event=0x7ffed74c6830, oe=0x1921558) at util/session.c:663
#16 0x00000000004da7cd in perf_session__process_user_event (session=0x1921310, event=0x7ffed74c6830, file_offset=1097721904) at util/session.c:1119
#17 0x00000000004daced in perf_session__process_event (session=0x1921310, event=0x7ffed74c6830, file_offset=1097721904) at util/session.c:1232
#18 0x00000000004db811 in __perf_session__process_events (session=0x1921310, data_offset=232, data_size=5774474704, file_size=5774474936) at util/session.c:1533 #19 0x00000000004dba01 in perf_session__process_events (session=0x1921310) at util/session.c:1580
#20 0x000000000042ff9f in __cmd_report (rep=0x7fffffffc810) at builtin-report.c:487
#21 0x00000000004315d9 in cmd_report (argc=0, argv=0x7fffffffddd0, prefix=0x0) at builtin-report.c:878
#22 0x0000000000490fb8 in run_builtin (p=0x886528 <commands+168>, argc=1, argv=0x7fffffffddd0) at perf.c:370
#23 0x0000000000491217 in handle_internal_command (argc=1, argv=0x7fffffffddd0) at perf.c:429
#24 0x0000000000491363 in run_argv (argcp=0x7fffffffdc2c, argv=0x7fffffffdc20) at perf.c:473
#25 0x00000000004916c4 in main (argc=1, argv=0x7fffffffddd0) at perf.c:588
(gdb)

Looking at the frame #1 I see:

(gdb) p left->hists
$22 = (struct hists *) 0x1922d80
(gdb) p right->hists
$23 = (struct hists *) 0x1922d80
(gdb)

I.e. both look like fine hist_entry instances, both are on the same struct hists, but:

(gdb) p right->ms.map->dso
$25 = (struct dso *) 0x1924ba0
(gdb) p right->ms.ma
There is no member named ma.
(gdb) p right->ms.map
$26 = (struct map *) 0x182ab3120
(gdb) p right->ms.map->dso
$27 = (struct dso *) 0x1924ba0
(gdb) p right->ms.map->dso->name
$28 = 0x1924cc0 "/usr/lib64/libc-2.18.so"
(gdb) p left->ms.map
$29 = (struct map *) 0xd5325b0
(gdb) p left->ms.map->dso
$30 = (struct dso *) 0x1
(gdb) p *left->ms.map
$31 = {{rb_node = {__rb_parent_color = 0, rb_right = 0x118cdc3c8, rb_left = 0x0}, node = {next = 0x0, prev = 0x118cdc3c8}}, start = 0, end = 0, type = 71 'G', referenced = 138,
erange_warned = 8, priv = 0, prot = 0, flags = 0, pgoff = 81, reloc = 559687, maj = 0, min = 0, ino = 559687, ino_generation = 0, map_ip = 0x0, unmap_ip = 0x0, dso = 0x1, groups = 0xd5302a0}
(gdb)

Will continue investigating later...

- Arnaldo

Quoted 78 lines

Program received signal SIGSEGV, Segmentation fault. 0x00007ffff5fb229e in __strcmp_sse2_unaligned () from /usr/lib/libc.so.6 (gdb) bt

#0  0x00007ffff5fb229e in __strcmp_sse2_unaligned () from /usr/lib/libc.so.6
#1  0x00000000004d3948 in _sort__dso_cmp (map_r=<optimized out>, map_l=<optimized out>) at util/sort.c:142
#2  sort__dso_cmp (left=<optimized out>, right=<optimized out>) at util/sort.c:148
#3  0x00000000004d7f08 in hist_entry__cmp (right=0x7fffffffc530, left=0x323a27f0) at util/hist.c:911
#4  add_hist_entry (sample_self=true, al=0x7fffffffc710, entry=0x7fffffffc530, hists=0x18f6690) at util/hist.c:389
#5  __hists__add_entry (hists=0x18f6690, al=0x7fffffffc710, sym_parent=<optimized out>, bi=bi@entry=0x0, mi=mi@entry=0x0, period=<optimized out>,
    weight=0, transaction=0, sample_self=true) at util/hist.c:471
#6  0x00000000004d8234 in iter_add_single_normal_entry (iter=0x7fffffffc740, al=<optimized out>) at util/hist.c:662
#7  0x00000000004d8765 in hist_entry_iter__add (iter=0x7fffffffc740, al=0x7fffffffc710, evsel=0x18f6550, sample=<optimized out>,
    max_stack_depth=<optimized out>, arg=0x7fffffffd0a0) at util/hist.c:871
#8  0x0000000000436353 in process_sample_event (tool=0x7fffffffd0a0, event=<optimized out>, sample=0x7fffffffc870, evsel=0x18f6550,
    machine=<optimized out>) at builtin-report.c:171
#9  0x00000000004bbe23 in perf_evlist__deliver_sample (machine=0x18f4cc0, evsel=0x18f6550, sample=0x7fffffffc870, event=0x7fffe0bd3220,
    tool=0x7fffffffd0a0, evlist=0x18f5b50) at util/session.c:972
#10 machines__deliver_event (machines=machines@entry=0x18f4cc0, evlist=<optimized out>, event=event@entry=0x7fffe0bd3220,
    sample=sample@entry=0x7fffffffc870, tool=tool@entry=0x7fffffffd0a0, file_offset=file_offset@entry=1821434400) at util/session.c:1009

#11 0x00000000004bc681 in perf_session__deliver_event (file_offset=1821434400, tool=0x7fffffffd0a0, sample=0x7fffffffc870, event=0x7fffe0bd3220,
session=<optimized out>) at util/session.c:1050
#12 ordered_events__deliver_event (oe=0x18f4e00, event=<optimized out>) at util/session.c:109
#13 0x00000000004bf12b in __ordered_events__flush (oe=0x18f4e00) at util/ordered-events.c:207
#14 ordered_events__flush (oe=0x18f4e00, how=OE_FLUSH__ROUND) at util/ordered-events.c:271
#15 0x00000000004bc8aa in perf_session__process_user_event (file_offset=1821919744, event=0x7fffe0c49a00, session=0x18f4c00) at util/session.c:1087 #16 perf_session__process_event (session=session@entry=0x18f4c00, event=event@entry=0x7fffe0c49a00, file_offset=file_offset@entry=1821919744)

    at util/session.c:1200
#17 0x00000000004bdcd0 in __perf_session__process_events (file_size=2160054608, data_size=<optimized out>, data_offset=<optimized out>,
    session=0x18f4c00) at util/session.c:1501

#18 perf_session__process_events (session=session@entry=0x18f4c00) at util/session.c:1548
#19 0x0000000000437609 in __cmd_report (rep=0x7fffffffd0a0) at builtin-report.c:487
#20 cmd_report (argc=0, argv=0x7fffffffe8d0, prefix=<optimized out>) at builtin-report.c:878
#21 0x000000000047de33 in run_builtin (p=p@entry=0x85a6e8 <commands+168>, argc=argc@entry=6, argv=argv@entry=0x7fffffffe8d0) at perf.c:370 #22 0x000000000042893a in handle_internal_command (argv=0x7fffffffe8d0, argc=6) at perf.c:429
#23 run_argv (argv=0x7fffffffe660, argcp=0x7fffffffe66c) at perf.c:473
#24 main (argc=6, argv=0x7fffffffe8d0) at perf.c:588

Quoted 40 lines

But I think this is a longstanding bug in handling hist_entries, i.e. probably we have more than one pointer to a hist_entry and are accessing it in two places at the same time, with one of them deleting it and possibly reusing the data.

Quoted 23 lines

perf: Segmentation fault
-------- backtrace --------
perf[0x51c7cb] /usr/lib/libc.so.6(+0x33540)[0x7f37eb37e540] /usr/lib/libc.so.6(+0x9029e)[0x7f37eb3db29e] perf[0x4dd9c8] perf(__hists__add_entry+0x188)[0x4e2258] perf[0x4e2580] perf(hist_entry_iter__add+0x9d)[0x4e2a7d] perf[0x437fda]
perf[0x4c4c8e]
perf[0x4c5176]
perf[0x4c8bab]
perf[0x4c53c2]
perf[0x4c5f0c] perf(perf_session__process_events+0xb3)[0x4c6b23] perf(cmd_report+0x12a0)[0x439310]
perf[0x483ec3]
perf(main+0x60a)[0x42979a] /usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7f37eb36b800] perf(_start+0x29)[0x4298b9]
[0x0]

Quoted 1 line

It seems like some memory area was corrupted..

Right, looks like use after free, for instance, freeing something still on a list or rbtree :-/

- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/