aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/kprobes/core.c54
-rw-r--r--arch/x86/kernel/kprobes/opt.c2
-rw-r--r--kernel/events/core.c2
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Documentation/perf-record.txt12
-rw-r--r--tools/perf/Makefile2
-rw-r--r--tools/perf/bench/mem-memcpy.c4
-rw-r--r--tools/perf/builtin-sched.c26
-rw-r--r--tools/perf/builtin-stat.c5
-rw-r--r--tools/perf/builtin-trace.c7
-rw-r--r--tools/perf/config/Makefile17
-rw-r--r--tools/perf/config/Makefile.arch23
-rw-r--r--tools/perf/config/feature-checks/Makefile16
-rw-r--r--tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c7
-rw-r--r--tools/perf/config/utilities.mak3
-rw-r--r--tools/perf/ui/browsers/hists.c6
-rw-r--r--tools/perf/util/Build2
-rw-r--r--tools/perf/util/build-id.c5
-rw-r--r--tools/perf/util/cloexec.c18
-rw-r--r--tools/perf/util/event.c34
-rw-r--r--tools/perf/util/evlist.h2
-rw-r--r--tools/perf/util/hist.c2
-rw-r--r--tools/perf/util/hist.h2
-rw-r--r--tools/perf/util/machine.c44
-rw-r--r--tools/perf/util/machine.h1
-rw-r--r--tools/perf/util/probe-event.c23
-rw-r--r--tools/perf/util/probe-finder.c5
-rw-r--r--tools/perf/util/session.c6
-rw-r--r--tools/perf/util/symbol-elf.c5
-rw-r--r--tools/perf/util/thread.c14
-rw-r--r--tools/perf/util/thread.h13
31 files changed, 231 insertions, 132 deletions
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 6a1146ea4d4d..4e3d5a9621fe 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -223,27 +223,48 @@ static unsigned long
223__recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) 223__recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
224{ 224{
225 struct kprobe *kp; 225 struct kprobe *kp;
226 unsigned long faddr;
226 227
227 kp = get_kprobe((void *)addr); 228 kp = get_kprobe((void *)addr);
228 /* There is no probe, return original address */ 229 faddr = ftrace_location(addr);
229 if (!kp) 230 /*
231 * Addresses inside the ftrace location are refused by
232 * arch_check_ftrace_location(). Something went terribly wrong
233 * if such an address is checked here.
234 */
235 if (WARN_ON(faddr && faddr != addr))
236 return 0UL;
237 /*
238 * Use the current code if it is not modified by Kprobe
239 * and it cannot be modified by ftrace.
240 */
241 if (!kp && !faddr)
230 return addr; 242 return addr;
231 243
232 /* 244 /*
233 * Basically, kp->ainsn.insn has an original instruction. 245 * Basically, kp->ainsn.insn has an original instruction.
234 * However, RIP-relative instruction can not do single-stepping 246 * However, RIP-relative instruction can not do single-stepping
235 * at different place, __copy_instruction() tweaks the displacement of 247 * at different place, __copy_instruction() tweaks the displacement of
236 * that instruction. In that case, we can't recover the instruction 248 * that instruction. In that case, we can't recover the instruction
237 * from the kp->ainsn.insn. 249 * from the kp->ainsn.insn.
238 * 250 *
239 * On the other hand, kp->opcode has a copy of the first byte of 251 * On the other hand, in case on normal Kprobe, kp->opcode has a copy
240 * the probed instruction, which is overwritten by int3. And 252 * of the first byte of the probed instruction, which is overwritten
241 * the instruction at kp->addr is not modified by kprobes except 253 * by int3. And the instruction at kp->addr is not modified by kprobes
242 * for the first byte, we can recover the original instruction 254 * except for the first byte, we can recover the original instruction
243 * from it and kp->opcode. 255 * from it and kp->opcode.
256 *
257 * In case of Kprobes using ftrace, we do not have a copy of
258 * the original instruction. In fact, the ftrace location might
259 * be modified at anytime and even could be in an inconsistent state.
260 * Fortunately, we know that the original code is the ideal 5-byte
261 * long NOP.
244 */ 262 */
245 memcpy(buf, kp->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); 263 memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
246 buf[0] = kp->opcode; 264 if (faddr)
265 memcpy(buf, ideal_nops[NOP_ATOMIC5], 5);
266 else
267 buf[0] = kp->opcode;
247 return (unsigned long)buf; 268 return (unsigned long)buf;
248} 269}
249 270
@@ -251,6 +272,7 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
251 * Recover the probed instruction at addr for further analysis. 272 * Recover the probed instruction at addr for further analysis.
252 * Caller must lock kprobes by kprobe_mutex, or disable preemption 273 * Caller must lock kprobes by kprobe_mutex, or disable preemption
253 * for preventing to release referencing kprobes. 274 * for preventing to release referencing kprobes.
275 * Returns zero if the instruction can not get recovered.
254 */ 276 */
255unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr) 277unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr)
256{ 278{
@@ -285,6 +307,8 @@ static int can_probe(unsigned long paddr)
285 * normally used, we just go through if there is no kprobe. 307 * normally used, we just go through if there is no kprobe.
286 */ 308 */
287 __addr = recover_probed_instruction(buf, addr); 309 __addr = recover_probed_instruction(buf, addr);
310 if (!__addr)
311 return 0;
288 kernel_insn_init(&insn, (void *)__addr, MAX_INSN_SIZE); 312 kernel_insn_init(&insn, (void *)__addr, MAX_INSN_SIZE);
289 insn_get_length(&insn); 313 insn_get_length(&insn);
290 314
@@ -333,6 +357,8 @@ int __copy_instruction(u8 *dest, u8 *src)
333 unsigned long recovered_insn = 357 unsigned long recovered_insn =
334 recover_probed_instruction(buf, (unsigned long)src); 358 recover_probed_instruction(buf, (unsigned long)src);
335 359
360 if (!recovered_insn)
361 return 0;
336 kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE); 362 kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE);
337 insn_get_length(&insn); 363 insn_get_length(&insn);
338 /* Another subsystem puts a breakpoint, failed to recover */ 364 /* Another subsystem puts a breakpoint, failed to recover */
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c
index 0dd8d089c315..7b3b9d15c47a 100644
--- a/arch/x86/kernel/kprobes/opt.c
+++ b/arch/x86/kernel/kprobes/opt.c
@@ -259,6 +259,8 @@ static int can_optimize(unsigned long paddr)
259 */ 259 */
260 return 0; 260 return 0;
261 recovered_insn = recover_probed_instruction(buf, addr); 261 recovered_insn = recover_probed_instruction(buf, addr);
262 if (!recovered_insn)
263 return 0;
262 kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE); 264 kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE);
263 insn_get_length(&insn); 265 insn_get_length(&insn);
264 /* Another subsystem puts a breakpoint */ 266 /* Another subsystem puts a breakpoint */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index af924bc38121..8bb20cc39a92 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4446,7 +4446,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
4446 * If we have rb pages ensure they're a power-of-two number, so we 4446 * If we have rb pages ensure they're a power-of-two number, so we
4447 * can do bitmasks instead of modulo. 4447 * can do bitmasks instead of modulo.
4448 */ 4448 */
4449 if (!is_power_of_2(nr_pages)) 4449 if (nr_pages != 0 && !is_power_of_2(nr_pages))
4450 return -EINVAL; 4450 return -EINVAL;
4451 4451
4452 if (vma_size != PAGE_SIZE * (1 + nr_pages)) 4452 if (vma_size != PAGE_SIZE * (1 + nr_pages))
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 40399c3d97d6..68328f517a2e 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -1,6 +1,7 @@
1PERF-CFLAGS 1PERF-CFLAGS
2PERF-GUI-VARS 2PERF-GUI-VARS
3PERF-VERSION-FILE 3PERF-VERSION-FILE
4PERF-FEATURES
4perf 5perf
5perf-read-vdso32 6perf-read-vdso32
6perf-read-vdsox32 7perf-read-vdsox32
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index cae75c11120f..355c4f5569b5 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -55,6 +55,11 @@ OPTIONS
55 If you want to profile write accesses in [0x1000~1008), just set 55 If you want to profile write accesses in [0x1000~1008), just set
56 'mem:0x1000/8:w'. 56 'mem:0x1000/8:w'.
57 57
58 - a group of events surrounded by a pair of brace ("{event1,event2,...}").
59 Each event is separated by commas and the group should be quoted to
60 prevent the shell interpretation. You also need to use --group on
61 "perf report" to view group events together.
62
58--filter=<filter>:: 63--filter=<filter>::
59 Event filter. 64 Event filter.
60 65
@@ -62,9 +67,6 @@ OPTIONS
62--all-cpus:: 67--all-cpus::
63 System-wide collection from all CPUs. 68 System-wide collection from all CPUs.
64 69
65-l::
66 Scale counter values.
67
68-p:: 70-p::
69--pid=:: 71--pid=::
70 Record events on existing process ID (comma separated list). 72 Record events on existing process ID (comma separated list).
@@ -107,6 +109,10 @@ OPTIONS
107 specification with appended unit character - B/K/M/G. The 109 specification with appended unit character - B/K/M/G. The
108 size is rounded up to have nearest pages power of two value. 110 size is rounded up to have nearest pages power of two value.
109 111
112--group::
113 Put all events in a single event group. This precedes the --event
114 option and remains only for backward compatibility. See --event.
115
110-g:: 116-g::
111 Enables call-graph (stack chain/backtrace) recording. 117 Enables call-graph (stack chain/backtrace) recording.
112 118
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index cb2e5868c8e8..d5020aeb5626 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -25,7 +25,7 @@ unexport MAKEFLAGS
25# 25#
26ifeq ($(JOBS),) 26ifeq ($(JOBS),)
27 JOBS := $(shell grep -c ^processor /proc/cpuinfo 2>/dev/null) 27 JOBS := $(shell grep -c ^processor /proc/cpuinfo 2>/dev/null)
28 ifeq ($(JOBS),) 28 ifeq ($(JOBS),0)
29 JOBS := 1 29 JOBS := 1
30 endif 30 endif
31endif 31endif
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 6c14afe8c1b1..db1d3a29d97f 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -289,7 +289,7 @@ static u64 do_memcpy_cycle(const struct routine *r, size_t len, bool prefault)
289 memcpy_t fn = r->fn.memcpy; 289 memcpy_t fn = r->fn.memcpy;
290 int i; 290 int i;
291 291
292 memcpy_alloc_mem(&src, &dst, len); 292 memcpy_alloc_mem(&dst, &src, len);
293 293
294 if (prefault) 294 if (prefault)
295 fn(dst, src, len); 295 fn(dst, src, len);
@@ -312,7 +312,7 @@ static double do_memcpy_gettimeofday(const struct routine *r, size_t len,
312 void *src = NULL, *dst = NULL; 312 void *src = NULL, *dst = NULL;
313 int i; 313 int i;
314 314
315 memcpy_alloc_mem(&src, &dst, len); 315 memcpy_alloc_mem(&dst, &src, len);
316 316
317 if (prefault) 317 if (prefault)
318 fn(dst, src, len); 318 fn(dst, src, len);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 7ce296618717..a3ebf1d3c29d 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -831,7 +831,7 @@ static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread)
831 return -1; 831 return -1;
832 } 832 }
833 833
834 atoms->thread = thread; 834 atoms->thread = thread__get(thread);
835 INIT_LIST_HEAD(&atoms->work_list); 835 INIT_LIST_HEAD(&atoms->work_list);
836 __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid); 836 __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid);
837 return 0; 837 return 0;
@@ -1439,8 +1439,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1439 return err; 1439 return err;
1440} 1440}
1441 1441
1442static int perf_sched__read_events(struct perf_sched *sched, 1442static int perf_sched__read_events(struct perf_sched *sched)
1443 struct perf_session **psession)
1444{ 1443{
1445 const struct perf_evsel_str_handler handlers[] = { 1444 const struct perf_evsel_str_handler handlers[] = {
1446 { "sched:sched_switch", process_sched_switch_event, }, 1445 { "sched:sched_switch", process_sched_switch_event, },
@@ -1454,6 +1453,7 @@ static int perf_sched__read_events(struct perf_sched *sched,
1454 .path = input_name, 1453 .path = input_name,
1455 .mode = PERF_DATA_MODE_READ, 1454 .mode = PERF_DATA_MODE_READ,
1456 }; 1455 };
1456 int rc = -1;
1457 1457
1458 session = perf_session__new(&file, false, &sched->tool); 1458 session = perf_session__new(&file, false, &sched->tool);
1459 if (session == NULL) { 1459 if (session == NULL) {
@@ -1478,16 +1478,10 @@ static int perf_sched__read_events(struct perf_sched *sched,
1478 sched->nr_lost_chunks = session->evlist->stats.nr_events[PERF_RECORD_LOST]; 1478 sched->nr_lost_chunks = session->evlist->stats.nr_events[PERF_RECORD_LOST];
1479 } 1479 }
1480 1480
1481 if (psession) 1481 rc = 0;
1482 *psession = session;
1483 else
1484 perf_session__delete(session);
1485
1486 return 0;
1487
1488out_delete: 1482out_delete:
1489 perf_session__delete(session); 1483 perf_session__delete(session);
1490 return -1; 1484 return rc;
1491} 1485}
1492 1486
1493static void print_bad_events(struct perf_sched *sched) 1487static void print_bad_events(struct perf_sched *sched)
@@ -1515,12 +1509,10 @@ static void print_bad_events(struct perf_sched *sched)
1515static int perf_sched__lat(struct perf_sched *sched) 1509static int perf_sched__lat(struct perf_sched *sched)
1516{ 1510{
1517 struct rb_node *next; 1511 struct rb_node *next;
1518 struct perf_session *session;
1519 1512
1520 setup_pager(); 1513 setup_pager();
1521 1514
1522 /* save session -- references to threads are held in work_list */ 1515 if (perf_sched__read_events(sched))
1523 if (perf_sched__read_events(sched, &session))
1524 return -1; 1516 return -1;
1525 1517
1526 perf_sched__sort_lat(sched); 1518 perf_sched__sort_lat(sched);
@@ -1537,6 +1529,7 @@ static int perf_sched__lat(struct perf_sched *sched)
1537 work_list = rb_entry(next, struct work_atoms, node); 1529 work_list = rb_entry(next, struct work_atoms, node);
1538 output_lat_thread(sched, work_list); 1530 output_lat_thread(sched, work_list);
1539 next = rb_next(next); 1531 next = rb_next(next);
1532 thread__zput(work_list->thread);
1540 } 1533 }
1541 1534
1542 printf(" -----------------------------------------------------------------------------------------------------------------\n"); 1535 printf(" -----------------------------------------------------------------------------------------------------------------\n");
@@ -1548,7 +1541,6 @@ static int perf_sched__lat(struct perf_sched *sched)
1548 print_bad_events(sched); 1541 print_bad_events(sched);
1549 printf("\n"); 1542 printf("\n");
1550 1543
1551 perf_session__delete(session);
1552 return 0; 1544 return 0;
1553} 1545}
1554 1546
@@ -1557,7 +1549,7 @@ static int perf_sched__map(struct perf_sched *sched)
1557 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); 1549 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);
1558 1550
1559 setup_pager(); 1551 setup_pager();
1560 if (perf_sched__read_events(sched, NULL)) 1552 if (perf_sched__read_events(sched))
1561 return -1; 1553 return -1;
1562 print_bad_events(sched); 1554 print_bad_events(sched);
1563 return 0; 1555 return 0;
@@ -1572,7 +1564,7 @@ static int perf_sched__replay(struct perf_sched *sched)
1572 1564
1573 test_calibrations(sched); 1565 test_calibrations(sched);
1574 1566
1575 if (perf_sched__read_events(sched, NULL)) 1567 if (perf_sched__read_events(sched))
1576 return -1; 1568 return -1;
1577 1569
1578 printf("nr_run_events: %ld\n", sched->nr_run_events); 1570 printf("nr_run_events: %ld\n", sched->nr_run_events);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e598e4e98170..d28949d210cc 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -510,6 +510,9 @@ static int read_counter(struct perf_evsel *counter)
510 int ncpus = perf_evsel__nr_cpus(counter); 510 int ncpus = perf_evsel__nr_cpus(counter);
511 int cpu, thread; 511 int cpu, thread;
512 512
513 if (!counter->supported)
514 return -ENOENT;
515
513 if (counter->system_wide) 516 if (counter->system_wide)
514 nthreads = 1; 517 nthreads = 1;
515 518
@@ -1285,7 +1288,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1285 if (prefix) 1288 if (prefix)
1286 fprintf(output, "%s", prefix); 1289 fprintf(output, "%s", prefix);
1287 1290
1288 if (scaled == -1) { 1291 if (scaled == -1 || !counter->supported) {
1289 fprintf(output, "%*s%s", 1292 fprintf(output, "%*s%s",
1290 csv_output ? 0 : 18, 1293 csv_output ? 0 : 18,
1291 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 1294 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index d95a8f4d988c..211614fba217 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1741,7 +1741,10 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1741 } else 1741 } else
1742 ttrace->entry_pending = true; 1742 ttrace->entry_pending = true;
1743 1743
1744 trace->current = thread; 1744 if (trace->current != thread) {
1745 thread__put(trace->current);
1746 trace->current = thread__get(thread);
1747 }
1745 1748
1746 return 0; 1749 return 0;
1747} 1750}
@@ -2274,6 +2277,8 @@ next_event:
2274 } 2277 }
2275 2278
2276out_disable: 2279out_disable:
2280 thread__zput(trace->current);
2281
2277 perf_evlist__disable(evlist); 2282 perf_evlist__disable(evlist);
2278 2283
2279 if (!err) { 2284 if (!err) {
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index c3570b5f3bf3..d44c64d64465 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -531,7 +531,7 @@ else
531 ifneq ($(feature-libperl), 1) 531 ifneq ($(feature-libperl), 1)
532 CFLAGS += -DNO_LIBPERL 532 CFLAGS += -DNO_LIBPERL
533 NO_LIBPERL := 1 533 NO_LIBPERL := 1
534 msg := $(warning Missing perl devel files. Disabling perl scripting support, consider installing perl-ExtUtils-Embed); 534 msg := $(warning Missing perl devel files. Disabling perl scripting support, please install perl-ExtUtils-Embed/libperl-dev);
535 else 535 else
536 LDFLAGS += $(PERL_EMBED_LDFLAGS) 536 LDFLAGS += $(PERL_EMBED_LDFLAGS)
537 EXTLIBS += $(PERL_EMBED_LIBADD) 537 EXTLIBS += $(PERL_EMBED_LIBADD)
@@ -548,22 +548,21 @@ endif
548disable-python = $(eval $(disable-python_code)) 548disable-python = $(eval $(disable-python_code))
549define disable-python_code 549define disable-python_code
550 CFLAGS += -DNO_LIBPYTHON 550 CFLAGS += -DNO_LIBPYTHON
551 $(if $(1),$(warning No $(1) was found)) 551 $(warning $1)
552 $(warning Python support will not be built)
553 NO_LIBPYTHON := 1 552 NO_LIBPYTHON := 1
554endef 553endef
555 554
556ifdef NO_LIBPYTHON 555ifdef NO_LIBPYTHON
557 $(call disable-python) 556 $(call disable-python,Python support disabled by user)
558else 557else
559 558
560 ifndef PYTHON 559 ifndef PYTHON
561 $(call disable-python,python interpreter) 560 $(call disable-python,No python interpreter was found: disables Python support - please install python-devel/python-dev)
562 else 561 else
563 PYTHON_WORD := $(call shell-wordify,$(PYTHON)) 562 PYTHON_WORD := $(call shell-wordify,$(PYTHON))
564 563
565 ifndef PYTHON_CONFIG 564 ifndef PYTHON_CONFIG
566 $(call disable-python,python-config tool) 565 $(call disable-python,No 'python-config' tool was found: disables Python support - please install python-devel/python-dev)
567 else 566 else
568 567
569 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG)) 568 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
@@ -575,7 +574,7 @@ else
575 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 574 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
576 575
577 ifneq ($(feature-libpython), 1) 576 ifneq ($(feature-libpython), 1)
578 $(call disable-python,Python.h (for Python 2.x)) 577 $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev)
579 else 578 else
580 579
581 ifneq ($(feature-libpython-version), 1) 580 ifneq ($(feature-libpython-version), 1)
@@ -636,7 +635,7 @@ else
636 EXTLIBS += -liberty 635 EXTLIBS += -liberty
637 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT 636 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
638 else 637 else
639 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling) 638 msg := $(warning No bfd.h/libbfd found, please install binutils-dev[el]/zlib-static/libiberty-dev to gain symbol demangling)
640 CFLAGS += -DNO_DEMANGLE 639 CFLAGS += -DNO_DEMANGLE
641 endif 640 endif
642 endif 641 endif
@@ -707,7 +706,7 @@ endif
707 706
708ifndef NO_LIBBABELTRACE 707ifndef NO_LIBBABELTRACE
709 ifeq ($(feature-libbabeltrace), 0) 708 ifeq ($(feature-libbabeltrace), 0)
710 msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-devel/libbabeltrace-ctf-dev); 709 msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev);
711 NO_LIBBABELTRACE := 1 710 NO_LIBBABELTRACE := 1
712 else 711 else
713 CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS) 712 CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS)
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch
index ff95a68741d1..e9720571341d 100644
--- a/tools/perf/config/Makefile.arch
+++ b/tools/perf/config/Makefile.arch
@@ -1,28 +1,15 @@
1ifndef ARCH
2ARCH := $(shell uname -m 2>/dev/null || echo not)
3endif
1 4
2uname_M := $(shell uname -m 2>/dev/null || echo not) 5ARCH := $(shell echo $(ARCH) | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
3 6 -e s/sun4u/sparc/ -e s/sparc64/sparc/ \
4RAW_ARCH := $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
5 -e s/arm.*/arm/ -e s/sa110/arm/ \ 7 -e s/arm.*/arm/ -e s/sa110/arm/ \
6 -e s/s390x/s390/ -e s/parisc64/parisc/ \ 8 -e s/s390x/s390/ -e s/parisc64/parisc/ \
7 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ 9 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
8 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \ 10 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
9 -e s/tile.*/tile/ ) 11 -e s/tile.*/tile/ )
10 12
11# Additional ARCH settings for x86
12ifeq ($(RAW_ARCH),i386)
13 ARCH ?= x86
14endif
15
16ifeq ($(RAW_ARCH),x86_64)
17 ARCH ?= x86
18
19 ifneq (, $(findstring m32,$(CFLAGS)))
20 RAW_ARCH := x86_32
21 endif
22endif
23
24ARCH ?= $(RAW_ARCH)
25
26LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) 13LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
27ifeq ($(LP64), 1) 14ifeq ($(LP64), 1)
28 IS_64_BIT := 1 15 IS_64_BIT := 1
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 70c9aebe9da3..8fe067864957 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -39,24 +39,24 @@ PKG_CONFIG := $(CROSS_COMPILE)pkg-config
39 39
40all: $(FILES) 40all: $(FILES)
41 41
42BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS) 42BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
43 43
44############################### 44###############################
45 45
46test-all.bin: 46test-all.bin:
47 $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -lbabeltrace 47 $(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -lbabeltrace
48 48
49test-hello.bin: 49test-hello.bin:
50 $(BUILD) 50 $(BUILD)
51 51
52test-pthread-attr-setaffinity-np.bin: 52test-pthread-attr-setaffinity-np.bin:
53 $(BUILD) -D_GNU_SOURCE -Werror -lpthread 53 $(BUILD) -D_GNU_SOURCE -lpthread
54 54
55test-stackprotector-all.bin: 55test-stackprotector-all.bin:
56 $(BUILD) -Werror -fstack-protector-all 56 $(BUILD) -fstack-protector-all
57 57
58test-fortify-source.bin: 58test-fortify-source.bin:
59 $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2 59 $(BUILD) -O2 -D_FORTIFY_SOURCE=2
60 60
61test-bionic.bin: 61test-bionic.bin:
62 $(BUILD) 62 $(BUILD)
@@ -119,10 +119,10 @@ test-libbfd.bin:
119 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 119 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
120 120
121test-liberty.bin: 121test-liberty.bin:
122 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty 122 $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
123 123
124test-liberty-z.bin: 124test-liberty-z.bin:
125 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz 125 $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
126 126
127test-cplus-demangle.bin: 127test-cplus-demangle.bin:
128 $(BUILD) -liberty 128 $(BUILD) -liberty
@@ -140,7 +140,7 @@ test-libbabeltrace.bin:
140 $(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace) 140 $(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace)
141 141
142test-sync-compare-and-swap.bin: 142test-sync-compare-and-swap.bin:
143 $(BUILD) -Werror 143 $(BUILD)
144 144
145test-compile-32.bin: 145test-compile-32.bin:
146 $(CC) -m32 -o $(OUTPUT)$@ test-compile.c 146 $(CC) -m32 -o $(OUTPUT)$@ test-compile.c
diff --git a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c b/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c
index 0a0d3ecb4e8a..fdada5e8d454 100644
--- a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c
+++ b/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c
@@ -1,14 +1,17 @@
1#include <stdint.h> 1#include <stdint.h>
2#include <pthread.h> 2#include <pthread.h>
3#include <sched.h>
3 4
4int main(void) 5int main(void)
5{ 6{
6 int ret = 0; 7 int ret = 0;
7 pthread_attr_t thread_attr; 8 pthread_attr_t thread_attr;
9 cpu_set_t cs;
8 10
9 pthread_attr_init(&thread_attr); 11 pthread_attr_init(&thread_attr);
10 /* don't care abt exact args, just the API itself in libpthread */ 12 CPU_ZERO(&cs);
11 ret = pthread_attr_setaffinity_np(&thread_attr, 0, NULL); 13
14 ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cs), &cs);
12 15
13 return ret; 16 return ret;
14} 17}
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index 7076a62d0ff7..c16ce833079c 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -175,6 +175,5 @@ _ge-abspath = $(if $(is-executable),$(1))
175define get-executable-or-default 175define get-executable-or-default
176$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2))) 176$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2)))
177endef 177endef
178_ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2))) 178_ge_attempt = $(if $(get-executable),$(get-executable),$(call _gea_err,$(2)))
179_gea_warn = $(warning The path '$(1)' is not executable.)
180_gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) 179_gea_err = $(if $(1),$(error Please set '$(1)' appropriately))
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 788506eef567..ad312d91caed 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1467,7 +1467,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1467 perf_hpp__set_user_width(symbol_conf.col_width_list_str); 1467 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
1468 1468
1469 while (1) { 1469 while (1) {
1470 const struct thread *thread = NULL; 1470 struct thread *thread = NULL;
1471 const struct dso *dso = NULL; 1471 const struct dso *dso = NULL;
1472 int choice = 0, 1472 int choice = 0,
1473 annotate = -2, zoom_dso = -2, zoom_thread = -2, 1473 annotate = -2, zoom_dso = -2, zoom_thread = -2,
@@ -1754,13 +1754,13 @@ zoom_thread:
1754 pstack__remove(fstack, &browser->hists->thread_filter); 1754 pstack__remove(fstack, &browser->hists->thread_filter);
1755zoom_out_thread: 1755zoom_out_thread:
1756 ui_helpline__pop(); 1756 ui_helpline__pop();
1757 browser->hists->thread_filter = NULL; 1757 thread__zput(browser->hists->thread_filter);
1758 perf_hpp__set_elide(HISTC_THREAD, false); 1758 perf_hpp__set_elide(HISTC_THREAD, false);
1759 } else { 1759 } else {
1760 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", 1760 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
1761 thread->comm_set ? thread__comm_str(thread) : "", 1761 thread->comm_set ? thread__comm_str(thread) : "",
1762 thread->tid); 1762 thread->tid);
1763 browser->hists->thread_filter = thread; 1763 browser->hists->thread_filter = thread__get(thread);
1764 perf_hpp__set_elide(HISTC_THREAD, false); 1764 perf_hpp__set_elide(HISTC_THREAD, false);
1765 pstack__push(fstack, &browser->hists->thread_filter); 1765 pstack__push(fstack, &browser->hists->thread_filter);
1766 } 1766 }
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index a2c8047d25f7..972a6e0da7ad 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -71,7 +71,7 @@ libperf-y += stat.o
71libperf-y += record.o 71libperf-y += record.o
72libperf-y += srcline.o 72libperf-y += srcline.o
73libperf-y += data.o 73libperf-y += data.o
74libperf-y += tsc.o 74libperf-$(CONFIG_X86) += tsc.o
75libperf-y += cloexec.o 75libperf-y += cloexec.o
76libperf-y += thread-stack.o 76libperf-y += thread-stack.o
77 77
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index ffdc338df925..a19674666b4e 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -61,8 +61,9 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
61 61
62 if (thread) { 62 if (thread) {
63 rb_erase(&thread->rb_node, &machine->threads); 63 rb_erase(&thread->rb_node, &machine->threads);
64 machine->last_match = NULL; 64 if (machine->last_match == thread)
65 thread__delete(thread); 65 thread__zput(machine->last_match);
66 thread__put(thread);
66 } 67 }
67 68
68 return 0; 69 return 0;
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index 47b78b3f0325..6da965bdbc2c 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -25,6 +25,10 @@ static int perf_flag_probe(void)
25 if (cpu < 0) 25 if (cpu < 0)
26 cpu = 0; 26 cpu = 0;
27 27
28 /*
29 * Using -1 for the pid is a workaround to avoid gratuitous jump label
30 * changes.
31 */
28 while (1) { 32 while (1) {
29 /* check cloexec flag */ 33 /* check cloexec flag */
30 fd = sys_perf_event_open(&attr, pid, cpu, -1, 34 fd = sys_perf_event_open(&attr, pid, cpu, -1,
@@ -47,16 +51,24 @@ static int perf_flag_probe(void)
47 err, strerror_r(err, sbuf, sizeof(sbuf))); 51 err, strerror_r(err, sbuf, sizeof(sbuf)));
48 52
49 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ 53 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
50 fd = sys_perf_event_open(&attr, pid, cpu, -1, 0); 54 while (1) {
55 fd = sys_perf_event_open(&attr, pid, cpu, -1, 0);
56 if (fd < 0 && pid == -1 && errno == EACCES) {
57 pid = 0;
58 continue;
59 }
60 break;
61 }
51 err = errno; 62 err = errno;
52 63
64 if (fd >= 0)
65 close(fd);
66
53 if (WARN_ONCE(fd < 0 && err != EBUSY, 67 if (WARN_ONCE(fd < 0 && err != EBUSY,
54 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", 68 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
55 err, strerror_r(err, sbuf, sizeof(sbuf)))) 69 err, strerror_r(err, sbuf, sizeof(sbuf))))
56 return -1; 70 return -1;
57 71
58 close(fd);
59
60 return 0; 72 return 0;
61} 73}
62 74
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 9e806d855b04..d5efa5092ce6 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -95,9 +95,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
95 return tgid; 95 return tgid;
96} 96}
97 97
98static pid_t perf_event__synthesize_comm(struct perf_tool *tool, 98static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid,
99 union perf_event *event, pid_t pid,
100 perf_event__handler_t process,
101 struct machine *machine) 99 struct machine *machine)
102{ 100{
103 size_t size; 101 size_t size;
@@ -124,6 +122,19 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
124 (sizeof(event->comm.comm) - size) + 122 (sizeof(event->comm.comm) - size) +
125 machine->id_hdr_size); 123 machine->id_hdr_size);
126 event->comm.tid = pid; 124 event->comm.tid = pid;
125out:
126 return tgid;
127}
128
129static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
130 union perf_event *event, pid_t pid,
131 perf_event__handler_t process,
132 struct machine *machine)
133{
134 pid_t tgid = perf_event__prepare_comm(event, pid, machine);
135
136 if (tgid == -1)
137 goto out;
127 138
128 if (process(tool, event, &synth_sample, machine) != 0) 139 if (process(tool, event, &synth_sample, machine) != 0)
129 return -1; 140 return -1;
@@ -139,7 +150,6 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
139{ 150{
140 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); 151 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
141 152
142 /* this is really a clone event but we use fork to synthesize it */
143 event->fork.ppid = tgid; 153 event->fork.ppid = tgid;
144 event->fork.ptid = tgid; 154 event->fork.ptid = tgid;
145 event->fork.pid = tgid; 155 event->fork.pid = tgid;
@@ -368,19 +378,23 @@ static int __event__synthesize_thread(union perf_event *comm_event,
368 if (*end) 378 if (*end)
369 continue; 379 continue;
370 380
371 tgid = perf_event__synthesize_comm(tool, comm_event, _pid, 381 tgid = perf_event__prepare_comm(comm_event, _pid, machine);
372 process, machine);
373 if (tgid == -1) 382 if (tgid == -1)
374 return -1; 383 return -1;
375 384
385 if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
386 process, machine) < 0)
387 return -1;
388 /*
389 * Send the prepared comm event
390 */
391 if (process(tool, comm_event, &synth_sample, machine) != 0)
392 return -1;
393
376 if (_pid == pid) { 394 if (_pid == pid) {
377 /* process the parent's maps too */ 395 /* process the parent's maps too */
378 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 396 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
379 process, machine, mmap_data); 397 process, machine, mmap_data);
380 } else {
381 /* only fork the tid's map, to save time */
382 rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
383 process, machine);
384 } 398 }
385 399
386 if (rc) 400 if (rc)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index d4768a30f884..f07c984465f0 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -28,7 +28,7 @@ struct perf_mmap {
28 int mask; 28 int mask;
29 int refcnt; 29 int refcnt;
30 unsigned int prev; 30 unsigned int prev;
31 char event_copy[PERF_SAMPLE_MAX_SIZE]; 31 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
32}; 32};
33 33
34struct perf_evlist { 34struct perf_evlist {
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 70b48a65064c..95f5ab707b74 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -355,6 +355,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
355 callchain_init(he->callchain); 355 callchain_init(he->callchain);
356 356
357 INIT_LIST_HEAD(&he->pairs.node); 357 INIT_LIST_HEAD(&he->pairs.node);
358 thread__get(he->thread);
358 } 359 }
359 360
360 return he; 361 return he;
@@ -941,6 +942,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
941 942
942void hist_entry__delete(struct hist_entry *he) 943void hist_entry__delete(struct hist_entry *he)
943{ 944{
945 thread__zput(he->thread);
944 zfree(&he->branch_info); 946 zfree(&he->branch_info);
945 zfree(&he->mem_info); 947 zfree(&he->mem_info);
946 zfree(&he->stat_acc); 948 zfree(&he->stat_acc);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 2b690d028907..e988c9fcd1bc 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -60,7 +60,7 @@ struct hists {
60 struct rb_root entries_collapsed; 60 struct rb_root entries_collapsed;
61 u64 nr_entries; 61 u64 nr_entries;
62 u64 nr_non_filtered_entries; 62 u64 nr_non_filtered_entries;
63 const struct thread *thread_filter; 63 struct thread *thread_filter;
64 const struct dso *dso_filter; 64 const struct dso *dso_filter;
65 const char *uid_filter_str; 65 const char *uid_filter_str;
66 const char *symbol_filter_str; 66 const char *symbol_filter_str;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 9e0f60a7e7b3..24f8c978cfd4 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -14,6 +14,8 @@
14#include "unwind.h" 14#include "unwind.h"
15#include "linux/hash.h" 15#include "linux/hash.h"
16 16
17static void machine__remove_thread(struct machine *machine, struct thread *th);
18
17static void dsos__init(struct dsos *dsos) 19static void dsos__init(struct dsos *dsos)
18{ 20{
19 INIT_LIST_HEAD(&dsos->head); 21 INIT_LIST_HEAD(&dsos->head);
@@ -89,16 +91,6 @@ static void dsos__delete(struct dsos *dsos)
89 } 91 }
90} 92}
91 93
92void machine__delete_dead_threads(struct machine *machine)
93{
94 struct thread *n, *t;
95
96 list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
97 list_del(&t->node);
98 thread__delete(t);
99 }
100}
101
102void machine__delete_threads(struct machine *machine) 94void machine__delete_threads(struct machine *machine)
103{ 95{
104 struct rb_node *nd = rb_first(&machine->threads); 96 struct rb_node *nd = rb_first(&machine->threads);
@@ -106,9 +98,8 @@ void machine__delete_threads(struct machine *machine)
106 while (nd) { 98 while (nd) {
107 struct thread *t = rb_entry(nd, struct thread, rb_node); 99 struct thread *t = rb_entry(nd, struct thread, rb_node);
108 100
109 rb_erase(&t->rb_node, &machine->threads);
110 nd = rb_next(nd); 101 nd = rb_next(nd);
111 thread__delete(t); 102 machine__remove_thread(machine, t);
112 } 103 }
113} 104}
114 105
@@ -361,9 +352,13 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
361 * the full rbtree: 352 * the full rbtree:
362 */ 353 */
363 th = machine->last_match; 354 th = machine->last_match;
364 if (th && th->tid == tid) { 355 if (th != NULL) {
365 machine__update_thread_pid(machine, th, pid); 356 if (th->tid == tid) {
366 return th; 357 machine__update_thread_pid(machine, th, pid);
358 return th;
359 }
360
361 thread__zput(machine->last_match);
367 } 362 }
368 363
369 while (*p != NULL) { 364 while (*p != NULL) {
@@ -371,7 +366,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
371 th = rb_entry(parent, struct thread, rb_node); 366 th = rb_entry(parent, struct thread, rb_node);
372 367
373 if (th->tid == tid) { 368 if (th->tid == tid) {
374 machine->last_match = th; 369 machine->last_match = thread__get(th);
375 machine__update_thread_pid(machine, th, pid); 370 machine__update_thread_pid(machine, th, pid);
376 return th; 371 return th;
377 } 372 }
@@ -403,8 +398,11 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
403 thread__delete(th); 398 thread__delete(th);
404 return NULL; 399 return NULL;
405 } 400 }
406 401 /*
407 machine->last_match = th; 402 * It is now in the rbtree, get a ref
403 */
404 thread__get(th);
405 machine->last_match = thread__get(th);
408 } 406 }
409 407
410 return th; 408 return th;
@@ -1238,13 +1236,17 @@ out_problem:
1238 1236
1239static void machine__remove_thread(struct machine *machine, struct thread *th) 1237static void machine__remove_thread(struct machine *machine, struct thread *th)
1240{ 1238{
1241 machine->last_match = NULL; 1239 if (machine->last_match == th)
1240 thread__zput(machine->last_match);
1241
1242 rb_erase(&th->rb_node, &machine->threads); 1242 rb_erase(&th->rb_node, &machine->threads);
1243 /* 1243 /*
1244 * We may have references to this thread, for instance in some hist_entry 1244 * Move it first to the dead_threads list, then drop the reference,
1245 * instances, so just move them to a separate list. 1245 * if this is the last reference, then the thread__delete destructor
1246 * will be called and we will remove it from the dead_threads list.
1246 */ 1247 */
1247 list_add_tail(&th->node, &machine->dead_threads); 1248 list_add_tail(&th->node, &machine->dead_threads);
1249 thread__put(th);
1248} 1250}
1249 1251
1250int machine__process_fork_event(struct machine *machine, union perf_event *event, 1252int machine__process_fork_event(struct machine *machine, union perf_event *event,
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index e8b7779a0a3f..e2faf3b47e7b 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -118,7 +118,6 @@ void machines__set_comm_exec(struct machines *machines, bool comm_exec);
118struct machine *machine__new_host(void); 118struct machine *machine__new_host(void);
119int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 119int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
120void machine__exit(struct machine *machine); 120void machine__exit(struct machine *machine);
121void machine__delete_dead_threads(struct machine *machine);
122void machine__delete_threads(struct machine *machine); 121void machine__delete_threads(struct machine *machine);
123void machine__delete(struct machine *machine); 122void machine__delete(struct machine *machine);
124 123
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 7c0e765fa2e3..1c570c2fa7cc 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2199,6 +2199,27 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2199 return ret; 2199 return ret;
2200} 2200}
2201 2201
2202/* Warn if the current kernel's uprobe implementation is old */
2203static void warn_uprobe_event_compat(struct probe_trace_event *tev)
2204{
2205 int i;
2206 char *buf = synthesize_probe_trace_command(tev);
2207
2208 /* Old uprobe event doesn't support memory dereference */
2209 if (!tev->uprobes || tev->nargs == 0 || !buf)
2210 goto out;
2211
2212 for (i = 0; i < tev->nargs; i++)
2213 if (strglobmatch(tev->args[i].value, "[$@+-]*")) {
2214 pr_warning("Please upgrade your kernel to at least "
2215 "3.14 to have access to feature %s\n",
2216 tev->args[i].value);
2217 break;
2218 }
2219out:
2220 free(buf);
2221}
2222
2202static int __add_probe_trace_events(struct perf_probe_event *pev, 2223static int __add_probe_trace_events(struct perf_probe_event *pev,
2203 struct probe_trace_event *tevs, 2224 struct probe_trace_event *tevs,
2204 int ntevs, bool allow_suffix) 2225 int ntevs, bool allow_suffix)
@@ -2295,6 +2316,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2295 */ 2316 */
2296 allow_suffix = true; 2317 allow_suffix = true;
2297 } 2318 }
2319 if (ret == -EINVAL && pev->uprobes)
2320 warn_uprobe_event_compat(tev);
2298 2321
2299 /* Note that it is possible to skip all events because of blacklist */ 2322 /* Note that it is possible to skip all events because of blacklist */
2300 if (ret >= 0 && tev->event) { 2323 if (ret >= 0 && tev->event) {
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index d14193518e4d..46f009aa486c 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1345,11 +1345,8 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1345 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; 1345 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
1346 int baseline = 0, lineno = 0, ret = 0; 1346 int baseline = 0, lineno = 0, ret = 0;
1347 1347
1348 /* Adjust address with bias */
1349 addr += dbg->bias;
1350
1351 /* Find cu die */ 1348 /* Find cu die */
1352 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) { 1349 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
1353 pr_warning("Failed to find debug information for address %lx\n", 1350 pr_warning("Failed to find debug information for address %lx\n",
1354 addr); 1351 addr);
1355 ret = -EINVAL; 1352 ret = -EINVAL;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index e4f166981ff0..ed4e5cf2bd9d 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -138,11 +138,6 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
138 return NULL; 138 return NULL;
139} 139}
140 140
141static void perf_session__delete_dead_threads(struct perf_session *session)
142{
143 machine__delete_dead_threads(&session->machines.host);
144}
145
146static void perf_session__delete_threads(struct perf_session *session) 141static void perf_session__delete_threads(struct perf_session *session)
147{ 142{
148 machine__delete_threads(&session->machines.host); 143 machine__delete_threads(&session->machines.host);
@@ -167,7 +162,6 @@ static void perf_session_env__delete(struct perf_session_env *env)
167void perf_session__delete(struct perf_session *session) 162void perf_session__delete(struct perf_session *session)
168{ 163{
169 perf_session__destroy_kernel_maps(session); 164 perf_session__destroy_kernel_maps(session);
170 perf_session__delete_dead_threads(session);
171 perf_session__delete_threads(session); 165 perf_session__delete_threads(session);
172 perf_session_env__delete(&session->header.env); 166 perf_session_env__delete(&session->header.env);
173 machines__exit(&session->machines); 167 machines__exit(&session->machines);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index b02731a19d1f..ada16762fac2 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -11,6 +11,11 @@
11#include <symbol/kallsyms.h> 11#include <symbol/kallsyms.h>
12#include "debug.h" 12#include "debug.h"
13 13
14#ifndef EM_AARCH64
15#define EM_AARCH64 183 /* ARM 64 bit */
16#endif
17
18
14#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT 19#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
15extern char *cplus_demangle(const char *, int); 20extern char *cplus_demangle(const char *, int);
16 21
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 9ebc8b1f9be5..a5dbba95107f 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -82,6 +82,20 @@ void thread__delete(struct thread *thread)
82 free(thread); 82 free(thread);
83} 83}
84 84
85struct thread *thread__get(struct thread *thread)
86{
87 ++thread->refcnt;
88 return thread;
89}
90
91void thread__put(struct thread *thread)
92{
93 if (thread && --thread->refcnt == 0) {
94 list_del_init(&thread->node);
95 thread__delete(thread);
96 }
97}
98
85struct comm *thread__comm(const struct thread *thread) 99struct comm *thread__comm(const struct thread *thread)
86{ 100{
87 if (list_empty(&thread->comm_list)) 101 if (list_empty(&thread->comm_list))
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 160fd066a7d1..783b6688d2f7 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -20,6 +20,7 @@ struct thread {
20 pid_t tid; 20 pid_t tid;
21 pid_t ppid; 21 pid_t ppid;
22 int cpu; 22 int cpu;
23 int refcnt;
23 char shortname[3]; 24 char shortname[3];
24 bool comm_set; 25 bool comm_set;
25 bool dead; /* if set thread has exited */ 26 bool dead; /* if set thread has exited */
@@ -37,6 +38,18 @@ struct comm;
37struct thread *thread__new(pid_t pid, pid_t tid); 38struct thread *thread__new(pid_t pid, pid_t tid);
38int thread__init_map_groups(struct thread *thread, struct machine *machine); 39int thread__init_map_groups(struct thread *thread, struct machine *machine);
39void thread__delete(struct thread *thread); 40void thread__delete(struct thread *thread);
41
42struct thread *thread__get(struct thread *thread);
43void thread__put(struct thread *thread);
44
45static inline void __thread__zput(struct thread **thread)
46{
47 thread__put(*thread);
48 *thread = NULL;
49}
50
51#define thread__zput(thread) __thread__zput(&thread)
52
40static inline void thread__exited(struct thread *thread) 53static inline void thread__exited(struct thread *thread)
41{ 54{
42 thread->dead = true; 55 thread->dead = true;