perf/core improvements and fixes
Subsystems (2)
Arnaldo Carvalho de Melo
maintainerHi 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
Arnaldo Carvalho de Melo
maintainerPATCH 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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 2/30 perf probe: Fix a typo for the flags of open
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 3/30 perf probe: Fix to return 0 when positive value returned
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 4/30 perf probe: Make --line checks validate C-style function name
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 5/30 perf probe: Skip kernel symbols which is out of .text
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 6/30 perf probe: Support $params special probe argument
In reply to Arnaldo Carvalho de MeloFrom: 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
--- 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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 7/30 perf tools: Move x86 barrier.h stuff to tools/arch/x86/include/asm/barrier.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -0,0 +1,3 @@ +#if defined(__i386__) || defined(__x86_64__) +#include "../../arch/x86/include/asm/barrier.h" +#endif
tools/perf/MANIFEST +2 -0
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 8/30 perf tools: Move powerpc barrier.h stuff to tools/arch/powerpc/include/asm/barrier.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 9/30 perf tools: Move s390 barrier.h stuff to tools/arch/s390/include/asm/barrier.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 10/30 perf tools: Move barrier() definition to tools/include/linux/compiler.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 11/30 tools: Adopt asm-generic/barrier.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 12/30 perf tools: Move sh barrier.h stuff to tools/arch/sh/include/asm/barrier.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 13/30 perf tools: Move sparc barrier.h stuff to tools/arch/sparc/include/asm/barrier.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 14/30 perf tools: Move alpha barrier.h stuff to tools/arch/alpha/include/asm/barrier.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 15/30 perf tools: Move ia64 barrier.h stuff to tools/arch/ia64/include/asm/barrier.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 16/30 perf tools: Move arm(64) barrier.h stuff to tools/arch/arm*/include/asm/barrier.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 17/30 perf tools: Move xtensa barrier.h stuff to tools/arch/xtensa/include/asm/barrier.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 18/30 perf tools: Move mips barrier.h stuff to tools/arch/mips/include/asm/barrier.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 19/30 perf tools: Move tile barrier.h stuff to tools/arch/tile/include/asm/barrier.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 20/30 perf tools: Move generic barriers out of perf-sys.h
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 21/30 tools include: Add basic atomic.h implementation from the kernel sources
In reply to Arnaldo Carvalho de MeloFrom: 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.
--- 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
@@ -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) +{ + asmvolatile (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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 22/30 perf tools: Use atomic_t to implement thread__{get,put} refcnt
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 23/30 perf machine: Protect the machine->threads with a rwlock
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 24/30 perf bench futex: Support parallel waker threads
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 25/30 perf bench futex: Handle spurious wakeups
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 26/30 perf probe: Use perf_probe_event.target instead of passing as an argument
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 27/30 perf probe: Introduce probe_conf global configs
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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", ¶ms.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" , ¶ms.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), #endifOPT__DRY_RUN (&probe_event_dry_run), -OPT_INTEGER ('\0' ,"max-probes" , ¶ms.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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 28/30 perf probe: Add --no-inlines option to avoid searching inline functions
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
@@ -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" ), #endifOPT__DRY_RUN (&probe_event_dry_run), OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
tools/perf/util/probe-event.h +1 -0
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 29/30 perf probe: Support glob wildcards for function name
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 30/30 perf build: Disable libdw DWARF unwind when built with NO_DWARF
In reply to Arnaldo Carvalho de MeloFrom: "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
@@ -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
Quoted 186 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit
cb307113746b4d184155d2c412e8069aeaa60d42:
perf_event: Don't allowvmalloc()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.gittags/perf-core-for-mingofor 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.hmb/rmb/wmb API fromtools/perf/to kernel liketools/arch/hierarchy (Arnaldo Carvalho de Melo)- Borrow
atomic.hfrom 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)Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Arnaldo Carvalho de Melo (17):
perf tools: Move x86barrier.hstuff totools/arch/x86/include/asm/barrier.hperf tools: Move powerpcbarrier.hstuff totools/arch/powerpc/include/asm/barrier.hperf tools: Move s390barrier.hstuff totools/arch/s390/include/asm/barrier.hperf tools: Movebarrier()definition totools/include/linux/compiler.h
tools: Adoptasm-generic/barrier.h
perf tools: Move shbarrier.hstuff totools/arch/sh/include/asm/barrier.hperf tools: Move sparcbarrier.hstuff totools/arch/sparc/include/asm/barrier.hperf tools: Move alphabarrier.hstuff totools/arch/alpha/include/asm/barrier.hperf tools: Move ia64barrier.hstuff totools/arch/ia64/include/asm/barrier.hperf tools: Move arm(64)barrier.hstuff totools/arch/arm*/include/asm/barrier.hperf tools: Move xtensabarrier.hstuff totools/arch/xtensa/include/asm/barrier.hperf tools: Move mipsbarrier.hstuff totools/arch/mips/include/asm/barrier.hperf tools: Move tilebarrier.hstuff totools/arch/tile/include/asm/barrier.hperf tools: Move generic barriers out ofperf-sys.h
tools include: Add basicatomic.himplementation from the kernel sources perf tools: Useatomic_tto implement thread__{get,put} refcnt
perf machine: Protect themachine->threadswith a rwlockDavidlohr Bueso (2):
perf bench futex: Support parallel waker threads perf bench futex: Handle spurious wakeupsMasami Hiramatsu (10):
perf probe: Fix to closeprobe_eventsfile 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: Introduceprobe_confglobal configs
perf probe: Add --no-inlines option to avoid searching inline functions perf probe: Support glob wildcards for function nameNaveen N. Rao (1):
perf build: Disable libdw DWARF unwind when built withNO_DWARFtools/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
Namhyung Kim
maintainerHi Arnaldo,
Quoted 36 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit
cb307113746b4d184155d2c412e8069aeaa60d42:
perf_event: Don't allowvmalloc()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.gittags/perf-core-for-mingofor 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
Arnaldo Carvalho de Melo
maintainerEm 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
Namhyung Kim
maintainerQuoted 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: 23813Sample 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
Arnaldo Carvalho de Melo
maintainerEm 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.dataTotal 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: 23813Sample 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
Namhyung Kim
maintainerHi 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.dataTotal 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: 23813Sample 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/perf0x4e2580We 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 ahist_entryand 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/
Arnaldo Carvalho de Melo
maintainerEm 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/perf0x4e2580We 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.
0x00007ffff5fb229ein__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
0x00000000004bc681inperf_session__deliver_event(file_offset=1821434400, tool=0x7fffffffd0a0, sample=0x7fffffffc870, event=0x7fffe0bd3220,
session=<optimized out>) atutil/session.c:1050
#12ordered_events__deliver_event(oe=0x18f4e00, event=<optimized out>) atutil/session.c:109
#130x00000000004bf12bin__ordered_events__flush(oe=0x18f4e00) atutil/ordered-events.c:207
#14ordered_events__flush(oe=0x18f4e00, how=OE_FLUSH__ROUND) atutil/ordered-events.c:271
#150x00000000004bc8aainperf_session__process_user_event(file_offset=1821919744, event=0x7fffe0c49a00, session=0x18f4c00) atutil/session.c:1087#16perf_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) atutil/session.c:1548
#190x0000000000437609in__cmd_report(rep=0x7fffffffd0a0) at builtin-report.c:487
#20cmd_report(argc=0, argv=0x7fffffffe8d0, prefix=<optimized out>) at builtin-report.c:878
#210x000000000047de33inrun_builtin(p=p@entry=0x85a6e8 <commands+168>, argc=argc@entry=6, argv=argv@entry=0x7fffffffe8d0) at perf.c:370 #220x000000000042893ainhandle_internal_command(argv=0x7fffffffe8d0, argc=6) at perf.c:429
#23run_argv(argv=0x7fffffffe660, argcp=0x7fffffffe66c) at perf.c:473
#24 main (argc=6, argv=0x7fffffffe8d0) at perf.c:588Quoted 40 lines
But I think this is a longstanding bug in handling
hist_entries, i.e. probably we have more than one pointer to ahist_entryand 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/