aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/trace/ftrace-design.txt7
-rw-r--r--Documentation/trace/ftrace.txt151
-rw-r--r--Documentation/trace/kprobetrace.txt16
-rw-r--r--arch/x86/ia32/ia32entry.S2
-rw-r--r--arch/x86/include/asm/cpufeature.h2
-rw-r--r--arch/x86/include/asm/kdebug.h1
-rw-r--r--arch/x86/include/asm/msr-index.h3
-rw-r--r--arch/x86/include/asm/nmi.h1
-rw-r--r--arch/x86/include/asm/smp.h10
-rw-r--r--arch/x86/kernel/cpu/perf_event.c170
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd.c175
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c417
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c97
-rw-r--r--arch/x86/kernel/cpu/perf_event_p4.c8
-rw-r--r--arch/x86/kernel/cpu/perf_event_p6.c4
-rw-r--r--arch/x86/kernel/cpu/perfctr-watchdog.c4
-rw-r--r--arch/x86/kernel/dumpstack.c25
-rw-r--r--arch/x86/kernel/entry_32.S6
-rw-r--r--arch/x86/kernel/entry_64.S6
-rw-r--r--arch/x86/kernel/ftrace.c15
-rw-r--r--arch/x86/kernel/kgdb.c9
-rw-r--r--arch/x86/kernel/kprobes.c8
-rw-r--r--arch/x86/kernel/vmlinux.lds.S1
-rw-r--r--arch/x86/kvm/trace.h8
-rw-r--r--include/asm-generic/sections.h1
-rw-r--r--include/asm-generic/vmlinux.lds.h6
-rw-r--r--include/linux/cgroup.h4
-rw-r--r--include/linux/cgroup_subsys.h4
-rw-r--r--include/linux/ftrace.h2
-rw-r--r--include/linux/ftrace_event.h2
-rw-r--r--include/linux/perf_event.h50
-rw-r--r--include/linux/ring_buffer.h2
-rw-r--r--include/linux/sched.h7
-rw-r--r--include/linux/syscalls.h10
-rw-r--r--include/trace/events/mce.h8
-rw-r--r--include/trace/events/module.h5
-rw-r--r--include/trace/events/skb.h4
-rw-r--r--init/Kconfig10
-rw-r--r--kernel/cgroup.c54
-rw-r--r--kernel/perf_event.c1004
-rw-r--r--kernel/sched.c37
-rw-r--r--kernel/sysctl.c2
-rw-r--r--kernel/trace/ftrace.c52
-rw-r--r--kernel/trace/ring_buffer.c24
-rw-r--r--kernel/trace/trace.c38
-rw-r--r--kernel/trace/trace.h41
-rw-r--r--kernel/trace/trace_entries.h6
-rw-r--r--kernel/trace/trace_events.c2
-rw-r--r--kernel/trace/trace_events_filter.c885
-rw-r--r--kernel/trace/trace_kprobe.c111
-rw-r--r--kernel/trace/trace_output.c36
-rw-r--r--kernel/trace/trace_sched_switch.c48
-rw-r--r--kernel/trace/trace_syscalls.c42
-rw-r--r--scripts/kconfig/streamline_config.pl2
-rw-r--r--scripts/recordmcount.c3
-rwxr-xr-xscripts/recordmcount.pl1
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Documentation/Makefile19
-rw-r--r--tools/perf/Documentation/perf-list.txt23
-rw-r--r--tools/perf/Documentation/perf-lock.txt12
-rw-r--r--tools/perf/Documentation/perf-probe.txt26
-rw-r--r--tools/perf/Documentation/perf-record.txt11
-rw-r--r--tools/perf/Documentation/perf-stat.txt11
-rw-r--r--tools/perf/Makefile649
-rw-r--r--tools/perf/bench/sched-pipe.c2
-rw-r--r--tools/perf/builtin-annotate.c351
-rw-r--r--tools/perf/builtin-diff.c16
-rw-r--r--tools/perf/builtin-inject.c82
-rw-r--r--tools/perf/builtin-kmem.c10
-rw-r--r--tools/perf/builtin-list.c43
-rw-r--r--tools/perf/builtin-lock.c8
-rw-r--r--tools/perf/builtin-probe.c70
-rw-r--r--tools/perf/builtin-record.c450
-rw-r--r--tools/perf/builtin-report.c225
-rw-r--r--tools/perf/builtin-sched.c27
-rw-r--r--tools/perf/builtin-script.c17
-rw-r--r--tools/perf/builtin-stat.c118
-rw-r--r--tools/perf/builtin-test.c184
-rw-r--r--tools/perf/builtin-timechart.c13
-rw-r--r--tools/perf/builtin-top.c1029
-rw-r--r--tools/perf/perf.h26
-rwxr-xr-xtools/perf/python/twatch.py41
-rw-r--r--tools/perf/util/annotate.c605
-rw-r--r--tools/perf/util/annotate.h103
-rw-r--r--tools/perf/util/build-id.c21
-rw-r--r--tools/perf/util/cache.h7
-rw-r--r--tools/perf/util/callchain.c227
-rw-r--r--tools/perf/util/callchain.h76
-rw-r--r--tools/perf/util/cgroup.c178
-rw-r--r--tools/perf/util/cgroup.h17
-rw-r--r--tools/perf/util/cpumap.c5
-rw-r--r--tools/perf/util/cpumap.h2
-rw-r--r--tools/perf/util/debug.c2
-rw-r--r--tools/perf/util/debug.h2
-rw-r--r--tools/perf/util/event.c374
-rw-r--r--tools/perf/util/event.h78
-rw-r--r--tools/perf/util/evlist.c394
-rw-r--r--tools/perf/util/evlist.h68
-rw-r--r--tools/perf/util/evsel.c234
-rw-r--r--tools/perf/util/evsel.h47
-rw-r--r--tools/perf/util/exec_cmd.c19
-rw-r--r--tools/perf/util/header.c535
-rw-r--r--tools/perf/util/header.h95
-rw-r--r--tools/perf/util/hist.c250
-rw-r--r--tools/perf/util/hist.h60
-rw-r--r--tools/perf/util/include/linux/list.h1
-rw-r--r--tools/perf/util/parse-events.c175
-rw-r--r--tools/perf/util/parse-events.h12
-rw-r--r--tools/perf/util/probe-event.c159
-rw-r--r--tools/perf/util/probe-event.h4
-rw-r--r--tools/perf/util/probe-finder.c533
-rw-r--r--tools/perf/util/python.c896
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c3
-rw-r--r--tools/perf/util/session.c266
-rw-r--r--tools/perf/util/session.h41
-rw-r--r--tools/perf/util/setup.py19
-rw-r--r--tools/perf/util/strfilter.c199
-rw-r--r--tools/perf/util/strfilter.h48
-rw-r--r--tools/perf/util/symbol.c5
-rw-r--r--tools/perf/util/symbol.h1
-rw-r--r--tools/perf/util/thread.c55
-rw-r--r--tools/perf/util/thread.h14
-rw-r--r--tools/perf/util/thread_map.c64
-rw-r--r--tools/perf/util/thread_map.h15
-rw-r--r--tools/perf/util/top.c238
-rw-r--r--tools/perf/util/top.h66
-rw-r--r--tools/perf/util/trace-event-parse.c2
-rw-r--r--tools/perf/util/ui/browser.c25
-rw-r--r--tools/perf/util/ui/browser.h3
-rw-r--r--tools/perf/util/ui/browsers/annotate.c178
-rw-r--r--tools/perf/util/ui/browsers/hists.c197
-rw-r--r--tools/perf/util/ui/browsers/map.c2
-rw-r--r--tools/perf/util/ui/browsers/top.c213
-rw-r--r--tools/perf/util/ui/helpline.c5
-rw-r--r--tools/perf/util/ui/libslang.h6
-rw-r--r--tools/perf/util/ui/setup.c8
-rw-r--r--tools/perf/util/ui/ui.h8
-rw-r--r--tools/perf/util/ui/util.c7
-rw-r--r--tools/perf/util/util.h26
-rwxr-xr-xtools/testing/ktest/ktest.pl2
140 files changed, 9295 insertions, 4713 deletions
diff --git a/Documentation/trace/ftrace-design.txt b/Documentation/trace/ftrace-design.txt
index dc52bd442c92..79fcafc7fd64 100644
--- a/Documentation/trace/ftrace-design.txt
+++ b/Documentation/trace/ftrace-design.txt
@@ -247,6 +247,13 @@ You need very few things to get the syscalls tracing in an arch.
247- Support the TIF_SYSCALL_TRACEPOINT thread flags. 247- Support the TIF_SYSCALL_TRACEPOINT thread flags.
248- Put the trace_sys_enter() and trace_sys_exit() tracepoints calls from ptrace 248- Put the trace_sys_enter() and trace_sys_exit() tracepoints calls from ptrace
249 in the ptrace syscalls tracing path. 249 in the ptrace syscalls tracing path.
250- If the system call table on this arch is more complicated than a simple array
251 of addresses of the system calls, implement an arch_syscall_addr to return
252 the address of a given system call.
253- If the symbol names of the system calls do not match the function names on
254 this arch, define ARCH_HAS_SYSCALL_MATCH_SYM_NAME in asm/ftrace.h and
255 implement arch_syscall_match_sym_name with the appropriate logic to return
256 true if the function name corresponds with the symbol name.
250- Tag this arch as HAVE_SYSCALL_TRACEPOINTS. 257- Tag this arch as HAVE_SYSCALL_TRACEPOINTS.
251 258
252 259
diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index 557c1edeccaf..1ebc24cf9a55 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -80,11 +80,11 @@ of ftrace. Here is a list of some of the key files:
80 tracers listed here can be configured by 80 tracers listed here can be configured by
81 echoing their name into current_tracer. 81 echoing their name into current_tracer.
82 82
83 tracing_enabled: 83 tracing_on:
84 84
85 This sets or displays whether the current_tracer 85 This sets or displays whether writing to the trace
86 is activated and tracing or not. Echo 0 into this 86 ring buffer is enabled. Echo 0 into this file to disable
87 file to disable the tracer or 1 to enable it. 87 the tracer or 1 to enable it.
88 88
89 trace: 89 trace:
90 90
@@ -202,10 +202,6 @@ Here is the list of current tracers that may be configured.
202 to draw a graph of function calls similar to C code 202 to draw a graph of function calls similar to C code
203 source. 203 source.
204 204
205 "sched_switch"
206
207 Traces the context switches and wakeups between tasks.
208
209 "irqsoff" 205 "irqsoff"
210 206
211 Traces the areas that disable interrupts and saves 207 Traces the areas that disable interrupts and saves
@@ -273,39 +269,6 @@ format, the function name that was traced "path_put" and the
273parent function that called this function "path_walk". The 269parent function that called this function "path_walk". The
274timestamp is the time at which the function was entered. 270timestamp is the time at which the function was entered.
275 271
276The sched_switch tracer also includes tracing of task wakeups
277and context switches.
278
279 ksoftirqd/1-7 [01] 1453.070013: 7:115:R + 2916:115:S
280 ksoftirqd/1-7 [01] 1453.070013: 7:115:R + 10:115:S
281 ksoftirqd/1-7 [01] 1453.070013: 7:115:R ==> 10:115:R
282 events/1-10 [01] 1453.070013: 10:115:S ==> 2916:115:R
283 kondemand/1-2916 [01] 1453.070013: 2916:115:S ==> 7:115:R
284 ksoftirqd/1-7 [01] 1453.070013: 7:115:S ==> 0:140:R
285
286Wake ups are represented by a "+" and the context switches are
287shown as "==>". The format is:
288
289 Context switches:
290
291 Previous task Next Task
292
293 <pid>:<prio>:<state> ==> <pid>:<prio>:<state>
294
295 Wake ups:
296
297 Current task Task waking up
298
299 <pid>:<prio>:<state> + <pid>:<prio>:<state>
300
301The prio is the internal kernel priority, which is the inverse
302of the priority that is usually displayed by user-space tools.
303Zero represents the highest priority (99). Prio 100 starts the
304"nice" priorities with 100 being equal to nice -20 and 139 being
305nice 19. The prio "140" is reserved for the idle task which is
306the lowest priority thread (pid 0).
307
308
309Latency trace format 272Latency trace format
310-------------------- 273--------------------
311 274
@@ -491,78 +454,10 @@ x494] <- /root/a.out[+0x4a8] <- /lib/libc-2.7.so[+0x1e1a6]
491 latencies, as described in "Latency 454 latencies, as described in "Latency
492 trace format". 455 trace format".
493 456
494sched_switch 457 overwrite - This controls what happens when the trace buffer is
495------------ 458 full. If "1" (default), the oldest events are
496 459 discarded and overwritten. If "0", then the newest
497This tracer simply records schedule switches. Here is an example 460 events are discarded.
498of how to use it.
499
500 # echo sched_switch > current_tracer
501 # echo 1 > tracing_enabled
502 # sleep 1
503 # echo 0 > tracing_enabled
504 # cat trace
505
506# tracer: sched_switch
507#
508# TASK-PID CPU# TIMESTAMP FUNCTION
509# | | | | |
510 bash-3997 [01] 240.132281: 3997:120:R + 4055:120:R
511 bash-3997 [01] 240.132284: 3997:120:R ==> 4055:120:R
512 sleep-4055 [01] 240.132371: 4055:120:S ==> 3997:120:R
513 bash-3997 [01] 240.132454: 3997:120:R + 4055:120:S
514 bash-3997 [01] 240.132457: 3997:120:R ==> 4055:120:R
515 sleep-4055 [01] 240.132460: 4055:120:D ==> 3997:120:R
516 bash-3997 [01] 240.132463: 3997:120:R + 4055:120:D
517 bash-3997 [01] 240.132465: 3997:120:R ==> 4055:120:R
518 <idle>-0 [00] 240.132589: 0:140:R + 4:115:S
519 <idle>-0 [00] 240.132591: 0:140:R ==> 4:115:R
520 ksoftirqd/0-4 [00] 240.132595: 4:115:S ==> 0:140:R
521 <idle>-0 [00] 240.132598: 0:140:R + 4:115:S
522 <idle>-0 [00] 240.132599: 0:140:R ==> 4:115:R
523 ksoftirqd/0-4 [00] 240.132603: 4:115:S ==> 0:140:R
524 sleep-4055 [01] 240.133058: 4055:120:S ==> 3997:120:R
525 [...]
526
527
528As we have discussed previously about this format, the header
529shows the name of the trace and points to the options. The
530"FUNCTION" is a misnomer since here it represents the wake ups
531and context switches.
532
533The sched_switch file only lists the wake ups (represented with
534'+') and context switches ('==>') with the previous task or
535current task first followed by the next task or task waking up.
536The format for both of these is PID:KERNEL-PRIO:TASK-STATE.
537Remember that the KERNEL-PRIO is the inverse of the actual
538priority with zero (0) being the highest priority and the nice
539values starting at 100 (nice -20). Below is a quick chart to map
540the kernel priority to user land priorities.
541
542 Kernel Space User Space
543 ===============================================================
544 0(high) to 98(low) user RT priority 99(high) to 1(low)
545 with SCHED_RR or SCHED_FIFO
546 ---------------------------------------------------------------
547 99 sched_priority is not used in scheduling
548 decisions(it must be specified as 0)
549 ---------------------------------------------------------------
550 100(high) to 139(low) user nice -20(high) to 19(low)
551 ---------------------------------------------------------------
552 140 idle task priority
553 ---------------------------------------------------------------
554
555The task states are:
556
557 R - running : wants to run, may not actually be running
558 S - sleep : process is waiting to be woken up (handles signals)
559 D - disk sleep (uninterruptible sleep) : process must be woken up
560 (ignores signals)
561 T - stopped : process suspended
562 t - traced : process is being traced (with something like gdb)
563 Z - zombie : process waiting to be cleaned up
564 X - unknown
565
566 461
567ftrace_enabled 462ftrace_enabled
568-------------- 463--------------
@@ -607,10 +502,10 @@ an example:
607 # echo irqsoff > current_tracer 502 # echo irqsoff > current_tracer
608 # echo latency-format > trace_options 503 # echo latency-format > trace_options
609 # echo 0 > tracing_max_latency 504 # echo 0 > tracing_max_latency
610 # echo 1 > tracing_enabled 505 # echo 1 > tracing_on
611 # ls -ltr 506 # ls -ltr
612 [...] 507 [...]
613 # echo 0 > tracing_enabled 508 # echo 0 > tracing_on
614 # cat trace 509 # cat trace
615# tracer: irqsoff 510# tracer: irqsoff
616# 511#
@@ -715,10 +610,10 @@ is much like the irqsoff tracer.
715 # echo preemptoff > current_tracer 610 # echo preemptoff > current_tracer
716 # echo latency-format > trace_options 611 # echo latency-format > trace_options
717 # echo 0 > tracing_max_latency 612 # echo 0 > tracing_max_latency
718 # echo 1 > tracing_enabled 613 # echo 1 > tracing_on
719 # ls -ltr 614 # ls -ltr
720 [...] 615 [...]
721 # echo 0 > tracing_enabled 616 # echo 0 > tracing_on
722 # cat trace 617 # cat trace
723# tracer: preemptoff 618# tracer: preemptoff
724# 619#
@@ -863,10 +758,10 @@ tracers.
863 # echo preemptirqsoff > current_tracer 758 # echo preemptirqsoff > current_tracer
864 # echo latency-format > trace_options 759 # echo latency-format > trace_options
865 # echo 0 > tracing_max_latency 760 # echo 0 > tracing_max_latency
866 # echo 1 > tracing_enabled 761 # echo 1 > tracing_on
867 # ls -ltr 762 # ls -ltr
868 [...] 763 [...]
869 # echo 0 > tracing_enabled 764 # echo 0 > tracing_on
870 # cat trace 765 # cat trace
871# tracer: preemptirqsoff 766# tracer: preemptirqsoff
872# 767#
@@ -1026,9 +921,9 @@ Instead of performing an 'ls', we will run 'sleep 1' under
1026 # echo wakeup > current_tracer 921 # echo wakeup > current_tracer
1027 # echo latency-format > trace_options 922 # echo latency-format > trace_options
1028 # echo 0 > tracing_max_latency 923 # echo 0 > tracing_max_latency
1029 # echo 1 > tracing_enabled 924 # echo 1 > tracing_on
1030 # chrt -f 5 sleep 1 925 # chrt -f 5 sleep 1
1031 # echo 0 > tracing_enabled 926 # echo 0 > tracing_on
1032 # cat trace 927 # cat trace
1033# tracer: wakeup 928# tracer: wakeup
1034# 929#
@@ -1140,9 +1035,9 @@ ftrace_enabled is set; otherwise this tracer is a nop.
1140 1035
1141 # sysctl kernel.ftrace_enabled=1 1036 # sysctl kernel.ftrace_enabled=1
1142 # echo function > current_tracer 1037 # echo function > current_tracer
1143 # echo 1 > tracing_enabled 1038 # echo 1 > tracing_on
1144 # usleep 1 1039 # usleep 1
1145 # echo 0 > tracing_enabled 1040 # echo 0 > tracing_on
1146 # cat trace 1041 # cat trace
1147# tracer: function 1042# tracer: function
1148# 1043#
@@ -1180,7 +1075,7 @@ int trace_fd;
1180[...] 1075[...]
1181int main(int argc, char *argv[]) { 1076int main(int argc, char *argv[]) {
1182 [...] 1077 [...]
1183 trace_fd = open(tracing_file("tracing_enabled"), O_WRONLY); 1078 trace_fd = open(tracing_file("tracing_on"), O_WRONLY);
1184 [...] 1079 [...]
1185 if (condition_hit()) { 1080 if (condition_hit()) {
1186 write(trace_fd, "0", 1); 1081 write(trace_fd, "0", 1);
@@ -1631,9 +1526,9 @@ If I am only interested in sys_nanosleep and hrtimer_interrupt:
1631 # echo sys_nanosleep hrtimer_interrupt \ 1526 # echo sys_nanosleep hrtimer_interrupt \
1632 > set_ftrace_filter 1527 > set_ftrace_filter
1633 # echo function > current_tracer 1528 # echo function > current_tracer
1634 # echo 1 > tracing_enabled 1529 # echo 1 > tracing_on
1635 # usleep 1 1530 # usleep 1
1636 # echo 0 > tracing_enabled 1531 # echo 0 > tracing_on
1637 # cat trace 1532 # cat trace
1638# tracer: ftrace 1533# tracer: ftrace
1639# 1534#
@@ -1879,9 +1774,9 @@ different. The trace is live.
1879 # echo function > current_tracer 1774 # echo function > current_tracer
1880 # cat trace_pipe > /tmp/trace.out & 1775 # cat trace_pipe > /tmp/trace.out &
1881[1] 4153 1776[1] 4153
1882 # echo 1 > tracing_enabled 1777 # echo 1 > tracing_on
1883 # usleep 1 1778 # usleep 1
1884 # echo 0 > tracing_enabled 1779 # echo 0 > tracing_on
1885 # cat trace 1780 # cat trace
1886# tracer: function 1781# tracer: function
1887# 1782#
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt
index 5f77d94598dd..6d27ab8d6e9f 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -42,11 +42,25 @@ Synopsis of kprobe_events
42 +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**) 42 +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
43 NAME=FETCHARG : Set NAME as the argument name of FETCHARG. 43 NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
44 FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types 44 FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
45 (u8/u16/u32/u64/s8/s16/s32/s64) and string are supported. 45 (u8/u16/u32/u64/s8/s16/s32/s64), "string" and bitfield
46 are supported.
46 47
47 (*) only for return probe. 48 (*) only for return probe.
48 (**) this is useful for fetching a field of data structures. 49 (**) this is useful for fetching a field of data structures.
49 50
51Types
52-----
53Several types are supported for fetch-args. Kprobe tracer will access memory
54by given type. Prefix 's' and 'u' means those types are signed and unsigned
55respectively. Traced arguments are shown in decimal (signed) or hex (unsigned).
56String type is a special type, which fetches a "null-terminated" string from
57kernel space. This means it will fail and store NULL if the string container
58has been paged out.
59Bitfield is another special type, which takes 3 parameters, bit-width, bit-
60offset, and container-size (usually 32). The syntax is;
61
62 b<bit-width>@<bit-offset>/<container-size>
63
50 64
51Per-Probe Event Filtering 65Per-Probe Event Filtering
52------------------------- 66-------------------------
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 98d353edfff3..f27b709754bf 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -25,6 +25,8 @@
25#define sysretl_audit ia32_ret_from_sys_call 25#define sysretl_audit ia32_ret_from_sys_call
26#endif 26#endif
27 27
28 .section .entry.text, "ax"
29
28#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8) 30#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
29 31
30 .macro IA32_ARG_FIXUP noebp=0 32 .macro IA32_ARG_FIXUP noebp=0
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 220e2ea08e80..91f3e087cf21 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -160,6 +160,7 @@
160#define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */ 160#define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */
161#define X86_FEATURE_TBM (6*32+21) /* trailing bit manipulations */ 161#define X86_FEATURE_TBM (6*32+21) /* trailing bit manipulations */
162#define X86_FEATURE_TOPOEXT (6*32+22) /* topology extensions CPUID leafs */ 162#define X86_FEATURE_TOPOEXT (6*32+22) /* topology extensions CPUID leafs */
163#define X86_FEATURE_PERFCTR_CORE (6*32+23) /* core performance counter extensions */
163 164
164/* 165/*
165 * Auxiliary flags: Linux defined - For features scattered in various 166 * Auxiliary flags: Linux defined - For features scattered in various
@@ -279,6 +280,7 @@ extern const char * const x86_power_flags[32];
279#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) 280#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE)
280#define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) 281#define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR)
281#define cpu_has_pclmulqdq boot_cpu_has(X86_FEATURE_PCLMULQDQ) 282#define cpu_has_pclmulqdq boot_cpu_has(X86_FEATURE_PCLMULQDQ)
283#define cpu_has_perfctr_core boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
282 284
283#if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) 285#if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
284# define cpu_has_invlpg 1 286# define cpu_has_invlpg 1
diff --git a/arch/x86/include/asm/kdebug.h b/arch/x86/include/asm/kdebug.h
index ca242d35e873..518bbbb9ee59 100644
--- a/arch/x86/include/asm/kdebug.h
+++ b/arch/x86/include/asm/kdebug.h
@@ -13,7 +13,6 @@ enum die_val {
13 DIE_PANIC, 13 DIE_PANIC,
14 DIE_NMI, 14 DIE_NMI,
15 DIE_DIE, 15 DIE_DIE,
16 DIE_NMIWATCHDOG,
17 DIE_KERNELDEBUG, 16 DIE_KERNELDEBUG,
18 DIE_TRAP, 17 DIE_TRAP,
19 DIE_GPF, 18 DIE_GPF,
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 43a18c77676d..823d48223400 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -52,6 +52,9 @@
52#define MSR_IA32_MCG_STATUS 0x0000017a 52#define MSR_IA32_MCG_STATUS 0x0000017a
53#define MSR_IA32_MCG_CTL 0x0000017b 53#define MSR_IA32_MCG_CTL 0x0000017b
54 54
55#define MSR_OFFCORE_RSP_0 0x000001a6
56#define MSR_OFFCORE_RSP_1 0x000001a7
57
55#define MSR_IA32_PEBS_ENABLE 0x000003f1 58#define MSR_IA32_PEBS_ENABLE 0x000003f1
56#define MSR_IA32_DS_AREA 0x00000600 59#define MSR_IA32_DS_AREA 0x00000600
57#define MSR_IA32_PERF_CAPABILITIES 0x00000345 60#define MSR_IA32_PERF_CAPABILITIES 0x00000345
diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h
index c76f5b92b840..07f46016d3ff 100644
--- a/arch/x86/include/asm/nmi.h
+++ b/arch/x86/include/asm/nmi.h
@@ -7,7 +7,6 @@
7 7
8#ifdef CONFIG_X86_LOCAL_APIC 8#ifdef CONFIG_X86_LOCAL_APIC
9 9
10extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
11extern int avail_to_resrv_perfctr_nmi_bit(unsigned int); 10extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
12extern int reserve_perfctr_nmi(unsigned int); 11extern int reserve_perfctr_nmi(unsigned int);
13extern void release_perfctr_nmi(unsigned int); 12extern void release_perfctr_nmi(unsigned int);
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index 1f4695136776..c1bbfa89a0e2 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -17,10 +17,20 @@
17#endif 17#endif
18#include <asm/thread_info.h> 18#include <asm/thread_info.h>
19#include <asm/cpumask.h> 19#include <asm/cpumask.h>
20#include <asm/cpufeature.h>
20 21
21extern int smp_num_siblings; 22extern int smp_num_siblings;
22extern unsigned int num_processors; 23extern unsigned int num_processors;
23 24
25static inline bool cpu_has_ht_siblings(void)
26{
27 bool has_siblings = false;
28#ifdef CONFIG_SMP
29 has_siblings = cpu_has_ht && smp_num_siblings > 1;
30#endif
31 return has_siblings;
32}
33
24DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map); 34DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map);
25DECLARE_PER_CPU(cpumask_var_t, cpu_core_map); 35DECLARE_PER_CPU(cpumask_var_t, cpu_core_map);
26DECLARE_PER_CPU(u16, cpu_llc_id); 36DECLARE_PER_CPU(u16, cpu_llc_id);
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 9d977a2ea693..26604188aa49 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -30,6 +30,7 @@
30#include <asm/stacktrace.h> 30#include <asm/stacktrace.h>
31#include <asm/nmi.h> 31#include <asm/nmi.h>
32#include <asm/compat.h> 32#include <asm/compat.h>
33#include <asm/smp.h>
33 34
34#if 0 35#if 0
35#undef wrmsrl 36#undef wrmsrl
@@ -93,6 +94,8 @@ struct amd_nb {
93 struct event_constraint event_constraints[X86_PMC_IDX_MAX]; 94 struct event_constraint event_constraints[X86_PMC_IDX_MAX];
94}; 95};
95 96
97struct intel_percore;
98
96#define MAX_LBR_ENTRIES 16 99#define MAX_LBR_ENTRIES 16
97 100
98struct cpu_hw_events { 101struct cpu_hw_events {
@@ -128,6 +131,13 @@ struct cpu_hw_events {
128 struct perf_branch_entry lbr_entries[MAX_LBR_ENTRIES]; 131 struct perf_branch_entry lbr_entries[MAX_LBR_ENTRIES];
129 132
130 /* 133 /*
134 * Intel percore register state.
135 * Coordinate shared resources between HT threads.
136 */
137 int percore_used; /* Used by this CPU? */
138 struct intel_percore *per_core;
139
140 /*
131 * AMD specific bits 141 * AMD specific bits
132 */ 142 */
133 struct amd_nb *amd_nb; 143 struct amd_nb *amd_nb;
@@ -166,8 +176,10 @@ struct cpu_hw_events {
166/* 176/*
167 * Constraint on the Event code + UMask 177 * Constraint on the Event code + UMask
168 */ 178 */
169#define PEBS_EVENT_CONSTRAINT(c, n) \ 179#define INTEL_UEVENT_CONSTRAINT(c, n) \
170 EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK) 180 EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
181#define PEBS_EVENT_CONSTRAINT(c, n) \
182 INTEL_UEVENT_CONSTRAINT(c, n)
171 183
172#define EVENT_CONSTRAINT_END \ 184#define EVENT_CONSTRAINT_END \
173 EVENT_CONSTRAINT(0, 0, 0) 185 EVENT_CONSTRAINT(0, 0, 0)
@@ -175,6 +187,28 @@ struct cpu_hw_events {
175#define for_each_event_constraint(e, c) \ 187#define for_each_event_constraint(e, c) \
176 for ((e) = (c); (e)->weight; (e)++) 188 for ((e) = (c); (e)->weight; (e)++)
177 189
190/*
191 * Extra registers for specific events.
192 * Some events need large masks and require external MSRs.
193 * Define a mapping to these extra registers.
194 */
195struct extra_reg {
196 unsigned int event;
197 unsigned int msr;
198 u64 config_mask;
199 u64 valid_mask;
200};
201
202#define EVENT_EXTRA_REG(e, ms, m, vm) { \
203 .event = (e), \
204 .msr = (ms), \
205 .config_mask = (m), \
206 .valid_mask = (vm), \
207 }
208#define INTEL_EVENT_EXTRA_REG(event, msr, vm) \
209 EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm)
210#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0)
211
178union perf_capabilities { 212union perf_capabilities {
179 struct { 213 struct {
180 u64 lbr_format : 6; 214 u64 lbr_format : 6;
@@ -219,6 +253,7 @@ struct x86_pmu {
219 void (*put_event_constraints)(struct cpu_hw_events *cpuc, 253 void (*put_event_constraints)(struct cpu_hw_events *cpuc,
220 struct perf_event *event); 254 struct perf_event *event);
221 struct event_constraint *event_constraints; 255 struct event_constraint *event_constraints;
256 struct event_constraint *percore_constraints;
222 void (*quirks)(void); 257 void (*quirks)(void);
223 int perfctr_second_write; 258 int perfctr_second_write;
224 259
@@ -247,6 +282,11 @@ struct x86_pmu {
247 */ 282 */
248 unsigned long lbr_tos, lbr_from, lbr_to; /* MSR base regs */ 283 unsigned long lbr_tos, lbr_from, lbr_to; /* MSR base regs */
249 int lbr_nr; /* hardware stack size */ 284 int lbr_nr; /* hardware stack size */
285
286 /*
287 * Extra registers for events
288 */
289 struct extra_reg *extra_regs;
250}; 290};
251 291
252static struct x86_pmu x86_pmu __read_mostly; 292static struct x86_pmu x86_pmu __read_mostly;
@@ -271,6 +311,10 @@ static u64 __read_mostly hw_cache_event_ids
271 [PERF_COUNT_HW_CACHE_MAX] 311 [PERF_COUNT_HW_CACHE_MAX]
272 [PERF_COUNT_HW_CACHE_OP_MAX] 312 [PERF_COUNT_HW_CACHE_OP_MAX]
273 [PERF_COUNT_HW_CACHE_RESULT_MAX]; 313 [PERF_COUNT_HW_CACHE_RESULT_MAX];
314static u64 __read_mostly hw_cache_extra_regs
315 [PERF_COUNT_HW_CACHE_MAX]
316 [PERF_COUNT_HW_CACHE_OP_MAX]
317 [PERF_COUNT_HW_CACHE_RESULT_MAX];
274 318
275/* 319/*
276 * Propagate event elapsed time into the generic event. 320 * Propagate event elapsed time into the generic event.
@@ -298,7 +342,7 @@ x86_perf_event_update(struct perf_event *event)
298 */ 342 */
299again: 343again:
300 prev_raw_count = local64_read(&hwc->prev_count); 344 prev_raw_count = local64_read(&hwc->prev_count);
301 rdmsrl(hwc->event_base + idx, new_raw_count); 345 rdmsrl(hwc->event_base, new_raw_count);
302 346
303 if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, 347 if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
304 new_raw_count) != prev_raw_count) 348 new_raw_count) != prev_raw_count)
@@ -321,6 +365,49 @@ again:
321 return new_raw_count; 365 return new_raw_count;
322} 366}
323 367
368/* using X86_FEATURE_PERFCTR_CORE to later implement ALTERNATIVE() here */
369static inline int x86_pmu_addr_offset(int index)
370{
371 if (boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
372 return index << 1;
373 return index;
374}
375
376static inline unsigned int x86_pmu_config_addr(int index)
377{
378 return x86_pmu.eventsel + x86_pmu_addr_offset(index);
379}
380
381static inline unsigned int x86_pmu_event_addr(int index)
382{
383 return x86_pmu.perfctr + x86_pmu_addr_offset(index);
384}
385
386/*
387 * Find and validate any extra registers to set up.
388 */
389static int x86_pmu_extra_regs(u64 config, struct perf_event *event)
390{
391 struct extra_reg *er;
392
393 event->hw.extra_reg = 0;
394 event->hw.extra_config = 0;
395
396 if (!x86_pmu.extra_regs)
397 return 0;
398
399 for (er = x86_pmu.extra_regs; er->msr; er++) {
400 if (er->event != (config & er->config_mask))
401 continue;
402 if (event->attr.config1 & ~er->valid_mask)
403 return -EINVAL;
404 event->hw.extra_reg = er->msr;
405 event->hw.extra_config = event->attr.config1;
406 break;
407 }
408 return 0;
409}
410
324static atomic_t active_events; 411static atomic_t active_events;
325static DEFINE_MUTEX(pmc_reserve_mutex); 412static DEFINE_MUTEX(pmc_reserve_mutex);
326 413
@@ -331,12 +418,12 @@ static bool reserve_pmc_hardware(void)
331 int i; 418 int i;
332 419
333 for (i = 0; i < x86_pmu.num_counters; i++) { 420 for (i = 0; i < x86_pmu.num_counters; i++) {
334 if (!reserve_perfctr_nmi(x86_pmu.perfctr + i)) 421 if (!reserve_perfctr_nmi(x86_pmu_event_addr(i)))
335 goto perfctr_fail; 422 goto perfctr_fail;
336 } 423 }
337 424
338 for (i = 0; i < x86_pmu.num_counters; i++) { 425 for (i = 0; i < x86_pmu.num_counters; i++) {
339 if (!reserve_evntsel_nmi(x86_pmu.eventsel + i)) 426 if (!reserve_evntsel_nmi(x86_pmu_config_addr(i)))
340 goto eventsel_fail; 427 goto eventsel_fail;
341 } 428 }
342 429
@@ -344,13 +431,13 @@ static bool reserve_pmc_hardware(void)
344 431
345eventsel_fail: 432eventsel_fail:
346 for (i--; i >= 0; i--) 433 for (i--; i >= 0; i--)
347 release_evntsel_nmi(x86_pmu.eventsel + i); 434 release_evntsel_nmi(x86_pmu_config_addr(i));
348 435
349 i = x86_pmu.num_counters; 436 i = x86_pmu.num_counters;
350 437
351perfctr_fail: 438perfctr_fail:
352 for (i--; i >= 0; i--) 439 for (i--; i >= 0; i--)
353 release_perfctr_nmi(x86_pmu.perfctr + i); 440 release_perfctr_nmi(x86_pmu_event_addr(i));
354 441
355 return false; 442 return false;
356} 443}
@@ -360,8 +447,8 @@ static void release_pmc_hardware(void)
360 int i; 447 int i;
361 448
362 for (i = 0; i < x86_pmu.num_counters; i++) { 449 for (i = 0; i < x86_pmu.num_counters; i++) {
363 release_perfctr_nmi(x86_pmu.perfctr + i); 450 release_perfctr_nmi(x86_pmu_event_addr(i));
364 release_evntsel_nmi(x86_pmu.eventsel + i); 451 release_evntsel_nmi(x86_pmu_config_addr(i));
365 } 452 }
366} 453}
367 454
@@ -382,7 +469,7 @@ static bool check_hw_exists(void)
382 * complain and bail. 469 * complain and bail.
383 */ 470 */
384 for (i = 0; i < x86_pmu.num_counters; i++) { 471 for (i = 0; i < x86_pmu.num_counters; i++) {
385 reg = x86_pmu.eventsel + i; 472 reg = x86_pmu_config_addr(i);
386 ret = rdmsrl_safe(reg, &val); 473 ret = rdmsrl_safe(reg, &val);
387 if (ret) 474 if (ret)
388 goto msr_fail; 475 goto msr_fail;
@@ -407,8 +494,8 @@ static bool check_hw_exists(void)
407 * that don't trap on the MSR access and always return 0s. 494 * that don't trap on the MSR access and always return 0s.
408 */ 495 */
409 val = 0xabcdUL; 496 val = 0xabcdUL;
410 ret = checking_wrmsrl(x86_pmu.perfctr, val); 497 ret = checking_wrmsrl(x86_pmu_event_addr(0), val);
411 ret |= rdmsrl_safe(x86_pmu.perfctr, &val_new); 498 ret |= rdmsrl_safe(x86_pmu_event_addr(0), &val_new);
412 if (ret || val != val_new) 499 if (ret || val != val_new)
413 goto msr_fail; 500 goto msr_fail;
414 501
@@ -442,8 +529,9 @@ static inline int x86_pmu_initialized(void)
442} 529}
443 530
444static inline int 531static inline int
445set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr) 532set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event *event)
446{ 533{
534 struct perf_event_attr *attr = &event->attr;
447 unsigned int cache_type, cache_op, cache_result; 535 unsigned int cache_type, cache_op, cache_result;
448 u64 config, val; 536 u64 config, val;
449 537
@@ -470,8 +558,8 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr)
470 return -EINVAL; 558 return -EINVAL;
471 559
472 hwc->config |= val; 560 hwc->config |= val;
473 561 attr->config1 = hw_cache_extra_regs[cache_type][cache_op][cache_result];
474 return 0; 562 return x86_pmu_extra_regs(val, event);
475} 563}
476 564
477static int x86_setup_perfctr(struct perf_event *event) 565static int x86_setup_perfctr(struct perf_event *event)
@@ -496,10 +584,10 @@ static int x86_setup_perfctr(struct perf_event *event)
496 } 584 }
497 585
498 if (attr->type == PERF_TYPE_RAW) 586 if (attr->type == PERF_TYPE_RAW)
499 return 0; 587 return x86_pmu_extra_regs(event->attr.config, event);
500 588
501 if (attr->type == PERF_TYPE_HW_CACHE) 589 if (attr->type == PERF_TYPE_HW_CACHE)
502 return set_ext_hw_attr(hwc, attr); 590 return set_ext_hw_attr(hwc, event);
503 591
504 if (attr->config >= x86_pmu.max_events) 592 if (attr->config >= x86_pmu.max_events)
505 return -EINVAL; 593 return -EINVAL;
@@ -617,11 +705,11 @@ static void x86_pmu_disable_all(void)
617 705
618 if (!test_bit(idx, cpuc->active_mask)) 706 if (!test_bit(idx, cpuc->active_mask))
619 continue; 707 continue;
620 rdmsrl(x86_pmu.eventsel + idx, val); 708 rdmsrl(x86_pmu_config_addr(idx), val);
621 if (!(val & ARCH_PERFMON_EVENTSEL_ENABLE)) 709 if (!(val & ARCH_PERFMON_EVENTSEL_ENABLE))
622 continue; 710 continue;
623 val &= ~ARCH_PERFMON_EVENTSEL_ENABLE; 711 val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
624 wrmsrl(x86_pmu.eventsel + idx, val); 712 wrmsrl(x86_pmu_config_addr(idx), val);
625 } 713 }
626} 714}
627 715
@@ -642,21 +730,26 @@ static void x86_pmu_disable(struct pmu *pmu)
642 x86_pmu.disable_all(); 730 x86_pmu.disable_all();
643} 731}
644 732
733static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
734 u64 enable_mask)
735{
736 if (hwc->extra_reg)
737 wrmsrl(hwc->extra_reg, hwc->extra_config);
738 wrmsrl(hwc->config_base, hwc->config | enable_mask);
739}
740
645static void x86_pmu_enable_all(int added) 741static void x86_pmu_enable_all(int added)
646{ 742{
647 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 743 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
648 int idx; 744 int idx;
649 745
650 for (idx = 0; idx < x86_pmu.num_counters; idx++) { 746 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
651 struct perf_event *event = cpuc->events[idx]; 747 struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
652 u64 val;
653 748
654 if (!test_bit(idx, cpuc->active_mask)) 749 if (!test_bit(idx, cpuc->active_mask))
655 continue; 750 continue;
656 751
657 val = event->hw.config; 752 __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
658 val |= ARCH_PERFMON_EVENTSEL_ENABLE;
659 wrmsrl(x86_pmu.eventsel + idx, val);
660 } 753 }
661} 754}
662 755
@@ -821,15 +914,10 @@ static inline void x86_assign_hw_event(struct perf_event *event,
821 hwc->event_base = 0; 914 hwc->event_base = 0;
822 } else if (hwc->idx >= X86_PMC_IDX_FIXED) { 915 } else if (hwc->idx >= X86_PMC_IDX_FIXED) {
823 hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL; 916 hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
824 /* 917 hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0;
825 * We set it so that event_base + idx in wrmsr/rdmsr maps to
826 * MSR_ARCH_PERFMON_FIXED_CTR0 ... CTR2:
827 */
828 hwc->event_base =
829 MSR_ARCH_PERFMON_FIXED_CTR0 - X86_PMC_IDX_FIXED;
830 } else { 918 } else {
831 hwc->config_base = x86_pmu.eventsel; 919 hwc->config_base = x86_pmu_config_addr(hwc->idx);
832 hwc->event_base = x86_pmu.perfctr; 920 hwc->event_base = x86_pmu_event_addr(hwc->idx);
833 } 921 }
834} 922}
835 923
@@ -915,17 +1003,11 @@ static void x86_pmu_enable(struct pmu *pmu)
915 x86_pmu.enable_all(added); 1003 x86_pmu.enable_all(added);
916} 1004}
917 1005
918static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
919 u64 enable_mask)
920{
921 wrmsrl(hwc->config_base + hwc->idx, hwc->config | enable_mask);
922}
923
924static inline void x86_pmu_disable_event(struct perf_event *event) 1006static inline void x86_pmu_disable_event(struct perf_event *event)
925{ 1007{
926 struct hw_perf_event *hwc = &event->hw; 1008 struct hw_perf_event *hwc = &event->hw;
927 1009
928 wrmsrl(hwc->config_base + hwc->idx, hwc->config); 1010 wrmsrl(hwc->config_base, hwc->config);
929} 1011}
930 1012
931static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); 1013static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left);
@@ -978,7 +1060,7 @@ x86_perf_event_set_period(struct perf_event *event)
978 */ 1060 */
979 local64_set(&hwc->prev_count, (u64)-left); 1061 local64_set(&hwc->prev_count, (u64)-left);
980 1062
981 wrmsrl(hwc->event_base + idx, (u64)(-left) & x86_pmu.cntval_mask); 1063 wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask);
982 1064
983 /* 1065 /*
984 * Due to erratum on certan cpu we need 1066 * Due to erratum on certan cpu we need
@@ -986,7 +1068,7 @@ x86_perf_event_set_period(struct perf_event *event)
986 * is updated properly 1068 * is updated properly
987 */ 1069 */
988 if (x86_pmu.perfctr_second_write) { 1070 if (x86_pmu.perfctr_second_write) {
989 wrmsrl(hwc->event_base + idx, 1071 wrmsrl(hwc->event_base,
990 (u64)(-left) & x86_pmu.cntval_mask); 1072 (u64)(-left) & x86_pmu.cntval_mask);
991 } 1073 }
992 1074
@@ -1113,8 +1195,8 @@ void perf_event_print_debug(void)
1113 pr_info("CPU#%d: active: %016llx\n", cpu, *(u64 *)cpuc->active_mask); 1195 pr_info("CPU#%d: active: %016llx\n", cpu, *(u64 *)cpuc->active_mask);
1114 1196
1115 for (idx = 0; idx < x86_pmu.num_counters; idx++) { 1197 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
1116 rdmsrl(x86_pmu.eventsel + idx, pmc_ctrl); 1198 rdmsrl(x86_pmu_config_addr(idx), pmc_ctrl);
1117 rdmsrl(x86_pmu.perfctr + idx, pmc_count); 1199 rdmsrl(x86_pmu_event_addr(idx), pmc_count);
1118 1200
1119 prev_left = per_cpu(pmc_prev_left[idx], cpu); 1201 prev_left = per_cpu(pmc_prev_left[idx], cpu);
1120 1202
@@ -1389,7 +1471,7 @@ static void __init pmu_check_apic(void)
1389 pr_info("no hardware sampling interrupt available.\n"); 1471 pr_info("no hardware sampling interrupt available.\n");
1390} 1472}
1391 1473
1392int __init init_hw_perf_events(void) 1474static int __init init_hw_perf_events(void)
1393{ 1475{
1394 struct event_constraint *c; 1476 struct event_constraint *c;
1395 int err; 1477 int err;
@@ -1608,7 +1690,7 @@ out:
1608 return ret; 1690 return ret;
1609} 1691}
1610 1692
1611int x86_pmu_event_init(struct perf_event *event) 1693static int x86_pmu_event_init(struct perf_event *event)
1612{ 1694{
1613 struct pmu *tmp; 1695 struct pmu *tmp;
1614 int err; 1696 int err;
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index 67e2202a6039..461f62bbd774 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -127,6 +127,11 @@ static int amd_pmu_hw_config(struct perf_event *event)
127/* 127/*
128 * AMD64 events are detected based on their event codes. 128 * AMD64 events are detected based on their event codes.
129 */ 129 */
130static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
131{
132 return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
133}
134
130static inline int amd_is_nb_event(struct hw_perf_event *hwc) 135static inline int amd_is_nb_event(struct hw_perf_event *hwc)
131{ 136{
132 return (hwc->config & 0xe0) == 0xe0; 137 return (hwc->config & 0xe0) == 0xe0;
@@ -385,13 +390,181 @@ static __initconst const struct x86_pmu amd_pmu = {
385 .cpu_dead = amd_pmu_cpu_dead, 390 .cpu_dead = amd_pmu_cpu_dead,
386}; 391};
387 392
393/* AMD Family 15h */
394
395#define AMD_EVENT_TYPE_MASK 0x000000F0ULL
396
397#define AMD_EVENT_FP 0x00000000ULL ... 0x00000010ULL
398#define AMD_EVENT_LS 0x00000020ULL ... 0x00000030ULL
399#define AMD_EVENT_DC 0x00000040ULL ... 0x00000050ULL
400#define AMD_EVENT_CU 0x00000060ULL ... 0x00000070ULL
401#define AMD_EVENT_IC_DE 0x00000080ULL ... 0x00000090ULL
402#define AMD_EVENT_EX_LS 0x000000C0ULL
403#define AMD_EVENT_DE 0x000000D0ULL
404#define AMD_EVENT_NB 0x000000E0ULL ... 0x000000F0ULL
405
406/*
407 * AMD family 15h event code/PMC mappings:
408 *
409 * type = event_code & 0x0F0:
410 *
411 * 0x000 FP PERF_CTL[5:3]
412 * 0x010 FP PERF_CTL[5:3]
413 * 0x020 LS PERF_CTL[5:0]
414 * 0x030 LS PERF_CTL[5:0]
415 * 0x040 DC PERF_CTL[5:0]
416 * 0x050 DC PERF_CTL[5:0]
417 * 0x060 CU PERF_CTL[2:0]
418 * 0x070 CU PERF_CTL[2:0]
419 * 0x080 IC/DE PERF_CTL[2:0]
420 * 0x090 IC/DE PERF_CTL[2:0]
421 * 0x0A0 ---
422 * 0x0B0 ---
423 * 0x0C0 EX/LS PERF_CTL[5:0]
424 * 0x0D0 DE PERF_CTL[2:0]
425 * 0x0E0 NB NB_PERF_CTL[3:0]
426 * 0x0F0 NB NB_PERF_CTL[3:0]
427 *
428 * Exceptions:
429 *
430 * 0x003 FP PERF_CTL[3]
431 * 0x00B FP PERF_CTL[3]
432 * 0x00D FP PERF_CTL[3]
433 * 0x023 DE PERF_CTL[2:0]
434 * 0x02D LS PERF_CTL[3]
435 * 0x02E LS PERF_CTL[3,0]
436 * 0x043 CU PERF_CTL[2:0]
437 * 0x045 CU PERF_CTL[2:0]
438 * 0x046 CU PERF_CTL[2:0]
439 * 0x054 CU PERF_CTL[2:0]
440 * 0x055 CU PERF_CTL[2:0]
441 * 0x08F IC PERF_CTL[0]
442 * 0x187 DE PERF_CTL[0]
443 * 0x188 DE PERF_CTL[0]
444 * 0x0DB EX PERF_CTL[5:0]
445 * 0x0DC LS PERF_CTL[5:0]
446 * 0x0DD LS PERF_CTL[5:0]
447 * 0x0DE LS PERF_CTL[5:0]
448 * 0x0DF LS PERF_CTL[5:0]
449 * 0x1D6 EX PERF_CTL[5:0]
450 * 0x1D8 EX PERF_CTL[5:0]
451 */
452
453static struct event_constraint amd_f15_PMC0 = EVENT_CONSTRAINT(0, 0x01, 0);
454static struct event_constraint amd_f15_PMC20 = EVENT_CONSTRAINT(0, 0x07, 0);
455static struct event_constraint amd_f15_PMC3 = EVENT_CONSTRAINT(0, 0x08, 0);
456static struct event_constraint amd_f15_PMC30 = EVENT_CONSTRAINT(0, 0x09, 0);
457static struct event_constraint amd_f15_PMC50 = EVENT_CONSTRAINT(0, 0x3F, 0);
458static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0);
459
460static struct event_constraint *
461amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *event)
462{
463 unsigned int event_code = amd_get_event_code(&event->hw);
464
465 switch (event_code & AMD_EVENT_TYPE_MASK) {
466 case AMD_EVENT_FP:
467 switch (event_code) {
468 case 0x003:
469 case 0x00B:
470 case 0x00D:
471 return &amd_f15_PMC3;
472 default:
473 return &amd_f15_PMC53;
474 }
475 case AMD_EVENT_LS:
476 case AMD_EVENT_DC:
477 case AMD_EVENT_EX_LS:
478 switch (event_code) {
479 case 0x023:
480 case 0x043:
481 case 0x045:
482 case 0x046:
483 case 0x054:
484 case 0x055:
485 return &amd_f15_PMC20;
486 case 0x02D:
487 return &amd_f15_PMC3;
488 case 0x02E:
489 return &amd_f15_PMC30;
490 default:
491 return &amd_f15_PMC50;
492 }
493 case AMD_EVENT_CU:
494 case AMD_EVENT_IC_DE:
495 case AMD_EVENT_DE:
496 switch (event_code) {
497 case 0x08F:
498 case 0x187:
499 case 0x188:
500 return &amd_f15_PMC0;
501 case 0x0DB ... 0x0DF:
502 case 0x1D6:
503 case 0x1D8:
504 return &amd_f15_PMC50;
505 default:
506 return &amd_f15_PMC20;
507 }
508 case AMD_EVENT_NB:
509 /* not yet implemented */
510 return &emptyconstraint;
511 default:
512 return &emptyconstraint;
513 }
514}
515
516static __initconst const struct x86_pmu amd_pmu_f15h = {
517 .name = "AMD Family 15h",
518 .handle_irq = x86_pmu_handle_irq,
519 .disable_all = x86_pmu_disable_all,
520 .enable_all = x86_pmu_enable_all,
521 .enable = x86_pmu_enable_event,
522 .disable = x86_pmu_disable_event,
523 .hw_config = amd_pmu_hw_config,
524 .schedule_events = x86_schedule_events,
525 .eventsel = MSR_F15H_PERF_CTL,
526 .perfctr = MSR_F15H_PERF_CTR,
527 .event_map = amd_pmu_event_map,
528 .max_events = ARRAY_SIZE(amd_perfmon_event_map),
529 .num_counters = 6,
530 .cntval_bits = 48,
531 .cntval_mask = (1ULL << 48) - 1,
532 .apic = 1,
533 /* use highest bit to detect overflow */
534 .max_period = (1ULL << 47) - 1,
535 .get_event_constraints = amd_get_event_constraints_f15h,
536 /* nortbridge counters not yet implemented: */
537#if 0
538 .put_event_constraints = amd_put_event_constraints,
539
540 .cpu_prepare = amd_pmu_cpu_prepare,
541 .cpu_starting = amd_pmu_cpu_starting,
542 .cpu_dead = amd_pmu_cpu_dead,
543#endif
544};
545
388static __init int amd_pmu_init(void) 546static __init int amd_pmu_init(void)
389{ 547{
390 /* Performance-monitoring supported from K7 and later: */ 548 /* Performance-monitoring supported from K7 and later: */
391 if (boot_cpu_data.x86 < 6) 549 if (boot_cpu_data.x86 < 6)
392 return -ENODEV; 550 return -ENODEV;
393 551
394 x86_pmu = amd_pmu; 552 /*
553 * If core performance counter extensions exists, it must be
554 * family 15h, otherwise fail. See x86_pmu_addr_offset().
555 */
556 switch (boot_cpu_data.x86) {
557 case 0x15:
558 if (!cpu_has_perfctr_core)
559 return -ENODEV;
560 x86_pmu = amd_pmu_f15h;
561 break;
562 default:
563 if (cpu_has_perfctr_core)
564 return -ENODEV;
565 x86_pmu = amd_pmu;
566 break;
567 }
395 568
396 /* Events are common for all AMDs */ 569 /* Events are common for all AMDs */
397 memcpy(hw_cache_event_ids, amd_hw_cache_event_ids, 570 memcpy(hw_cache_event_ids, amd_hw_cache_event_ids,
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 008835c1d79c..8fc2b2cee1da 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1,5 +1,27 @@
1#ifdef CONFIG_CPU_SUP_INTEL 1#ifdef CONFIG_CPU_SUP_INTEL
2 2
3#define MAX_EXTRA_REGS 2
4
5/*
6 * Per register state.
7 */
8struct er_account {
9 int ref; /* reference count */
10 unsigned int extra_reg; /* extra MSR number */
11 u64 extra_config; /* extra MSR config */
12};
13
14/*
15 * Per core state
16 * This used to coordinate shared registers for HT threads.
17 */
18struct intel_percore {
19 raw_spinlock_t lock; /* protect structure */
20 struct er_account regs[MAX_EXTRA_REGS];
21 int refcnt; /* number of threads */
22 unsigned core_id;
23};
24
3/* 25/*
4 * Intel PerfMon, used on Core and later. 26 * Intel PerfMon, used on Core and later.
5 */ 27 */
@@ -64,6 +86,18 @@ static struct event_constraint intel_nehalem_event_constraints[] =
64 EVENT_CONSTRAINT_END 86 EVENT_CONSTRAINT_END
65}; 87};
66 88
89static struct extra_reg intel_nehalem_extra_regs[] =
90{
91 INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff),
92 EVENT_EXTRA_END
93};
94
95static struct event_constraint intel_nehalem_percore_constraints[] =
96{
97 INTEL_EVENT_CONSTRAINT(0xb7, 0),
98 EVENT_CONSTRAINT_END
99};
100
67static struct event_constraint intel_westmere_event_constraints[] = 101static struct event_constraint intel_westmere_event_constraints[] =
68{ 102{
69 FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ 103 FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
@@ -76,6 +110,33 @@ static struct event_constraint intel_westmere_event_constraints[] =
76 EVENT_CONSTRAINT_END 110 EVENT_CONSTRAINT_END
77}; 111};
78 112
113static struct event_constraint intel_snb_event_constraints[] =
114{
115 FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
116 FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
117 /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */
118 INTEL_EVENT_CONSTRAINT(0x48, 0x4), /* L1D_PEND_MISS.PENDING */
119 INTEL_EVENT_CONSTRAINT(0xb7, 0x1), /* OFF_CORE_RESPONSE_0 */
120 INTEL_EVENT_CONSTRAINT(0xbb, 0x8), /* OFF_CORE_RESPONSE_1 */
121 INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
122 INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
123 EVENT_CONSTRAINT_END
124};
125
126static struct extra_reg intel_westmere_extra_regs[] =
127{
128 INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff),
129 INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0xffff),
130 EVENT_EXTRA_END
131};
132
133static struct event_constraint intel_westmere_percore_constraints[] =
134{
135 INTEL_EVENT_CONSTRAINT(0xb7, 0),
136 INTEL_EVENT_CONSTRAINT(0xbb, 0),
137 EVENT_CONSTRAINT_END
138};
139
79static struct event_constraint intel_gen_event_constraints[] = 140static struct event_constraint intel_gen_event_constraints[] =
80{ 141{
81 FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ 142 FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
@@ -89,6 +150,106 @@ static u64 intel_pmu_event_map(int hw_event)
89 return intel_perfmon_event_map[hw_event]; 150 return intel_perfmon_event_map[hw_event];
90} 151}
91 152
153static __initconst const u64 snb_hw_cache_event_ids
154 [PERF_COUNT_HW_CACHE_MAX]
155 [PERF_COUNT_HW_CACHE_OP_MAX]
156 [PERF_COUNT_HW_CACHE_RESULT_MAX] =
157{
158 [ C(L1D) ] = {
159 [ C(OP_READ) ] = {
160 [ C(RESULT_ACCESS) ] = 0xf1d0, /* MEM_UOP_RETIRED.LOADS */
161 [ C(RESULT_MISS) ] = 0x0151, /* L1D.REPLACEMENT */
162 },
163 [ C(OP_WRITE) ] = {
164 [ C(RESULT_ACCESS) ] = 0xf2d0, /* MEM_UOP_RETIRED.STORES */
165 [ C(RESULT_MISS) ] = 0x0851, /* L1D.ALL_M_REPLACEMENT */
166 },
167 [ C(OP_PREFETCH) ] = {
168 [ C(RESULT_ACCESS) ] = 0x0,
169 [ C(RESULT_MISS) ] = 0x024e, /* HW_PRE_REQ.DL1_MISS */
170 },
171 },
172 [ C(L1I ) ] = {
173 [ C(OP_READ) ] = {
174 [ C(RESULT_ACCESS) ] = 0x0,
175 [ C(RESULT_MISS) ] = 0x0280, /* ICACHE.MISSES */
176 },
177 [ C(OP_WRITE) ] = {
178 [ C(RESULT_ACCESS) ] = -1,
179 [ C(RESULT_MISS) ] = -1,
180 },
181 [ C(OP_PREFETCH) ] = {
182 [ C(RESULT_ACCESS) ] = 0x0,
183 [ C(RESULT_MISS) ] = 0x0,
184 },
185 },
186 [ C(LL ) ] = {
187 /*
188 * TBD: Need Off-core Response Performance Monitoring support
189 */
190 [ C(OP_READ) ] = {
191 /* OFFCORE_RESPONSE_0.ANY_DATA.LOCAL_CACHE */
192 [ C(RESULT_ACCESS) ] = 0x01b7,
193 /* OFFCORE_RESPONSE_1.ANY_DATA.ANY_LLC_MISS */
194 [ C(RESULT_MISS) ] = 0x01bb,
195 },
196 [ C(OP_WRITE) ] = {
197 /* OFFCORE_RESPONSE_0.ANY_RFO.LOCAL_CACHE */
198 [ C(RESULT_ACCESS) ] = 0x01b7,
199 /* OFFCORE_RESPONSE_1.ANY_RFO.ANY_LLC_MISS */
200 [ C(RESULT_MISS) ] = 0x01bb,
201 },
202 [ C(OP_PREFETCH) ] = {
203 /* OFFCORE_RESPONSE_0.PREFETCH.LOCAL_CACHE */
204 [ C(RESULT_ACCESS) ] = 0x01b7,
205 /* OFFCORE_RESPONSE_1.PREFETCH.ANY_LLC_MISS */
206 [ C(RESULT_MISS) ] = 0x01bb,
207 },
208 },
209 [ C(DTLB) ] = {
210 [ C(OP_READ) ] = {
211 [ C(RESULT_ACCESS) ] = 0x81d0, /* MEM_UOP_RETIRED.ALL_LOADS */
212 [ C(RESULT_MISS) ] = 0x0108, /* DTLB_LOAD_MISSES.CAUSES_A_WALK */
213 },
214 [ C(OP_WRITE) ] = {
215 [ C(RESULT_ACCESS) ] = 0x82d0, /* MEM_UOP_RETIRED.ALL_STORES */
216 [ C(RESULT_MISS) ] = 0x0149, /* DTLB_STORE_MISSES.MISS_CAUSES_A_WALK */
217 },
218 [ C(OP_PREFETCH) ] = {
219 [ C(RESULT_ACCESS) ] = 0x0,
220 [ C(RESULT_MISS) ] = 0x0,
221 },
222 },
223 [ C(ITLB) ] = {
224 [ C(OP_READ) ] = {
225 [ C(RESULT_ACCESS) ] = 0x1085, /* ITLB_MISSES.STLB_HIT */
226 [ C(RESULT_MISS) ] = 0x0185, /* ITLB_MISSES.CAUSES_A_WALK */
227 },
228 [ C(OP_WRITE) ] = {
229 [ C(RESULT_ACCESS) ] = -1,
230 [ C(RESULT_MISS) ] = -1,
231 },
232 [ C(OP_PREFETCH) ] = {
233 [ C(RESULT_ACCESS) ] = -1,
234 [ C(RESULT_MISS) ] = -1,
235 },
236 },
237 [ C(BPU ) ] = {
238 [ C(OP_READ) ] = {
239 [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */
240 [ C(RESULT_MISS) ] = 0x00c5, /* BR_MISP_RETIRED.ALL_BRANCHES */
241 },
242 [ C(OP_WRITE) ] = {
243 [ C(RESULT_ACCESS) ] = -1,
244 [ C(RESULT_MISS) ] = -1,
245 },
246 [ C(OP_PREFETCH) ] = {
247 [ C(RESULT_ACCESS) ] = -1,
248 [ C(RESULT_MISS) ] = -1,
249 },
250 },
251};
252
92static __initconst const u64 westmere_hw_cache_event_ids 253static __initconst const u64 westmere_hw_cache_event_ids
93 [PERF_COUNT_HW_CACHE_MAX] 254 [PERF_COUNT_HW_CACHE_MAX]
94 [PERF_COUNT_HW_CACHE_OP_MAX] 255 [PERF_COUNT_HW_CACHE_OP_MAX]
@@ -124,16 +285,26 @@ static __initconst const u64 westmere_hw_cache_event_ids
124 }, 285 },
125 [ C(LL ) ] = { 286 [ C(LL ) ] = {
126 [ C(OP_READ) ] = { 287 [ C(OP_READ) ] = {
127 [ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS */ 288 /* OFFCORE_RESPONSE_0.ANY_DATA.LOCAL_CACHE */
128 [ C(RESULT_MISS) ] = 0x0224, /* L2_RQSTS.LD_MISS */ 289 [ C(RESULT_ACCESS) ] = 0x01b7,
290 /* OFFCORE_RESPONSE_1.ANY_DATA.ANY_LLC_MISS */
291 [ C(RESULT_MISS) ] = 0x01bb,
129 }, 292 },
293 /*
294 * Use RFO, not WRITEBACK, because a write miss would typically occur
295 * on RFO.
296 */
130 [ C(OP_WRITE) ] = { 297 [ C(OP_WRITE) ] = {
131 [ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS */ 298 /* OFFCORE_RESPONSE_1.ANY_RFO.LOCAL_CACHE */
132 [ C(RESULT_MISS) ] = 0x0824, /* L2_RQSTS.RFO_MISS */ 299 [ C(RESULT_ACCESS) ] = 0x01bb,
300 /* OFFCORE_RESPONSE_0.ANY_RFO.ANY_LLC_MISS */
301 [ C(RESULT_MISS) ] = 0x01b7,
133 }, 302 },
134 [ C(OP_PREFETCH) ] = { 303 [ C(OP_PREFETCH) ] = {
135 [ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference */ 304 /* OFFCORE_RESPONSE_0.PREFETCH.LOCAL_CACHE */
136 [ C(RESULT_MISS) ] = 0x412e, /* LLC Misses */ 305 [ C(RESULT_ACCESS) ] = 0x01b7,
306 /* OFFCORE_RESPONSE_1.PREFETCH.ANY_LLC_MISS */
307 [ C(RESULT_MISS) ] = 0x01bb,
137 }, 308 },
138 }, 309 },
139 [ C(DTLB) ] = { 310 [ C(DTLB) ] = {
@@ -180,6 +351,39 @@ static __initconst const u64 westmere_hw_cache_event_ids
180 }, 351 },
181}; 352};
182 353
354/*
355 * OFFCORE_RESPONSE MSR bits (subset), See IA32 SDM Vol 3 30.6.1.3
356 */
357
358#define DMND_DATA_RD (1 << 0)
359#define DMND_RFO (1 << 1)
360#define DMND_WB (1 << 3)
361#define PF_DATA_RD (1 << 4)
362#define PF_DATA_RFO (1 << 5)
363#define RESP_UNCORE_HIT (1 << 8)
364#define RESP_MISS (0xf600) /* non uncore hit */
365
366static __initconst const u64 nehalem_hw_cache_extra_regs
367 [PERF_COUNT_HW_CACHE_MAX]
368 [PERF_COUNT_HW_CACHE_OP_MAX]
369 [PERF_COUNT_HW_CACHE_RESULT_MAX] =
370{
371 [ C(LL ) ] = {
372 [ C(OP_READ) ] = {
373 [ C(RESULT_ACCESS) ] = DMND_DATA_RD|RESP_UNCORE_HIT,
374 [ C(RESULT_MISS) ] = DMND_DATA_RD|RESP_MISS,
375 },
376 [ C(OP_WRITE) ] = {
377 [ C(RESULT_ACCESS) ] = DMND_RFO|DMND_WB|RESP_UNCORE_HIT,
378 [ C(RESULT_MISS) ] = DMND_RFO|DMND_WB|RESP_MISS,
379 },
380 [ C(OP_PREFETCH) ] = {
381 [ C(RESULT_ACCESS) ] = PF_DATA_RD|PF_DATA_RFO|RESP_UNCORE_HIT,
382 [ C(RESULT_MISS) ] = PF_DATA_RD|PF_DATA_RFO|RESP_MISS,
383 },
384 }
385};
386
183static __initconst const u64 nehalem_hw_cache_event_ids 387static __initconst const u64 nehalem_hw_cache_event_ids
184 [PERF_COUNT_HW_CACHE_MAX] 388 [PERF_COUNT_HW_CACHE_MAX]
185 [PERF_COUNT_HW_CACHE_OP_MAX] 389 [PERF_COUNT_HW_CACHE_OP_MAX]
@@ -215,16 +419,26 @@ static __initconst const u64 nehalem_hw_cache_event_ids
215 }, 419 },
216 [ C(LL ) ] = { 420 [ C(LL ) ] = {
217 [ C(OP_READ) ] = { 421 [ C(OP_READ) ] = {
218 [ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS */ 422 /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
219 [ C(RESULT_MISS) ] = 0x0224, /* L2_RQSTS.LD_MISS */ 423 [ C(RESULT_ACCESS) ] = 0x01b7,
424 /* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
425 [ C(RESULT_MISS) ] = 0x01b7,
220 }, 426 },
427 /*
428 * Use RFO, not WRITEBACK, because a write miss would typically occur
429 * on RFO.
430 */
221 [ C(OP_WRITE) ] = { 431 [ C(OP_WRITE) ] = {
222 [ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS */ 432 /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
223 [ C(RESULT_MISS) ] = 0x0824, /* L2_RQSTS.RFO_MISS */ 433 [ C(RESULT_ACCESS) ] = 0x01b7,
434 /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
435 [ C(RESULT_MISS) ] = 0x01b7,
224 }, 436 },
225 [ C(OP_PREFETCH) ] = { 437 [ C(OP_PREFETCH) ] = {
226 [ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference */ 438 /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
227 [ C(RESULT_MISS) ] = 0x412e, /* LLC Misses */ 439 [ C(RESULT_ACCESS) ] = 0x01b7,
440 /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
441 [ C(RESULT_MISS) ] = 0x01b7,
228 }, 442 },
229 }, 443 },
230 [ C(DTLB) ] = { 444 [ C(DTLB) ] = {
@@ -691,8 +905,8 @@ static void intel_pmu_reset(void)
691 printk("clearing PMU state on CPU#%d\n", smp_processor_id()); 905 printk("clearing PMU state on CPU#%d\n", smp_processor_id());
692 906
693 for (idx = 0; idx < x86_pmu.num_counters; idx++) { 907 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
694 checking_wrmsrl(x86_pmu.eventsel + idx, 0ull); 908 checking_wrmsrl(x86_pmu_config_addr(idx), 0ull);
695 checking_wrmsrl(x86_pmu.perfctr + idx, 0ull); 909 checking_wrmsrl(x86_pmu_event_addr(idx), 0ull);
696 } 910 }
697 for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) 911 for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++)
698 checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); 912 checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull);
@@ -794,6 +1008,67 @@ intel_bts_constraints(struct perf_event *event)
794} 1008}
795 1009
796static struct event_constraint * 1010static struct event_constraint *
1011intel_percore_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
1012{
1013 struct hw_perf_event *hwc = &event->hw;
1014 unsigned int e = hwc->config & ARCH_PERFMON_EVENTSEL_EVENT;
1015 struct event_constraint *c;
1016 struct intel_percore *pc;
1017 struct er_account *era;
1018 int i;
1019 int free_slot;
1020 int found;
1021
1022 if (!x86_pmu.percore_constraints || hwc->extra_alloc)
1023 return NULL;
1024
1025 for (c = x86_pmu.percore_constraints; c->cmask; c++) {
1026 if (e != c->code)
1027 continue;
1028
1029 /*
1030 * Allocate resource per core.
1031 */
1032 pc = cpuc->per_core;
1033 if (!pc)
1034 break;
1035 c = &emptyconstraint;
1036 raw_spin_lock(&pc->lock);
1037 free_slot = -1;
1038 found = 0;
1039 for (i = 0; i < MAX_EXTRA_REGS; i++) {
1040 era = &pc->regs[i];
1041 if (era->ref > 0 && hwc->extra_reg == era->extra_reg) {
1042 /* Allow sharing same config */
1043 if (hwc->extra_config == era->extra_config) {
1044 era->ref++;
1045 cpuc->percore_used = 1;
1046 hwc->extra_alloc = 1;
1047 c = NULL;
1048 }
1049 /* else conflict */
1050 found = 1;
1051 break;
1052 } else if (era->ref == 0 && free_slot == -1)
1053 free_slot = i;
1054 }
1055 if (!found && free_slot != -1) {
1056 era = &pc->regs[free_slot];
1057 era->ref = 1;
1058 era->extra_reg = hwc->extra_reg;
1059 era->extra_config = hwc->extra_config;
1060 cpuc->percore_used = 1;
1061 hwc->extra_alloc = 1;
1062 c = NULL;
1063 }
1064 raw_spin_unlock(&pc->lock);
1065 return c;
1066 }
1067
1068 return NULL;
1069}
1070
1071static struct event_constraint *
797intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) 1072intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
798{ 1073{
799 struct event_constraint *c; 1074 struct event_constraint *c;
@@ -806,9 +1081,51 @@ intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event
806 if (c) 1081 if (c)
807 return c; 1082 return c;
808 1083
1084 c = intel_percore_constraints(cpuc, event);
1085 if (c)
1086 return c;
1087
809 return x86_get_event_constraints(cpuc, event); 1088 return x86_get_event_constraints(cpuc, event);
810} 1089}
811 1090
1091static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
1092 struct perf_event *event)
1093{
1094 struct extra_reg *er;
1095 struct intel_percore *pc;
1096 struct er_account *era;
1097 struct hw_perf_event *hwc = &event->hw;
1098 int i, allref;
1099
1100 if (!cpuc->percore_used)
1101 return;
1102
1103 for (er = x86_pmu.extra_regs; er->msr; er++) {
1104 if (er->event != (hwc->config & er->config_mask))
1105 continue;
1106
1107 pc = cpuc->per_core;
1108 raw_spin_lock(&pc->lock);
1109 for (i = 0; i < MAX_EXTRA_REGS; i++) {
1110 era = &pc->regs[i];
1111 if (era->ref > 0 &&
1112 era->extra_config == hwc->extra_config &&
1113 era->extra_reg == er->msr) {
1114 era->ref--;
1115 hwc->extra_alloc = 0;
1116 break;
1117 }
1118 }
1119 allref = 0;
1120 for (i = 0; i < MAX_EXTRA_REGS; i++)
1121 allref += pc->regs[i].ref;
1122 if (allref == 0)
1123 cpuc->percore_used = 0;
1124 raw_spin_unlock(&pc->lock);
1125 break;
1126 }
1127}
1128
812static int intel_pmu_hw_config(struct perf_event *event) 1129static int intel_pmu_hw_config(struct perf_event *event)
813{ 1130{
814 int ret = x86_pmu_hw_config(event); 1131 int ret = x86_pmu_hw_config(event);
@@ -880,20 +1197,67 @@ static __initconst const struct x86_pmu core_pmu = {
880 */ 1197 */
881 .max_period = (1ULL << 31) - 1, 1198 .max_period = (1ULL << 31) - 1,
882 .get_event_constraints = intel_get_event_constraints, 1199 .get_event_constraints = intel_get_event_constraints,
1200 .put_event_constraints = intel_put_event_constraints,
883 .event_constraints = intel_core_event_constraints, 1201 .event_constraints = intel_core_event_constraints,
884}; 1202};
885 1203
1204static int intel_pmu_cpu_prepare(int cpu)
1205{
1206 struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
1207
1208 if (!cpu_has_ht_siblings())
1209 return NOTIFY_OK;
1210
1211 cpuc->per_core = kzalloc_node(sizeof(struct intel_percore),
1212 GFP_KERNEL, cpu_to_node(cpu));
1213 if (!cpuc->per_core)
1214 return NOTIFY_BAD;
1215
1216 raw_spin_lock_init(&cpuc->per_core->lock);
1217 cpuc->per_core->core_id = -1;
1218 return NOTIFY_OK;
1219}
1220
886static void intel_pmu_cpu_starting(int cpu) 1221static void intel_pmu_cpu_starting(int cpu)
887{ 1222{
1223 struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
1224 int core_id = topology_core_id(cpu);
1225 int i;
1226
888 init_debug_store_on_cpu(cpu); 1227 init_debug_store_on_cpu(cpu);
889 /* 1228 /*
890 * Deal with CPUs that don't clear their LBRs on power-up. 1229 * Deal with CPUs that don't clear their LBRs on power-up.
891 */ 1230 */
892 intel_pmu_lbr_reset(); 1231 intel_pmu_lbr_reset();
1232
1233 if (!cpu_has_ht_siblings())
1234 return;
1235
1236 for_each_cpu(i, topology_thread_cpumask(cpu)) {
1237 struct intel_percore *pc = per_cpu(cpu_hw_events, i).per_core;
1238
1239 if (pc && pc->core_id == core_id) {
1240 kfree(cpuc->per_core);
1241 cpuc->per_core = pc;
1242 break;
1243 }
1244 }
1245
1246 cpuc->per_core->core_id = core_id;
1247 cpuc->per_core->refcnt++;
893} 1248}
894 1249
895static void intel_pmu_cpu_dying(int cpu) 1250static void intel_pmu_cpu_dying(int cpu)
896{ 1251{
1252 struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
1253 struct intel_percore *pc = cpuc->per_core;
1254
1255 if (pc) {
1256 if (pc->core_id == -1 || --pc->refcnt == 0)
1257 kfree(pc);
1258 cpuc->per_core = NULL;
1259 }
1260
897 fini_debug_store_on_cpu(cpu); 1261 fini_debug_store_on_cpu(cpu);
898} 1262}
899 1263
@@ -918,7 +1282,9 @@ static __initconst const struct x86_pmu intel_pmu = {
918 */ 1282 */
919 .max_period = (1ULL << 31) - 1, 1283 .max_period = (1ULL << 31) - 1,
920 .get_event_constraints = intel_get_event_constraints, 1284 .get_event_constraints = intel_get_event_constraints,
1285 .put_event_constraints = intel_put_event_constraints,
921 1286
1287 .cpu_prepare = intel_pmu_cpu_prepare,
922 .cpu_starting = intel_pmu_cpu_starting, 1288 .cpu_starting = intel_pmu_cpu_starting,
923 .cpu_dying = intel_pmu_cpu_dying, 1289 .cpu_dying = intel_pmu_cpu_dying,
924}; 1290};
@@ -1024,6 +1390,7 @@ static __init int intel_pmu_init(void)
1024 intel_pmu_lbr_init_core(); 1390 intel_pmu_lbr_init_core();
1025 1391
1026 x86_pmu.event_constraints = intel_core2_event_constraints; 1392 x86_pmu.event_constraints = intel_core2_event_constraints;
1393 x86_pmu.pebs_constraints = intel_core2_pebs_event_constraints;
1027 pr_cont("Core2 events, "); 1394 pr_cont("Core2 events, ");
1028 break; 1395 break;
1029 1396
@@ -1032,11 +1399,16 @@ static __init int intel_pmu_init(void)
1032 case 46: /* 45 nm nehalem-ex, "Beckton" */ 1399 case 46: /* 45 nm nehalem-ex, "Beckton" */
1033 memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids, 1400 memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids,
1034 sizeof(hw_cache_event_ids)); 1401 sizeof(hw_cache_event_ids));
1402 memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
1403 sizeof(hw_cache_extra_regs));
1035 1404
1036 intel_pmu_lbr_init_nhm(); 1405 intel_pmu_lbr_init_nhm();
1037 1406
1038 x86_pmu.event_constraints = intel_nehalem_event_constraints; 1407 x86_pmu.event_constraints = intel_nehalem_event_constraints;
1408 x86_pmu.pebs_constraints = intel_nehalem_pebs_event_constraints;
1409 x86_pmu.percore_constraints = intel_nehalem_percore_constraints;
1039 x86_pmu.enable_all = intel_pmu_nhm_enable_all; 1410 x86_pmu.enable_all = intel_pmu_nhm_enable_all;
1411 x86_pmu.extra_regs = intel_nehalem_extra_regs;
1040 pr_cont("Nehalem events, "); 1412 pr_cont("Nehalem events, ");
1041 break; 1413 break;
1042 1414
@@ -1047,6 +1419,7 @@ static __init int intel_pmu_init(void)
1047 intel_pmu_lbr_init_atom(); 1419 intel_pmu_lbr_init_atom();
1048 1420
1049 x86_pmu.event_constraints = intel_gen_event_constraints; 1421 x86_pmu.event_constraints = intel_gen_event_constraints;
1422 x86_pmu.pebs_constraints = intel_atom_pebs_event_constraints;
1050 pr_cont("Atom events, "); 1423 pr_cont("Atom events, ");
1051 break; 1424 break;
1052 1425
@@ -1054,14 +1427,30 @@ static __init int intel_pmu_init(void)
1054 case 44: /* 32 nm nehalem, "Gulftown" */ 1427 case 44: /* 32 nm nehalem, "Gulftown" */
1055 memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids, 1428 memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids,
1056 sizeof(hw_cache_event_ids)); 1429 sizeof(hw_cache_event_ids));
1430 memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
1431 sizeof(hw_cache_extra_regs));
1057 1432
1058 intel_pmu_lbr_init_nhm(); 1433 intel_pmu_lbr_init_nhm();
1059 1434
1060 x86_pmu.event_constraints = intel_westmere_event_constraints; 1435 x86_pmu.event_constraints = intel_westmere_event_constraints;
1436 x86_pmu.percore_constraints = intel_westmere_percore_constraints;
1061 x86_pmu.enable_all = intel_pmu_nhm_enable_all; 1437 x86_pmu.enable_all = intel_pmu_nhm_enable_all;
1438 x86_pmu.pebs_constraints = intel_westmere_pebs_event_constraints;
1439 x86_pmu.extra_regs = intel_westmere_extra_regs;
1062 pr_cont("Westmere events, "); 1440 pr_cont("Westmere events, ");
1063 break; 1441 break;
1064 1442
1443 case 42: /* SandyBridge */
1444 memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
1445 sizeof(hw_cache_event_ids));
1446
1447 intel_pmu_lbr_init_nhm();
1448
1449 x86_pmu.event_constraints = intel_snb_event_constraints;
1450 x86_pmu.pebs_constraints = intel_snb_pebs_events;
1451 pr_cont("SandyBridge events, ");
1452 break;
1453
1065 default: 1454 default:
1066 /* 1455 /*
1067 * default constraints for v2 and up 1456 * default constraints for v2 and up
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index b7dcd9f2b8a0..b95c66ae4a2a 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -361,30 +361,88 @@ static int intel_pmu_drain_bts_buffer(void)
361/* 361/*
362 * PEBS 362 * PEBS
363 */ 363 */
364 364static struct event_constraint intel_core2_pebs_event_constraints[] = {
365static struct event_constraint intel_core_pebs_events[] = { 365 PEBS_EVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
366 PEBS_EVENT_CONSTRAINT(0x00c0, 0x1), /* INSTR_RETIRED.ANY */
367 PEBS_EVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */ 366 PEBS_EVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
368 PEBS_EVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */ 367 PEBS_EVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
369 PEBS_EVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */ 368 PEBS_EVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */
370 PEBS_EVENT_CONSTRAINT(0x01cb, 0x1), /* MEM_LOAD_RETIRED.L1D_MISS */ 369 INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */
371 PEBS_EVENT_CONSTRAINT(0x02cb, 0x1), /* MEM_LOAD_RETIRED.L1D_LINE_MISS */ 370 EVENT_CONSTRAINT_END
372 PEBS_EVENT_CONSTRAINT(0x04cb, 0x1), /* MEM_LOAD_RETIRED.L2_MISS */ 371};
373 PEBS_EVENT_CONSTRAINT(0x08cb, 0x1), /* MEM_LOAD_RETIRED.L2_LINE_MISS */ 372
374 PEBS_EVENT_CONSTRAINT(0x10cb, 0x1), /* MEM_LOAD_RETIRED.DTLB_MISS */ 373static struct event_constraint intel_atom_pebs_event_constraints[] = {
374 PEBS_EVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
375 PEBS_EVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */
376 INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */
375 EVENT_CONSTRAINT_END 377 EVENT_CONSTRAINT_END
376}; 378};
377 379
378static struct event_constraint intel_nehalem_pebs_events[] = { 380static struct event_constraint intel_nehalem_pebs_event_constraints[] = {
379 PEBS_EVENT_CONSTRAINT(0x00c0, 0xf), /* INSTR_RETIRED.ANY */ 381 INTEL_EVENT_CONSTRAINT(0x0b, 0xf), /* MEM_INST_RETIRED.* */
380 PEBS_EVENT_CONSTRAINT(0xfec1, 0xf), /* X87_OPS_RETIRED.ANY */ 382 INTEL_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */
381 PEBS_EVENT_CONSTRAINT(0x00c5, 0xf), /* BR_INST_RETIRED.MISPRED */ 383 PEBS_EVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
382 PEBS_EVENT_CONSTRAINT(0x1fc7, 0xf), /* SIMD_INST_RETURED.ANY */ 384 INTEL_EVENT_CONSTRAINT(0xc0, 0xf), /* INST_RETIRED.ANY */
383 PEBS_EVENT_CONSTRAINT(0x01cb, 0xf), /* MEM_LOAD_RETIRED.L1D_MISS */ 385 INTEL_EVENT_CONSTRAINT(0xc2, 0xf), /* UOPS_RETIRED.* */
384 PEBS_EVENT_CONSTRAINT(0x02cb, 0xf), /* MEM_LOAD_RETIRED.L1D_LINE_MISS */ 386 INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */
385 PEBS_EVENT_CONSTRAINT(0x04cb, 0xf), /* MEM_LOAD_RETIRED.L2_MISS */ 387 PEBS_EVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */
386 PEBS_EVENT_CONSTRAINT(0x08cb, 0xf), /* MEM_LOAD_RETIRED.L2_LINE_MISS */ 388 INTEL_EVENT_CONSTRAINT(0xc7, 0xf), /* SSEX_UOPS_RETIRED.* */
387 PEBS_EVENT_CONSTRAINT(0x10cb, 0xf), /* MEM_LOAD_RETIRED.DTLB_MISS */ 389 PEBS_EVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
390 INTEL_EVENT_CONSTRAINT(0xcb, 0xf), /* MEM_LOAD_RETIRED.* */
391 INTEL_EVENT_CONSTRAINT(0xf7, 0xf), /* FP_ASSIST.* */
392 EVENT_CONSTRAINT_END
393};
394
395static struct event_constraint intel_westmere_pebs_event_constraints[] = {
396 INTEL_EVENT_CONSTRAINT(0x0b, 0xf), /* MEM_INST_RETIRED.* */
397 INTEL_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */
398 PEBS_EVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
399 INTEL_EVENT_CONSTRAINT(0xc0, 0xf), /* INSTR_RETIRED.* */
400 INTEL_EVENT_CONSTRAINT(0xc2, 0xf), /* UOPS_RETIRED.* */
401
402 INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */
403 INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */
404 INTEL_EVENT_CONSTRAINT(0xc7, 0xf), /* SSEX_UOPS_RETIRED.* */
405 PEBS_EVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
406 INTEL_EVENT_CONSTRAINT(0xcb, 0xf), /* MEM_LOAD_RETIRED.* */
407 INTEL_EVENT_CONSTRAINT(0xf7, 0xf), /* FP_ASSIST.* */
408 EVENT_CONSTRAINT_END
409};
410
411static struct event_constraint intel_snb_pebs_events[] = {
412 PEBS_EVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
413 PEBS_EVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
414 PEBS_EVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */
415 PEBS_EVENT_CONSTRAINT(0x01c4, 0xf), /* BR_INST_RETIRED.CONDITIONAL */
416 PEBS_EVENT_CONSTRAINT(0x02c4, 0xf), /* BR_INST_RETIRED.NEAR_CALL */
417 PEBS_EVENT_CONSTRAINT(0x04c4, 0xf), /* BR_INST_RETIRED.ALL_BRANCHES */
418 PEBS_EVENT_CONSTRAINT(0x08c4, 0xf), /* BR_INST_RETIRED.NEAR_RETURN */
419 PEBS_EVENT_CONSTRAINT(0x10c4, 0xf), /* BR_INST_RETIRED.NOT_TAKEN */
420 PEBS_EVENT_CONSTRAINT(0x20c4, 0xf), /* BR_INST_RETIRED.NEAR_TAKEN */
421 PEBS_EVENT_CONSTRAINT(0x40c4, 0xf), /* BR_INST_RETIRED.FAR_BRANCH */
422 PEBS_EVENT_CONSTRAINT(0x01c5, 0xf), /* BR_MISP_RETIRED.CONDITIONAL */
423 PEBS_EVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */
424 PEBS_EVENT_CONSTRAINT(0x04c5, 0xf), /* BR_MISP_RETIRED.ALL_BRANCHES */
425 PEBS_EVENT_CONSTRAINT(0x10c5, 0xf), /* BR_MISP_RETIRED.NOT_TAKEN */
426 PEBS_EVENT_CONSTRAINT(0x20c5, 0xf), /* BR_MISP_RETIRED.TAKEN */
427 PEBS_EVENT_CONSTRAINT(0x01cd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
428 PEBS_EVENT_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORE */
429 PEBS_EVENT_CONSTRAINT(0x11d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_LOADS */
430 PEBS_EVENT_CONSTRAINT(0x12d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_STORES */
431 PEBS_EVENT_CONSTRAINT(0x21d0, 0xf), /* MEM_UOP_RETIRED.LOCK_LOADS */
432 PEBS_EVENT_CONSTRAINT(0x22d0, 0xf), /* MEM_UOP_RETIRED.LOCK_STORES */
433 PEBS_EVENT_CONSTRAINT(0x41d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_LOADS */
434 PEBS_EVENT_CONSTRAINT(0x42d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_STORES */
435 PEBS_EVENT_CONSTRAINT(0x81d0, 0xf), /* MEM_UOP_RETIRED.ANY_LOADS */
436 PEBS_EVENT_CONSTRAINT(0x82d0, 0xf), /* MEM_UOP_RETIRED.ANY_STORES */
437 PEBS_EVENT_CONSTRAINT(0x01d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.L1_HIT */
438 PEBS_EVENT_CONSTRAINT(0x02d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.L2_HIT */
439 PEBS_EVENT_CONSTRAINT(0x04d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.LLC_HIT */
440 PEBS_EVENT_CONSTRAINT(0x40d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.HIT_LFB */
441 PEBS_EVENT_CONSTRAINT(0x01d2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS */
442 PEBS_EVENT_CONSTRAINT(0x02d2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT */
443 PEBS_EVENT_CONSTRAINT(0x04d2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM */
444 PEBS_EVENT_CONSTRAINT(0x08d2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_NONE */
445 PEBS_EVENT_CONSTRAINT(0x02d4, 0xf), /* MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS */
388 EVENT_CONSTRAINT_END 446 EVENT_CONSTRAINT_END
389}; 447};
390 448
@@ -695,20 +753,17 @@ static void intel_ds_init(void)
695 printk(KERN_CONT "PEBS fmt0%c, ", pebs_type); 753 printk(KERN_CONT "PEBS fmt0%c, ", pebs_type);
696 x86_pmu.pebs_record_size = sizeof(struct pebs_record_core); 754 x86_pmu.pebs_record_size = sizeof(struct pebs_record_core);
697 x86_pmu.drain_pebs = intel_pmu_drain_pebs_core; 755 x86_pmu.drain_pebs = intel_pmu_drain_pebs_core;
698 x86_pmu.pebs_constraints = intel_core_pebs_events;
699 break; 756 break;
700 757
701 case 1: 758 case 1:
702 printk(KERN_CONT "PEBS fmt1%c, ", pebs_type); 759 printk(KERN_CONT "PEBS fmt1%c, ", pebs_type);
703 x86_pmu.pebs_record_size = sizeof(struct pebs_record_nhm); 760 x86_pmu.pebs_record_size = sizeof(struct pebs_record_nhm);
704 x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm; 761 x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
705 x86_pmu.pebs_constraints = intel_nehalem_pebs_events;
706 break; 762 break;
707 763
708 default: 764 default:
709 printk(KERN_CONT "no PEBS fmt%d%c, ", format, pebs_type); 765 printk(KERN_CONT "no PEBS fmt%d%c, ", format, pebs_type);
710 x86_pmu.pebs = 0; 766 x86_pmu.pebs = 0;
711 break;
712 } 767 }
713 } 768 }
714} 769}
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
index ff751a9f182b..3769ac822f96 100644
--- a/arch/x86/kernel/cpu/perf_event_p4.c
+++ b/arch/x86/kernel/cpu/perf_event_p4.c
@@ -764,9 +764,9 @@ static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc)
764 u64 v; 764 u64 v;
765 765
766 /* an official way for overflow indication */ 766 /* an official way for overflow indication */
767 rdmsrl(hwc->config_base + hwc->idx, v); 767 rdmsrl(hwc->config_base, v);
768 if (v & P4_CCCR_OVF) { 768 if (v & P4_CCCR_OVF) {
769 wrmsrl(hwc->config_base + hwc->idx, v & ~P4_CCCR_OVF); 769 wrmsrl(hwc->config_base, v & ~P4_CCCR_OVF);
770 return 1; 770 return 1;
771 } 771 }
772 772
@@ -815,7 +815,7 @@ static inline void p4_pmu_disable_event(struct perf_event *event)
815 * state we need to clear P4_CCCR_OVF, otherwise interrupt get 815 * state we need to clear P4_CCCR_OVF, otherwise interrupt get
816 * asserted again and again 816 * asserted again and again
817 */ 817 */
818 (void)checking_wrmsrl(hwc->config_base + hwc->idx, 818 (void)checking_wrmsrl(hwc->config_base,
819 (u64)(p4_config_unpack_cccr(hwc->config)) & 819 (u64)(p4_config_unpack_cccr(hwc->config)) &
820 ~P4_CCCR_ENABLE & ~P4_CCCR_OVF & ~P4_CCCR_RESERVED); 820 ~P4_CCCR_ENABLE & ~P4_CCCR_OVF & ~P4_CCCR_RESERVED);
821} 821}
@@ -885,7 +885,7 @@ static void p4_pmu_enable_event(struct perf_event *event)
885 p4_pmu_enable_pebs(hwc->config); 885 p4_pmu_enable_pebs(hwc->config);
886 886
887 (void)checking_wrmsrl(escr_addr, escr_conf); 887 (void)checking_wrmsrl(escr_addr, escr_conf);
888 (void)checking_wrmsrl(hwc->config_base + hwc->idx, 888 (void)checking_wrmsrl(hwc->config_base,
889 (cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE); 889 (cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE);
890} 890}
891 891
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
index 34ba07be2cda..20c097e33860 100644
--- a/arch/x86/kernel/cpu/perf_event_p6.c
+++ b/arch/x86/kernel/cpu/perf_event_p6.c
@@ -68,7 +68,7 @@ p6_pmu_disable_event(struct perf_event *event)
68 if (cpuc->enabled) 68 if (cpuc->enabled)
69 val |= ARCH_PERFMON_EVENTSEL_ENABLE; 69 val |= ARCH_PERFMON_EVENTSEL_ENABLE;
70 70
71 (void)checking_wrmsrl(hwc->config_base + hwc->idx, val); 71 (void)checking_wrmsrl(hwc->config_base, val);
72} 72}
73 73
74static void p6_pmu_enable_event(struct perf_event *event) 74static void p6_pmu_enable_event(struct perf_event *event)
@@ -81,7 +81,7 @@ static void p6_pmu_enable_event(struct perf_event *event)
81 if (cpuc->enabled) 81 if (cpuc->enabled)
82 val |= ARCH_PERFMON_EVENTSEL_ENABLE; 82 val |= ARCH_PERFMON_EVENTSEL_ENABLE;
83 83
84 (void)checking_wrmsrl(hwc->config_base + hwc->idx, val); 84 (void)checking_wrmsrl(hwc->config_base, val);
85} 85}
86 86
87static __initconst const struct x86_pmu p6_pmu = { 87static __initconst const struct x86_pmu p6_pmu = {
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
index d5a236615501..966512b2cacf 100644
--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
+++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
@@ -46,6 +46,8 @@ static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
46 /* returns the bit offset of the performance counter register */ 46 /* returns the bit offset of the performance counter register */
47 switch (boot_cpu_data.x86_vendor) { 47 switch (boot_cpu_data.x86_vendor) {
48 case X86_VENDOR_AMD: 48 case X86_VENDOR_AMD:
49 if (msr >= MSR_F15H_PERF_CTR)
50 return (msr - MSR_F15H_PERF_CTR) >> 1;
49 return msr - MSR_K7_PERFCTR0; 51 return msr - MSR_K7_PERFCTR0;
50 case X86_VENDOR_INTEL: 52 case X86_VENDOR_INTEL:
51 if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) 53 if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
@@ -70,6 +72,8 @@ static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
70 /* returns the bit offset of the event selection register */ 72 /* returns the bit offset of the event selection register */
71 switch (boot_cpu_data.x86_vendor) { 73 switch (boot_cpu_data.x86_vendor) {
72 case X86_VENDOR_AMD: 74 case X86_VENDOR_AMD:
75 if (msr >= MSR_F15H_PERF_CTL)
76 return (msr - MSR_F15H_PERF_CTL) >> 1;
73 return msr - MSR_K7_EVNTSEL0; 77 return msr - MSR_K7_EVNTSEL0;
74 case X86_VENDOR_INTEL: 78 case X86_VENDOR_INTEL:
75 if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) 79 if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index df20723a6a1b..220a1c11cfde 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -320,31 +320,6 @@ void die(const char *str, struct pt_regs *regs, long err)
320 oops_end(flags, regs, sig); 320 oops_end(flags, regs, sig);
321} 321}
322 322
323void notrace __kprobes
324die_nmi(char *str, struct pt_regs *regs, int do_panic)
325{
326 unsigned long flags;
327
328 if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP)
329 return;
330
331 /*
332 * We are in trouble anyway, lets at least try
333 * to get a message out.
334 */
335 flags = oops_begin();
336 printk(KERN_EMERG "%s", str);
337 printk(" on CPU%d, ip %08lx, registers:\n",
338 smp_processor_id(), regs->ip);
339 show_registers(regs);
340 oops_end(flags, regs, 0);
341 if (do_panic || panic_on_oops)
342 panic("Non maskable interrupt");
343 nmi_exit();
344 local_irq_enable();
345 do_exit(SIGBUS);
346}
347
348static int __init oops_setup(char *s) 323static int __init oops_setup(char *s)
349{ 324{
350 if (!s) 325 if (!s)
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index c8b4efad7ebb..f5accf8eaa78 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -65,6 +65,8 @@
65#define sysexit_audit syscall_exit_work 65#define sysexit_audit syscall_exit_work
66#endif 66#endif
67 67
68 .section .entry.text, "ax"
69
68/* 70/*
69 * We use macros for low-level operations which need to be overridden 71 * We use macros for low-level operations which need to be overridden
70 * for paravirtualization. The following will never clobber any registers: 72 * for paravirtualization. The following will never clobber any registers:
@@ -788,7 +790,7 @@ ENDPROC(ptregs_clone)
788 */ 790 */
789.section .init.rodata,"a" 791.section .init.rodata,"a"
790ENTRY(interrupt) 792ENTRY(interrupt)
791.text 793.section .entry.text, "ax"
792 .p2align 5 794 .p2align 5
793 .p2align CONFIG_X86_L1_CACHE_SHIFT 795 .p2align CONFIG_X86_L1_CACHE_SHIFT
794ENTRY(irq_entries_start) 796ENTRY(irq_entries_start)
@@ -807,7 +809,7 @@ vector=FIRST_EXTERNAL_VECTOR
807 .endif 809 .endif
808 .previous 810 .previous
809 .long 1b 811 .long 1b
810 .text 812 .section .entry.text, "ax"
811vector=vector+1 813vector=vector+1
812 .endif 814 .endif
813 .endr 815 .endr
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index aed1ffbeb0c9..0a0ed794edb2 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -61,6 +61,8 @@
61#define __AUDIT_ARCH_LE 0x40000000 61#define __AUDIT_ARCH_LE 0x40000000
62 62
63 .code64 63 .code64
64 .section .entry.text, "ax"
65
64#ifdef CONFIG_FUNCTION_TRACER 66#ifdef CONFIG_FUNCTION_TRACER
65#ifdef CONFIG_DYNAMIC_FTRACE 67#ifdef CONFIG_DYNAMIC_FTRACE
66ENTRY(mcount) 68ENTRY(mcount)
@@ -744,7 +746,7 @@ END(stub_rt_sigreturn)
744 */ 746 */
745 .section .init.rodata,"a" 747 .section .init.rodata,"a"
746ENTRY(interrupt) 748ENTRY(interrupt)
747 .text 749 .section .entry.text
748 .p2align 5 750 .p2align 5
749 .p2align CONFIG_X86_L1_CACHE_SHIFT 751 .p2align CONFIG_X86_L1_CACHE_SHIFT
750ENTRY(irq_entries_start) 752ENTRY(irq_entries_start)
@@ -763,7 +765,7 @@ vector=FIRST_EXTERNAL_VECTOR
763 .endif 765 .endif
764 .previous 766 .previous
765 .quad 1b 767 .quad 1b
766 .text 768 .section .entry.text
767vector=vector+1 769vector=vector+1
768 .endif 770 .endif
769 .endr 771 .endr
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 382eb2936d4d..a93742a57468 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -437,18 +437,19 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
437 return; 437 return;
438 } 438 }
439 439
440 if (ftrace_push_return_trace(old, self_addr, &trace.depth,
441 frame_pointer) == -EBUSY) {
442 *parent = old;
443 return;
444 }
445
446 trace.func = self_addr; 440 trace.func = self_addr;
441 trace.depth = current->curr_ret_stack + 1;
447 442
448 /* Only trace if the calling function expects to */ 443 /* Only trace if the calling function expects to */
449 if (!ftrace_graph_entry(&trace)) { 444 if (!ftrace_graph_entry(&trace)) {
450 current->curr_ret_stack--;
451 *parent = old; 445 *parent = old;
446 return;
447 }
448
449 if (ftrace_push_return_trace(old, self_addr, &trace.depth,
450 frame_pointer) == -EBUSY) {
451 *parent = old;
452 return;
452 } 453 }
453} 454}
454#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 455#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index a4130005028a..7c64c420a9f6 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -533,15 +533,6 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
533 } 533 }
534 return NOTIFY_DONE; 534 return NOTIFY_DONE;
535 535
536 case DIE_NMIWATCHDOG:
537 if (atomic_read(&kgdb_active) != -1) {
538 /* KGDB CPU roundup: */
539 kgdb_nmicallback(raw_smp_processor_id(), regs);
540 return NOTIFY_STOP;
541 }
542 /* Enter debugger: */
543 break;
544
545 case DIE_DEBUG: 536 case DIE_DEBUG:
546 if (atomic_read(&kgdb_cpu_doing_single_step) != -1) { 537 if (atomic_read(&kgdb_cpu_doing_single_step) != -1) {
547 if (user_mode(regs)) 538 if (user_mode(regs))
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index d91c477b3f62..c969fd9d1566 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -1276,6 +1276,14 @@ static int __kprobes can_optimize(unsigned long paddr)
1276 if (!kallsyms_lookup_size_offset(paddr, &size, &offset)) 1276 if (!kallsyms_lookup_size_offset(paddr, &size, &offset))
1277 return 0; 1277 return 0;
1278 1278
1279 /*
1280 * Do not optimize in the entry code due to the unstable
1281 * stack handling.
1282 */
1283 if ((paddr >= (unsigned long )__entry_text_start) &&
1284 (paddr < (unsigned long )__entry_text_end))
1285 return 0;
1286
1279 /* Check there is enough space for a relative jump. */ 1287 /* Check there is enough space for a relative jump. */
1280 if (size - offset < RELATIVEJUMP_SIZE) 1288 if (size - offset < RELATIVEJUMP_SIZE)
1281 return 0; 1289 return 0;
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index bf4700755184..6d4341d5c52a 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -105,6 +105,7 @@ SECTIONS
105 SCHED_TEXT 105 SCHED_TEXT
106 LOCK_TEXT 106 LOCK_TEXT
107 KPROBES_TEXT 107 KPROBES_TEXT
108 ENTRY_TEXT
108 IRQENTRY_TEXT 109 IRQENTRY_TEXT
109 *(.fixup) 110 *(.fixup)
110 *(.gnu.warning) 111 *(.gnu.warning)
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index 1357d7cf4ec8..db932760ea82 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -62,21 +62,21 @@ TRACE_EVENT(kvm_hv_hypercall,
62 TP_ARGS(code, fast, rep_cnt, rep_idx, ingpa, outgpa), 62 TP_ARGS(code, fast, rep_cnt, rep_idx, ingpa, outgpa),
63 63
64 TP_STRUCT__entry( 64 TP_STRUCT__entry(
65 __field( __u16, code )
66 __field( bool, fast )
67 __field( __u16, rep_cnt ) 65 __field( __u16, rep_cnt )
68 __field( __u16, rep_idx ) 66 __field( __u16, rep_idx )
69 __field( __u64, ingpa ) 67 __field( __u64, ingpa )
70 __field( __u64, outgpa ) 68 __field( __u64, outgpa )
69 __field( __u16, code )
70 __field( bool, fast )
71 ), 71 ),
72 72
73 TP_fast_assign( 73 TP_fast_assign(
74 __entry->code = code;
75 __entry->fast = fast;
76 __entry->rep_cnt = rep_cnt; 74 __entry->rep_cnt = rep_cnt;
77 __entry->rep_idx = rep_idx; 75 __entry->rep_idx = rep_idx;
78 __entry->ingpa = ingpa; 76 __entry->ingpa = ingpa;
79 __entry->outgpa = outgpa; 77 __entry->outgpa = outgpa;
78 __entry->code = code;
79 __entry->fast = fast;
80 ), 80 ),
81 81
82 TP_printk("code 0x%x %s cnt 0x%x idx 0x%x in 0x%llx out 0x%llx", 82 TP_printk("code 0x%x %s cnt 0x%x idx 0x%x in 0x%llx out 0x%llx",
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index b3bfabc258f3..c1a1216e29ce 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -11,6 +11,7 @@ extern char _sinittext[], _einittext[];
11extern char _end[]; 11extern char _end[];
12extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[]; 12extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
13extern char __kprobes_text_start[], __kprobes_text_end[]; 13extern char __kprobes_text_start[], __kprobes_text_end[];
14extern char __entry_text_start[], __entry_text_end[];
14extern char __initdata_begin[], __initdata_end[]; 15extern char __initdata_begin[], __initdata_end[];
15extern char __start_rodata[], __end_rodata[]; 16extern char __start_rodata[], __end_rodata[];
16 17
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index fe77e3395b40..906c3ceca9a2 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -424,6 +424,12 @@
424 *(.kprobes.text) \ 424 *(.kprobes.text) \
425 VMLINUX_SYMBOL(__kprobes_text_end) = .; 425 VMLINUX_SYMBOL(__kprobes_text_end) = .;
426 426
427#define ENTRY_TEXT \
428 ALIGN_FUNCTION(); \
429 VMLINUX_SYMBOL(__entry_text_start) = .; \
430 *(.entry.text) \
431 VMLINUX_SYMBOL(__entry_text_end) = .;
432
427#ifdef CONFIG_FUNCTION_GRAPH_TRACER 433#ifdef CONFIG_FUNCTION_GRAPH_TRACER
428#define IRQENTRY_TEXT \ 434#define IRQENTRY_TEXT \
429 ALIGN_FUNCTION(); \ 435 ALIGN_FUNCTION(); \
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index ce104e33cd22..e654fa239916 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -474,7 +474,8 @@ struct cgroup_subsys {
474 struct cgroup *old_cgrp, struct task_struct *tsk, 474 struct cgroup *old_cgrp, struct task_struct *tsk,
475 bool threadgroup); 475 bool threadgroup);
476 void (*fork)(struct cgroup_subsys *ss, struct task_struct *task); 476 void (*fork)(struct cgroup_subsys *ss, struct task_struct *task);
477 void (*exit)(struct cgroup_subsys *ss, struct task_struct *task); 477 void (*exit)(struct cgroup_subsys *ss, struct cgroup *cgrp,
478 struct cgroup *old_cgrp, struct task_struct *task);
478 int (*populate)(struct cgroup_subsys *ss, 479 int (*populate)(struct cgroup_subsys *ss,
479 struct cgroup *cgrp); 480 struct cgroup *cgrp);
480 void (*post_clone)(struct cgroup_subsys *ss, struct cgroup *cgrp); 481 void (*post_clone)(struct cgroup_subsys *ss, struct cgroup *cgrp);
@@ -626,6 +627,7 @@ bool css_is_ancestor(struct cgroup_subsys_state *cg,
626/* Get id and depth of css */ 627/* Get id and depth of css */
627unsigned short css_id(struct cgroup_subsys_state *css); 628unsigned short css_id(struct cgroup_subsys_state *css);
628unsigned short css_depth(struct cgroup_subsys_state *css); 629unsigned short css_depth(struct cgroup_subsys_state *css);
630struct cgroup_subsys_state *cgroup_css_from_dir(struct file *f, int id);
629 631
630#else /* !CONFIG_CGROUPS */ 632#else /* !CONFIG_CGROUPS */
631 633
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
index ccefff02b6cb..cdbfcb8780ec 100644
--- a/include/linux/cgroup_subsys.h
+++ b/include/linux/cgroup_subsys.h
@@ -65,4 +65,8 @@ SUBSYS(net_cls)
65SUBSYS(blkio) 65SUBSYS(blkio)
66#endif 66#endif
67 67
68#ifdef CONFIG_CGROUP_PERF
69SUBSYS(perf)
70#endif
71
68/* */ 72/* */
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index dcd6a7c3a435..ca29e03c1fac 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -428,6 +428,7 @@ extern void unregister_ftrace_graph(void);
428 428
429extern void ftrace_graph_init_task(struct task_struct *t); 429extern void ftrace_graph_init_task(struct task_struct *t);
430extern void ftrace_graph_exit_task(struct task_struct *t); 430extern void ftrace_graph_exit_task(struct task_struct *t);
431extern void ftrace_graph_init_idle_task(struct task_struct *t, int cpu);
431 432
432static inline int task_curr_ret_stack(struct task_struct *t) 433static inline int task_curr_ret_stack(struct task_struct *t)
433{ 434{
@@ -451,6 +452,7 @@ static inline void unpause_graph_tracing(void)
451 452
452static inline void ftrace_graph_init_task(struct task_struct *t) { } 453static inline void ftrace_graph_init_task(struct task_struct *t) { }
453static inline void ftrace_graph_exit_task(struct task_struct *t) { } 454static inline void ftrace_graph_exit_task(struct task_struct *t) { }
455static inline void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) { }
454 456
455static inline int register_ftrace_graph(trace_func_graph_ret_t retfunc, 457static inline int register_ftrace_graph(trace_func_graph_ret_t retfunc,
456 trace_func_graph_ent_t entryfunc) 458 trace_func_graph_ent_t entryfunc)
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 47e3997f7b5c..22b32af1b5ec 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -37,7 +37,6 @@ struct trace_entry {
37 unsigned char flags; 37 unsigned char flags;
38 unsigned char preempt_count; 38 unsigned char preempt_count;
39 int pid; 39 int pid;
40 int lock_depth;
41}; 40};
42 41
43#define FTRACE_MAX_EVENT \ 42#define FTRACE_MAX_EVENT \
@@ -208,7 +207,6 @@ struct ftrace_event_call {
208 207
209#define PERF_MAX_TRACE_SIZE 2048 208#define PERF_MAX_TRACE_SIZE 2048
210 209
211#define MAX_FILTER_PRED 32
212#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */ 210#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */
213 211
214extern void destroy_preds(struct ftrace_event_call *call); 212extern void destroy_preds(struct ftrace_event_call *call);
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index dda5b0a3ff60..614615b8d42b 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -225,8 +225,14 @@ struct perf_event_attr {
225 }; 225 };
226 226
227 __u32 bp_type; 227 __u32 bp_type;
228 __u64 bp_addr; 228 union {
229 __u64 bp_len; 229 __u64 bp_addr;
230 __u64 config1; /* extension of config */
231 };
232 union {
233 __u64 bp_len;
234 __u64 config2; /* extension of config1 */
235 };
230}; 236};
231 237
232/* 238/*
@@ -464,6 +470,7 @@ enum perf_callchain_context {
464 470
465#define PERF_FLAG_FD_NO_GROUP (1U << 0) 471#define PERF_FLAG_FD_NO_GROUP (1U << 0)
466#define PERF_FLAG_FD_OUTPUT (1U << 1) 472#define PERF_FLAG_FD_OUTPUT (1U << 1)
473#define PERF_FLAG_PID_CGROUP (1U << 2) /* pid=cgroup id, per-cpu mode only */
467 474
468#ifdef __KERNEL__ 475#ifdef __KERNEL__
469/* 476/*
@@ -471,6 +478,7 @@ enum perf_callchain_context {
471 */ 478 */
472 479
473#ifdef CONFIG_PERF_EVENTS 480#ifdef CONFIG_PERF_EVENTS
481# include <linux/cgroup.h>
474# include <asm/perf_event.h> 482# include <asm/perf_event.h>
475# include <asm/local64.h> 483# include <asm/local64.h>
476#endif 484#endif
@@ -539,6 +547,9 @@ struct hw_perf_event {
539 unsigned long event_base; 547 unsigned long event_base;
540 int idx; 548 int idx;
541 int last_cpu; 549 int last_cpu;
550 unsigned int extra_reg;
551 u64 extra_config;
552 int extra_alloc;
542 }; 553 };
543 struct { /* software */ 554 struct { /* software */
544 struct hrtimer hrtimer; 555 struct hrtimer hrtimer;
@@ -716,6 +727,22 @@ struct swevent_hlist {
716#define PERF_ATTACH_GROUP 0x02 727#define PERF_ATTACH_GROUP 0x02
717#define PERF_ATTACH_TASK 0x04 728#define PERF_ATTACH_TASK 0x04
718 729
730#ifdef CONFIG_CGROUP_PERF
731/*
732 * perf_cgroup_info keeps track of time_enabled for a cgroup.
733 * This is a per-cpu dynamically allocated data structure.
734 */
735struct perf_cgroup_info {
736 u64 time;
737 u64 timestamp;
738};
739
740struct perf_cgroup {
741 struct cgroup_subsys_state css;
742 struct perf_cgroup_info *info; /* timing info, one per cpu */
743};
744#endif
745
719/** 746/**
720 * struct perf_event - performance event kernel representation: 747 * struct perf_event - performance event kernel representation:
721 */ 748 */
@@ -832,6 +859,11 @@ struct perf_event {
832 struct event_filter *filter; 859 struct event_filter *filter;
833#endif 860#endif
834 861
862#ifdef CONFIG_CGROUP_PERF
863 struct perf_cgroup *cgrp; /* cgroup event is attach to */
864 int cgrp_defer_enabled;
865#endif
866
835#endif /* CONFIG_PERF_EVENTS */ 867#endif /* CONFIG_PERF_EVENTS */
836}; 868};
837 869
@@ -886,6 +918,7 @@ struct perf_event_context {
886 u64 generation; 918 u64 generation;
887 int pin_count; 919 int pin_count;
888 struct rcu_head rcu_head; 920 struct rcu_head rcu_head;
921 int nr_cgroups; /* cgroup events present */
889}; 922};
890 923
891/* 924/*
@@ -905,6 +938,9 @@ struct perf_cpu_context {
905 struct list_head rotation_list; 938 struct list_head rotation_list;
906 int jiffies_interval; 939 int jiffies_interval;
907 struct pmu *active_pmu; 940 struct pmu *active_pmu;
941#ifdef CONFIG_CGROUP_PERF
942 struct perf_cgroup *cgrp;
943#endif
908}; 944};
909 945
910struct perf_output_handle { 946struct perf_output_handle {
@@ -1040,11 +1076,11 @@ have_event:
1040 __perf_sw_event(event_id, nr, nmi, regs, addr); 1076 __perf_sw_event(event_id, nr, nmi, regs, addr);
1041} 1077}
1042 1078
1043extern atomic_t perf_task_events; 1079extern atomic_t perf_sched_events;
1044 1080
1045static inline void perf_event_task_sched_in(struct task_struct *task) 1081static inline void perf_event_task_sched_in(struct task_struct *task)
1046{ 1082{
1047 COND_STMT(&perf_task_events, __perf_event_task_sched_in(task)); 1083 COND_STMT(&perf_sched_events, __perf_event_task_sched_in(task));
1048} 1084}
1049 1085
1050static inline 1086static inline
@@ -1052,7 +1088,7 @@ void perf_event_task_sched_out(struct task_struct *task, struct task_struct *nex
1052{ 1088{
1053 perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0); 1089 perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
1054 1090
1055 COND_STMT(&perf_task_events, __perf_event_task_sched_out(task, next)); 1091 COND_STMT(&perf_sched_events, __perf_event_task_sched_out(task, next));
1056} 1092}
1057 1093
1058extern void perf_event_mmap(struct vm_area_struct *vma); 1094extern void perf_event_mmap(struct vm_area_struct *vma);
@@ -1083,6 +1119,10 @@ extern int sysctl_perf_event_paranoid;
1083extern int sysctl_perf_event_mlock; 1119extern int sysctl_perf_event_mlock;
1084extern int sysctl_perf_event_sample_rate; 1120extern int sysctl_perf_event_sample_rate;
1085 1121
1122extern int perf_proc_update_handler(struct ctl_table *table, int write,
1123 void __user *buffer, size_t *lenp,
1124 loff_t *ppos);
1125
1086static inline bool perf_paranoid_tracepoint_raw(void) 1126static inline bool perf_paranoid_tracepoint_raw(void)
1087{ 1127{
1088 return sysctl_perf_event_paranoid > -1; 1128 return sysctl_perf_event_paranoid > -1;
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index 8d3a2486544d..ab38ac80b0f9 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -100,6 +100,8 @@ void ring_buffer_free(struct ring_buffer *buffer);
100 100
101int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size); 101int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size);
102 102
103void ring_buffer_change_overwrite(struct ring_buffer *buffer, int val);
104
103struct ring_buffer_event *ring_buffer_lock_reserve(struct ring_buffer *buffer, 105struct ring_buffer_event *ring_buffer_lock_reserve(struct ring_buffer *buffer,
104 unsigned long length); 106 unsigned long length);
105int ring_buffer_unlock_commit(struct ring_buffer *buffer, 107int ring_buffer_unlock_commit(struct ring_buffer *buffer,
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 777d8a5ed06b..c57e5278df83 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2578,13 +2578,6 @@ static inline void inc_syscw(struct task_struct *tsk)
2578#define TASK_SIZE_OF(tsk) TASK_SIZE 2578#define TASK_SIZE_OF(tsk) TASK_SIZE
2579#endif 2579#endif
2580 2580
2581/*
2582 * Call the function if the target task is executing on a CPU right now:
2583 */
2584extern void task_oncpu_function_call(struct task_struct *p,
2585 void (*func) (void *info), void *info);
2586
2587
2588#ifdef CONFIG_MM_OWNER 2581#ifdef CONFIG_MM_OWNER
2589extern void mm_update_next_owner(struct mm_struct *mm); 2582extern void mm_update_next_owner(struct mm_struct *mm);
2590extern void mm_init_owner(struct mm_struct *mm, struct task_struct *p); 2583extern void mm_init_owner(struct mm_struct *mm, struct task_struct *p);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 2d9b79c0f224..4acc6b6088b0 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -133,11 +133,11 @@ extern struct trace_event_functions exit_syscall_print_funcs;
133 .class = &event_class_syscall_enter, \ 133 .class = &event_class_syscall_enter, \
134 .event.funcs = &enter_syscall_print_funcs, \ 134 .event.funcs = &enter_syscall_print_funcs, \
135 .data = (void *)&__syscall_meta_##sname,\ 135 .data = (void *)&__syscall_meta_##sname,\
136 .flags = TRACE_EVENT_FL_CAP_ANY, \
136 }; \ 137 }; \
137 static struct ftrace_event_call __used \ 138 static struct ftrace_event_call __used \
138 __attribute__((section("_ftrace_events"))) \ 139 __attribute__((section("_ftrace_events"))) \
139 *__event_enter_##sname = &event_enter_##sname; \ 140 *__event_enter_##sname = &event_enter_##sname;
140 __TRACE_EVENT_FLAGS(enter_##sname, TRACE_EVENT_FL_CAP_ANY)
141 141
142#define SYSCALL_TRACE_EXIT_EVENT(sname) \ 142#define SYSCALL_TRACE_EXIT_EVENT(sname) \
143 static struct syscall_metadata __syscall_meta_##sname; \ 143 static struct syscall_metadata __syscall_meta_##sname; \
@@ -147,11 +147,11 @@ extern struct trace_event_functions exit_syscall_print_funcs;
147 .class = &event_class_syscall_exit, \ 147 .class = &event_class_syscall_exit, \
148 .event.funcs = &exit_syscall_print_funcs, \ 148 .event.funcs = &exit_syscall_print_funcs, \
149 .data = (void *)&__syscall_meta_##sname,\ 149 .data = (void *)&__syscall_meta_##sname,\
150 .flags = TRACE_EVENT_FL_CAP_ANY, \
150 }; \ 151 }; \
151 static struct ftrace_event_call __used \ 152 static struct ftrace_event_call __used \
152 __attribute__((section("_ftrace_events"))) \ 153 __attribute__((section("_ftrace_events"))) \
153 *__event_exit_##sname = &event_exit_##sname; \ 154 *__event_exit_##sname = &event_exit_##sname;
154 __TRACE_EVENT_FLAGS(exit_##sname, TRACE_EVENT_FL_CAP_ANY)
155 155
156#define SYSCALL_METADATA(sname, nb) \ 156#define SYSCALL_METADATA(sname, nb) \
157 SYSCALL_TRACE_ENTER_EVENT(sname); \ 157 SYSCALL_TRACE_ENTER_EVENT(sname); \
@@ -159,6 +159,7 @@ extern struct trace_event_functions exit_syscall_print_funcs;
159 static struct syscall_metadata __used \ 159 static struct syscall_metadata __used \
160 __syscall_meta_##sname = { \ 160 __syscall_meta_##sname = { \
161 .name = "sys"#sname, \ 161 .name = "sys"#sname, \
162 .syscall_nr = -1, /* Filled in at boot */ \
162 .nb_args = nb, \ 163 .nb_args = nb, \
163 .types = types_##sname, \ 164 .types = types_##sname, \
164 .args = args_##sname, \ 165 .args = args_##sname, \
@@ -176,6 +177,7 @@ extern struct trace_event_functions exit_syscall_print_funcs;
176 static struct syscall_metadata __used \ 177 static struct syscall_metadata __used \
177 __syscall_meta__##sname = { \ 178 __syscall_meta__##sname = { \
178 .name = "sys_"#sname, \ 179 .name = "sys_"#sname, \
180 .syscall_nr = -1, /* Filled in at boot */ \
179 .nb_args = 0, \ 181 .nb_args = 0, \
180 .enter_event = &event_enter__##sname, \ 182 .enter_event = &event_enter__##sname, \
181 .exit_event = &event_exit__##sname, \ 183 .exit_event = &event_exit__##sname, \
diff --git a/include/trace/events/mce.h b/include/trace/events/mce.h
index 7eee77895cb3..4cbbcef6baa8 100644
--- a/include/trace/events/mce.h
+++ b/include/trace/events/mce.h
@@ -17,36 +17,36 @@ TRACE_EVENT(mce_record,
17 TP_STRUCT__entry( 17 TP_STRUCT__entry(
18 __field( u64, mcgcap ) 18 __field( u64, mcgcap )
19 __field( u64, mcgstatus ) 19 __field( u64, mcgstatus )
20 __field( u8, bank )
21 __field( u64, status ) 20 __field( u64, status )
22 __field( u64, addr ) 21 __field( u64, addr )
23 __field( u64, misc ) 22 __field( u64, misc )
24 __field( u64, ip ) 23 __field( u64, ip )
25 __field( u8, cs )
26 __field( u64, tsc ) 24 __field( u64, tsc )
27 __field( u64, walltime ) 25 __field( u64, walltime )
28 __field( u32, cpu ) 26 __field( u32, cpu )
29 __field( u32, cpuid ) 27 __field( u32, cpuid )
30 __field( u32, apicid ) 28 __field( u32, apicid )
31 __field( u32, socketid ) 29 __field( u32, socketid )
30 __field( u8, cs )
31 __field( u8, bank )
32 __field( u8, cpuvendor ) 32 __field( u8, cpuvendor )
33 ), 33 ),
34 34
35 TP_fast_assign( 35 TP_fast_assign(
36 __entry->mcgcap = m->mcgcap; 36 __entry->mcgcap = m->mcgcap;
37 __entry->mcgstatus = m->mcgstatus; 37 __entry->mcgstatus = m->mcgstatus;
38 __entry->bank = m->bank;
39 __entry->status = m->status; 38 __entry->status = m->status;
40 __entry->addr = m->addr; 39 __entry->addr = m->addr;
41 __entry->misc = m->misc; 40 __entry->misc = m->misc;
42 __entry->ip = m->ip; 41 __entry->ip = m->ip;
43 __entry->cs = m->cs;
44 __entry->tsc = m->tsc; 42 __entry->tsc = m->tsc;
45 __entry->walltime = m->time; 43 __entry->walltime = m->time;
46 __entry->cpu = m->extcpu; 44 __entry->cpu = m->extcpu;
47 __entry->cpuid = m->cpuid; 45 __entry->cpuid = m->cpuid;
48 __entry->apicid = m->apicid; 46 __entry->apicid = m->apicid;
49 __entry->socketid = m->socketid; 47 __entry->socketid = m->socketid;
48 __entry->cs = m->cs;
49 __entry->bank = m->bank;
50 __entry->cpuvendor = m->cpuvendor; 50 __entry->cpuvendor = m->cpuvendor;
51 ), 51 ),
52 52
diff --git a/include/trace/events/module.h b/include/trace/events/module.h
index c6bae36547e5..21a546d27c0c 100644
--- a/include/trace/events/module.h
+++ b/include/trace/events/module.h
@@ -108,14 +108,14 @@ TRACE_EVENT(module_request,
108 TP_ARGS(name, wait, ip), 108 TP_ARGS(name, wait, ip),
109 109
110 TP_STRUCT__entry( 110 TP_STRUCT__entry(
111 __field( bool, wait )
112 __field( unsigned long, ip ) 111 __field( unsigned long, ip )
112 __field( bool, wait )
113 __string( name, name ) 113 __string( name, name )
114 ), 114 ),
115 115
116 TP_fast_assign( 116 TP_fast_assign(
117 __entry->wait = wait;
118 __entry->ip = ip; 117 __entry->ip = ip;
118 __entry->wait = wait;
119 __assign_str(name, name); 119 __assign_str(name, name);
120 ), 120 ),
121 121
@@ -129,4 +129,3 @@ TRACE_EVENT(module_request,
129 129
130/* This part must be outside protection */ 130/* This part must be outside protection */
131#include <trace/define_trace.h> 131#include <trace/define_trace.h>
132
diff --git a/include/trace/events/skb.h b/include/trace/events/skb.h
index f10293c41b1e..0c68ae22da22 100644
--- a/include/trace/events/skb.h
+++ b/include/trace/events/skb.h
@@ -19,14 +19,14 @@ TRACE_EVENT(kfree_skb,
19 19
20 TP_STRUCT__entry( 20 TP_STRUCT__entry(
21 __field( void *, skbaddr ) 21 __field( void *, skbaddr )
22 __field( unsigned short, protocol )
23 __field( void *, location ) 22 __field( void *, location )
23 __field( unsigned short, protocol )
24 ), 24 ),
25 25
26 TP_fast_assign( 26 TP_fast_assign(
27 __entry->skbaddr = skb; 27 __entry->skbaddr = skb;
28 __entry->protocol = ntohs(skb->protocol);
29 __entry->location = location; 28 __entry->location = location;
29 __entry->protocol = ntohs(skb->protocol);
30 ), 30 ),
31 31
32 TP_printk("skbaddr=%p protocol=%u location=%p", 32 TP_printk("skbaddr=%p protocol=%u location=%p",
diff --git a/init/Kconfig b/init/Kconfig
index e72fa17fe559..5721d27af626 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -695,6 +695,16 @@ config CGROUP_MEM_RES_CTLR_SWAP_ENABLED
695 select this option (if, for some reason, they need to disable it 695 select this option (if, for some reason, they need to disable it
696 then noswapaccount does the trick). 696 then noswapaccount does the trick).
697 697
698config CGROUP_PERF
699 bool "Enable perf_event per-cpu per-container group (cgroup) monitoring"
700 depends on PERF_EVENTS && CGROUPS
701 help
702 This option extends the per-cpu mode to restrict monitoring to
703 threads which belong to the cgroup specified and run on the
704 designated cpu.
705
706 Say N if unsure.
707
698menuconfig CGROUP_SCHED 708menuconfig CGROUP_SCHED
699 bool "Group CPU scheduler" 709 bool "Group CPU scheduler"
700 depends on EXPERIMENTAL 710 depends on EXPERIMENTAL
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index b24d7027b83c..95362d15128c 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4230,20 +4230,8 @@ void cgroup_post_fork(struct task_struct *child)
4230 */ 4230 */
4231void cgroup_exit(struct task_struct *tsk, int run_callbacks) 4231void cgroup_exit(struct task_struct *tsk, int run_callbacks)
4232{ 4232{
4233 int i;
4234 struct css_set *cg; 4233 struct css_set *cg;
4235 4234 int i;
4236 if (run_callbacks && need_forkexit_callback) {
4237 /*
4238 * modular subsystems can't use callbacks, so no need to lock
4239 * the subsys array
4240 */
4241 for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
4242 struct cgroup_subsys *ss = subsys[i];
4243 if (ss->exit)
4244 ss->exit(ss, tsk);
4245 }
4246 }
4247 4235
4248 /* 4236 /*
4249 * Unlink from the css_set task list if necessary. 4237 * Unlink from the css_set task list if necessary.
@@ -4261,7 +4249,24 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
4261 task_lock(tsk); 4249 task_lock(tsk);
4262 cg = tsk->cgroups; 4250 cg = tsk->cgroups;
4263 tsk->cgroups = &init_css_set; 4251 tsk->cgroups = &init_css_set;
4252
4253 if (run_callbacks && need_forkexit_callback) {
4254 /*
4255 * modular subsystems can't use callbacks, so no need to lock
4256 * the subsys array
4257 */
4258 for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
4259 struct cgroup_subsys *ss = subsys[i];
4260 if (ss->exit) {
4261 struct cgroup *old_cgrp =
4262 rcu_dereference_raw(cg->subsys[i])->cgroup;
4263 struct cgroup *cgrp = task_cgroup(tsk, i);
4264 ss->exit(ss, cgrp, old_cgrp, tsk);
4265 }
4266 }
4267 }
4264 task_unlock(tsk); 4268 task_unlock(tsk);
4269
4265 if (cg) 4270 if (cg)
4266 put_css_set_taskexit(cg); 4271 put_css_set_taskexit(cg);
4267} 4272}
@@ -4813,6 +4818,29 @@ css_get_next(struct cgroup_subsys *ss, int id,
4813 return ret; 4818 return ret;
4814} 4819}
4815 4820
4821/*
4822 * get corresponding css from file open on cgroupfs directory
4823 */
4824struct cgroup_subsys_state *cgroup_css_from_dir(struct file *f, int id)
4825{
4826 struct cgroup *cgrp;
4827 struct inode *inode;
4828 struct cgroup_subsys_state *css;
4829
4830 inode = f->f_dentry->d_inode;
4831 /* check in cgroup filesystem dir */
4832 if (inode->i_op != &cgroup_dir_inode_operations)
4833 return ERR_PTR(-EBADF);
4834
4835 if (id < 0 || id >= CGROUP_SUBSYS_COUNT)
4836 return ERR_PTR(-EINVAL);
4837
4838 /* get cgroup */
4839 cgrp = __d_cgrp(f->f_dentry);
4840 css = cgrp->subsys[id];
4841 return css ? css : ERR_PTR(-ENOENT);
4842}
4843
4816#ifdef CONFIG_CGROUP_DEBUG 4844#ifdef CONFIG_CGROUP_DEBUG
4817static struct cgroup_subsys_state *debug_create(struct cgroup_subsys *ss, 4845static struct cgroup_subsys_state *debug_create(struct cgroup_subsys *ss,
4818 struct cgroup *cont) 4846 struct cgroup *cont)
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 656222fcf767..ed253aa24ba4 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -38,13 +38,96 @@
38 38
39#include <asm/irq_regs.h> 39#include <asm/irq_regs.h>
40 40
41struct remote_function_call {
42 struct task_struct *p;
43 int (*func)(void *info);
44 void *info;
45 int ret;
46};
47
48static void remote_function(void *data)
49{
50 struct remote_function_call *tfc = data;
51 struct task_struct *p = tfc->p;
52
53 if (p) {
54 tfc->ret = -EAGAIN;
55 if (task_cpu(p) != smp_processor_id() || !task_curr(p))
56 return;
57 }
58
59 tfc->ret = tfc->func(tfc->info);
60}
61
62/**
63 * task_function_call - call a function on the cpu on which a task runs
64 * @p: the task to evaluate
65 * @func: the function to be called
66 * @info: the function call argument
67 *
68 * Calls the function @func when the task is currently running. This might
69 * be on the current CPU, which just calls the function directly
70 *
71 * returns: @func return value, or
72 * -ESRCH - when the process isn't running
73 * -EAGAIN - when the process moved away
74 */
75static int
76task_function_call(struct task_struct *p, int (*func) (void *info), void *info)
77{
78 struct remote_function_call data = {
79 .p = p,
80 .func = func,
81 .info = info,
82 .ret = -ESRCH, /* No such (running) process */
83 };
84
85 if (task_curr(p))
86 smp_call_function_single(task_cpu(p), remote_function, &data, 1);
87
88 return data.ret;
89}
90
91/**
92 * cpu_function_call - call a function on the cpu
93 * @func: the function to be called
94 * @info: the function call argument
95 *
96 * Calls the function @func on the remote cpu.
97 *
98 * returns: @func return value or -ENXIO when the cpu is offline
99 */
100static int cpu_function_call(int cpu, int (*func) (void *info), void *info)
101{
102 struct remote_function_call data = {
103 .p = NULL,
104 .func = func,
105 .info = info,
106 .ret = -ENXIO, /* No such CPU */
107 };
108
109 smp_call_function_single(cpu, remote_function, &data, 1);
110
111 return data.ret;
112}
113
114#define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\
115 PERF_FLAG_FD_OUTPUT |\
116 PERF_FLAG_PID_CGROUP)
117
41enum event_type_t { 118enum event_type_t {
42 EVENT_FLEXIBLE = 0x1, 119 EVENT_FLEXIBLE = 0x1,
43 EVENT_PINNED = 0x2, 120 EVENT_PINNED = 0x2,
44 EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED, 121 EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED,
45}; 122};
46 123
47atomic_t perf_task_events __read_mostly; 124/*
125 * perf_sched_events : >0 events exist
126 * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu
127 */
128atomic_t perf_sched_events __read_mostly;
129static DEFINE_PER_CPU(atomic_t, perf_cgroup_events);
130
48static atomic_t nr_mmap_events __read_mostly; 131static atomic_t nr_mmap_events __read_mostly;
49static atomic_t nr_comm_events __read_mostly; 132static atomic_t nr_comm_events __read_mostly;
50static atomic_t nr_task_events __read_mostly; 133static atomic_t nr_task_events __read_mostly;
@@ -67,7 +150,24 @@ int sysctl_perf_event_mlock __read_mostly = 512; /* 'free' kb per user */
67/* 150/*
68 * max perf event sample rate 151 * max perf event sample rate
69 */ 152 */
70int sysctl_perf_event_sample_rate __read_mostly = 100000; 153#define DEFAULT_MAX_SAMPLE_RATE 100000
154int sysctl_perf_event_sample_rate __read_mostly = DEFAULT_MAX_SAMPLE_RATE;
155static int max_samples_per_tick __read_mostly =
156 DIV_ROUND_UP(DEFAULT_MAX_SAMPLE_RATE, HZ);
157
158int perf_proc_update_handler(struct ctl_table *table, int write,
159 void __user *buffer, size_t *lenp,
160 loff_t *ppos)
161{
162 int ret = proc_dointvec(table, write, buffer, lenp, ppos);
163
164 if (ret || !write)
165 return ret;
166
167 max_samples_per_tick = DIV_ROUND_UP(sysctl_perf_event_sample_rate, HZ);
168
169 return 0;
170}
71 171
72static atomic64_t perf_event_id; 172static atomic64_t perf_event_id;
73 173
@@ -75,7 +175,11 @@ static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
75 enum event_type_t event_type); 175 enum event_type_t event_type);
76 176
77static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx, 177static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
78 enum event_type_t event_type); 178 enum event_type_t event_type,
179 struct task_struct *task);
180
181static void update_context_time(struct perf_event_context *ctx);
182static u64 perf_event_time(struct perf_event *event);
79 183
80void __weak perf_event_print_debug(void) { } 184void __weak perf_event_print_debug(void) { }
81 185
@@ -89,6 +193,360 @@ static inline u64 perf_clock(void)
89 return local_clock(); 193 return local_clock();
90} 194}
91 195
196static inline struct perf_cpu_context *
197__get_cpu_context(struct perf_event_context *ctx)
198{
199 return this_cpu_ptr(ctx->pmu->pmu_cpu_context);
200}
201
202#ifdef CONFIG_CGROUP_PERF
203
204/*
205 * Must ensure cgroup is pinned (css_get) before calling
206 * this function. In other words, we cannot call this function
207 * if there is no cgroup event for the current CPU context.
208 */
209static inline struct perf_cgroup *
210perf_cgroup_from_task(struct task_struct *task)
211{
212 return container_of(task_subsys_state(task, perf_subsys_id),
213 struct perf_cgroup, css);
214}
215
216static inline bool
217perf_cgroup_match(struct perf_event *event)
218{
219 struct perf_event_context *ctx = event->ctx;
220 struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
221
222 return !event->cgrp || event->cgrp == cpuctx->cgrp;
223}
224
225static inline void perf_get_cgroup(struct perf_event *event)
226{
227 css_get(&event->cgrp->css);
228}
229
230static inline void perf_put_cgroup(struct perf_event *event)
231{
232 css_put(&event->cgrp->css);
233}
234
235static inline void perf_detach_cgroup(struct perf_event *event)
236{
237 perf_put_cgroup(event);
238 event->cgrp = NULL;
239}
240
241static inline int is_cgroup_event(struct perf_event *event)
242{
243 return event->cgrp != NULL;
244}
245
246static inline u64 perf_cgroup_event_time(struct perf_event *event)
247{
248 struct perf_cgroup_info *t;
249
250 t = per_cpu_ptr(event->cgrp->info, event->cpu);
251 return t->time;
252}
253
254static inline void __update_cgrp_time(struct perf_cgroup *cgrp)
255{
256 struct perf_cgroup_info *info;
257 u64 now;
258
259 now = perf_clock();
260
261 info = this_cpu_ptr(cgrp->info);
262
263 info->time += now - info->timestamp;
264 info->timestamp = now;
265}
266
267static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx)
268{
269 struct perf_cgroup *cgrp_out = cpuctx->cgrp;
270 if (cgrp_out)
271 __update_cgrp_time(cgrp_out);
272}
273
274static inline void update_cgrp_time_from_event(struct perf_event *event)
275{
276 struct perf_cgroup *cgrp;
277
278 /*
279 * ensure we access cgroup data only when needed and
280 * when we know the cgroup is pinned (css_get)
281 */
282 if (!is_cgroup_event(event))
283 return;
284
285 cgrp = perf_cgroup_from_task(current);
286 /*
287 * Do not update time when cgroup is not active
288 */
289 if (cgrp == event->cgrp)
290 __update_cgrp_time(event->cgrp);
291}
292
293static inline void
294perf_cgroup_set_timestamp(struct task_struct *task,
295 struct perf_event_context *ctx)
296{
297 struct perf_cgroup *cgrp;
298 struct perf_cgroup_info *info;
299
300 /*
301 * ctx->lock held by caller
302 * ensure we do not access cgroup data
303 * unless we have the cgroup pinned (css_get)
304 */
305 if (!task || !ctx->nr_cgroups)
306 return;
307
308 cgrp = perf_cgroup_from_task(task);
309 info = this_cpu_ptr(cgrp->info);
310 info->timestamp = ctx->timestamp;
311}
312
313#define PERF_CGROUP_SWOUT 0x1 /* cgroup switch out every event */
314#define PERF_CGROUP_SWIN 0x2 /* cgroup switch in events based on task */
315
316/*
317 * reschedule events based on the cgroup constraint of task.
318 *
319 * mode SWOUT : schedule out everything
320 * mode SWIN : schedule in based on cgroup for next
321 */
322void perf_cgroup_switch(struct task_struct *task, int mode)
323{
324 struct perf_cpu_context *cpuctx;
325 struct pmu *pmu;
326 unsigned long flags;
327
328 /*
329 * disable interrupts to avoid geting nr_cgroup
330 * changes via __perf_event_disable(). Also
331 * avoids preemption.
332 */
333 local_irq_save(flags);
334
335 /*
336 * we reschedule only in the presence of cgroup
337 * constrained events.
338 */
339 rcu_read_lock();
340
341 list_for_each_entry_rcu(pmu, &pmus, entry) {
342
343 cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
344
345 perf_pmu_disable(cpuctx->ctx.pmu);
346
347 /*
348 * perf_cgroup_events says at least one
349 * context on this CPU has cgroup events.
350 *
351 * ctx->nr_cgroups reports the number of cgroup
352 * events for a context.
353 */
354 if (cpuctx->ctx.nr_cgroups > 0) {
355
356 if (mode & PERF_CGROUP_SWOUT) {
357 cpu_ctx_sched_out(cpuctx, EVENT_ALL);
358 /*
359 * must not be done before ctxswout due
360 * to event_filter_match() in event_sched_out()
361 */
362 cpuctx->cgrp = NULL;
363 }
364
365 if (mode & PERF_CGROUP_SWIN) {
366 /* set cgrp before ctxsw in to
367 * allow event_filter_match() to not
368 * have to pass task around
369 */
370 cpuctx->cgrp = perf_cgroup_from_task(task);
371 cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
372 }
373 }
374
375 perf_pmu_enable(cpuctx->ctx.pmu);
376 }
377
378 rcu_read_unlock();
379
380 local_irq_restore(flags);
381}
382
383static inline void perf_cgroup_sched_out(struct task_struct *task)
384{
385 perf_cgroup_switch(task, PERF_CGROUP_SWOUT);
386}
387
388static inline void perf_cgroup_sched_in(struct task_struct *task)
389{
390 perf_cgroup_switch(task, PERF_CGROUP_SWIN);
391}
392
393static inline int perf_cgroup_connect(int fd, struct perf_event *event,
394 struct perf_event_attr *attr,
395 struct perf_event *group_leader)
396{
397 struct perf_cgroup *cgrp;
398 struct cgroup_subsys_state *css;
399 struct file *file;
400 int ret = 0, fput_needed;
401
402 file = fget_light(fd, &fput_needed);
403 if (!file)
404 return -EBADF;
405
406 css = cgroup_css_from_dir(file, perf_subsys_id);
407 if (IS_ERR(css)) {
408 ret = PTR_ERR(css);
409 goto out;
410 }
411
412 cgrp = container_of(css, struct perf_cgroup, css);
413 event->cgrp = cgrp;
414
415 /* must be done before we fput() the file */
416 perf_get_cgroup(event);
417
418 /*
419 * all events in a group must monitor
420 * the same cgroup because a task belongs
421 * to only one perf cgroup at a time
422 */
423 if (group_leader && group_leader->cgrp != cgrp) {
424 perf_detach_cgroup(event);
425 ret = -EINVAL;
426 }
427out:
428 fput_light(file, fput_needed);
429 return ret;
430}
431
432static inline void
433perf_cgroup_set_shadow_time(struct perf_event *event, u64 now)
434{
435 struct perf_cgroup_info *t;
436 t = per_cpu_ptr(event->cgrp->info, event->cpu);
437 event->shadow_ctx_time = now - t->timestamp;
438}
439
440static inline void
441perf_cgroup_defer_enabled(struct perf_event *event)
442{
443 /*
444 * when the current task's perf cgroup does not match
445 * the event's, we need to remember to call the
446 * perf_mark_enable() function the first time a task with
447 * a matching perf cgroup is scheduled in.
448 */
449 if (is_cgroup_event(event) && !perf_cgroup_match(event))
450 event->cgrp_defer_enabled = 1;
451}
452
453static inline void
454perf_cgroup_mark_enabled(struct perf_event *event,
455 struct perf_event_context *ctx)
456{
457 struct perf_event *sub;
458 u64 tstamp = perf_event_time(event);
459
460 if (!event->cgrp_defer_enabled)
461 return;
462
463 event->cgrp_defer_enabled = 0;
464
465 event->tstamp_enabled = tstamp - event->total_time_enabled;
466 list_for_each_entry(sub, &event->sibling_list, group_entry) {
467 if (sub->state >= PERF_EVENT_STATE_INACTIVE) {
468 sub->tstamp_enabled = tstamp - sub->total_time_enabled;
469 sub->cgrp_defer_enabled = 0;
470 }
471 }
472}
473#else /* !CONFIG_CGROUP_PERF */
474
475static inline bool
476perf_cgroup_match(struct perf_event *event)
477{
478 return true;
479}
480
481static inline void perf_detach_cgroup(struct perf_event *event)
482{}
483
484static inline int is_cgroup_event(struct perf_event *event)
485{
486 return 0;
487}
488
489static inline u64 perf_cgroup_event_cgrp_time(struct perf_event *event)
490{
491 return 0;
492}
493
494static inline void update_cgrp_time_from_event(struct perf_event *event)
495{
496}
497
498static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx)
499{
500}
501
502static inline void perf_cgroup_sched_out(struct task_struct *task)
503{
504}
505
506static inline void perf_cgroup_sched_in(struct task_struct *task)
507{
508}
509
510static inline int perf_cgroup_connect(pid_t pid, struct perf_event *event,
511 struct perf_event_attr *attr,
512 struct perf_event *group_leader)
513{
514 return -EINVAL;
515}
516
517static inline void
518perf_cgroup_set_timestamp(struct task_struct *task,
519 struct perf_event_context *ctx)
520{
521}
522
523void
524perf_cgroup_switch(struct task_struct *task, struct task_struct *next)
525{
526}
527
528static inline void
529perf_cgroup_set_shadow_time(struct perf_event *event, u64 now)
530{
531}
532
533static inline u64 perf_cgroup_event_time(struct perf_event *event)
534{
535 return 0;
536}
537
538static inline void
539perf_cgroup_defer_enabled(struct perf_event *event)
540{
541}
542
543static inline void
544perf_cgroup_mark_enabled(struct perf_event *event,
545 struct perf_event_context *ctx)
546{
547}
548#endif
549
92void perf_pmu_disable(struct pmu *pmu) 550void perf_pmu_disable(struct pmu *pmu)
93{ 551{
94 int *count = this_cpu_ptr(pmu->pmu_disable_count); 552 int *count = this_cpu_ptr(pmu->pmu_disable_count);
@@ -254,7 +712,6 @@ static void perf_unpin_context(struct perf_event_context *ctx)
254 raw_spin_lock_irqsave(&ctx->lock, flags); 712 raw_spin_lock_irqsave(&ctx->lock, flags);
255 --ctx->pin_count; 713 --ctx->pin_count;
256 raw_spin_unlock_irqrestore(&ctx->lock, flags); 714 raw_spin_unlock_irqrestore(&ctx->lock, flags);
257 put_ctx(ctx);
258} 715}
259 716
260/* 717/*
@@ -271,6 +728,10 @@ static void update_context_time(struct perf_event_context *ctx)
271static u64 perf_event_time(struct perf_event *event) 728static u64 perf_event_time(struct perf_event *event)
272{ 729{
273 struct perf_event_context *ctx = event->ctx; 730 struct perf_event_context *ctx = event->ctx;
731
732 if (is_cgroup_event(event))
733 return perf_cgroup_event_time(event);
734
274 return ctx ? ctx->time : 0; 735 return ctx ? ctx->time : 0;
275} 736}
276 737
@@ -285,9 +746,20 @@ static void update_event_times(struct perf_event *event)
285 if (event->state < PERF_EVENT_STATE_INACTIVE || 746 if (event->state < PERF_EVENT_STATE_INACTIVE ||
286 event->group_leader->state < PERF_EVENT_STATE_INACTIVE) 747 event->group_leader->state < PERF_EVENT_STATE_INACTIVE)
287 return; 748 return;
288 749 /*
289 if (ctx->is_active) 750 * in cgroup mode, time_enabled represents
751 * the time the event was enabled AND active
752 * tasks were in the monitored cgroup. This is
753 * independent of the activity of the context as
754 * there may be a mix of cgroup and non-cgroup events.
755 *
756 * That is why we treat cgroup events differently
757 * here.
758 */
759 if (is_cgroup_event(event))
290 run_end = perf_event_time(event); 760 run_end = perf_event_time(event);
761 else if (ctx->is_active)
762 run_end = ctx->time;
291 else 763 else
292 run_end = event->tstamp_stopped; 764 run_end = event->tstamp_stopped;
293 765
@@ -299,6 +771,7 @@ static void update_event_times(struct perf_event *event)
299 run_end = perf_event_time(event); 771 run_end = perf_event_time(event);
300 772
301 event->total_time_running = run_end - event->tstamp_running; 773 event->total_time_running = run_end - event->tstamp_running;
774
302} 775}
303 776
304/* 777/*
@@ -347,6 +820,9 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
347 list_add_tail(&event->group_entry, list); 820 list_add_tail(&event->group_entry, list);
348 } 821 }
349 822
823 if (is_cgroup_event(event))
824 ctx->nr_cgroups++;
825
350 list_add_rcu(&event->event_entry, &ctx->event_list); 826 list_add_rcu(&event->event_entry, &ctx->event_list);
351 if (!ctx->nr_events) 827 if (!ctx->nr_events)
352 perf_pmu_rotate_start(ctx->pmu); 828 perf_pmu_rotate_start(ctx->pmu);
@@ -473,6 +949,9 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
473 949
474 event->attach_state &= ~PERF_ATTACH_CONTEXT; 950 event->attach_state &= ~PERF_ATTACH_CONTEXT;
475 951
952 if (is_cgroup_event(event))
953 ctx->nr_cgroups--;
954
476 ctx->nr_events--; 955 ctx->nr_events--;
477 if (event->attr.inherit_stat) 956 if (event->attr.inherit_stat)
478 ctx->nr_stat--; 957 ctx->nr_stat--;
@@ -544,7 +1023,8 @@ out:
544static inline int 1023static inline int
545event_filter_match(struct perf_event *event) 1024event_filter_match(struct perf_event *event)
546{ 1025{
547 return event->cpu == -1 || event->cpu == smp_processor_id(); 1026 return (event->cpu == -1 || event->cpu == smp_processor_id())
1027 && perf_cgroup_match(event);
548} 1028}
549 1029
550static void 1030static void
@@ -562,7 +1042,7 @@ event_sched_out(struct perf_event *event,
562 */ 1042 */
563 if (event->state == PERF_EVENT_STATE_INACTIVE 1043 if (event->state == PERF_EVENT_STATE_INACTIVE
564 && !event_filter_match(event)) { 1044 && !event_filter_match(event)) {
565 delta = ctx->time - event->tstamp_stopped; 1045 delta = tstamp - event->tstamp_stopped;
566 event->tstamp_running += delta; 1046 event->tstamp_running += delta;
567 event->tstamp_stopped = tstamp; 1047 event->tstamp_stopped = tstamp;
568 } 1048 }
@@ -606,47 +1086,30 @@ group_sched_out(struct perf_event *group_event,
606 cpuctx->exclusive = 0; 1086 cpuctx->exclusive = 0;
607} 1087}
608 1088
609static inline struct perf_cpu_context *
610__get_cpu_context(struct perf_event_context *ctx)
611{
612 return this_cpu_ptr(ctx->pmu->pmu_cpu_context);
613}
614
615/* 1089/*
616 * Cross CPU call to remove a performance event 1090 * Cross CPU call to remove a performance event
617 * 1091 *
618 * We disable the event on the hardware level first. After that we 1092 * We disable the event on the hardware level first. After that we
619 * remove it from the context list. 1093 * remove it from the context list.
620 */ 1094 */
621static void __perf_event_remove_from_context(void *info) 1095static int __perf_remove_from_context(void *info)
622{ 1096{
623 struct perf_event *event = info; 1097 struct perf_event *event = info;
624 struct perf_event_context *ctx = event->ctx; 1098 struct perf_event_context *ctx = event->ctx;
625 struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); 1099 struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
626 1100
627 /*
628 * If this is a task context, we need to check whether it is
629 * the current task context of this cpu. If not it has been
630 * scheduled out before the smp call arrived.
631 */
632 if (ctx->task && cpuctx->task_ctx != ctx)
633 return;
634
635 raw_spin_lock(&ctx->lock); 1101 raw_spin_lock(&ctx->lock);
636
637 event_sched_out(event, cpuctx, ctx); 1102 event_sched_out(event, cpuctx, ctx);
638
639 list_del_event(event, ctx); 1103 list_del_event(event, ctx);
640
641 raw_spin_unlock(&ctx->lock); 1104 raw_spin_unlock(&ctx->lock);
1105
1106 return 0;
642} 1107}
643 1108
644 1109
645/* 1110/*
646 * Remove the event from a task's (or a CPU's) list of events. 1111 * Remove the event from a task's (or a CPU's) list of events.
647 * 1112 *
648 * Must be called with ctx->mutex held.
649 *
650 * CPU events are removed with a smp call. For task events we only 1113 * CPU events are removed with a smp call. For task events we only
651 * call when the task is on a CPU. 1114 * call when the task is on a CPU.
652 * 1115 *
@@ -657,49 +1120,48 @@ static void __perf_event_remove_from_context(void *info)
657 * When called from perf_event_exit_task, it's OK because the 1120 * When called from perf_event_exit_task, it's OK because the
658 * context has been detached from its task. 1121 * context has been detached from its task.
659 */ 1122 */
660static void perf_event_remove_from_context(struct perf_event *event) 1123static void perf_remove_from_context(struct perf_event *event)
661{ 1124{
662 struct perf_event_context *ctx = event->ctx; 1125 struct perf_event_context *ctx = event->ctx;
663 struct task_struct *task = ctx->task; 1126 struct task_struct *task = ctx->task;
664 1127
1128 lockdep_assert_held(&ctx->mutex);
1129
665 if (!task) { 1130 if (!task) {
666 /* 1131 /*
667 * Per cpu events are removed via an smp call and 1132 * Per cpu events are removed via an smp call and
668 * the removal is always successful. 1133 * the removal is always successful.
669 */ 1134 */
670 smp_call_function_single(event->cpu, 1135 cpu_function_call(event->cpu, __perf_remove_from_context, event);
671 __perf_event_remove_from_context,
672 event, 1);
673 return; 1136 return;
674 } 1137 }
675 1138
676retry: 1139retry:
677 task_oncpu_function_call(task, __perf_event_remove_from_context, 1140 if (!task_function_call(task, __perf_remove_from_context, event))
678 event); 1141 return;
679 1142
680 raw_spin_lock_irq(&ctx->lock); 1143 raw_spin_lock_irq(&ctx->lock);
681 /* 1144 /*
682 * If the context is active we need to retry the smp call. 1145 * If we failed to find a running task, but find the context active now
1146 * that we've acquired the ctx->lock, retry.
683 */ 1147 */
684 if (ctx->nr_active && !list_empty(&event->group_entry)) { 1148 if (ctx->is_active) {
685 raw_spin_unlock_irq(&ctx->lock); 1149 raw_spin_unlock_irq(&ctx->lock);
686 goto retry; 1150 goto retry;
687 } 1151 }
688 1152
689 /* 1153 /*
690 * The lock prevents that this context is scheduled in so we 1154 * Since the task isn't running, its safe to remove the event, us
691 * can remove the event safely, if the call above did not 1155 * holding the ctx->lock ensures the task won't get scheduled in.
692 * succeed.
693 */ 1156 */
694 if (!list_empty(&event->group_entry)) 1157 list_del_event(event, ctx);
695 list_del_event(event, ctx);
696 raw_spin_unlock_irq(&ctx->lock); 1158 raw_spin_unlock_irq(&ctx->lock);
697} 1159}
698 1160
699/* 1161/*
700 * Cross CPU call to disable a performance event 1162 * Cross CPU call to disable a performance event
701 */ 1163 */
702static void __perf_event_disable(void *info) 1164static int __perf_event_disable(void *info)
703{ 1165{
704 struct perf_event *event = info; 1166 struct perf_event *event = info;
705 struct perf_event_context *ctx = event->ctx; 1167 struct perf_event_context *ctx = event->ctx;
@@ -708,9 +1170,12 @@ static void __perf_event_disable(void *info)
708 /* 1170 /*
709 * If this is a per-task event, need to check whether this 1171 * If this is a per-task event, need to check whether this
710 * event's task is the current task on this cpu. 1172 * event's task is the current task on this cpu.
1173 *
1174 * Can trigger due to concurrent perf_event_context_sched_out()
1175 * flipping contexts around.
711 */ 1176 */
712 if (ctx->task && cpuctx->task_ctx != ctx) 1177 if (ctx->task && cpuctx->task_ctx != ctx)
713 return; 1178 return -EINVAL;
714 1179
715 raw_spin_lock(&ctx->lock); 1180 raw_spin_lock(&ctx->lock);
716 1181
@@ -720,6 +1185,7 @@ static void __perf_event_disable(void *info)
720 */ 1185 */
721 if (event->state >= PERF_EVENT_STATE_INACTIVE) { 1186 if (event->state >= PERF_EVENT_STATE_INACTIVE) {
722 update_context_time(ctx); 1187 update_context_time(ctx);
1188 update_cgrp_time_from_event(event);
723 update_group_times(event); 1189 update_group_times(event);
724 if (event == event->group_leader) 1190 if (event == event->group_leader)
725 group_sched_out(event, cpuctx, ctx); 1191 group_sched_out(event, cpuctx, ctx);
@@ -729,6 +1195,8 @@ static void __perf_event_disable(void *info)
729 } 1195 }
730 1196
731 raw_spin_unlock(&ctx->lock); 1197 raw_spin_unlock(&ctx->lock);
1198
1199 return 0;
732} 1200}
733 1201
734/* 1202/*
@@ -753,13 +1221,13 @@ void perf_event_disable(struct perf_event *event)
753 /* 1221 /*
754 * Disable the event on the cpu that it's on 1222 * Disable the event on the cpu that it's on
755 */ 1223 */
756 smp_call_function_single(event->cpu, __perf_event_disable, 1224 cpu_function_call(event->cpu, __perf_event_disable, event);
757 event, 1);
758 return; 1225 return;
759 } 1226 }
760 1227
761retry: 1228retry:
762 task_oncpu_function_call(task, __perf_event_disable, event); 1229 if (!task_function_call(task, __perf_event_disable, event))
1230 return;
763 1231
764 raw_spin_lock_irq(&ctx->lock); 1232 raw_spin_lock_irq(&ctx->lock);
765 /* 1233 /*
@@ -767,6 +1235,11 @@ retry:
767 */ 1235 */
768 if (event->state == PERF_EVENT_STATE_ACTIVE) { 1236 if (event->state == PERF_EVENT_STATE_ACTIVE) {
769 raw_spin_unlock_irq(&ctx->lock); 1237 raw_spin_unlock_irq(&ctx->lock);
1238 /*
1239 * Reload the task pointer, it might have been changed by
1240 * a concurrent perf_event_context_sched_out().
1241 */
1242 task = ctx->task;
770 goto retry; 1243 goto retry;
771 } 1244 }
772 1245
@@ -778,10 +1251,44 @@ retry:
778 update_group_times(event); 1251 update_group_times(event);
779 event->state = PERF_EVENT_STATE_OFF; 1252 event->state = PERF_EVENT_STATE_OFF;
780 } 1253 }
781
782 raw_spin_unlock_irq(&ctx->lock); 1254 raw_spin_unlock_irq(&ctx->lock);
783} 1255}
784 1256
1257static void perf_set_shadow_time(struct perf_event *event,
1258 struct perf_event_context *ctx,
1259 u64 tstamp)
1260{
1261 /*
1262 * use the correct time source for the time snapshot
1263 *
1264 * We could get by without this by leveraging the
1265 * fact that to get to this function, the caller
1266 * has most likely already called update_context_time()
1267 * and update_cgrp_time_xx() and thus both timestamp
1268 * are identical (or very close). Given that tstamp is,
1269 * already adjusted for cgroup, we could say that:
1270 * tstamp - ctx->timestamp
1271 * is equivalent to
1272 * tstamp - cgrp->timestamp.
1273 *
1274 * Then, in perf_output_read(), the calculation would
1275 * work with no changes because:
1276 * - event is guaranteed scheduled in
1277 * - no scheduled out in between
1278 * - thus the timestamp would be the same
1279 *
1280 * But this is a bit hairy.
1281 *
1282 * So instead, we have an explicit cgroup call to remain
1283 * within the time time source all along. We believe it
1284 * is cleaner and simpler to understand.
1285 */
1286 if (is_cgroup_event(event))
1287 perf_cgroup_set_shadow_time(event, tstamp);
1288 else
1289 event->shadow_ctx_time = tstamp - ctx->timestamp;
1290}
1291
785#define MAX_INTERRUPTS (~0ULL) 1292#define MAX_INTERRUPTS (~0ULL)
786 1293
787static void perf_log_throttle(struct perf_event *event, int enable); 1294static void perf_log_throttle(struct perf_event *event, int enable);
@@ -822,7 +1329,7 @@ event_sched_in(struct perf_event *event,
822 1329
823 event->tstamp_running += tstamp - event->tstamp_stopped; 1330 event->tstamp_running += tstamp - event->tstamp_stopped;
824 1331
825 event->shadow_ctx_time = tstamp - ctx->timestamp; 1332 perf_set_shadow_time(event, ctx, tstamp);
826 1333
827 if (!is_software_event(event)) 1334 if (!is_software_event(event))
828 cpuctx->active_oncpu++; 1335 cpuctx->active_oncpu++;
@@ -943,12 +1450,15 @@ static void add_event_to_ctx(struct perf_event *event,
943 event->tstamp_stopped = tstamp; 1450 event->tstamp_stopped = tstamp;
944} 1451}
945 1452
1453static void perf_event_context_sched_in(struct perf_event_context *ctx,
1454 struct task_struct *tsk);
1455
946/* 1456/*
947 * Cross CPU call to install and enable a performance event 1457 * Cross CPU call to install and enable a performance event
948 * 1458 *
949 * Must be called with ctx->mutex held 1459 * Must be called with ctx->mutex held
950 */ 1460 */
951static void __perf_install_in_context(void *info) 1461static int __perf_install_in_context(void *info)
952{ 1462{
953 struct perf_event *event = info; 1463 struct perf_event *event = info;
954 struct perf_event_context *ctx = event->ctx; 1464 struct perf_event_context *ctx = event->ctx;
@@ -957,21 +1467,22 @@ static void __perf_install_in_context(void *info)
957 int err; 1467 int err;
958 1468
959 /* 1469 /*
960 * If this is a task context, we need to check whether it is 1470 * In case we're installing a new context to an already running task,
961 * the current task context of this cpu. If not it has been 1471 * could also happen before perf_event_task_sched_in() on architectures
962 * scheduled out before the smp call arrived. 1472 * which do context switches with IRQs enabled.
963 * Or possibly this is the right context but it isn't
964 * on this cpu because it had no events.
965 */ 1473 */
966 if (ctx->task && cpuctx->task_ctx != ctx) { 1474 if (ctx->task && !cpuctx->task_ctx)
967 if (cpuctx->task_ctx || ctx->task != current) 1475 perf_event_context_sched_in(ctx, ctx->task);
968 return;
969 cpuctx->task_ctx = ctx;
970 }
971 1476
972 raw_spin_lock(&ctx->lock); 1477 raw_spin_lock(&ctx->lock);
973 ctx->is_active = 1; 1478 ctx->is_active = 1;
974 update_context_time(ctx); 1479 update_context_time(ctx);
1480 /*
1481 * update cgrp time only if current cgrp
1482 * matches event->cgrp. Must be done before
1483 * calling add_event_to_ctx()
1484 */
1485 update_cgrp_time_from_event(event);
975 1486
976 add_event_to_ctx(event, ctx); 1487 add_event_to_ctx(event, ctx);
977 1488
@@ -1012,6 +1523,8 @@ static void __perf_install_in_context(void *info)
1012 1523
1013unlock: 1524unlock:
1014 raw_spin_unlock(&ctx->lock); 1525 raw_spin_unlock(&ctx->lock);
1526
1527 return 0;
1015} 1528}
1016 1529
1017/* 1530/*
@@ -1023,8 +1536,6 @@ unlock:
1023 * If the event is attached to a task which is on a CPU we use a smp 1536 * If the event is attached to a task which is on a CPU we use a smp
1024 * call to enable it in the task context. The task might have been 1537 * call to enable it in the task context. The task might have been
1025 * scheduled away, but we check this in the smp call again. 1538 * scheduled away, but we check this in the smp call again.
1026 *
1027 * Must be called with ctx->mutex held.
1028 */ 1539 */
1029static void 1540static void
1030perf_install_in_context(struct perf_event_context *ctx, 1541perf_install_in_context(struct perf_event_context *ctx,
@@ -1033,6 +1544,8 @@ perf_install_in_context(struct perf_event_context *ctx,
1033{ 1544{
1034 struct task_struct *task = ctx->task; 1545 struct task_struct *task = ctx->task;
1035 1546
1547 lockdep_assert_held(&ctx->mutex);
1548
1036 event->ctx = ctx; 1549 event->ctx = ctx;
1037 1550
1038 if (!task) { 1551 if (!task) {
@@ -1040,31 +1553,29 @@ perf_install_in_context(struct perf_event_context *ctx,
1040 * Per cpu events are installed via an smp call and 1553 * Per cpu events are installed via an smp call and
1041 * the install is always successful. 1554 * the install is always successful.
1042 */ 1555 */
1043 smp_call_function_single(cpu, __perf_install_in_context, 1556 cpu_function_call(cpu, __perf_install_in_context, event);
1044 event, 1);
1045 return; 1557 return;
1046 } 1558 }
1047 1559
1048retry: 1560retry:
1049 task_oncpu_function_call(task, __perf_install_in_context, 1561 if (!task_function_call(task, __perf_install_in_context, event))
1050 event); 1562 return;
1051 1563
1052 raw_spin_lock_irq(&ctx->lock); 1564 raw_spin_lock_irq(&ctx->lock);
1053 /* 1565 /*
1054 * we need to retry the smp call. 1566 * If we failed to find a running task, but find the context active now
1567 * that we've acquired the ctx->lock, retry.
1055 */ 1568 */
1056 if (ctx->is_active && list_empty(&event->group_entry)) { 1569 if (ctx->is_active) {
1057 raw_spin_unlock_irq(&ctx->lock); 1570 raw_spin_unlock_irq(&ctx->lock);
1058 goto retry; 1571 goto retry;
1059 } 1572 }
1060 1573
1061 /* 1574 /*
1062 * The lock prevents that this context is scheduled in so we 1575 * Since the task isn't running, its safe to add the event, us holding
1063 * can add the event safely, if it the call above did not 1576 * the ctx->lock ensures the task won't get scheduled in.
1064 * succeed.
1065 */ 1577 */
1066 if (list_empty(&event->group_entry)) 1578 add_event_to_ctx(event, ctx);
1067 add_event_to_ctx(event, ctx);
1068 raw_spin_unlock_irq(&ctx->lock); 1579 raw_spin_unlock_irq(&ctx->lock);
1069} 1580}
1070 1581
@@ -1093,7 +1604,7 @@ static void __perf_event_mark_enabled(struct perf_event *event,
1093/* 1604/*
1094 * Cross CPU call to enable a performance event 1605 * Cross CPU call to enable a performance event
1095 */ 1606 */
1096static void __perf_event_enable(void *info) 1607static int __perf_event_enable(void *info)
1097{ 1608{
1098 struct perf_event *event = info; 1609 struct perf_event *event = info;
1099 struct perf_event_context *ctx = event->ctx; 1610 struct perf_event_context *ctx = event->ctx;
@@ -1101,26 +1612,27 @@ static void __perf_event_enable(void *info)
1101 struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); 1612 struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
1102 int err; 1613 int err;
1103 1614
1104 /* 1615 if (WARN_ON_ONCE(!ctx->is_active))
1105 * If this is a per-task event, need to check whether this 1616 return -EINVAL;
1106 * event's task is the current task on this cpu.
1107 */
1108 if (ctx->task && cpuctx->task_ctx != ctx) {
1109 if (cpuctx->task_ctx || ctx->task != current)
1110 return;
1111 cpuctx->task_ctx = ctx;
1112 }
1113 1617
1114 raw_spin_lock(&ctx->lock); 1618 raw_spin_lock(&ctx->lock);
1115 ctx->is_active = 1;
1116 update_context_time(ctx); 1619 update_context_time(ctx);
1117 1620
1118 if (event->state >= PERF_EVENT_STATE_INACTIVE) 1621 if (event->state >= PERF_EVENT_STATE_INACTIVE)
1119 goto unlock; 1622 goto unlock;
1623
1624 /*
1625 * set current task's cgroup time reference point
1626 */
1627 perf_cgroup_set_timestamp(current, ctx);
1628
1120 __perf_event_mark_enabled(event, ctx); 1629 __perf_event_mark_enabled(event, ctx);
1121 1630
1122 if (!event_filter_match(event)) 1631 if (!event_filter_match(event)) {
1632 if (is_cgroup_event(event))
1633 perf_cgroup_defer_enabled(event);
1123 goto unlock; 1634 goto unlock;
1635 }
1124 1636
1125 /* 1637 /*
1126 * If the event is in a group and isn't the group leader, 1638 * If the event is in a group and isn't the group leader,
@@ -1153,6 +1665,8 @@ static void __perf_event_enable(void *info)
1153 1665
1154unlock: 1666unlock:
1155 raw_spin_unlock(&ctx->lock); 1667 raw_spin_unlock(&ctx->lock);
1668
1669 return 0;
1156} 1670}
1157 1671
1158/* 1672/*
@@ -1173,8 +1687,7 @@ void perf_event_enable(struct perf_event *event)
1173 /* 1687 /*
1174 * Enable the event on the cpu that it's on 1688 * Enable the event on the cpu that it's on
1175 */ 1689 */
1176 smp_call_function_single(event->cpu, __perf_event_enable, 1690 cpu_function_call(event->cpu, __perf_event_enable, event);
1177 event, 1);
1178 return; 1691 return;
1179 } 1692 }
1180 1693
@@ -1193,8 +1706,15 @@ void perf_event_enable(struct perf_event *event)
1193 event->state = PERF_EVENT_STATE_OFF; 1706 event->state = PERF_EVENT_STATE_OFF;
1194 1707
1195retry: 1708retry:
1709 if (!ctx->is_active) {
1710 __perf_event_mark_enabled(event, ctx);
1711 goto out;
1712 }
1713
1196 raw_spin_unlock_irq(&ctx->lock); 1714 raw_spin_unlock_irq(&ctx->lock);
1197 task_oncpu_function_call(task, __perf_event_enable, event); 1715
1716 if (!task_function_call(task, __perf_event_enable, event))
1717 return;
1198 1718
1199 raw_spin_lock_irq(&ctx->lock); 1719 raw_spin_lock_irq(&ctx->lock);
1200 1720
@@ -1202,15 +1722,14 @@ retry:
1202 * If the context is active and the event is still off, 1722 * If the context is active and the event is still off,
1203 * we need to retry the cross-call. 1723 * we need to retry the cross-call.
1204 */ 1724 */
1205 if (ctx->is_active && event->state == PERF_EVENT_STATE_OFF) 1725 if (ctx->is_active && event->state == PERF_EVENT_STATE_OFF) {
1726 /*
1727 * task could have been flipped by a concurrent
1728 * perf_event_context_sched_out()
1729 */
1730 task = ctx->task;
1206 goto retry; 1731 goto retry;
1207 1732 }
1208 /*
1209 * Since we have the lock this context can't be scheduled
1210 * in, so we can change the state safely.
1211 */
1212 if (event->state == PERF_EVENT_STATE_OFF)
1213 __perf_event_mark_enabled(event, ctx);
1214 1733
1215out: 1734out:
1216 raw_spin_unlock_irq(&ctx->lock); 1735 raw_spin_unlock_irq(&ctx->lock);
@@ -1242,6 +1761,7 @@ static void ctx_sched_out(struct perf_event_context *ctx,
1242 if (likely(!ctx->nr_events)) 1761 if (likely(!ctx->nr_events))
1243 goto out; 1762 goto out;
1244 update_context_time(ctx); 1763 update_context_time(ctx);
1764 update_cgrp_time_from_cpuctx(cpuctx);
1245 1765
1246 if (!ctx->nr_active) 1766 if (!ctx->nr_active)
1247 goto out; 1767 goto out;
@@ -1354,8 +1874,8 @@ static void perf_event_sync_stat(struct perf_event_context *ctx,
1354 } 1874 }
1355} 1875}
1356 1876
1357void perf_event_context_sched_out(struct task_struct *task, int ctxn, 1877static void perf_event_context_sched_out(struct task_struct *task, int ctxn,
1358 struct task_struct *next) 1878 struct task_struct *next)
1359{ 1879{
1360 struct perf_event_context *ctx = task->perf_event_ctxp[ctxn]; 1880 struct perf_event_context *ctx = task->perf_event_ctxp[ctxn];
1361 struct perf_event_context *next_ctx; 1881 struct perf_event_context *next_ctx;
@@ -1431,6 +1951,14 @@ void __perf_event_task_sched_out(struct task_struct *task,
1431 1951
1432 for_each_task_context_nr(ctxn) 1952 for_each_task_context_nr(ctxn)
1433 perf_event_context_sched_out(task, ctxn, next); 1953 perf_event_context_sched_out(task, ctxn, next);
1954
1955 /*
1956 * if cgroup events exist on this CPU, then we need
1957 * to check if we have to switch out PMU state.
1958 * cgroup event are system-wide mode only
1959 */
1960 if (atomic_read(&__get_cpu_var(perf_cgroup_events)))
1961 perf_cgroup_sched_out(task);
1434} 1962}
1435 1963
1436static void task_ctx_sched_out(struct perf_event_context *ctx, 1964static void task_ctx_sched_out(struct perf_event_context *ctx,
@@ -1469,6 +1997,10 @@ ctx_pinned_sched_in(struct perf_event_context *ctx,
1469 if (!event_filter_match(event)) 1997 if (!event_filter_match(event))
1470 continue; 1998 continue;
1471 1999
2000 /* may need to reset tstamp_enabled */
2001 if (is_cgroup_event(event))
2002 perf_cgroup_mark_enabled(event, ctx);
2003
1472 if (group_can_go_on(event, cpuctx, 1)) 2004 if (group_can_go_on(event, cpuctx, 1))
1473 group_sched_in(event, cpuctx, ctx); 2005 group_sched_in(event, cpuctx, ctx);
1474 2006
@@ -1501,6 +2033,10 @@ ctx_flexible_sched_in(struct perf_event_context *ctx,
1501 if (!event_filter_match(event)) 2033 if (!event_filter_match(event))
1502 continue; 2034 continue;
1503 2035
2036 /* may need to reset tstamp_enabled */
2037 if (is_cgroup_event(event))
2038 perf_cgroup_mark_enabled(event, ctx);
2039
1504 if (group_can_go_on(event, cpuctx, can_add_hw)) { 2040 if (group_can_go_on(event, cpuctx, can_add_hw)) {
1505 if (group_sched_in(event, cpuctx, ctx)) 2041 if (group_sched_in(event, cpuctx, ctx))
1506 can_add_hw = 0; 2042 can_add_hw = 0;
@@ -1511,15 +2047,19 @@ ctx_flexible_sched_in(struct perf_event_context *ctx,
1511static void 2047static void
1512ctx_sched_in(struct perf_event_context *ctx, 2048ctx_sched_in(struct perf_event_context *ctx,
1513 struct perf_cpu_context *cpuctx, 2049 struct perf_cpu_context *cpuctx,
1514 enum event_type_t event_type) 2050 enum event_type_t event_type,
2051 struct task_struct *task)
1515{ 2052{
2053 u64 now;
2054
1516 raw_spin_lock(&ctx->lock); 2055 raw_spin_lock(&ctx->lock);
1517 ctx->is_active = 1; 2056 ctx->is_active = 1;
1518 if (likely(!ctx->nr_events)) 2057 if (likely(!ctx->nr_events))
1519 goto out; 2058 goto out;
1520 2059
1521 ctx->timestamp = perf_clock(); 2060 now = perf_clock();
1522 2061 ctx->timestamp = now;
2062 perf_cgroup_set_timestamp(task, ctx);
1523 /* 2063 /*
1524 * First go through the list and put on any pinned groups 2064 * First go through the list and put on any pinned groups
1525 * in order to give them the best chance of going on. 2065 * in order to give them the best chance of going on.
@@ -1536,11 +2076,12 @@ out:
1536} 2076}
1537 2077
1538static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx, 2078static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
1539 enum event_type_t event_type) 2079 enum event_type_t event_type,
2080 struct task_struct *task)
1540{ 2081{
1541 struct perf_event_context *ctx = &cpuctx->ctx; 2082 struct perf_event_context *ctx = &cpuctx->ctx;
1542 2083
1543 ctx_sched_in(ctx, cpuctx, event_type); 2084 ctx_sched_in(ctx, cpuctx, event_type, task);
1544} 2085}
1545 2086
1546static void task_ctx_sched_in(struct perf_event_context *ctx, 2087static void task_ctx_sched_in(struct perf_event_context *ctx,
@@ -1548,15 +2089,16 @@ static void task_ctx_sched_in(struct perf_event_context *ctx,
1548{ 2089{
1549 struct perf_cpu_context *cpuctx; 2090 struct perf_cpu_context *cpuctx;
1550 2091
1551 cpuctx = __get_cpu_context(ctx); 2092 cpuctx = __get_cpu_context(ctx);
1552 if (cpuctx->task_ctx == ctx) 2093 if (cpuctx->task_ctx == ctx)
1553 return; 2094 return;
1554 2095
1555 ctx_sched_in(ctx, cpuctx, event_type); 2096 ctx_sched_in(ctx, cpuctx, event_type, NULL);
1556 cpuctx->task_ctx = ctx; 2097 cpuctx->task_ctx = ctx;
1557} 2098}
1558 2099
1559void perf_event_context_sched_in(struct perf_event_context *ctx) 2100static void perf_event_context_sched_in(struct perf_event_context *ctx,
2101 struct task_struct *task)
1560{ 2102{
1561 struct perf_cpu_context *cpuctx; 2103 struct perf_cpu_context *cpuctx;
1562 2104
@@ -1572,9 +2114,9 @@ void perf_event_context_sched_in(struct perf_event_context *ctx)
1572 */ 2114 */
1573 cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); 2115 cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
1574 2116
1575 ctx_sched_in(ctx, cpuctx, EVENT_PINNED); 2117 ctx_sched_in(ctx, cpuctx, EVENT_PINNED, task);
1576 cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE); 2118 cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE, task);
1577 ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE); 2119 ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE, task);
1578 2120
1579 cpuctx->task_ctx = ctx; 2121 cpuctx->task_ctx = ctx;
1580 2122
@@ -1607,8 +2149,15 @@ void __perf_event_task_sched_in(struct task_struct *task)
1607 if (likely(!ctx)) 2149 if (likely(!ctx))
1608 continue; 2150 continue;
1609 2151
1610 perf_event_context_sched_in(ctx); 2152 perf_event_context_sched_in(ctx, task);
1611 } 2153 }
2154 /*
2155 * if cgroup events exist on this CPU, then we need
2156 * to check if we have to switch in PMU state.
2157 * cgroup event are system-wide mode only
2158 */
2159 if (atomic_read(&__get_cpu_var(perf_cgroup_events)))
2160 perf_cgroup_sched_in(task);
1612} 2161}
1613 2162
1614static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count) 2163static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count)
@@ -1638,7 +2187,7 @@ static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count)
1638 * Reduce accuracy by one bit such that @a and @b converge 2187 * Reduce accuracy by one bit such that @a and @b converge
1639 * to a similar magnitude. 2188 * to a similar magnitude.
1640 */ 2189 */
1641#define REDUCE_FLS(a, b) \ 2190#define REDUCE_FLS(a, b) \
1642do { \ 2191do { \
1643 if (a##_fls > b##_fls) { \ 2192 if (a##_fls > b##_fls) { \
1644 a >>= 1; \ 2193 a >>= 1; \
@@ -1808,7 +2357,7 @@ static void perf_rotate_context(struct perf_cpu_context *cpuctx)
1808 if (ctx) 2357 if (ctx)
1809 rotate_ctx(ctx); 2358 rotate_ctx(ctx);
1810 2359
1811 cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE); 2360 cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE, current);
1812 if (ctx) 2361 if (ctx)
1813 task_ctx_sched_in(ctx, EVENT_FLEXIBLE); 2362 task_ctx_sched_in(ctx, EVENT_FLEXIBLE);
1814 2363
@@ -1887,7 +2436,7 @@ static void perf_event_enable_on_exec(struct perf_event_context *ctx)
1887 2436
1888 raw_spin_unlock(&ctx->lock); 2437 raw_spin_unlock(&ctx->lock);
1889 2438
1890 perf_event_context_sched_in(ctx); 2439 perf_event_context_sched_in(ctx, ctx->task);
1891out: 2440out:
1892 local_irq_restore(flags); 2441 local_irq_restore(flags);
1893} 2442}
@@ -1912,8 +2461,10 @@ static void __perf_event_read(void *info)
1912 return; 2461 return;
1913 2462
1914 raw_spin_lock(&ctx->lock); 2463 raw_spin_lock(&ctx->lock);
1915 if (ctx->is_active) 2464 if (ctx->is_active) {
1916 update_context_time(ctx); 2465 update_context_time(ctx);
2466 update_cgrp_time_from_event(event);
2467 }
1917 update_event_times(event); 2468 update_event_times(event);
1918 if (event->state == PERF_EVENT_STATE_ACTIVE) 2469 if (event->state == PERF_EVENT_STATE_ACTIVE)
1919 event->pmu->read(event); 2470 event->pmu->read(event);
@@ -1944,8 +2495,10 @@ static u64 perf_event_read(struct perf_event *event)
1944 * (e.g., thread is blocked), in that case 2495 * (e.g., thread is blocked), in that case
1945 * we cannot update context time 2496 * we cannot update context time
1946 */ 2497 */
1947 if (ctx->is_active) 2498 if (ctx->is_active) {
1948 update_context_time(ctx); 2499 update_context_time(ctx);
2500 update_cgrp_time_from_event(event);
2501 }
1949 update_event_times(event); 2502 update_event_times(event);
1950 raw_spin_unlock_irqrestore(&ctx->lock, flags); 2503 raw_spin_unlock_irqrestore(&ctx->lock, flags);
1951 } 2504 }
@@ -2224,6 +2777,9 @@ errout:
2224 2777
2225} 2778}
2226 2779
2780/*
2781 * Returns a matching context with refcount and pincount.
2782 */
2227static struct perf_event_context * 2783static struct perf_event_context *
2228find_get_context(struct pmu *pmu, struct task_struct *task, int cpu) 2784find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
2229{ 2785{
@@ -2248,6 +2804,7 @@ find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
2248 cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); 2804 cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
2249 ctx = &cpuctx->ctx; 2805 ctx = &cpuctx->ctx;
2250 get_ctx(ctx); 2806 get_ctx(ctx);
2807 ++ctx->pin_count;
2251 2808
2252 return ctx; 2809 return ctx;
2253 } 2810 }
@@ -2261,6 +2818,7 @@ retry:
2261 ctx = perf_lock_task_context(task, ctxn, &flags); 2818 ctx = perf_lock_task_context(task, ctxn, &flags);
2262 if (ctx) { 2819 if (ctx) {
2263 unclone_ctx(ctx); 2820 unclone_ctx(ctx);
2821 ++ctx->pin_count;
2264 raw_spin_unlock_irqrestore(&ctx->lock, flags); 2822 raw_spin_unlock_irqrestore(&ctx->lock, flags);
2265 } 2823 }
2266 2824
@@ -2282,8 +2840,10 @@ retry:
2282 err = -ESRCH; 2840 err = -ESRCH;
2283 else if (task->perf_event_ctxp[ctxn]) 2841 else if (task->perf_event_ctxp[ctxn])
2284 err = -EAGAIN; 2842 err = -EAGAIN;
2285 else 2843 else {
2844 ++ctx->pin_count;
2286 rcu_assign_pointer(task->perf_event_ctxp[ctxn], ctx); 2845 rcu_assign_pointer(task->perf_event_ctxp[ctxn], ctx);
2846 }
2287 mutex_unlock(&task->perf_event_mutex); 2847 mutex_unlock(&task->perf_event_mutex);
2288 2848
2289 if (unlikely(err)) { 2849 if (unlikely(err)) {
@@ -2323,7 +2883,7 @@ static void free_event(struct perf_event *event)
2323 2883
2324 if (!event->parent) { 2884 if (!event->parent) {
2325 if (event->attach_state & PERF_ATTACH_TASK) 2885 if (event->attach_state & PERF_ATTACH_TASK)
2326 jump_label_dec(&perf_task_events); 2886 jump_label_dec(&perf_sched_events);
2327 if (event->attr.mmap || event->attr.mmap_data) 2887 if (event->attr.mmap || event->attr.mmap_data)
2328 atomic_dec(&nr_mmap_events); 2888 atomic_dec(&nr_mmap_events);
2329 if (event->attr.comm) 2889 if (event->attr.comm)
@@ -2332,6 +2892,10 @@ static void free_event(struct perf_event *event)
2332 atomic_dec(&nr_task_events); 2892 atomic_dec(&nr_task_events);
2333 if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) 2893 if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
2334 put_callchain_buffers(); 2894 put_callchain_buffers();
2895 if (is_cgroup_event(event)) {
2896 atomic_dec(&per_cpu(perf_cgroup_events, event->cpu));
2897 jump_label_dec(&perf_sched_events);
2898 }
2335 } 2899 }
2336 2900
2337 if (event->buffer) { 2901 if (event->buffer) {
@@ -2339,6 +2903,9 @@ static void free_event(struct perf_event *event)
2339 event->buffer = NULL; 2903 event->buffer = NULL;
2340 } 2904 }
2341 2905
2906 if (is_cgroup_event(event))
2907 perf_detach_cgroup(event);
2908
2342 if (event->destroy) 2909 if (event->destroy)
2343 event->destroy(event); 2910 event->destroy(event);
2344 2911
@@ -4406,26 +4973,14 @@ static int __perf_event_overflow(struct perf_event *event, int nmi,
4406 if (unlikely(!is_sampling_event(event))) 4973 if (unlikely(!is_sampling_event(event)))
4407 return 0; 4974 return 0;
4408 4975
4409 if (!throttle) { 4976 if (unlikely(hwc->interrupts >= max_samples_per_tick)) {
4410 hwc->interrupts++; 4977 if (throttle) {
4411 } else { 4978 hwc->interrupts = MAX_INTERRUPTS;
4412 if (hwc->interrupts != MAX_INTERRUPTS) { 4979 perf_log_throttle(event, 0);
4413 hwc->interrupts++;
4414 if (HZ * hwc->interrupts >
4415 (u64)sysctl_perf_event_sample_rate) {
4416 hwc->interrupts = MAX_INTERRUPTS;
4417 perf_log_throttle(event, 0);
4418 ret = 1;
4419 }
4420 } else {
4421 /*
4422 * Keep re-disabling events even though on the previous
4423 * pass we disabled it - just in case we raced with a
4424 * sched-in and the event got enabled again:
4425 */
4426 ret = 1; 4980 ret = 1;
4427 } 4981 }
4428 } 4982 } else
4983 hwc->interrupts++;
4429 4984
4430 if (event->attr.freq) { 4985 if (event->attr.freq) {
4431 u64 now = perf_clock(); 4986 u64 now = perf_clock();
@@ -5062,6 +5617,10 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
5062 u64 period; 5617 u64 period;
5063 5618
5064 event = container_of(hrtimer, struct perf_event, hw.hrtimer); 5619 event = container_of(hrtimer, struct perf_event, hw.hrtimer);
5620
5621 if (event->state != PERF_EVENT_STATE_ACTIVE)
5622 return HRTIMER_NORESTART;
5623
5065 event->pmu->read(event); 5624 event->pmu->read(event);
5066 5625
5067 perf_sample_data_init(&data, 0); 5626 perf_sample_data_init(&data, 0);
@@ -5088,9 +5647,6 @@ static void perf_swevent_start_hrtimer(struct perf_event *event)
5088 if (!is_sampling_event(event)) 5647 if (!is_sampling_event(event))
5089 return; 5648 return;
5090 5649
5091 hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
5092 hwc->hrtimer.function = perf_swevent_hrtimer;
5093
5094 period = local64_read(&hwc->period_left); 5650 period = local64_read(&hwc->period_left);
5095 if (period) { 5651 if (period) {
5096 if (period < 0) 5652 if (period < 0)
@@ -5117,6 +5673,30 @@ static void perf_swevent_cancel_hrtimer(struct perf_event *event)
5117 } 5673 }
5118} 5674}
5119 5675
5676static void perf_swevent_init_hrtimer(struct perf_event *event)
5677{
5678 struct hw_perf_event *hwc = &event->hw;
5679
5680 if (!is_sampling_event(event))
5681 return;
5682
5683 hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
5684 hwc->hrtimer.function = perf_swevent_hrtimer;
5685
5686 /*
5687 * Since hrtimers have a fixed rate, we can do a static freq->period
5688 * mapping and avoid the whole period adjust feedback stuff.
5689 */
5690 if (event->attr.freq) {
5691 long freq = event->attr.sample_freq;
5692
5693 event->attr.sample_period = NSEC_PER_SEC / freq;
5694 hwc->sample_period = event->attr.sample_period;
5695 local64_set(&hwc->period_left, hwc->sample_period);
5696 event->attr.freq = 0;
5697 }
5698}
5699
5120/* 5700/*
5121 * Software event: cpu wall time clock 5701 * Software event: cpu wall time clock
5122 */ 5702 */
@@ -5169,6 +5749,8 @@ static int cpu_clock_event_init(struct perf_event *event)
5169 if (event->attr.config != PERF_COUNT_SW_CPU_CLOCK) 5749 if (event->attr.config != PERF_COUNT_SW_CPU_CLOCK)
5170 return -ENOENT; 5750 return -ENOENT;
5171 5751
5752 perf_swevent_init_hrtimer(event);
5753
5172 return 0; 5754 return 0;
5173} 5755}
5174 5756
@@ -5224,16 +5806,9 @@ static void task_clock_event_del(struct perf_event *event, int flags)
5224 5806
5225static void task_clock_event_read(struct perf_event *event) 5807static void task_clock_event_read(struct perf_event *event)
5226{ 5808{
5227 u64 time; 5809 u64 now = perf_clock();
5228 5810 u64 delta = now - event->ctx->timestamp;
5229 if (!in_nmi()) { 5811 u64 time = event->ctx->time + delta;
5230 update_context_time(event->ctx);
5231 time = event->ctx->time;
5232 } else {
5233 u64 now = perf_clock();
5234 u64 delta = now - event->ctx->timestamp;
5235 time = event->ctx->time + delta;
5236 }
5237 5812
5238 task_clock_event_update(event, time); 5813 task_clock_event_update(event, time);
5239} 5814}
@@ -5246,6 +5821,8 @@ static int task_clock_event_init(struct perf_event *event)
5246 if (event->attr.config != PERF_COUNT_SW_TASK_CLOCK) 5821 if (event->attr.config != PERF_COUNT_SW_TASK_CLOCK)
5247 return -ENOENT; 5822 return -ENOENT;
5248 5823
5824 perf_swevent_init_hrtimer(event);
5825
5249 return 0; 5826 return 0;
5250} 5827}
5251 5828
@@ -5517,17 +6094,22 @@ struct pmu *perf_init_event(struct perf_event *event)
5517{ 6094{
5518 struct pmu *pmu = NULL; 6095 struct pmu *pmu = NULL;
5519 int idx; 6096 int idx;
6097 int ret;
5520 6098
5521 idx = srcu_read_lock(&pmus_srcu); 6099 idx = srcu_read_lock(&pmus_srcu);
5522 6100
5523 rcu_read_lock(); 6101 rcu_read_lock();
5524 pmu = idr_find(&pmu_idr, event->attr.type); 6102 pmu = idr_find(&pmu_idr, event->attr.type);
5525 rcu_read_unlock(); 6103 rcu_read_unlock();
5526 if (pmu) 6104 if (pmu) {
6105 ret = pmu->event_init(event);
6106 if (ret)
6107 pmu = ERR_PTR(ret);
5527 goto unlock; 6108 goto unlock;
6109 }
5528 6110
5529 list_for_each_entry_rcu(pmu, &pmus, entry) { 6111 list_for_each_entry_rcu(pmu, &pmus, entry) {
5530 int ret = pmu->event_init(event); 6112 ret = pmu->event_init(event);
5531 if (!ret) 6113 if (!ret)
5532 goto unlock; 6114 goto unlock;
5533 6115
@@ -5653,7 +6235,7 @@ done:
5653 6235
5654 if (!event->parent) { 6236 if (!event->parent) {
5655 if (event->attach_state & PERF_ATTACH_TASK) 6237 if (event->attach_state & PERF_ATTACH_TASK)
5656 jump_label_inc(&perf_task_events); 6238 jump_label_inc(&perf_sched_events);
5657 if (event->attr.mmap || event->attr.mmap_data) 6239 if (event->attr.mmap || event->attr.mmap_data)
5658 atomic_inc(&nr_mmap_events); 6240 atomic_inc(&nr_mmap_events);
5659 if (event->attr.comm) 6241 if (event->attr.comm)
@@ -5828,7 +6410,7 @@ SYSCALL_DEFINE5(perf_event_open,
5828 int err; 6410 int err;
5829 6411
5830 /* for future expandability... */ 6412 /* for future expandability... */
5831 if (flags & ~(PERF_FLAG_FD_NO_GROUP | PERF_FLAG_FD_OUTPUT)) 6413 if (flags & ~PERF_FLAG_ALL)
5832 return -EINVAL; 6414 return -EINVAL;
5833 6415
5834 err = perf_copy_attr(attr_uptr, &attr); 6416 err = perf_copy_attr(attr_uptr, &attr);
@@ -5845,6 +6427,15 @@ SYSCALL_DEFINE5(perf_event_open,
5845 return -EINVAL; 6427 return -EINVAL;
5846 } 6428 }
5847 6429
6430 /*
6431 * In cgroup mode, the pid argument is used to pass the fd
6432 * opened to the cgroup directory in cgroupfs. The cpu argument
6433 * designates the cpu on which to monitor threads from that
6434 * cgroup.
6435 */
6436 if ((flags & PERF_FLAG_PID_CGROUP) && (pid == -1 || cpu == -1))
6437 return -EINVAL;
6438
5848 event_fd = get_unused_fd_flags(O_RDWR); 6439 event_fd = get_unused_fd_flags(O_RDWR);
5849 if (event_fd < 0) 6440 if (event_fd < 0)
5850 return event_fd; 6441 return event_fd;
@@ -5862,7 +6453,7 @@ SYSCALL_DEFINE5(perf_event_open,
5862 group_leader = NULL; 6453 group_leader = NULL;
5863 } 6454 }
5864 6455
5865 if (pid != -1) { 6456 if (pid != -1 && !(flags & PERF_FLAG_PID_CGROUP)) {
5866 task = find_lively_task_by_vpid(pid); 6457 task = find_lively_task_by_vpid(pid);
5867 if (IS_ERR(task)) { 6458 if (IS_ERR(task)) {
5868 err = PTR_ERR(task); 6459 err = PTR_ERR(task);
@@ -5876,6 +6467,19 @@ SYSCALL_DEFINE5(perf_event_open,
5876 goto err_task; 6467 goto err_task;
5877 } 6468 }
5878 6469
6470 if (flags & PERF_FLAG_PID_CGROUP) {
6471 err = perf_cgroup_connect(pid, event, &attr, group_leader);
6472 if (err)
6473 goto err_alloc;
6474 /*
6475 * one more event:
6476 * - that has cgroup constraint on event->cpu
6477 * - that may need work on context switch
6478 */
6479 atomic_inc(&per_cpu(perf_cgroup_events, event->cpu));
6480 jump_label_inc(&perf_sched_events);
6481 }
6482
5879 /* 6483 /*
5880 * Special case software events and allow them to be part of 6484 * Special case software events and allow them to be part of
5881 * any hardware group. 6485 * any hardware group.
@@ -5961,10 +6565,10 @@ SYSCALL_DEFINE5(perf_event_open,
5961 struct perf_event_context *gctx = group_leader->ctx; 6565 struct perf_event_context *gctx = group_leader->ctx;
5962 6566
5963 mutex_lock(&gctx->mutex); 6567 mutex_lock(&gctx->mutex);
5964 perf_event_remove_from_context(group_leader); 6568 perf_remove_from_context(group_leader);
5965 list_for_each_entry(sibling, &group_leader->sibling_list, 6569 list_for_each_entry(sibling, &group_leader->sibling_list,
5966 group_entry) { 6570 group_entry) {
5967 perf_event_remove_from_context(sibling); 6571 perf_remove_from_context(sibling);
5968 put_ctx(gctx); 6572 put_ctx(gctx);
5969 } 6573 }
5970 mutex_unlock(&gctx->mutex); 6574 mutex_unlock(&gctx->mutex);
@@ -5987,6 +6591,7 @@ SYSCALL_DEFINE5(perf_event_open,
5987 6591
5988 perf_install_in_context(ctx, event, cpu); 6592 perf_install_in_context(ctx, event, cpu);
5989 ++ctx->generation; 6593 ++ctx->generation;
6594 perf_unpin_context(ctx);
5990 mutex_unlock(&ctx->mutex); 6595 mutex_unlock(&ctx->mutex);
5991 6596
5992 event->owner = current; 6597 event->owner = current;
@@ -6012,6 +6617,7 @@ SYSCALL_DEFINE5(perf_event_open,
6012 return event_fd; 6617 return event_fd;
6013 6618
6014err_context: 6619err_context:
6620 perf_unpin_context(ctx);
6015 put_ctx(ctx); 6621 put_ctx(ctx);
6016err_alloc: 6622err_alloc:
6017 free_event(event); 6623 free_event(event);
@@ -6062,6 +6668,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
6062 mutex_lock(&ctx->mutex); 6668 mutex_lock(&ctx->mutex);
6063 perf_install_in_context(ctx, event, cpu); 6669 perf_install_in_context(ctx, event, cpu);
6064 ++ctx->generation; 6670 ++ctx->generation;
6671 perf_unpin_context(ctx);
6065 mutex_unlock(&ctx->mutex); 6672 mutex_unlock(&ctx->mutex);
6066 6673
6067 return event; 6674 return event;
@@ -6115,7 +6722,7 @@ __perf_event_exit_task(struct perf_event *child_event,
6115{ 6722{
6116 struct perf_event *parent_event; 6723 struct perf_event *parent_event;
6117 6724
6118 perf_event_remove_from_context(child_event); 6725 perf_remove_from_context(child_event);
6119 6726
6120 parent_event = child_event->parent; 6727 parent_event = child_event->parent;
6121 /* 6728 /*
@@ -6422,7 +7029,7 @@ inherit_task_group(struct perf_event *event, struct task_struct *parent,
6422 return 0; 7029 return 0;
6423 } 7030 }
6424 7031
6425 child_ctx = child->perf_event_ctxp[ctxn]; 7032 child_ctx = child->perf_event_ctxp[ctxn];
6426 if (!child_ctx) { 7033 if (!child_ctx) {
6427 /* 7034 /*
6428 * This is executed from the parent task context, so 7035 * This is executed from the parent task context, so
@@ -6537,6 +7144,7 @@ int perf_event_init_context(struct task_struct *child, int ctxn)
6537 mutex_unlock(&parent_ctx->mutex); 7144 mutex_unlock(&parent_ctx->mutex);
6538 7145
6539 perf_unpin_context(parent_ctx); 7146 perf_unpin_context(parent_ctx);
7147 put_ctx(parent_ctx);
6540 7148
6541 return ret; 7149 return ret;
6542} 7150}
@@ -6606,9 +7214,9 @@ static void __perf_event_exit_context(void *__info)
6606 perf_pmu_rotate_stop(ctx->pmu); 7214 perf_pmu_rotate_stop(ctx->pmu);
6607 7215
6608 list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry) 7216 list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry)
6609 __perf_event_remove_from_context(event); 7217 __perf_remove_from_context(event);
6610 list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, group_entry) 7218 list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, group_entry)
6611 __perf_event_remove_from_context(event); 7219 __perf_remove_from_context(event);
6612} 7220}
6613 7221
6614static void perf_event_exit_cpu_context(int cpu) 7222static void perf_event_exit_cpu_context(int cpu)
@@ -6732,3 +7340,83 @@ unlock:
6732 return ret; 7340 return ret;
6733} 7341}
6734device_initcall(perf_event_sysfs_init); 7342device_initcall(perf_event_sysfs_init);
7343
7344#ifdef CONFIG_CGROUP_PERF
7345static struct cgroup_subsys_state *perf_cgroup_create(
7346 struct cgroup_subsys *ss, struct cgroup *cont)
7347{
7348 struct perf_cgroup *jc;
7349
7350 jc = kzalloc(sizeof(*jc), GFP_KERNEL);
7351 if (!jc)
7352 return ERR_PTR(-ENOMEM);
7353
7354 jc->info = alloc_percpu(struct perf_cgroup_info);
7355 if (!jc->info) {
7356 kfree(jc);
7357 return ERR_PTR(-ENOMEM);
7358 }
7359
7360 return &jc->css;
7361}
7362
7363static void perf_cgroup_destroy(struct cgroup_subsys *ss,
7364 struct cgroup *cont)
7365{
7366 struct perf_cgroup *jc;
7367 jc = container_of(cgroup_subsys_state(cont, perf_subsys_id),
7368 struct perf_cgroup, css);
7369 free_percpu(jc->info);
7370 kfree(jc);
7371}
7372
7373static int __perf_cgroup_move(void *info)
7374{
7375 struct task_struct *task = info;
7376 perf_cgroup_switch(task, PERF_CGROUP_SWOUT | PERF_CGROUP_SWIN);
7377 return 0;
7378}
7379
7380static void perf_cgroup_move(struct task_struct *task)
7381{
7382 task_function_call(task, __perf_cgroup_move, task);
7383}
7384
7385static void perf_cgroup_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
7386 struct cgroup *old_cgrp, struct task_struct *task,
7387 bool threadgroup)
7388{
7389 perf_cgroup_move(task);
7390 if (threadgroup) {
7391 struct task_struct *c;
7392 rcu_read_lock();
7393 list_for_each_entry_rcu(c, &task->thread_group, thread_group) {
7394 perf_cgroup_move(c);
7395 }
7396 rcu_read_unlock();
7397 }
7398}
7399
7400static void perf_cgroup_exit(struct cgroup_subsys *ss, struct cgroup *cgrp,
7401 struct cgroup *old_cgrp, struct task_struct *task)
7402{
7403 /*
7404 * cgroup_exit() is called in the copy_process() failure path.
7405 * Ignore this case since the task hasn't ran yet, this avoids
7406 * trying to poke a half freed task state from generic code.
7407 */
7408 if (!(task->flags & PF_EXITING))
7409 return;
7410
7411 perf_cgroup_move(task);
7412}
7413
7414struct cgroup_subsys perf_subsys = {
7415 .name = "perf_event",
7416 .subsys_id = perf_subsys_id,
7417 .create = perf_cgroup_create,
7418 .destroy = perf_cgroup_destroy,
7419 .exit = perf_cgroup_exit,
7420 .attach = perf_cgroup_attach,
7421};
7422#endif /* CONFIG_CGROUP_PERF */
diff --git a/kernel/sched.c b/kernel/sched.c
index 42eab5a8437d..57a18e8d28c8 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -606,9 +606,6 @@ static inline struct task_group *task_group(struct task_struct *p)
606 struct task_group *tg; 606 struct task_group *tg;
607 struct cgroup_subsys_state *css; 607 struct cgroup_subsys_state *css;
608 608
609 if (p->flags & PF_EXITING)
610 return &root_task_group;
611
612 css = task_subsys_state_check(p, cpu_cgroup_subsys_id, 609 css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
613 lockdep_is_held(&task_rq(p)->lock)); 610 lockdep_is_held(&task_rq(p)->lock));
614 tg = container_of(css, struct task_group, css); 611 tg = container_of(css, struct task_group, css);
@@ -2265,27 +2262,6 @@ void kick_process(struct task_struct *p)
2265EXPORT_SYMBOL_GPL(kick_process); 2262EXPORT_SYMBOL_GPL(kick_process);
2266#endif /* CONFIG_SMP */ 2263#endif /* CONFIG_SMP */
2267 2264
2268/**
2269 * task_oncpu_function_call - call a function on the cpu on which a task runs
2270 * @p: the task to evaluate
2271 * @func: the function to be called
2272 * @info: the function call argument
2273 *
2274 * Calls the function @func when the task is currently running. This might
2275 * be on the current CPU, which just calls the function directly
2276 */
2277void task_oncpu_function_call(struct task_struct *p,
2278 void (*func) (void *info), void *info)
2279{
2280 int cpu;
2281
2282 preempt_disable();
2283 cpu = task_cpu(p);
2284 if (task_curr(p))
2285 smp_call_function_single(cpu, func, info, 1);
2286 preempt_enable();
2287}
2288
2289#ifdef CONFIG_SMP 2265#ifdef CONFIG_SMP
2290/* 2266/*
2291 * ->cpus_allowed is protected by either TASK_WAKING or rq->lock held. 2267 * ->cpus_allowed is protected by either TASK_WAKING or rq->lock held.
@@ -2776,9 +2752,12 @@ static inline void
2776prepare_task_switch(struct rq *rq, struct task_struct *prev, 2752prepare_task_switch(struct rq *rq, struct task_struct *prev,
2777 struct task_struct *next) 2753 struct task_struct *next)
2778{ 2754{
2755 sched_info_switch(prev, next);
2756 perf_event_task_sched_out(prev, next);
2779 fire_sched_out_preempt_notifiers(prev, next); 2757 fire_sched_out_preempt_notifiers(prev, next);
2780 prepare_lock_switch(rq, next); 2758 prepare_lock_switch(rq, next);
2781 prepare_arch_switch(next); 2759 prepare_arch_switch(next);
2760 trace_sched_switch(prev, next);
2782} 2761}
2783 2762
2784/** 2763/**
@@ -2911,7 +2890,7 @@ context_switch(struct rq *rq, struct task_struct *prev,
2911 struct mm_struct *mm, *oldmm; 2890 struct mm_struct *mm, *oldmm;
2912 2891
2913 prepare_task_switch(rq, prev, next); 2892 prepare_task_switch(rq, prev, next);
2914 trace_sched_switch(prev, next); 2893
2915 mm = next->mm; 2894 mm = next->mm;
2916 oldmm = prev->active_mm; 2895 oldmm = prev->active_mm;
2917 /* 2896 /*
@@ -3989,9 +3968,6 @@ need_resched_nonpreemptible:
3989 rq->skip_clock_update = 0; 3968 rq->skip_clock_update = 0;
3990 3969
3991 if (likely(prev != next)) { 3970 if (likely(prev != next)) {
3992 sched_info_switch(prev, next);
3993 perf_event_task_sched_out(prev, next);
3994
3995 rq->nr_switches++; 3971 rq->nr_switches++;
3996 rq->curr = next; 3972 rq->curr = next;
3997 ++*switch_count; 3973 ++*switch_count;
@@ -5572,7 +5548,7 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
5572 * The idle tasks have their own, simple scheduling class: 5548 * The idle tasks have their own, simple scheduling class:
5573 */ 5549 */
5574 idle->sched_class = &idle_sched_class; 5550 idle->sched_class = &idle_sched_class;
5575 ftrace_graph_init_task(idle); 5551 ftrace_graph_init_idle_task(idle, cpu);
5576} 5552}
5577 5553
5578/* 5554/*
@@ -8885,7 +8861,8 @@ cpu_cgroup_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
8885} 8861}
8886 8862
8887static void 8863static void
8888cpu_cgroup_exit(struct cgroup_subsys *ss, struct task_struct *task) 8864cpu_cgroup_exit(struct cgroup_subsys *ss, struct cgroup *cgrp,
8865 struct cgroup *old_cgrp, struct task_struct *task)
8889{ 8866{
8890 /* 8867 /*
8891 * cgroup_exit() is called in the copy_process() failure path. 8868 * cgroup_exit() is called in the copy_process() failure path.
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 4eed0af5d144..19b9d85e06cc 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -948,7 +948,7 @@ static struct ctl_table kern_table[] = {
948 .data = &sysctl_perf_event_sample_rate, 948 .data = &sysctl_perf_event_sample_rate,
949 .maxlen = sizeof(sysctl_perf_event_sample_rate), 949 .maxlen = sizeof(sysctl_perf_event_sample_rate),
950 .mode = 0644, 950 .mode = 0644,
951 .proc_handler = proc_dointvec, 951 .proc_handler = perf_proc_update_handler,
952 }, 952 },
953#endif 953#endif
954#ifdef CONFIG_KMEMCHECK 954#ifdef CONFIG_KMEMCHECK
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index f3dadae83883..888b611897d3 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3328,7 +3328,7 @@ static int start_graph_tracing(void)
3328 /* The cpu_boot init_task->ret_stack will never be freed */ 3328 /* The cpu_boot init_task->ret_stack will never be freed */
3329 for_each_online_cpu(cpu) { 3329 for_each_online_cpu(cpu) {
3330 if (!idle_task(cpu)->ret_stack) 3330 if (!idle_task(cpu)->ret_stack)
3331 ftrace_graph_init_task(idle_task(cpu)); 3331 ftrace_graph_init_idle_task(idle_task(cpu), cpu);
3332 } 3332 }
3333 3333
3334 do { 3334 do {
@@ -3418,6 +3418,49 @@ void unregister_ftrace_graph(void)
3418 mutex_unlock(&ftrace_lock); 3418 mutex_unlock(&ftrace_lock);
3419} 3419}
3420 3420
3421static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack);
3422
3423static void
3424graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
3425{
3426 atomic_set(&t->tracing_graph_pause, 0);
3427 atomic_set(&t->trace_overrun, 0);
3428 t->ftrace_timestamp = 0;
3429 /* make curr_ret_stack visable before we add the ret_stack */
3430 smp_wmb();
3431 t->ret_stack = ret_stack;
3432}
3433
3434/*
3435 * Allocate a return stack for the idle task. May be the first
3436 * time through, or it may be done by CPU hotplug online.
3437 */
3438void ftrace_graph_init_idle_task(struct task_struct *t, int cpu)
3439{
3440 t->curr_ret_stack = -1;
3441 /*
3442 * The idle task has no parent, it either has its own
3443 * stack or no stack at all.
3444 */
3445 if (t->ret_stack)
3446 WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu));
3447
3448 if (ftrace_graph_active) {
3449 struct ftrace_ret_stack *ret_stack;
3450
3451 ret_stack = per_cpu(idle_ret_stack, cpu);
3452 if (!ret_stack) {
3453 ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
3454 * sizeof(struct ftrace_ret_stack),
3455 GFP_KERNEL);
3456 if (!ret_stack)
3457 return;
3458 per_cpu(idle_ret_stack, cpu) = ret_stack;
3459 }
3460 graph_init_task(t, ret_stack);
3461 }
3462}
3463
3421/* Allocate a return stack for newly created task */ 3464/* Allocate a return stack for newly created task */
3422void ftrace_graph_init_task(struct task_struct *t) 3465void ftrace_graph_init_task(struct task_struct *t)
3423{ 3466{
@@ -3433,12 +3476,7 @@ void ftrace_graph_init_task(struct task_struct *t)
3433 GFP_KERNEL); 3476 GFP_KERNEL);
3434 if (!ret_stack) 3477 if (!ret_stack)
3435 return; 3478 return;
3436 atomic_set(&t->tracing_graph_pause, 0); 3479 graph_init_task(t, ret_stack);
3437 atomic_set(&t->trace_overrun, 0);
3438 t->ftrace_timestamp = 0;
3439 /* make curr_ret_stack visable before we add the ret_stack */
3440 smp_wmb();
3441 t->ret_stack = ret_stack;
3442 } 3480 }
3443} 3481}
3444 3482
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index bd1c35a4fbcc..db7b439d23ee 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -5,7 +5,6 @@
5 */ 5 */
6#include <linux/ring_buffer.h> 6#include <linux/ring_buffer.h>
7#include <linux/trace_clock.h> 7#include <linux/trace_clock.h>
8#include <linux/ftrace_irq.h>
9#include <linux/spinlock.h> 8#include <linux/spinlock.h>
10#include <linux/debugfs.h> 9#include <linux/debugfs.h>
11#include <linux/uaccess.h> 10#include <linux/uaccess.h>
@@ -1429,6 +1428,17 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
1429} 1428}
1430EXPORT_SYMBOL_GPL(ring_buffer_resize); 1429EXPORT_SYMBOL_GPL(ring_buffer_resize);
1431 1430
1431void ring_buffer_change_overwrite(struct ring_buffer *buffer, int val)
1432{
1433 mutex_lock(&buffer->mutex);
1434 if (val)
1435 buffer->flags |= RB_FL_OVERWRITE;
1436 else
1437 buffer->flags &= ~RB_FL_OVERWRITE;
1438 mutex_unlock(&buffer->mutex);
1439}
1440EXPORT_SYMBOL_GPL(ring_buffer_change_overwrite);
1441
1432static inline void * 1442static inline void *
1433__rb_data_page_index(struct buffer_data_page *bpage, unsigned index) 1443__rb_data_page_index(struct buffer_data_page *bpage, unsigned index)
1434{ 1444{
@@ -2162,11 +2172,19 @@ rb_reserve_next_event(struct ring_buffer *buffer,
2162 if (likely(ts >= cpu_buffer->write_stamp)) { 2172 if (likely(ts >= cpu_buffer->write_stamp)) {
2163 delta = diff; 2173 delta = diff;
2164 if (unlikely(test_time_stamp(delta))) { 2174 if (unlikely(test_time_stamp(delta))) {
2175 int local_clock_stable = 1;
2176#ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
2177 local_clock_stable = sched_clock_stable;
2178#endif
2165 WARN_ONCE(delta > (1ULL << 59), 2179 WARN_ONCE(delta > (1ULL << 59),
2166 KERN_WARNING "Delta way too big! %llu ts=%llu write stamp = %llu\n", 2180 KERN_WARNING "Delta way too big! %llu ts=%llu write stamp = %llu\n%s",
2167 (unsigned long long)delta, 2181 (unsigned long long)delta,
2168 (unsigned long long)ts, 2182 (unsigned long long)ts,
2169 (unsigned long long)cpu_buffer->write_stamp); 2183 (unsigned long long)cpu_buffer->write_stamp,
2184 local_clock_stable ? "" :
2185 "If you just came from a suspend/resume,\n"
2186 "please switch to the trace global clock:\n"
2187 " echo global > /sys/kernel/debug/tracing/trace_clock\n");
2170 add_timestamp = 1; 2188 add_timestamp = 1;
2171 } 2189 }
2172 } 2190 }
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index dc53ecb80589..9541c27c1cf2 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -41,8 +41,6 @@
41#include "trace.h" 41#include "trace.h"
42#include "trace_output.h" 42#include "trace_output.h"
43 43
44#define TRACE_BUFFER_FLAGS (RB_FL_OVERWRITE)
45
46/* 44/*
47 * On boot up, the ring buffer is set to the minimum size, so that 45 * On boot up, the ring buffer is set to the minimum size, so that
48 * we do not waste memory on systems that are not using tracing. 46 * we do not waste memory on systems that are not using tracing.
@@ -340,7 +338,7 @@ static DECLARE_WAIT_QUEUE_HEAD(trace_wait);
340/* trace_flags holds trace_options default values */ 338/* trace_flags holds trace_options default values */
341unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK | 339unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK |
342 TRACE_ITER_ANNOTATE | TRACE_ITER_CONTEXT_INFO | TRACE_ITER_SLEEP_TIME | 340 TRACE_ITER_ANNOTATE | TRACE_ITER_CONTEXT_INFO | TRACE_ITER_SLEEP_TIME |
343 TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD; 341 TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD | TRACE_ITER_OVERWRITE;
344 342
345static int trace_stop_count; 343static int trace_stop_count;
346static DEFINE_SPINLOCK(tracing_start_lock); 344static DEFINE_SPINLOCK(tracing_start_lock);
@@ -425,6 +423,7 @@ static const char *trace_options[] = {
425 "sleep-time", 423 "sleep-time",
426 "graph-time", 424 "graph-time",
427 "record-cmd", 425 "record-cmd",
426 "overwrite",
428 NULL 427 NULL
429}; 428};
430 429
@@ -780,6 +779,11 @@ __acquires(kernel_lock)
780 tracing_reset_online_cpus(tr); 779 tracing_reset_online_cpus(tr);
781 780
782 current_trace = type; 781 current_trace = type;
782
783 /* If we expanded the buffers, make sure the max is expanded too */
784 if (ring_buffer_expanded && type->use_max_tr)
785 ring_buffer_resize(max_tr.buffer, trace_buf_size);
786
783 /* the test is responsible for initializing and enabling */ 787 /* the test is responsible for initializing and enabling */
784 pr_info("Testing tracer %s: ", type->name); 788 pr_info("Testing tracer %s: ", type->name);
785 ret = type->selftest(type, tr); 789 ret = type->selftest(type, tr);
@@ -792,6 +796,10 @@ __acquires(kernel_lock)
792 /* Only reset on passing, to avoid touching corrupted buffers */ 796 /* Only reset on passing, to avoid touching corrupted buffers */
793 tracing_reset_online_cpus(tr); 797 tracing_reset_online_cpus(tr);
794 798
799 /* Shrink the max buffer again */
800 if (ring_buffer_expanded && type->use_max_tr)
801 ring_buffer_resize(max_tr.buffer, 1);
802
795 printk(KERN_CONT "PASSED\n"); 803 printk(KERN_CONT "PASSED\n");
796 } 804 }
797#endif 805#endif
@@ -1102,7 +1110,6 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags,
1102 1110
1103 entry->preempt_count = pc & 0xff; 1111 entry->preempt_count = pc & 0xff;
1104 entry->pid = (tsk) ? tsk->pid : 0; 1112 entry->pid = (tsk) ? tsk->pid : 0;
1105 entry->lock_depth = (tsk) ? tsk->lock_depth : 0;
1106 entry->flags = 1113 entry->flags =
1107#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT 1114#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
1108 (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) | 1115 (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) |
@@ -1749,10 +1756,9 @@ static void print_lat_help_header(struct seq_file *m)
1749 seq_puts(m, "# | / _----=> need-resched \n"); 1756 seq_puts(m, "# | / _----=> need-resched \n");
1750 seq_puts(m, "# || / _---=> hardirq/softirq \n"); 1757 seq_puts(m, "# || / _---=> hardirq/softirq \n");
1751 seq_puts(m, "# ||| / _--=> preempt-depth \n"); 1758 seq_puts(m, "# ||| / _--=> preempt-depth \n");
1752 seq_puts(m, "# |||| /_--=> lock-depth \n"); 1759 seq_puts(m, "# |||| / delay \n");
1753 seq_puts(m, "# |||||/ delay \n"); 1760 seq_puts(m, "# cmd pid ||||| time | caller \n");
1754 seq_puts(m, "# cmd pid |||||| time | caller \n"); 1761 seq_puts(m, "# \\ / ||||| \\ | / \n");
1755 seq_puts(m, "# \\ / |||||| \\ | / \n");
1756} 1762}
1757 1763
1758static void print_func_help_header(struct seq_file *m) 1764static void print_func_help_header(struct seq_file *m)
@@ -2529,6 +2535,9 @@ static void set_tracer_flags(unsigned int mask, int enabled)
2529 2535
2530 if (mask == TRACE_ITER_RECORD_CMD) 2536 if (mask == TRACE_ITER_RECORD_CMD)
2531 trace_event_enable_cmd_record(enabled); 2537 trace_event_enable_cmd_record(enabled);
2538
2539 if (mask == TRACE_ITER_OVERWRITE)
2540 ring_buffer_change_overwrite(global_trace.buffer, enabled);
2532} 2541}
2533 2542
2534static ssize_t 2543static ssize_t
@@ -2710,6 +2719,10 @@ tracing_ctrl_write(struct file *filp, const char __user *ubuf,
2710 2719
2711 mutex_lock(&trace_types_lock); 2720 mutex_lock(&trace_types_lock);
2712 if (tracer_enabled ^ val) { 2721 if (tracer_enabled ^ val) {
2722
2723 /* Only need to warn if this is used to change the state */
2724 WARN_ONCE(1, "tracing_enabled is deprecated. Use tracing_on");
2725
2713 if (val) { 2726 if (val) {
2714 tracer_enabled = 1; 2727 tracer_enabled = 1;
2715 if (current_trace->start) 2728 if (current_trace->start)
@@ -4551,9 +4564,11 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
4551__init static int tracer_alloc_buffers(void) 4564__init static int tracer_alloc_buffers(void)
4552{ 4565{
4553 int ring_buf_size; 4566 int ring_buf_size;
4567 enum ring_buffer_flags rb_flags;
4554 int i; 4568 int i;
4555 int ret = -ENOMEM; 4569 int ret = -ENOMEM;
4556 4570
4571
4557 if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL)) 4572 if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL))
4558 goto out; 4573 goto out;
4559 4574
@@ -4566,12 +4581,13 @@ __init static int tracer_alloc_buffers(void)
4566 else 4581 else
4567 ring_buf_size = 1; 4582 ring_buf_size = 1;
4568 4583
4584 rb_flags = trace_flags & TRACE_ITER_OVERWRITE ? RB_FL_OVERWRITE : 0;
4585
4569 cpumask_copy(tracing_buffer_mask, cpu_possible_mask); 4586 cpumask_copy(tracing_buffer_mask, cpu_possible_mask);
4570 cpumask_copy(tracing_cpumask, cpu_all_mask); 4587 cpumask_copy(tracing_cpumask, cpu_all_mask);
4571 4588
4572 /* TODO: make the number of buffers hot pluggable with CPUS */ 4589 /* TODO: make the number of buffers hot pluggable with CPUS */
4573 global_trace.buffer = ring_buffer_alloc(ring_buf_size, 4590 global_trace.buffer = ring_buffer_alloc(ring_buf_size, rb_flags);
4574 TRACE_BUFFER_FLAGS);
4575 if (!global_trace.buffer) { 4591 if (!global_trace.buffer) {
4576 printk(KERN_ERR "tracer: failed to allocate ring buffer!\n"); 4592 printk(KERN_ERR "tracer: failed to allocate ring buffer!\n");
4577 WARN_ON(1); 4593 WARN_ON(1);
@@ -4581,7 +4597,7 @@ __init static int tracer_alloc_buffers(void)
4581 4597
4582 4598
4583#ifdef CONFIG_TRACER_MAX_TRACE 4599#ifdef CONFIG_TRACER_MAX_TRACE
4584 max_tr.buffer = ring_buffer_alloc(1, TRACE_BUFFER_FLAGS); 4600 max_tr.buffer = ring_buffer_alloc(1, rb_flags);
4585 if (!max_tr.buffer) { 4601 if (!max_tr.buffer) {
4586 printk(KERN_ERR "tracer: failed to allocate max ring buffer!\n"); 4602 printk(KERN_ERR "tracer: failed to allocate max ring buffer!\n");
4587 WARN_ON(1); 4603 WARN_ON(1);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 9021f8c0c0c3..5e9dfc6286dd 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -272,8 +272,8 @@ struct tracer {
272 /* If you handled the flag setting, return 0 */ 272 /* If you handled the flag setting, return 0 */
273 int (*set_flag)(u32 old_flags, u32 bit, int set); 273 int (*set_flag)(u32 old_flags, u32 bit, int set);
274 struct tracer *next; 274 struct tracer *next;
275 int print_max;
276 struct tracer_flags *flags; 275 struct tracer_flags *flags;
276 int print_max;
277 int use_max_tr; 277 int use_max_tr;
278}; 278};
279 279
@@ -606,6 +606,7 @@ enum trace_iterator_flags {
606 TRACE_ITER_SLEEP_TIME = 0x40000, 606 TRACE_ITER_SLEEP_TIME = 0x40000,
607 TRACE_ITER_GRAPH_TIME = 0x80000, 607 TRACE_ITER_GRAPH_TIME = 0x80000,
608 TRACE_ITER_RECORD_CMD = 0x100000, 608 TRACE_ITER_RECORD_CMD = 0x100000,
609 TRACE_ITER_OVERWRITE = 0x200000,
609}; 610};
610 611
611/* 612/*
@@ -661,8 +662,10 @@ struct ftrace_event_field {
661}; 662};
662 663
663struct event_filter { 664struct event_filter {
664 int n_preds; 665 int n_preds; /* Number assigned */
665 struct filter_pred **preds; 666 int a_preds; /* allocated */
667 struct filter_pred *preds;
668 struct filter_pred *root;
666 char *filter_string; 669 char *filter_string;
667}; 670};
668 671
@@ -674,11 +677,23 @@ struct event_subsystem {
674 int nr_events; 677 int nr_events;
675}; 678};
676 679
680#define FILTER_PRED_INVALID ((unsigned short)-1)
681#define FILTER_PRED_IS_RIGHT (1 << 15)
682#define FILTER_PRED_FOLD (1 << 15)
683
684/*
685 * The max preds is the size of unsigned short with
686 * two flags at the MSBs. One bit is used for both the IS_RIGHT
687 * and FOLD flags. The other is reserved.
688 *
689 * 2^14 preds is way more than enough.
690 */
691#define MAX_FILTER_PRED 16384
692
677struct filter_pred; 693struct filter_pred;
678struct regex; 694struct regex;
679 695
680typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event, 696typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event);
681 int val1, int val2);
682 697
683typedef int (*regex_match_func)(char *str, struct regex *r, int len); 698typedef int (*regex_match_func)(char *str, struct regex *r, int len);
684 699
@@ -700,11 +715,23 @@ struct filter_pred {
700 filter_pred_fn_t fn; 715 filter_pred_fn_t fn;
701 u64 val; 716 u64 val;
702 struct regex regex; 717 struct regex regex;
703 char *field_name; 718 /*
719 * Leaf nodes use field_name, ops is used by AND and OR
720 * nodes. The field_name is always freed when freeing a pred.
721 * We can overload field_name for ops and have it freed
722 * as well.
723 */
724 union {
725 char *field_name;
726 unsigned short *ops;
727 };
704 int offset; 728 int offset;
705 int not; 729 int not;
706 int op; 730 int op;
707 int pop_n; 731 unsigned short index;
732 unsigned short parent;
733 unsigned short left;
734 unsigned short right;
708}; 735};
709 736
710extern struct list_head ftrace_common_fields; 737extern struct list_head ftrace_common_fields;
diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h
index 6cf223764be8..1516cb3ec549 100644
--- a/kernel/trace/trace_entries.h
+++ b/kernel/trace/trace_entries.h
@@ -109,12 +109,12 @@ FTRACE_ENTRY(funcgraph_exit, ftrace_graph_ret_entry,
109 */ 109 */
110#define FTRACE_CTX_FIELDS \ 110#define FTRACE_CTX_FIELDS \
111 __field( unsigned int, prev_pid ) \ 111 __field( unsigned int, prev_pid ) \
112 __field( unsigned int, next_pid ) \
113 __field( unsigned int, next_cpu ) \
112 __field( unsigned char, prev_prio ) \ 114 __field( unsigned char, prev_prio ) \
113 __field( unsigned char, prev_state ) \ 115 __field( unsigned char, prev_state ) \
114 __field( unsigned int, next_pid ) \
115 __field( unsigned char, next_prio ) \ 116 __field( unsigned char, next_prio ) \
116 __field( unsigned char, next_state ) \ 117 __field( unsigned char, next_state )
117 __field( unsigned int, next_cpu )
118 118
119FTRACE_ENTRY(context_switch, ctx_switch_entry, 119FTRACE_ENTRY(context_switch, ctx_switch_entry,
120 120
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 5f499e0438a4..e88f74fe1d4c 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -116,7 +116,6 @@ static int trace_define_common_fields(void)
116 __common_field(unsigned char, flags); 116 __common_field(unsigned char, flags);
117 __common_field(unsigned char, preempt_count); 117 __common_field(unsigned char, preempt_count);
118 __common_field(int, pid); 118 __common_field(int, pid);
119 __common_field(int, lock_depth);
120 119
121 return ret; 120 return ret;
122} 121}
@@ -326,6 +325,7 @@ int trace_set_clr_event(const char *system, const char *event, int set)
326{ 325{
327 return __ftrace_set_clr_event(NULL, system, event, set); 326 return __ftrace_set_clr_event(NULL, system, event, set);
328} 327}
328EXPORT_SYMBOL_GPL(trace_set_clr_event);
329 329
330/* 128 should be much more than enough */ 330/* 128 should be much more than enough */
331#define EVENT_BUF_SIZE 127 331#define EVENT_BUF_SIZE 127
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 36d40104b17f..3249b4f77ef0 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -123,9 +123,13 @@ struct filter_parse_state {
123 } operand; 123 } operand;
124}; 124};
125 125
126struct pred_stack {
127 struct filter_pred **preds;
128 int index;
129};
130
126#define DEFINE_COMPARISON_PRED(type) \ 131#define DEFINE_COMPARISON_PRED(type) \
127static int filter_pred_##type(struct filter_pred *pred, void *event, \ 132static int filter_pred_##type(struct filter_pred *pred, void *event) \
128 int val1, int val2) \
129{ \ 133{ \
130 type *addr = (type *)(event + pred->offset); \ 134 type *addr = (type *)(event + pred->offset); \
131 type val = (type)pred->val; \ 135 type val = (type)pred->val; \
@@ -152,8 +156,7 @@ static int filter_pred_##type(struct filter_pred *pred, void *event, \
152} 156}
153 157
154#define DEFINE_EQUALITY_PRED(size) \ 158#define DEFINE_EQUALITY_PRED(size) \
155static int filter_pred_##size(struct filter_pred *pred, void *event, \ 159static int filter_pred_##size(struct filter_pred *pred, void *event) \
156 int val1, int val2) \
157{ \ 160{ \
158 u##size *addr = (u##size *)(event + pred->offset); \ 161 u##size *addr = (u##size *)(event + pred->offset); \
159 u##size val = (u##size)pred->val; \ 162 u##size val = (u##size)pred->val; \
@@ -178,23 +181,8 @@ DEFINE_EQUALITY_PRED(32);
178DEFINE_EQUALITY_PRED(16); 181DEFINE_EQUALITY_PRED(16);
179DEFINE_EQUALITY_PRED(8); 182DEFINE_EQUALITY_PRED(8);
180 183
181static int filter_pred_and(struct filter_pred *pred __attribute((unused)),
182 void *event __attribute((unused)),
183 int val1, int val2)
184{
185 return val1 && val2;
186}
187
188static int filter_pred_or(struct filter_pred *pred __attribute((unused)),
189 void *event __attribute((unused)),
190 int val1, int val2)
191{
192 return val1 || val2;
193}
194
195/* Filter predicate for fixed sized arrays of characters */ 184/* Filter predicate for fixed sized arrays of characters */
196static int filter_pred_string(struct filter_pred *pred, void *event, 185static int filter_pred_string(struct filter_pred *pred, void *event)
197 int val1, int val2)
198{ 186{
199 char *addr = (char *)(event + pred->offset); 187 char *addr = (char *)(event + pred->offset);
200 int cmp, match; 188 int cmp, match;
@@ -207,8 +195,7 @@ static int filter_pred_string(struct filter_pred *pred, void *event,
207} 195}
208 196
209/* Filter predicate for char * pointers */ 197/* Filter predicate for char * pointers */
210static int filter_pred_pchar(struct filter_pred *pred, void *event, 198static int filter_pred_pchar(struct filter_pred *pred, void *event)
211 int val1, int val2)
212{ 199{
213 char **addr = (char **)(event + pred->offset); 200 char **addr = (char **)(event + pred->offset);
214 int cmp, match; 201 int cmp, match;
@@ -231,8 +218,7 @@ static int filter_pred_pchar(struct filter_pred *pred, void *event,
231 * and add it to the address of the entry, and at last we have 218 * and add it to the address of the entry, and at last we have
232 * the address of the string. 219 * the address of the string.
233 */ 220 */
234static int filter_pred_strloc(struct filter_pred *pred, void *event, 221static int filter_pred_strloc(struct filter_pred *pred, void *event)
235 int val1, int val2)
236{ 222{
237 u32 str_item = *(u32 *)(event + pred->offset); 223 u32 str_item = *(u32 *)(event + pred->offset);
238 int str_loc = str_item & 0xffff; 224 int str_loc = str_item & 0xffff;
@@ -247,8 +233,7 @@ static int filter_pred_strloc(struct filter_pred *pred, void *event,
247 return match; 233 return match;
248} 234}
249 235
250static int filter_pred_none(struct filter_pred *pred, void *event, 236static int filter_pred_none(struct filter_pred *pred, void *event)
251 int val1, int val2)
252{ 237{
253 return 0; 238 return 0;
254} 239}
@@ -377,32 +362,147 @@ static void filter_build_regex(struct filter_pred *pred)
377 pred->not ^= not; 362 pred->not ^= not;
378} 363}
379 364
365enum move_type {
366 MOVE_DOWN,
367 MOVE_UP_FROM_LEFT,
368 MOVE_UP_FROM_RIGHT
369};
370
371static struct filter_pred *
372get_pred_parent(struct filter_pred *pred, struct filter_pred *preds,
373 int index, enum move_type *move)
374{
375 if (pred->parent & FILTER_PRED_IS_RIGHT)
376 *move = MOVE_UP_FROM_RIGHT;
377 else
378 *move = MOVE_UP_FROM_LEFT;
379 pred = &preds[pred->parent & ~FILTER_PRED_IS_RIGHT];
380
381 return pred;
382}
383
384/*
385 * A series of AND or ORs where found together. Instead of
386 * climbing up and down the tree branches, an array of the
387 * ops were made in order of checks. We can just move across
388 * the array and short circuit if needed.
389 */
390static int process_ops(struct filter_pred *preds,
391 struct filter_pred *op, void *rec)
392{
393 struct filter_pred *pred;
394 int type;
395 int match;
396 int i;
397
398 /*
399 * Micro-optimization: We set type to true if op
400 * is an OR and false otherwise (AND). Then we
401 * just need to test if the match is equal to
402 * the type, and if it is, we can short circuit the
403 * rest of the checks:
404 *
405 * if ((match && op->op == OP_OR) ||
406 * (!match && op->op == OP_AND))
407 * return match;
408 */
409 type = op->op == OP_OR;
410
411 for (i = 0; i < op->val; i++) {
412 pred = &preds[op->ops[i]];
413 match = pred->fn(pred, rec);
414 if (!!match == type)
415 return match;
416 }
417 return match;
418}
419
380/* return 1 if event matches, 0 otherwise (discard) */ 420/* return 1 if event matches, 0 otherwise (discard) */
381int filter_match_preds(struct event_filter *filter, void *rec) 421int filter_match_preds(struct event_filter *filter, void *rec)
382{ 422{
383 int match, top = 0, val1 = 0, val2 = 0; 423 int match = -1;
384 int stack[MAX_FILTER_PRED]; 424 enum move_type move = MOVE_DOWN;
425 struct filter_pred *preds;
385 struct filter_pred *pred; 426 struct filter_pred *pred;
386 int i; 427 struct filter_pred *root;
428 int n_preds;
429 int done = 0;
430
431 /* no filter is considered a match */
432 if (!filter)
433 return 1;
434
435 n_preds = filter->n_preds;
436
437 if (!n_preds)
438 return 1;
439
440 /*
441 * n_preds, root and filter->preds are protect with preemption disabled.
442 */
443 preds = rcu_dereference_sched(filter->preds);
444 root = rcu_dereference_sched(filter->root);
445 if (!root)
446 return 1;
447
448 pred = root;
387 449
388 for (i = 0; i < filter->n_preds; i++) { 450 /* match is currently meaningless */
389 pred = filter->preds[i]; 451 match = -1;
390 if (!pred->pop_n) { 452
391 match = pred->fn(pred, rec, val1, val2); 453 do {
392 stack[top++] = match; 454 switch (move) {
455 case MOVE_DOWN:
456 /* only AND and OR have children */
457 if (pred->left != FILTER_PRED_INVALID) {
458 /* If ops is set, then it was folded. */
459 if (!pred->ops) {
460 /* keep going to down the left side */
461 pred = &preds[pred->left];
462 continue;
463 }
464 /* We can treat folded ops as a leaf node */
465 match = process_ops(preds, pred, rec);
466 } else
467 match = pred->fn(pred, rec);
468 /* If this pred is the only pred */
469 if (pred == root)
470 break;
471 pred = get_pred_parent(pred, preds,
472 pred->parent, &move);
473 continue;
474 case MOVE_UP_FROM_LEFT:
475 /*
476 * Check for short circuits.
477 *
478 * Optimization: !!match == (pred->op == OP_OR)
479 * is the same as:
480 * if ((match && pred->op == OP_OR) ||
481 * (!match && pred->op == OP_AND))
482 */
483 if (!!match == (pred->op == OP_OR)) {
484 if (pred == root)
485 break;
486 pred = get_pred_parent(pred, preds,
487 pred->parent, &move);
488 continue;
489 }
490 /* now go down the right side of the tree. */
491 pred = &preds[pred->right];
492 move = MOVE_DOWN;
493 continue;
494 case MOVE_UP_FROM_RIGHT:
495 /* We finished this equation. */
496 if (pred == root)
497 break;
498 pred = get_pred_parent(pred, preds,
499 pred->parent, &move);
393 continue; 500 continue;
394 } 501 }
395 if (pred->pop_n > top) { 502 done = 1;
396 WARN_ON_ONCE(1); 503 } while (!done);
397 return 0;
398 }
399 val1 = stack[--top];
400 val2 = stack[--top];
401 match = pred->fn(pred, rec, val1, val2);
402 stack[top++] = match;
403 }
404 504
405 return stack[--top]; 505 return match;
406} 506}
407EXPORT_SYMBOL_GPL(filter_match_preds); 507EXPORT_SYMBOL_GPL(filter_match_preds);
408 508
@@ -414,6 +514,9 @@ static void parse_error(struct filter_parse_state *ps, int err, int pos)
414 514
415static void remove_filter_string(struct event_filter *filter) 515static void remove_filter_string(struct event_filter *filter)
416{ 516{
517 if (!filter)
518 return;
519
417 kfree(filter->filter_string); 520 kfree(filter->filter_string);
418 filter->filter_string = NULL; 521 filter->filter_string = NULL;
419} 522}
@@ -473,9 +576,10 @@ static void append_filter_err(struct filter_parse_state *ps,
473 576
474void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s) 577void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s)
475{ 578{
476 struct event_filter *filter = call->filter; 579 struct event_filter *filter;
477 580
478 mutex_lock(&event_mutex); 581 mutex_lock(&event_mutex);
582 filter = call->filter;
479 if (filter && filter->filter_string) 583 if (filter && filter->filter_string)
480 trace_seq_printf(s, "%s\n", filter->filter_string); 584 trace_seq_printf(s, "%s\n", filter->filter_string);
481 else 585 else
@@ -486,9 +590,10 @@ void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s)
486void print_subsystem_event_filter(struct event_subsystem *system, 590void print_subsystem_event_filter(struct event_subsystem *system,
487 struct trace_seq *s) 591 struct trace_seq *s)
488{ 592{
489 struct event_filter *filter = system->filter; 593 struct event_filter *filter;
490 594
491 mutex_lock(&event_mutex); 595 mutex_lock(&event_mutex);
596 filter = system->filter;
492 if (filter && filter->filter_string) 597 if (filter && filter->filter_string)
493 trace_seq_printf(s, "%s\n", filter->filter_string); 598 trace_seq_printf(s, "%s\n", filter->filter_string);
494 else 599 else
@@ -539,10 +644,58 @@ static void filter_clear_pred(struct filter_pred *pred)
539 pred->regex.len = 0; 644 pred->regex.len = 0;
540} 645}
541 646
542static int filter_set_pred(struct filter_pred *dest, 647static int __alloc_pred_stack(struct pred_stack *stack, int n_preds)
648{
649 stack->preds = kzalloc(sizeof(*stack->preds)*(n_preds + 1), GFP_KERNEL);
650 if (!stack->preds)
651 return -ENOMEM;
652 stack->index = n_preds;
653 return 0;
654}
655
656static void __free_pred_stack(struct pred_stack *stack)
657{
658 kfree(stack->preds);
659 stack->index = 0;
660}
661
662static int __push_pred_stack(struct pred_stack *stack,
663 struct filter_pred *pred)
664{
665 int index = stack->index;
666
667 if (WARN_ON(index == 0))
668 return -ENOSPC;
669
670 stack->preds[--index] = pred;
671 stack->index = index;
672 return 0;
673}
674
675static struct filter_pred *
676__pop_pred_stack(struct pred_stack *stack)
677{
678 struct filter_pred *pred;
679 int index = stack->index;
680
681 pred = stack->preds[index++];
682 if (!pred)
683 return NULL;
684
685 stack->index = index;
686 return pred;
687}
688
689static int filter_set_pred(struct event_filter *filter,
690 int idx,
691 struct pred_stack *stack,
543 struct filter_pred *src, 692 struct filter_pred *src,
544 filter_pred_fn_t fn) 693 filter_pred_fn_t fn)
545{ 694{
695 struct filter_pred *dest = &filter->preds[idx];
696 struct filter_pred *left;
697 struct filter_pred *right;
698
546 *dest = *src; 699 *dest = *src;
547 if (src->field_name) { 700 if (src->field_name) {
548 dest->field_name = kstrdup(src->field_name, GFP_KERNEL); 701 dest->field_name = kstrdup(src->field_name, GFP_KERNEL);
@@ -550,116 +703,140 @@ static int filter_set_pred(struct filter_pred *dest,
550 return -ENOMEM; 703 return -ENOMEM;
551 } 704 }
552 dest->fn = fn; 705 dest->fn = fn;
706 dest->index = idx;
553 707
554 return 0; 708 if (dest->op == OP_OR || dest->op == OP_AND) {
709 right = __pop_pred_stack(stack);
710 left = __pop_pred_stack(stack);
711 if (!left || !right)
712 return -EINVAL;
713 /*
714 * If both children can be folded
715 * and they are the same op as this op or a leaf,
716 * then this op can be folded.
717 */
718 if (left->index & FILTER_PRED_FOLD &&
719 (left->op == dest->op ||
720 left->left == FILTER_PRED_INVALID) &&
721 right->index & FILTER_PRED_FOLD &&
722 (right->op == dest->op ||
723 right->left == FILTER_PRED_INVALID))
724 dest->index |= FILTER_PRED_FOLD;
725
726 dest->left = left->index & ~FILTER_PRED_FOLD;
727 dest->right = right->index & ~FILTER_PRED_FOLD;
728 left->parent = dest->index & ~FILTER_PRED_FOLD;
729 right->parent = dest->index | FILTER_PRED_IS_RIGHT;
730 } else {
731 /*
732 * Make dest->left invalid to be used as a quick
733 * way to know this is a leaf node.
734 */
735 dest->left = FILTER_PRED_INVALID;
736
737 /* All leafs allow folding the parent ops. */
738 dest->index |= FILTER_PRED_FOLD;
739 }
740
741 return __push_pred_stack(stack, dest);
555} 742}
556 743
557static void filter_disable_preds(struct ftrace_event_call *call) 744static void __free_preds(struct event_filter *filter)
558{ 745{
559 struct event_filter *filter = call->filter;
560 int i; 746 int i;
561 747
562 call->flags &= ~TRACE_EVENT_FL_FILTERED; 748 if (filter->preds) {
749 for (i = 0; i < filter->a_preds; i++)
750 kfree(filter->preds[i].field_name);
751 kfree(filter->preds);
752 filter->preds = NULL;
753 }
754 filter->a_preds = 0;
563 filter->n_preds = 0; 755 filter->n_preds = 0;
564
565 for (i = 0; i < MAX_FILTER_PRED; i++)
566 filter->preds[i]->fn = filter_pred_none;
567} 756}
568 757
569static void __free_preds(struct event_filter *filter) 758static void filter_disable(struct ftrace_event_call *call)
570{ 759{
571 int i; 760 call->flags &= ~TRACE_EVENT_FL_FILTERED;
761}
572 762
763static void __free_filter(struct event_filter *filter)
764{
573 if (!filter) 765 if (!filter)
574 return; 766 return;
575 767
576 for (i = 0; i < MAX_FILTER_PRED; i++) { 768 __free_preds(filter);
577 if (filter->preds[i])
578 filter_free_pred(filter->preds[i]);
579 }
580 kfree(filter->preds);
581 kfree(filter->filter_string); 769 kfree(filter->filter_string);
582 kfree(filter); 770 kfree(filter);
583} 771}
584 772
773/*
774 * Called when destroying the ftrace_event_call.
775 * The call is being freed, so we do not need to worry about
776 * the call being currently used. This is for module code removing
777 * the tracepoints from within it.
778 */
585void destroy_preds(struct ftrace_event_call *call) 779void destroy_preds(struct ftrace_event_call *call)
586{ 780{
587 __free_preds(call->filter); 781 __free_filter(call->filter);
588 call->filter = NULL; 782 call->filter = NULL;
589 call->flags &= ~TRACE_EVENT_FL_FILTERED;
590} 783}
591 784
592static struct event_filter *__alloc_preds(void) 785static struct event_filter *__alloc_filter(void)
593{ 786{
594 struct event_filter *filter; 787 struct event_filter *filter;
788
789 filter = kzalloc(sizeof(*filter), GFP_KERNEL);
790 return filter;
791}
792
793static int __alloc_preds(struct event_filter *filter, int n_preds)
794{
595 struct filter_pred *pred; 795 struct filter_pred *pred;
596 int i; 796 int i;
597 797
598 filter = kzalloc(sizeof(*filter), GFP_KERNEL); 798 if (filter->preds)
599 if (!filter) 799 __free_preds(filter);
600 return ERR_PTR(-ENOMEM);
601 800
602 filter->n_preds = 0; 801 filter->preds =
802 kzalloc(sizeof(*filter->preds) * n_preds, GFP_KERNEL);
603 803
604 filter->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL);
605 if (!filter->preds) 804 if (!filter->preds)
606 goto oom; 805 return -ENOMEM;
607 806
608 for (i = 0; i < MAX_FILTER_PRED; i++) { 807 filter->a_preds = n_preds;
609 pred = kzalloc(sizeof(*pred), GFP_KERNEL); 808 filter->n_preds = 0;
610 if (!pred) 809
611 goto oom; 810 for (i = 0; i < n_preds; i++) {
811 pred = &filter->preds[i];
612 pred->fn = filter_pred_none; 812 pred->fn = filter_pred_none;
613 filter->preds[i] = pred;
614 } 813 }
615 814
616 return filter;
617
618oom:
619 __free_preds(filter);
620 return ERR_PTR(-ENOMEM);
621}
622
623static int init_preds(struct ftrace_event_call *call)
624{
625 if (call->filter)
626 return 0;
627
628 call->flags &= ~TRACE_EVENT_FL_FILTERED;
629 call->filter = __alloc_preds();
630 if (IS_ERR(call->filter))
631 return PTR_ERR(call->filter);
632
633 return 0; 815 return 0;
634} 816}
635 817
636static int init_subsystem_preds(struct event_subsystem *system) 818static void filter_free_subsystem_preds(struct event_subsystem *system)
637{ 819{
638 struct ftrace_event_call *call; 820 struct ftrace_event_call *call;
639 int err;
640 821
641 list_for_each_entry(call, &ftrace_events, list) { 822 list_for_each_entry(call, &ftrace_events, list) {
642 if (strcmp(call->class->system, system->name) != 0) 823 if (strcmp(call->class->system, system->name) != 0)
643 continue; 824 continue;
644 825
645 err = init_preds(call); 826 filter_disable(call);
646 if (err) 827 remove_filter_string(call->filter);
647 return err;
648 } 828 }
649
650 return 0;
651} 829}
652 830
653static void filter_free_subsystem_preds(struct event_subsystem *system) 831static void filter_free_subsystem_filters(struct event_subsystem *system)
654{ 832{
655 struct ftrace_event_call *call; 833 struct ftrace_event_call *call;
656 834
657 list_for_each_entry(call, &ftrace_events, list) { 835 list_for_each_entry(call, &ftrace_events, list) {
658 if (strcmp(call->class->system, system->name) != 0) 836 if (strcmp(call->class->system, system->name) != 0)
659 continue; 837 continue;
660 838 __free_filter(call->filter);
661 filter_disable_preds(call); 839 call->filter = NULL;
662 remove_filter_string(call->filter);
663 } 840 }
664} 841}
665 842
@@ -667,18 +844,19 @@ static int filter_add_pred_fn(struct filter_parse_state *ps,
667 struct ftrace_event_call *call, 844 struct ftrace_event_call *call,
668 struct event_filter *filter, 845 struct event_filter *filter,
669 struct filter_pred *pred, 846 struct filter_pred *pred,
847 struct pred_stack *stack,
670 filter_pred_fn_t fn) 848 filter_pred_fn_t fn)
671{ 849{
672 int idx, err; 850 int idx, err;
673 851
674 if (filter->n_preds == MAX_FILTER_PRED) { 852 if (WARN_ON(filter->n_preds == filter->a_preds)) {
675 parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0); 853 parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0);
676 return -ENOSPC; 854 return -ENOSPC;
677 } 855 }
678 856
679 idx = filter->n_preds; 857 idx = filter->n_preds;
680 filter_clear_pred(filter->preds[idx]); 858 filter_clear_pred(&filter->preds[idx]);
681 err = filter_set_pred(filter->preds[idx], pred, fn); 859 err = filter_set_pred(filter, idx, stack, pred, fn);
682 if (err) 860 if (err)
683 return err; 861 return err;
684 862
@@ -763,6 +941,7 @@ static int filter_add_pred(struct filter_parse_state *ps,
763 struct ftrace_event_call *call, 941 struct ftrace_event_call *call,
764 struct event_filter *filter, 942 struct event_filter *filter,
765 struct filter_pred *pred, 943 struct filter_pred *pred,
944 struct pred_stack *stack,
766 bool dry_run) 945 bool dry_run)
767{ 946{
768 struct ftrace_event_field *field; 947 struct ftrace_event_field *field;
@@ -770,17 +949,12 @@ static int filter_add_pred(struct filter_parse_state *ps,
770 unsigned long long val; 949 unsigned long long val;
771 int ret; 950 int ret;
772 951
773 pred->fn = filter_pred_none; 952 fn = pred->fn = filter_pred_none;
774 953
775 if (pred->op == OP_AND) { 954 if (pred->op == OP_AND)
776 pred->pop_n = 2;
777 fn = filter_pred_and;
778 goto add_pred_fn; 955 goto add_pred_fn;
779 } else if (pred->op == OP_OR) { 956 else if (pred->op == OP_OR)
780 pred->pop_n = 2;
781 fn = filter_pred_or;
782 goto add_pred_fn; 957 goto add_pred_fn;
783 }
784 958
785 field = find_event_field(call, pred->field_name); 959 field = find_event_field(call, pred->field_name);
786 if (!field) { 960 if (!field) {
@@ -829,7 +1003,7 @@ static int filter_add_pred(struct filter_parse_state *ps,
829 1003
830add_pred_fn: 1004add_pred_fn:
831 if (!dry_run) 1005 if (!dry_run)
832 return filter_add_pred_fn(ps, call, filter, pred, fn); 1006 return filter_add_pred_fn(ps, call, filter, pred, stack, fn);
833 return 0; 1007 return 0;
834} 1008}
835 1009
@@ -1187,6 +1361,234 @@ static int check_preds(struct filter_parse_state *ps)
1187 return 0; 1361 return 0;
1188} 1362}
1189 1363
1364static int count_preds(struct filter_parse_state *ps)
1365{
1366 struct postfix_elt *elt;
1367 int n_preds = 0;
1368
1369 list_for_each_entry(elt, &ps->postfix, list) {
1370 if (elt->op == OP_NONE)
1371 continue;
1372 n_preds++;
1373 }
1374
1375 return n_preds;
1376}
1377
1378/*
1379 * The tree is walked at filtering of an event. If the tree is not correctly
1380 * built, it may cause an infinite loop. Check here that the tree does
1381 * indeed terminate.
1382 */
1383static int check_pred_tree(struct event_filter *filter,
1384 struct filter_pred *root)
1385{
1386 struct filter_pred *preds;
1387 struct filter_pred *pred;
1388 enum move_type move = MOVE_DOWN;
1389 int count = 0;
1390 int done = 0;
1391 int max;
1392
1393 /*
1394 * The max that we can hit a node is three times.
1395 * Once going down, once coming up from left, and
1396 * once coming up from right. This is more than enough
1397 * since leafs are only hit a single time.
1398 */
1399 max = 3 * filter->n_preds;
1400
1401 preds = filter->preds;
1402 if (!preds)
1403 return -EINVAL;
1404 pred = root;
1405
1406 do {
1407 if (WARN_ON(count++ > max))
1408 return -EINVAL;
1409
1410 switch (move) {
1411 case MOVE_DOWN:
1412 if (pred->left != FILTER_PRED_INVALID) {
1413 pred = &preds[pred->left];
1414 continue;
1415 }
1416 /* A leaf at the root is just a leaf in the tree */
1417 if (pred == root)
1418 break;
1419 pred = get_pred_parent(pred, preds,
1420 pred->parent, &move);
1421 continue;
1422 case MOVE_UP_FROM_LEFT:
1423 pred = &preds[pred->right];
1424 move = MOVE_DOWN;
1425 continue;
1426 case MOVE_UP_FROM_RIGHT:
1427 if (pred == root)
1428 break;
1429 pred = get_pred_parent(pred, preds,
1430 pred->parent, &move);
1431 continue;
1432 }
1433 done = 1;
1434 } while (!done);
1435
1436 /* We are fine. */
1437 return 0;
1438}
1439
1440static int count_leafs(struct filter_pred *preds, struct filter_pred *root)
1441{
1442 struct filter_pred *pred;
1443 enum move_type move = MOVE_DOWN;
1444 int count = 0;
1445 int done = 0;
1446
1447 pred = root;
1448
1449 do {
1450 switch (move) {
1451 case MOVE_DOWN:
1452 if (pred->left != FILTER_PRED_INVALID) {
1453 pred = &preds[pred->left];
1454 continue;
1455 }
1456 /* A leaf at the root is just a leaf in the tree */
1457 if (pred == root)
1458 return 1;
1459 count++;
1460 pred = get_pred_parent(pred, preds,
1461 pred->parent, &move);
1462 continue;
1463 case MOVE_UP_FROM_LEFT:
1464 pred = &preds[pred->right];
1465 move = MOVE_DOWN;
1466 continue;
1467 case MOVE_UP_FROM_RIGHT:
1468 if (pred == root)
1469 break;
1470 pred = get_pred_parent(pred, preds,
1471 pred->parent, &move);
1472 continue;
1473 }
1474 done = 1;
1475 } while (!done);
1476
1477 return count;
1478}
1479
1480static int fold_pred(struct filter_pred *preds, struct filter_pred *root)
1481{
1482 struct filter_pred *pred;
1483 enum move_type move = MOVE_DOWN;
1484 int count = 0;
1485 int children;
1486 int done = 0;
1487
1488 /* No need to keep the fold flag */
1489 root->index &= ~FILTER_PRED_FOLD;
1490
1491 /* If the root is a leaf then do nothing */
1492 if (root->left == FILTER_PRED_INVALID)
1493 return 0;
1494
1495 /* count the children */
1496 children = count_leafs(preds, &preds[root->left]);
1497 children += count_leafs(preds, &preds[root->right]);
1498
1499 root->ops = kzalloc(sizeof(*root->ops) * children, GFP_KERNEL);
1500 if (!root->ops)
1501 return -ENOMEM;
1502
1503 root->val = children;
1504
1505 pred = root;
1506 do {
1507 switch (move) {
1508 case MOVE_DOWN:
1509 if (pred->left != FILTER_PRED_INVALID) {
1510 pred = &preds[pred->left];
1511 continue;
1512 }
1513 if (WARN_ON(count == children))
1514 return -EINVAL;
1515 pred->index &= ~FILTER_PRED_FOLD;
1516 root->ops[count++] = pred->index;
1517 pred = get_pred_parent(pred, preds,
1518 pred->parent, &move);
1519 continue;
1520 case MOVE_UP_FROM_LEFT:
1521 pred = &preds[pred->right];
1522 move = MOVE_DOWN;
1523 continue;
1524 case MOVE_UP_FROM_RIGHT:
1525 if (pred == root)
1526 break;
1527 pred = get_pred_parent(pred, preds,
1528 pred->parent, &move);
1529 continue;
1530 }
1531 done = 1;
1532 } while (!done);
1533
1534 return 0;
1535}
1536
1537/*
1538 * To optimize the processing of the ops, if we have several "ors" or
1539 * "ands" together, we can put them in an array and process them all
1540 * together speeding up the filter logic.
1541 */
1542static int fold_pred_tree(struct event_filter *filter,
1543 struct filter_pred *root)
1544{
1545 struct filter_pred *preds;
1546 struct filter_pred *pred;
1547 enum move_type move = MOVE_DOWN;
1548 int done = 0;
1549 int err;
1550
1551 preds = filter->preds;
1552 if (!preds)
1553 return -EINVAL;
1554 pred = root;
1555
1556 do {
1557 switch (move) {
1558 case MOVE_DOWN:
1559 if (pred->index & FILTER_PRED_FOLD) {
1560 err = fold_pred(preds, pred);
1561 if (err)
1562 return err;
1563 /* Folded nodes are like leafs */
1564 } else if (pred->left != FILTER_PRED_INVALID) {
1565 pred = &preds[pred->left];
1566 continue;
1567 }
1568
1569 /* A leaf at the root is just a leaf in the tree */
1570 if (pred == root)
1571 break;
1572 pred = get_pred_parent(pred, preds,
1573 pred->parent, &move);
1574 continue;
1575 case MOVE_UP_FROM_LEFT:
1576 pred = &preds[pred->right];
1577 move = MOVE_DOWN;
1578 continue;
1579 case MOVE_UP_FROM_RIGHT:
1580 if (pred == root)
1581 break;
1582 pred = get_pred_parent(pred, preds,
1583 pred->parent, &move);
1584 continue;
1585 }
1586 done = 1;
1587 } while (!done);
1588
1589 return 0;
1590}
1591
1190static int replace_preds(struct ftrace_event_call *call, 1592static int replace_preds(struct ftrace_event_call *call,
1191 struct event_filter *filter, 1593 struct event_filter *filter,
1192 struct filter_parse_state *ps, 1594 struct filter_parse_state *ps,
@@ -1195,14 +1597,32 @@ static int replace_preds(struct ftrace_event_call *call,
1195{ 1597{
1196 char *operand1 = NULL, *operand2 = NULL; 1598 char *operand1 = NULL, *operand2 = NULL;
1197 struct filter_pred *pred; 1599 struct filter_pred *pred;
1600 struct filter_pred *root;
1198 struct postfix_elt *elt; 1601 struct postfix_elt *elt;
1602 struct pred_stack stack = { }; /* init to NULL */
1199 int err; 1603 int err;
1200 int n_preds = 0; 1604 int n_preds = 0;
1201 1605
1606 n_preds = count_preds(ps);
1607 if (n_preds >= MAX_FILTER_PRED) {
1608 parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0);
1609 return -ENOSPC;
1610 }
1611
1202 err = check_preds(ps); 1612 err = check_preds(ps);
1203 if (err) 1613 if (err)
1204 return err; 1614 return err;
1205 1615
1616 if (!dry_run) {
1617 err = __alloc_pred_stack(&stack, n_preds);
1618 if (err)
1619 return err;
1620 err = __alloc_preds(filter, n_preds);
1621 if (err)
1622 goto fail;
1623 }
1624
1625 n_preds = 0;
1206 list_for_each_entry(elt, &ps->postfix, list) { 1626 list_for_each_entry(elt, &ps->postfix, list) {
1207 if (elt->op == OP_NONE) { 1627 if (elt->op == OP_NONE) {
1208 if (!operand1) 1628 if (!operand1)
@@ -1211,14 +1631,16 @@ static int replace_preds(struct ftrace_event_call *call,
1211 operand2 = elt->operand; 1631 operand2 = elt->operand;
1212 else { 1632 else {
1213 parse_error(ps, FILT_ERR_TOO_MANY_OPERANDS, 0); 1633 parse_error(ps, FILT_ERR_TOO_MANY_OPERANDS, 0);
1214 return -EINVAL; 1634 err = -EINVAL;
1635 goto fail;
1215 } 1636 }
1216 continue; 1637 continue;
1217 } 1638 }
1218 1639
1219 if (n_preds++ == MAX_FILTER_PRED) { 1640 if (WARN_ON(n_preds++ == MAX_FILTER_PRED)) {
1220 parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0); 1641 parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0);
1221 return -ENOSPC; 1642 err = -ENOSPC;
1643 goto fail;
1222 } 1644 }
1223 1645
1224 if (elt->op == OP_AND || elt->op == OP_OR) { 1646 if (elt->op == OP_AND || elt->op == OP_OR) {
@@ -1228,76 +1650,181 @@ static int replace_preds(struct ftrace_event_call *call,
1228 1650
1229 if (!operand1 || !operand2) { 1651 if (!operand1 || !operand2) {
1230 parse_error(ps, FILT_ERR_MISSING_FIELD, 0); 1652 parse_error(ps, FILT_ERR_MISSING_FIELD, 0);
1231 return -EINVAL; 1653 err = -EINVAL;
1654 goto fail;
1232 } 1655 }
1233 1656
1234 pred = create_pred(elt->op, operand1, operand2); 1657 pred = create_pred(elt->op, operand1, operand2);
1235add_pred: 1658add_pred:
1236 if (!pred) 1659 if (!pred) {
1237 return -ENOMEM; 1660 err = -ENOMEM;
1238 err = filter_add_pred(ps, call, filter, pred, dry_run); 1661 goto fail;
1662 }
1663 err = filter_add_pred(ps, call, filter, pred, &stack, dry_run);
1239 filter_free_pred(pred); 1664 filter_free_pred(pred);
1240 if (err) 1665 if (err)
1241 return err; 1666 goto fail;
1242 1667
1243 operand1 = operand2 = NULL; 1668 operand1 = operand2 = NULL;
1244 } 1669 }
1245 1670
1246 return 0; 1671 if (!dry_run) {
1672 /* We should have one item left on the stack */
1673 pred = __pop_pred_stack(&stack);
1674 if (!pred)
1675 return -EINVAL;
1676 /* This item is where we start from in matching */
1677 root = pred;
1678 /* Make sure the stack is empty */
1679 pred = __pop_pred_stack(&stack);
1680 if (WARN_ON(pred)) {
1681 err = -EINVAL;
1682 filter->root = NULL;
1683 goto fail;
1684 }
1685 err = check_pred_tree(filter, root);
1686 if (err)
1687 goto fail;
1688
1689 /* Optimize the tree */
1690 err = fold_pred_tree(filter, root);
1691 if (err)
1692 goto fail;
1693
1694 /* We don't set root until we know it works */
1695 barrier();
1696 filter->root = root;
1697 }
1698
1699 err = 0;
1700fail:
1701 __free_pred_stack(&stack);
1702 return err;
1247} 1703}
1248 1704
1705struct filter_list {
1706 struct list_head list;
1707 struct event_filter *filter;
1708};
1709
1249static int replace_system_preds(struct event_subsystem *system, 1710static int replace_system_preds(struct event_subsystem *system,
1250 struct filter_parse_state *ps, 1711 struct filter_parse_state *ps,
1251 char *filter_string) 1712 char *filter_string)
1252{ 1713{
1253 struct ftrace_event_call *call; 1714 struct ftrace_event_call *call;
1715 struct filter_list *filter_item;
1716 struct filter_list *tmp;
1717 LIST_HEAD(filter_list);
1254 bool fail = true; 1718 bool fail = true;
1255 int err; 1719 int err;
1256 1720
1257 list_for_each_entry(call, &ftrace_events, list) { 1721 list_for_each_entry(call, &ftrace_events, list) {
1258 struct event_filter *filter = call->filter;
1259 1722
1260 if (strcmp(call->class->system, system->name) != 0) 1723 if (strcmp(call->class->system, system->name) != 0)
1261 continue; 1724 continue;
1262 1725
1263 /* try to see if the filter can be applied */ 1726 /*
1264 err = replace_preds(call, filter, ps, filter_string, true); 1727 * Try to see if the filter can be applied
1728 * (filter arg is ignored on dry_run)
1729 */
1730 err = replace_preds(call, NULL, ps, filter_string, true);
1265 if (err) 1731 if (err)
1732 goto fail;
1733 }
1734
1735 list_for_each_entry(call, &ftrace_events, list) {
1736 struct event_filter *filter;
1737
1738 if (strcmp(call->class->system, system->name) != 0)
1266 continue; 1739 continue;
1267 1740
1268 /* really apply the filter */ 1741 filter_item = kzalloc(sizeof(*filter_item), GFP_KERNEL);
1269 filter_disable_preds(call); 1742 if (!filter_item)
1270 err = replace_preds(call, filter, ps, filter_string, false); 1743 goto fail_mem;
1744
1745 list_add_tail(&filter_item->list, &filter_list);
1746
1747 filter_item->filter = __alloc_filter();
1748 if (!filter_item->filter)
1749 goto fail_mem;
1750 filter = filter_item->filter;
1751
1752 /* Can only fail on no memory */
1753 err = replace_filter_string(filter, filter_string);
1271 if (err) 1754 if (err)
1272 filter_disable_preds(call); 1755 goto fail_mem;
1273 else { 1756
1757 err = replace_preds(call, filter, ps, filter_string, false);
1758 if (err) {
1759 filter_disable(call);
1760 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
1761 append_filter_err(ps, filter);
1762 } else
1274 call->flags |= TRACE_EVENT_FL_FILTERED; 1763 call->flags |= TRACE_EVENT_FL_FILTERED;
1275 replace_filter_string(filter, filter_string); 1764 /*
1276 } 1765 * Regardless of if this returned an error, we still
1766 * replace the filter for the call.
1767 */
1768 filter = call->filter;
1769 call->filter = filter_item->filter;
1770 filter_item->filter = filter;
1771
1277 fail = false; 1772 fail = false;
1278 } 1773 }
1279 1774
1280 if (fail) { 1775 if (fail)
1281 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0); 1776 goto fail;
1282 return -EINVAL; 1777
1778 /*
1779 * The calls can still be using the old filters.
1780 * Do a synchronize_sched() to ensure all calls are
1781 * done with them before we free them.
1782 */
1783 synchronize_sched();
1784 list_for_each_entry_safe(filter_item, tmp, &filter_list, list) {
1785 __free_filter(filter_item->filter);
1786 list_del(&filter_item->list);
1787 kfree(filter_item);
1283 } 1788 }
1284 return 0; 1789 return 0;
1790 fail:
1791 /* No call succeeded */
1792 list_for_each_entry_safe(filter_item, tmp, &filter_list, list) {
1793 list_del(&filter_item->list);
1794 kfree(filter_item);
1795 }
1796 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
1797 return -EINVAL;
1798 fail_mem:
1799 /* If any call succeeded, we still need to sync */
1800 if (!fail)
1801 synchronize_sched();
1802 list_for_each_entry_safe(filter_item, tmp, &filter_list, list) {
1803 __free_filter(filter_item->filter);
1804 list_del(&filter_item->list);
1805 kfree(filter_item);
1806 }
1807 return -ENOMEM;
1285} 1808}
1286 1809
1287int apply_event_filter(struct ftrace_event_call *call, char *filter_string) 1810int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
1288{ 1811{
1289 int err;
1290 struct filter_parse_state *ps; 1812 struct filter_parse_state *ps;
1813 struct event_filter *filter;
1814 struct event_filter *tmp;
1815 int err = 0;
1291 1816
1292 mutex_lock(&event_mutex); 1817 mutex_lock(&event_mutex);
1293 1818
1294 err = init_preds(call);
1295 if (err)
1296 goto out_unlock;
1297
1298 if (!strcmp(strstrip(filter_string), "0")) { 1819 if (!strcmp(strstrip(filter_string), "0")) {
1299 filter_disable_preds(call); 1820 filter_disable(call);
1300 remove_filter_string(call->filter); 1821 filter = call->filter;
1822 if (!filter)
1823 goto out_unlock;
1824 call->filter = NULL;
1825 /* Make sure the filter is not being used */
1826 synchronize_sched();
1827 __free_filter(filter);
1301 goto out_unlock; 1828 goto out_unlock;
1302 } 1829 }
1303 1830
@@ -1306,22 +1833,41 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
1306 if (!ps) 1833 if (!ps)
1307 goto out_unlock; 1834 goto out_unlock;
1308 1835
1309 filter_disable_preds(call); 1836 filter = __alloc_filter();
1310 replace_filter_string(call->filter, filter_string); 1837 if (!filter) {
1838 kfree(ps);
1839 goto out_unlock;
1840 }
1841
1842 replace_filter_string(filter, filter_string);
1311 1843
1312 parse_init(ps, filter_ops, filter_string); 1844 parse_init(ps, filter_ops, filter_string);
1313 err = filter_parse(ps); 1845 err = filter_parse(ps);
1314 if (err) { 1846 if (err) {
1315 append_filter_err(ps, call->filter); 1847 append_filter_err(ps, filter);
1316 goto out; 1848 goto out;
1317 } 1849 }
1318 1850
1319 err = replace_preds(call, call->filter, ps, filter_string, false); 1851 err = replace_preds(call, filter, ps, filter_string, false);
1320 if (err) 1852 if (err) {
1321 append_filter_err(ps, call->filter); 1853 filter_disable(call);
1322 else 1854 append_filter_err(ps, filter);
1855 } else
1323 call->flags |= TRACE_EVENT_FL_FILTERED; 1856 call->flags |= TRACE_EVENT_FL_FILTERED;
1324out: 1857out:
1858 /*
1859 * Always swap the call filter with the new filter
1860 * even if there was an error. If there was an error
1861 * in the filter, we disable the filter and show the error
1862 * string
1863 */
1864 tmp = call->filter;
1865 call->filter = filter;
1866 if (tmp) {
1867 /* Make sure the call is done with the filter */
1868 synchronize_sched();
1869 __free_filter(tmp);
1870 }
1325 filter_opstack_clear(ps); 1871 filter_opstack_clear(ps);
1326 postfix_clear(ps); 1872 postfix_clear(ps);
1327 kfree(ps); 1873 kfree(ps);
@@ -1334,18 +1880,21 @@ out_unlock:
1334int apply_subsystem_event_filter(struct event_subsystem *system, 1880int apply_subsystem_event_filter(struct event_subsystem *system,
1335 char *filter_string) 1881 char *filter_string)
1336{ 1882{
1337 int err;
1338 struct filter_parse_state *ps; 1883 struct filter_parse_state *ps;
1884 struct event_filter *filter;
1885 int err = 0;
1339 1886
1340 mutex_lock(&event_mutex); 1887 mutex_lock(&event_mutex);
1341 1888
1342 err = init_subsystem_preds(system);
1343 if (err)
1344 goto out_unlock;
1345
1346 if (!strcmp(strstrip(filter_string), "0")) { 1889 if (!strcmp(strstrip(filter_string), "0")) {
1347 filter_free_subsystem_preds(system); 1890 filter_free_subsystem_preds(system);
1348 remove_filter_string(system->filter); 1891 remove_filter_string(system->filter);
1892 filter = system->filter;
1893 system->filter = NULL;
1894 /* Ensure all filters are no longer used */
1895 synchronize_sched();
1896 filter_free_subsystem_filters(system);
1897 __free_filter(filter);
1349 goto out_unlock; 1898 goto out_unlock;
1350 } 1899 }
1351 1900
@@ -1354,7 +1903,17 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
1354 if (!ps) 1903 if (!ps)
1355 goto out_unlock; 1904 goto out_unlock;
1356 1905
1357 replace_filter_string(system->filter, filter_string); 1906 filter = __alloc_filter();
1907 if (!filter)
1908 goto out;
1909
1910 replace_filter_string(filter, filter_string);
1911 /*
1912 * No event actually uses the system filter
1913 * we can free it without synchronize_sched().
1914 */
1915 __free_filter(system->filter);
1916 system->filter = filter;
1358 1917
1359 parse_init(ps, filter_ops, filter_string); 1918 parse_init(ps, filter_ops, filter_string);
1360 err = filter_parse(ps); 1919 err = filter_parse(ps);
@@ -1384,7 +1943,7 @@ void ftrace_profile_free_filter(struct perf_event *event)
1384 struct event_filter *filter = event->filter; 1943 struct event_filter *filter = event->filter;
1385 1944
1386 event->filter = NULL; 1945 event->filter = NULL;
1387 __free_preds(filter); 1946 __free_filter(filter);
1388} 1947}
1389 1948
1390int ftrace_profile_set_filter(struct perf_event *event, int event_id, 1949int ftrace_profile_set_filter(struct perf_event *event, int event_id,
@@ -1410,8 +1969,8 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id,
1410 if (event->filter) 1969 if (event->filter)
1411 goto out_unlock; 1970 goto out_unlock;
1412 1971
1413 filter = __alloc_preds(); 1972 filter = __alloc_filter();
1414 if (IS_ERR(filter)) { 1973 if (!filter) {
1415 err = PTR_ERR(filter); 1974 err = PTR_ERR(filter);
1416 goto out_unlock; 1975 goto out_unlock;
1417 } 1976 }
@@ -1419,7 +1978,7 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id,
1419 err = -ENOMEM; 1978 err = -ENOMEM;
1420 ps = kzalloc(sizeof(*ps), GFP_KERNEL); 1979 ps = kzalloc(sizeof(*ps), GFP_KERNEL);
1421 if (!ps) 1980 if (!ps)
1422 goto free_preds; 1981 goto free_filter;
1423 1982
1424 parse_init(ps, filter_ops, filter_str); 1983 parse_init(ps, filter_ops, filter_str);
1425 err = filter_parse(ps); 1984 err = filter_parse(ps);
@@ -1435,9 +1994,9 @@ free_ps:
1435 postfix_clear(ps); 1994 postfix_clear(ps);
1436 kfree(ps); 1995 kfree(ps);
1437 1996
1438free_preds: 1997free_filter:
1439 if (err) 1998 if (err)
1440 __free_preds(filter); 1999 __free_filter(filter);
1441 2000
1442out_unlock: 2001out_unlock:
1443 mutex_unlock(&event_mutex); 2002 mutex_unlock(&event_mutex);
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 2dec9bcde8b4..8435b43b1782 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -353,6 +353,43 @@ static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data)
353 kfree(data); 353 kfree(data);
354} 354}
355 355
356/* Bitfield fetch function */
357struct bitfield_fetch_param {
358 struct fetch_param orig;
359 unsigned char hi_shift;
360 unsigned char low_shift;
361};
362
363#define DEFINE_FETCH_bitfield(type) \
364static __kprobes void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs,\
365 void *data, void *dest) \
366{ \
367 struct bitfield_fetch_param *bprm = data; \
368 type buf = 0; \
369 call_fetch(&bprm->orig, regs, &buf); \
370 if (buf) { \
371 buf <<= bprm->hi_shift; \
372 buf >>= bprm->low_shift; \
373 } \
374 *(type *)dest = buf; \
375}
376DEFINE_BASIC_FETCH_FUNCS(bitfield)
377#define fetch_bitfield_string NULL
378#define fetch_bitfield_string_size NULL
379
380static __kprobes void
381free_bitfield_fetch_param(struct bitfield_fetch_param *data)
382{
383 /*
384 * Don't check the bitfield itself, because this must be the
385 * last fetch function.
386 */
387 if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
388 free_deref_fetch_param(data->orig.data);
389 else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
390 free_symbol_cache(data->orig.data);
391 kfree(data);
392}
356/* Default (unsigned long) fetch type */ 393/* Default (unsigned long) fetch type */
357#define __DEFAULT_FETCH_TYPE(t) u##t 394#define __DEFAULT_FETCH_TYPE(t) u##t
358#define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) 395#define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t)
@@ -367,6 +404,7 @@ enum {
367 FETCH_MTD_memory, 404 FETCH_MTD_memory,
368 FETCH_MTD_symbol, 405 FETCH_MTD_symbol,
369 FETCH_MTD_deref, 406 FETCH_MTD_deref,
407 FETCH_MTD_bitfield,
370 FETCH_MTD_END, 408 FETCH_MTD_END,
371}; 409};
372 410
@@ -387,6 +425,7 @@ ASSIGN_FETCH_FUNC(retval, ftype), \
387ASSIGN_FETCH_FUNC(memory, ftype), \ 425ASSIGN_FETCH_FUNC(memory, ftype), \
388ASSIGN_FETCH_FUNC(symbol, ftype), \ 426ASSIGN_FETCH_FUNC(symbol, ftype), \
389ASSIGN_FETCH_FUNC(deref, ftype), \ 427ASSIGN_FETCH_FUNC(deref, ftype), \
428ASSIGN_FETCH_FUNC(bitfield, ftype), \
390 } \ 429 } \
391 } 430 }
392 431
@@ -430,9 +469,33 @@ static const struct fetch_type *find_fetch_type(const char *type)
430 if (!type) 469 if (!type)
431 type = DEFAULT_FETCH_TYPE_STR; 470 type = DEFAULT_FETCH_TYPE_STR;
432 471
472 /* Special case: bitfield */
473 if (*type == 'b') {
474 unsigned long bs;
475 type = strchr(type, '/');
476 if (!type)
477 goto fail;
478 type++;
479 if (strict_strtoul(type, 0, &bs))
480 goto fail;
481 switch (bs) {
482 case 8:
483 return find_fetch_type("u8");
484 case 16:
485 return find_fetch_type("u16");
486 case 32:
487 return find_fetch_type("u32");
488 case 64:
489 return find_fetch_type("u64");
490 default:
491 goto fail;
492 }
493 }
494
433 for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) 495 for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++)
434 if (strcmp(type, fetch_type_table[i].name) == 0) 496 if (strcmp(type, fetch_type_table[i].name) == 0)
435 return &fetch_type_table[i]; 497 return &fetch_type_table[i];
498fail:
436 return NULL; 499 return NULL;
437} 500}
438 501
@@ -586,7 +649,9 @@ error:
586 649
587static void free_probe_arg(struct probe_arg *arg) 650static void free_probe_arg(struct probe_arg *arg)
588{ 651{
589 if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) 652 if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn))
653 free_bitfield_fetch_param(arg->fetch.data);
654 else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn))
590 free_deref_fetch_param(arg->fetch.data); 655 free_deref_fetch_param(arg->fetch.data);
591 else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) 656 else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn))
592 free_symbol_cache(arg->fetch.data); 657 free_symbol_cache(arg->fetch.data);
@@ -767,16 +832,15 @@ static int __parse_probe_arg(char *arg, const struct fetch_type *t,
767 } 832 }
768 break; 833 break;
769 case '+': /* deref memory */ 834 case '+': /* deref memory */
835 arg++; /* Skip '+', because strict_strtol() rejects it. */
770 case '-': 836 case '-':
771 tmp = strchr(arg, '('); 837 tmp = strchr(arg, '(');
772 if (!tmp) 838 if (!tmp)
773 break; 839 break;
774 *tmp = '\0'; 840 *tmp = '\0';
775 ret = strict_strtol(arg + 1, 0, &offset); 841 ret = strict_strtol(arg, 0, &offset);
776 if (ret) 842 if (ret)
777 break; 843 break;
778 if (arg[0] == '-')
779 offset = -offset;
780 arg = tmp + 1; 844 arg = tmp + 1;
781 tmp = strrchr(arg, ')'); 845 tmp = strrchr(arg, ')');
782 if (tmp) { 846 if (tmp) {
@@ -807,6 +871,41 @@ static int __parse_probe_arg(char *arg, const struct fetch_type *t,
807 return ret; 871 return ret;
808} 872}
809 873
874#define BYTES_TO_BITS(nb) ((BITS_PER_LONG * (nb)) / sizeof(long))
875
876/* Bitfield type needs to be parsed into a fetch function */
877static int __parse_bitfield_probe_arg(const char *bf,
878 const struct fetch_type *t,
879 struct fetch_param *f)
880{
881 struct bitfield_fetch_param *bprm;
882 unsigned long bw, bo;
883 char *tail;
884
885 if (*bf != 'b')
886 return 0;
887
888 bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
889 if (!bprm)
890 return -ENOMEM;
891 bprm->orig = *f;
892 f->fn = t->fetch[FETCH_MTD_bitfield];
893 f->data = (void *)bprm;
894
895 bw = simple_strtoul(bf + 1, &tail, 0); /* Use simple one */
896 if (bw == 0 || *tail != '@')
897 return -EINVAL;
898
899 bf = tail + 1;
900 bo = simple_strtoul(bf, &tail, 0);
901 if (tail == bf || *tail != '/')
902 return -EINVAL;
903
904 bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo);
905 bprm->low_shift = bprm->hi_shift + bo;
906 return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0;
907}
908
810/* String length checking wrapper */ 909/* String length checking wrapper */
811static int parse_probe_arg(char *arg, struct trace_probe *tp, 910static int parse_probe_arg(char *arg, struct trace_probe *tp,
812 struct probe_arg *parg, int is_return) 911 struct probe_arg *parg, int is_return)
@@ -836,6 +935,8 @@ static int parse_probe_arg(char *arg, struct trace_probe *tp,
836 parg->offset = tp->size; 935 parg->offset = tp->size;
837 tp->size += parg->type->size; 936 tp->size += parg->type->size;
838 ret = __parse_probe_arg(arg, parg->type, &parg->fetch, is_return); 937 ret = __parse_probe_arg(arg, parg->type, &parg->fetch, is_return);
938 if (ret >= 0 && t != NULL)
939 ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch);
839 if (ret >= 0) { 940 if (ret >= 0) {
840 parg->fetch_size.fn = get_fetch_size_function(parg->type, 941 parg->fetch_size.fn = get_fetch_size_function(parg->type,
841 parg->fetch.fn); 942 parg->fetch.fn);
@@ -1130,7 +1231,7 @@ static int command_trace_probe(const char *buf)
1130 return ret; 1231 return ret;
1131} 1232}
1132 1233
1133#define WRITE_BUFSIZE 128 1234#define WRITE_BUFSIZE 4096
1134 1235
1135static ssize_t probes_write(struct file *file, const char __user *buffer, 1236static ssize_t probes_write(struct file *file, const char __user *buffer,
1136 size_t count, loff_t *ppos) 1237 size_t count, loff_t *ppos)
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index 02272baa2206..456be9063c2d 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -529,24 +529,34 @@ seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
529 * @entry: The trace entry field from the ring buffer 529 * @entry: The trace entry field from the ring buffer
530 * 530 *
531 * Prints the generic fields of irqs off, in hard or softirq, preempt 531 * Prints the generic fields of irqs off, in hard or softirq, preempt
532 * count and lock depth. 532 * count.
533 */ 533 */
534int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry) 534int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
535{ 535{
536 int hardirq, softirq; 536 char hardsoft_irq;
537 char need_resched;
538 char irqs_off;
539 int hardirq;
540 int softirq;
537 int ret; 541 int ret;
538 542
539 hardirq = entry->flags & TRACE_FLAG_HARDIRQ; 543 hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
540 softirq = entry->flags & TRACE_FLAG_SOFTIRQ; 544 softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
541 545
546 irqs_off =
547 (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
548 (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' :
549 '.';
550 need_resched =
551 (entry->flags & TRACE_FLAG_NEED_RESCHED) ? 'N' : '.';
552 hardsoft_irq =
553 (hardirq && softirq) ? 'H' :
554 hardirq ? 'h' :
555 softirq ? 's' :
556 '.';
557
542 if (!trace_seq_printf(s, "%c%c%c", 558 if (!trace_seq_printf(s, "%c%c%c",
543 (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : 559 irqs_off, need_resched, hardsoft_irq))
544 (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
545 'X' : '.',
546 (entry->flags & TRACE_FLAG_NEED_RESCHED) ?
547 'N' : '.',
548 (hardirq && softirq) ? 'H' :
549 hardirq ? 'h' : softirq ? 's' : '.'))
550 return 0; 560 return 0;
551 561
552 if (entry->preempt_count) 562 if (entry->preempt_count)
@@ -554,13 +564,7 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
554 else 564 else
555 ret = trace_seq_putc(s, '.'); 565 ret = trace_seq_putc(s, '.');
556 566
557 if (!ret) 567 return ret;
558 return 0;
559
560 if (entry->lock_depth < 0)
561 return trace_seq_putc(s, '.');
562
563 return trace_seq_printf(s, "%d", entry->lock_depth);
564} 568}
565 569
566static int 570static int
diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c
index 8f758d070c43..7e62c0a18456 100644
--- a/kernel/trace/trace_sched_switch.c
+++ b/kernel/trace/trace_sched_switch.c
@@ -247,51 +247,3 @@ void tracing_sched_switch_assign_trace(struct trace_array *tr)
247 ctx_trace = tr; 247 ctx_trace = tr;
248} 248}
249 249
250static void stop_sched_trace(struct trace_array *tr)
251{
252 tracing_stop_sched_switch_record();
253}
254
255static int sched_switch_trace_init(struct trace_array *tr)
256{
257 ctx_trace = tr;
258 tracing_reset_online_cpus(tr);
259 tracing_start_sched_switch_record();
260 return 0;
261}
262
263static void sched_switch_trace_reset(struct trace_array *tr)
264{
265 if (sched_ref)
266 stop_sched_trace(tr);
267}
268
269static void sched_switch_trace_start(struct trace_array *tr)
270{
271 sched_stopped = 0;
272}
273
274static void sched_switch_trace_stop(struct trace_array *tr)
275{
276 sched_stopped = 1;
277}
278
279static struct tracer sched_switch_trace __read_mostly =
280{
281 .name = "sched_switch",
282 .init = sched_switch_trace_init,
283 .reset = sched_switch_trace_reset,
284 .start = sched_switch_trace_start,
285 .stop = sched_switch_trace_stop,
286 .wait_pipe = poll_wait_pipe,
287#ifdef CONFIG_FTRACE_SELFTEST
288 .selftest = trace_selftest_startup_sched_switch,
289#endif
290};
291
292__init static int init_sched_switch_trace(void)
293{
294 return register_tracer(&sched_switch_trace);
295}
296device_initcall(init_sched_switch_trace);
297
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 5c9fe08d2093..ee7b5a0bb9f8 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -60,6 +60,19 @@ extern struct syscall_metadata *__stop_syscalls_metadata[];
60 60
61static struct syscall_metadata **syscalls_metadata; 61static struct syscall_metadata **syscalls_metadata;
62 62
63#ifndef ARCH_HAS_SYSCALL_MATCH_SYM_NAME
64static inline bool arch_syscall_match_sym_name(const char *sym, const char *name)
65{
66 /*
67 * Only compare after the "sys" prefix. Archs that use
68 * syscall wrappers may have syscalls symbols aliases prefixed
69 * with "SyS" instead of "sys", leading to an unwanted
70 * mismatch.
71 */
72 return !strcmp(sym + 3, name + 3);
73}
74#endif
75
63static __init struct syscall_metadata * 76static __init struct syscall_metadata *
64find_syscall_meta(unsigned long syscall) 77find_syscall_meta(unsigned long syscall)
65{ 78{
@@ -72,14 +85,11 @@ find_syscall_meta(unsigned long syscall)
72 stop = __stop_syscalls_metadata; 85 stop = __stop_syscalls_metadata;
73 kallsyms_lookup(syscall, NULL, NULL, NULL, str); 86 kallsyms_lookup(syscall, NULL, NULL, NULL, str);
74 87
88 if (arch_syscall_match_sym_name(str, "sys_ni_syscall"))
89 return NULL;
90
75 for ( ; start < stop; start++) { 91 for ( ; start < stop; start++) {
76 /* 92 if ((*start)->name && arch_syscall_match_sym_name(str, (*start)->name))
77 * Only compare after the "sys" prefix. Archs that use
78 * syscall wrappers may have syscalls symbols aliases prefixed
79 * with "SyS" instead of "sys", leading to an unwanted
80 * mismatch.
81 */
82 if ((*start)->name && !strcmp((*start)->name + 3, str + 3))
83 return *start; 93 return *start;
84 } 94 }
85 return NULL; 95 return NULL;
@@ -359,7 +369,7 @@ int reg_event_syscall_enter(struct ftrace_event_call *call)
359 int num; 369 int num;
360 370
361 num = ((struct syscall_metadata *)call->data)->syscall_nr; 371 num = ((struct syscall_metadata *)call->data)->syscall_nr;
362 if (num < 0 || num >= NR_syscalls) 372 if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
363 return -ENOSYS; 373 return -ENOSYS;
364 mutex_lock(&syscall_trace_lock); 374 mutex_lock(&syscall_trace_lock);
365 if (!sys_refcount_enter) 375 if (!sys_refcount_enter)
@@ -377,7 +387,7 @@ void unreg_event_syscall_enter(struct ftrace_event_call *call)
377 int num; 387 int num;
378 388
379 num = ((struct syscall_metadata *)call->data)->syscall_nr; 389 num = ((struct syscall_metadata *)call->data)->syscall_nr;
380 if (num < 0 || num >= NR_syscalls) 390 if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
381 return; 391 return;
382 mutex_lock(&syscall_trace_lock); 392 mutex_lock(&syscall_trace_lock);
383 sys_refcount_enter--; 393 sys_refcount_enter--;
@@ -393,7 +403,7 @@ int reg_event_syscall_exit(struct ftrace_event_call *call)
393 int num; 403 int num;
394 404
395 num = ((struct syscall_metadata *)call->data)->syscall_nr; 405 num = ((struct syscall_metadata *)call->data)->syscall_nr;
396 if (num < 0 || num >= NR_syscalls) 406 if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
397 return -ENOSYS; 407 return -ENOSYS;
398 mutex_lock(&syscall_trace_lock); 408 mutex_lock(&syscall_trace_lock);
399 if (!sys_refcount_exit) 409 if (!sys_refcount_exit)
@@ -411,7 +421,7 @@ void unreg_event_syscall_exit(struct ftrace_event_call *call)
411 int num; 421 int num;
412 422
413 num = ((struct syscall_metadata *)call->data)->syscall_nr; 423 num = ((struct syscall_metadata *)call->data)->syscall_nr;
414 if (num < 0 || num >= NR_syscalls) 424 if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
415 return; 425 return;
416 mutex_lock(&syscall_trace_lock); 426 mutex_lock(&syscall_trace_lock);
417 sys_refcount_exit--; 427 sys_refcount_exit--;
@@ -424,6 +434,14 @@ void unreg_event_syscall_exit(struct ftrace_event_call *call)
424int init_syscall_trace(struct ftrace_event_call *call) 434int init_syscall_trace(struct ftrace_event_call *call)
425{ 435{
426 int id; 436 int id;
437 int num;
438
439 num = ((struct syscall_metadata *)call->data)->syscall_nr;
440 if (num < 0 || num >= NR_syscalls) {
441 pr_debug("syscall %s metadata not mapped, disabling ftrace event\n",
442 ((struct syscall_metadata *)call->data)->name);
443 return -ENOSYS;
444 }
427 445
428 if (set_syscall_print_fmt(call) < 0) 446 if (set_syscall_print_fmt(call) < 0)
429 return -ENOMEM; 447 return -ENOMEM;
@@ -438,7 +456,7 @@ int init_syscall_trace(struct ftrace_event_call *call)
438 return id; 456 return id;
439} 457}
440 458
441unsigned long __init arch_syscall_addr(int nr) 459unsigned long __init __weak arch_syscall_addr(int nr)
442{ 460{
443 return (unsigned long)sys_call_table[nr]; 461 return (unsigned long)sys_call_table[nr];
444} 462}
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index fd81fc33d633..a4fe923c0131 100644
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -1,6 +1,6 @@
1#!/usr/bin/perl -w 1#!/usr/bin/perl -w
2# 2#
3# Copywrite 2005-2009 - Steven Rostedt 3# Copyright 2005-2009 - Steven Rostedt
4# Licensed under the terms of the GNU GPL License version 2 4# Licensed under the terms of the GNU GPL License version 2
5# 5#
6# It's simple enough to figure out how this works. 6# It's simple enough to figure out how this works.
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 038b3d1e2981..f9f6f52db772 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -206,7 +206,8 @@ static uint32_t (*w2)(uint16_t);
206static int 206static int
207is_mcounted_section_name(char const *const txtname) 207is_mcounted_section_name(char const *const txtname)
208{ 208{
209 return 0 == strcmp(".text", txtname) || 209 return 0 == strcmp(".text", txtname) ||
210 0 == strcmp(".ref.text", txtname) ||
210 0 == strcmp(".sched.text", txtname) || 211 0 == strcmp(".sched.text", txtname) ||
211 0 == strcmp(".spinlock.text", txtname) || 212 0 == strcmp(".spinlock.text", txtname) ||
212 0 == strcmp(".irqentry.text", txtname) || 213 0 == strcmp(".irqentry.text", txtname) ||
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 1d7963f4ee79..4be0deea71ca 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -130,6 +130,7 @@ if ($inputfile =~ m,kernel/trace/ftrace\.o$,) {
130# Acceptable sections to record. 130# Acceptable sections to record.
131my %text_sections = ( 131my %text_sections = (
132 ".text" => 1, 132 ".text" => 1,
133 ".ref.text" => 1,
133 ".sched.text" => 1, 134 ".sched.text" => 1,
134 ".spinlock.text" => 1, 135 ".spinlock.text" => 1,
135 ".irqentry.text" => 1, 136 ".irqentry.text" => 1,
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index cb43289e447f..416684be0ad3 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -1,4 +1,3 @@
1PERF-BUILD-OPTIONS
2PERF-CFLAGS 1PERF-CFLAGS
3PERF-GUI-VARS 2PERF-GUI-VARS
4PERF-VERSION-FILE 3PERF-VERSION-FILE
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index bd498d496952..4626a398836a 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -178,8 +178,8 @@ install-pdf: pdf
178 $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir) 178 $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir)
179 $(INSTALL) -m 644 user-manual.pdf $(DESTDIR)$(pdfdir) 179 $(INSTALL) -m 644 user-manual.pdf $(DESTDIR)$(pdfdir)
180 180
181install-html: html 181#install-html: html
182 '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir) 182# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
183 183
184../PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE 184../PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
185 $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) PERF-VERSION-FILE 185 $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) PERF-VERSION-FILE
@@ -288,15 +288,16 @@ $(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
288 sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+ && \ 288 sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+ && \
289 mv $@+ $@ 289 mv $@+ $@
290 290
291install-webdoc : html 291# UNIMPLEMENTED
292 '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(WEBDOC_DEST) 292#install-webdoc : html
293# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(WEBDOC_DEST)
293 294
294quick-install: quick-install-man 295# quick-install: quick-install-man
295 296
296quick-install-man: 297# quick-install-man:
297 '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(DOC_REF) $(DESTDIR)$(mandir) 298# '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(DOC_REF) $(DESTDIR)$(mandir)
298 299
299quick-install-html: 300#quick-install-html:
300 '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir) 301# '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir)
301 302
302.PHONY: .FORCE-PERF-VERSION-FILE 303.PHONY: .FORCE-PERF-VERSION-FILE
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 399751befeed..7a527f7e9da9 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -8,7 +8,7 @@ perf-list - List all symbolic event types
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf list' 11'perf list' [hw|sw|cache|tracepoint|event_glob]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
@@ -63,7 +63,26 @@ details. Some of them are referenced in the SEE ALSO section below.
63 63
64OPTIONS 64OPTIONS
65------- 65-------
66None 66
67Without options all known events will be listed.
68
69To limit the list use:
70
71. 'hw' or 'hardware' to list hardware events such as cache-misses, etc.
72
73. 'sw' or 'software' to list software events such as context switches, etc.
74
75. 'cache' or 'hwcache' to list hardware cache events such as L1-dcache-loads, etc.
76
77. 'tracepoint' to list all tracepoint events, alternatively use
78 'subsys_glob:event_glob' to filter by tracepoint subsystems such as sched,
79 block, etc.
80
81. If none of the above is matched, it will apply the supplied glob to all
82 events, printing the ones that match.
83
84One or more types can be used at the same time, listing the events for the
85types specified.
67 86
68SEE ALSO 87SEE ALSO
69-------- 88--------
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index 921de259ea10..4a26a2f3a6a3 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -24,8 +24,8 @@ and statistics with this 'perf lock' command.
24 24
25 'perf lock report' reports statistical data. 25 'perf lock report' reports statistical data.
26 26
27OPTIONS 27COMMON OPTIONS
28------- 28--------------
29 29
30-i:: 30-i::
31--input=<file>:: 31--input=<file>::
@@ -39,6 +39,14 @@ OPTIONS
39--dump-raw-trace:: 39--dump-raw-trace::
40 Dump raw trace in ASCII. 40 Dump raw trace in ASCII.
41 41
42REPORT OPTIONS
43--------------
44
45-k::
46--key=<value>::
47 Sorting key. Possible values: acquired (default), contended,
48 wait_total, wait_max, wait_min.
49
42SEE ALSO 50SEE ALSO
43-------- 51--------
44linkperf:perf[1] 52linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 86b797a35aa6..02bafce4b341 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -16,7 +16,7 @@ or
16or 16or
17'perf probe' --list 17'perf probe' --list
18or 18or
19'perf probe' [options] --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]' 19'perf probe' [options] --line='LINE'
20or 20or
21'perf probe' [options] --vars='PROBEPOINT' 21'perf probe' [options] --vars='PROBEPOINT'
22 22
@@ -73,6 +73,17 @@ OPTIONS
73 (Only for --vars) Show external defined variables in addition to local 73 (Only for --vars) Show external defined variables in addition to local
74 variables. 74 variables.
75 75
76-F::
77--funcs::
78 Show available functions in given module or kernel.
79
80--filter=FILTER::
81 (Only for --vars and --funcs) Set filter. FILTER is a combination of glob
82 pattern, see FILTER PATTERN for detail.
83 Default FILTER is "!__k???tab_* & !__crc_*" for --vars, and "!_*"
84 for --funcs.
85 If several filters are specified, only the last filter is used.
86
76-f:: 87-f::
77--force:: 88--force::
78 Forcibly add events with existing name. 89 Forcibly add events with existing name.
@@ -117,13 +128,14 @@ LINE SYNTAX
117----------- 128-----------
118Line range is described by following syntax. 129Line range is described by following syntax.
119 130
120 "FUNC[:RLN[+NUM|-RLN2]]|SRC[:ALN[+NUM|-ALN2]]" 131 "FUNC[@SRC][:RLN[+NUM|-RLN2]]|SRC[:ALN[+NUM|-ALN2]]"
121 132
122FUNC specifies the function name of showing lines. 'RLN' is the start line 133FUNC specifies the function name of showing lines. 'RLN' is the start line
123number from function entry line, and 'RLN2' is the end line number. As same as 134number from function entry line, and 'RLN2' is the end line number. As same as
124probe syntax, 'SRC' means the source file path, 'ALN' is start line number, 135probe syntax, 'SRC' means the source file path, 'ALN' is start line number,
125and 'ALN2' is end line number in the file. It is also possible to specify how 136and 'ALN2' is end line number in the file. It is also possible to specify how
126many lines to show by using 'NUM'. 137many lines to show by using 'NUM'. Moreover, 'FUNC@SRC' combination is good
138for searching a specific function when several functions share same name.
127So, "source.c:100-120" shows lines between 100th to l20th in source.c file. And "func:10+20" shows 20 lines from 10th line of func function. 139So, "source.c:100-120" shows lines between 100th to l20th in source.c file. And "func:10+20" shows 20 lines from 10th line of func function.
128 140
129LAZY MATCHING 141LAZY MATCHING
@@ -135,6 +147,14 @@ e.g.
135 147
136This provides some sort of flexibility and robustness to probe point definitions against minor code changes. For example, actual 10th line of schedule() can be moved easily by modifying schedule(), but the same line matching 'rq=cpu_rq*' may still exist in the function.) 148This provides some sort of flexibility and robustness to probe point definitions against minor code changes. For example, actual 10th line of schedule() can be moved easily by modifying schedule(), but the same line matching 'rq=cpu_rq*' may still exist in the function.)
137 149
150FILTER PATTERN
151--------------
152 The filter pattern is a glob matching pattern(s) to filter variables.
153 In addition, you can use "!" for specifying filter-out rule. You also can give several rules combined with "&" or "|", and fold those rules as one rule by using "(" ")".
154
155e.g.
156 With --filter "foo* | bar*", perf probe -V shows variables which start with "foo" or "bar".
157 With --filter "!foo* & *bar", perf probe -V shows variables which don't start with "foo" and end with "bar", like "fizzbar". But "foobar" is filtered out.
138 158
139EXAMPLES 159EXAMPLES
140-------- 160--------
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index e032716c839b..5a520f825295 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -137,6 +137,17 @@ Do not update the builid cache. This saves some overhead in situations
137where the information in the perf.data file (which includes buildids) 137where the information in the perf.data file (which includes buildids)
138is sufficient. 138is sufficient.
139 139
140-G name,...::
141--cgroup name,...::
142monitor only in the container (cgroup) called "name". This option is available only
143in per-cpu mode. The cgroup filesystem must be mounted. All threads belonging to
144container "name" are monitored when they run on the monitored CPUs. Multiple cgroups
145can be provided. Each cgroup is applied to the corresponding event, i.e., first cgroup
146to first event, second cgroup to second event and so on. It is possible to provide
147an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
148corresponding events, i.e., they always refer to events defined earlier on the command
149line.
150
140SEE ALSO 151SEE ALSO
141-------- 152--------
142linkperf:perf-stat[1], linkperf:perf-list[1] 153linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index b6da7affbbee..918cc38ee6d1 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -83,6 +83,17 @@ This option is only valid in system-wide mode.
83print counts using a CSV-style output to make it easy to import directly into 83print counts using a CSV-style output to make it easy to import directly into
84spreadsheets. Columns are separated by the string specified in SEP. 84spreadsheets. Columns are separated by the string specified in SEP.
85 85
86-G name::
87--cgroup name::
88monitor only in the container (cgroup) called "name". This option is available only
89in per-cpu mode. The cgroup filesystem must be mounted. All threads belonging to
90container "name" are monitored when they run on the monitored CPUs. Multiple cgroups
91can be provided. Each cgroup is applied to the corresponding event, i.e., first cgroup
92to first event, second cgroup to second event and so on. It is possible to provide
93an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
94corresponding events, i.e., they always refer to events defined earlier on the command
95line.
96
86EXAMPLES 97EXAMPLES
87-------- 98--------
88 99
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 7141c42e1469..9b8421805c5c 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -3,7 +3,7 @@ ifeq ("$(origin O)", "command line")
3endif 3endif
4 4
5# The default target of this Makefile is... 5# The default target of this Makefile is...
6all:: 6all:
7 7
8ifneq ($(OUTPUT),) 8ifneq ($(OUTPUT),)
9# check that the output directory actually exists 9# check that the output directory actually exists
@@ -11,152 +11,12 @@ OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd)
11$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist)) 11$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
12endif 12endif
13 13
14# Define V=1 to have a more verbose compile. 14# Define V to have a more verbose compile.
15# Define V=2 to have an even more verbose compile.
16#
17# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
18# or vsnprintf() return -1 instead of number of characters which would
19# have been written to the final string if enough space had been available.
20#
21# Define FREAD_READS_DIRECTORIES if your are on a system which succeeds
22# when attempting to read from an fopen'ed directory.
23#
24# Define NO_OPENSSL environment variable if you do not have OpenSSL.
25# This also implies MOZILLA_SHA1.
26#
27# Define CURLDIR=/foo/bar if your curl header and library files are in
28# /foo/bar/include and /foo/bar/lib directories.
29#
30# Define EXPATDIR=/foo/bar if your expat header and library files are in
31# /foo/bar/include and /foo/bar/lib directories.
32#
33# Define NO_D_INO_IN_DIRENT if you don't have d_ino in your struct dirent.
34#
35# Define NO_D_TYPE_IN_DIRENT if your platform defines DT_UNKNOWN but lacks
36# d_type in struct dirent (latest Cygwin -- will be fixed soonish).
37#
38# Define NO_C99_FORMAT if your formatted IO functions (printf/scanf et.al.)
39# do not support the 'size specifiers' introduced by C99, namely ll, hh,
40# j, z, t. (representing long long int, char, intmax_t, size_t, ptrdiff_t).
41# some C compilers supported these specifiers prior to C99 as an extension.
42#
43# Define NO_STRCASESTR if you don't have strcasestr.
44#
45# Define NO_MEMMEM if you don't have memmem.
46#
47# Define NO_STRTOUMAX if you don't have strtoumax in the C library.
48# If your compiler also does not support long long or does not have
49# strtoull, define NO_STRTOULL.
50#
51# Define NO_SETENV if you don't have setenv in the C library.
52#
53# Define NO_UNSETENV if you don't have unsetenv in the C library.
54#
55# Define NO_MKDTEMP if you don't have mkdtemp in the C library.
56#
57# Define NO_SYS_SELECT_H if you don't have sys/select.h.
58#
59# Define NO_SYMLINK_HEAD if you never want .perf/HEAD to be a symbolic link.
60# Enable it on Windows. By default, symrefs are still used.
61#
62# Define NO_SVN_TESTS if you want to skip time-consuming SVN interoperability
63# tests. These tests take up a significant amount of the total test time
64# but are not needed unless you plan to talk to SVN repos.
65#
66# Define NO_FINK if you are building on Darwin/Mac OS X, have Fink
67# installed in /sw, but don't want PERF to link against any libraries
68# installed there. If defined you may specify your own (or Fink's)
69# include directories and library directories by defining CFLAGS
70# and LDFLAGS appropriately.
71#
72# Define NO_DARWIN_PORTS if you are building on Darwin/Mac OS X,
73# have DarwinPorts installed in /opt/local, but don't want PERF to
74# link against any libraries installed there. If defined you may
75# specify your own (or DarwinPort's) include directories and
76# library directories by defining CFLAGS and LDFLAGS appropriately.
77#
78# Define PPC_SHA1 environment variable when running make to make use of
79# a bundled SHA1 routine optimized for PowerPC.
80#
81# Define ARM_SHA1 environment variable when running make to make use of
82# a bundled SHA1 routine optimized for ARM.
83#
84# Define MOZILLA_SHA1 environment variable when running make to make use of
85# a bundled SHA1 routine coming from Mozilla. It is GPL'd and should be fast
86# on non-x86 architectures (e.g. PowerPC), while the OpenSSL version (default
87# choice) has very fast version optimized for i586.
88#
89# Define NEEDS_SSL_WITH_CRYPTO if you need -lcrypto with -lssl (Darwin).
90#
91# Define NEEDS_LIBICONV if linking with libc is not enough (Darwin).
92#
93# Define NEEDS_SOCKET if linking with libc is not enough (SunOS,
94# Patrick Mauritz).
95#
96# Define NO_MMAP if you want to avoid mmap.
97#
98# Define NO_PTHREADS if you do not have or do not want to use Pthreads.
99#
100# Define NO_PREAD if you have a problem with pread() system call (e.g.
101# cygwin.dll before v1.5.22).
102#
103# Define NO_FAST_WORKING_DIRECTORY if accessing objects in pack files is
104# generally faster on your platform than accessing the working directory.
105#
106# Define NO_TRUSTABLE_FILEMODE if your filesystem may claim to support
107# the executable mode bit, but doesn't really do so.
108#
109# Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
110#
111# Define NO_SOCKADDR_STORAGE if your platform does not have struct
112# sockaddr_storage.
113#
114# Define NO_ICONV if your libc does not properly support iconv.
115#
116# Define OLD_ICONV if your library has an old iconv(), where the second
117# (input buffer pointer) parameter is declared with type (const char **).
118#
119# Define NO_DEFLATE_BOUND if your zlib does not have deflateBound.
120#
121# Define NO_R_TO_GCC_LINKER if your gcc does not like "-R/path/lib"
122# that tells runtime paths to dynamic libraries;
123# "-Wl,-rpath=/path/lib" is used instead.
124#
125# Define USE_NSEC below if you want perf to care about sub-second file mtimes
126# and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and
127# it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely
128# randomly break unless your underlying filesystem supports those sub-second
129# times (my ext3 doesn't).
130#
131# Define USE_ST_TIMESPEC if your "struct stat" uses "st_ctimespec" instead of
132# "st_ctim"
133#
134# Define NO_NSEC if your "struct stat" does not have "st_ctim.tv_nsec"
135# available. This automatically turns USE_NSEC off.
136#
137# Define USE_STDEV below if you want perf to care about the underlying device
138# change being considered an inode change from the update-index perspective.
139#
140# Define NO_ST_BLOCKS_IN_STRUCT_STAT if your platform does not have st_blocks
141# field that counts the on-disk footprint in 512-byte blocks.
142# 15#
143# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8 16# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8
144# 17#
145# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72. 18# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72.
146# 19#
147# Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's
148# MakeMaker (e.g. using ActiveState under Cygwin).
149#
150# Define NO_PERL if you do not want Perl scripts or libraries at all.
151#
152# Define INTERNAL_QSORT to use Git's implementation of qsort(), which
153# is a simplified version of the merge sort used in glibc. This is
154# recommended if Git triggers O(n^2) behavior in your platform's qsort().
155#
156# Define NO_EXTERNAL_GREP if you don't want "perf grep" to ever call
157# your external grep (e.g., if your system lacks grep, if its grep is
158# broken, or spawning external process is slower than built-in grep perf has).
159#
160# Define LDFLAGS=-static to build a static binary. 20# Define LDFLAGS=-static to build a static binary.
161# 21#
162# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds. 22# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
@@ -167,12 +27,7 @@ $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
167 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) 27 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
168-include $(OUTPUT)PERF-VERSION-FILE 28-include $(OUTPUT)PERF-VERSION-FILE
169 29
170uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') 30uname_M := $(shell uname -m 2>/dev/null || echo not)
171uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
172uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
173uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
174uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
175uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
176 31
177ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ 32ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
178 -e s/arm.*/arm/ -e s/sa110/arm/ \ 33 -e s/arm.*/arm/ -e s/sa110/arm/ \
@@ -191,8 +46,6 @@ ifeq ($(ARCH),x86_64)
191 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S 46 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S
192endif 47endif
193 48
194# CFLAGS and LDFLAGS are for the users to override from the command line.
195
196# 49#
197# Include saner warnings here, which can catch bugs: 50# Include saner warnings here, which can catch bugs:
198# 51#
@@ -270,22 +123,13 @@ CC = $(CROSS_COMPILE)gcc
270AR = $(CROSS_COMPILE)ar 123AR = $(CROSS_COMPILE)ar
271RM = rm -f 124RM = rm -f
272MKDIR = mkdir 125MKDIR = mkdir
273TAR = tar
274FIND = find 126FIND = find
275INSTALL = install 127INSTALL = install
276RPMBUILD = rpmbuild
277PTHREAD_LIBS = -lpthread
278 128
279# sparse is architecture-neutral, which means that we need to tell it 129# sparse is architecture-neutral, which means that we need to tell it
280# explicitly what architecture to check for. Fix this up for yours.. 130# explicitly what architecture to check for. Fix this up for yours..
281SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ 131SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
282 132
283ifeq ($(V), 2)
284 QUIET_STDERR = ">/dev/null"
285else
286 QUIET_STDERR = ">/dev/null 2>&1"
287endif
288
289-include feature-tests.mak 133-include feature-tests.mak
290 134
291ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y) 135ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y)
@@ -310,49 +154,37 @@ BASIC_LDFLAGS =
310 154
311# Guard against environment variables 155# Guard against environment variables
312BUILTIN_OBJS = 156BUILTIN_OBJS =
313BUILT_INS =
314COMPAT_CFLAGS =
315COMPAT_OBJS =
316LIB_H = 157LIB_H =
317LIB_OBJS = 158LIB_OBJS =
318SCRIPT_PERL = 159PYRF_OBJS =
319SCRIPT_SH = 160SCRIPT_SH =
320TEST_PROGRAMS =
321 161
322SCRIPT_SH += perf-archive.sh 162SCRIPT_SH += perf-archive.sh
323 163
324grep-libs = $(filter -l%,$(1)) 164grep-libs = $(filter -l%,$(1))
325strip-libs = $(filter-out -l%,$(1)) 165strip-libs = $(filter-out -l%,$(1))
326 166
167$(OUTPUT)python/perf.so: $(PYRF_OBJS)
168 $(QUIET_GEN)python util/setup.py --quiet build_ext --build-lib='$(OUTPUT)python' \
169 --build-temp='$(OUTPUT)python/temp'
327# 170#
328# No Perl scripts right now: 171# No Perl scripts right now:
329# 172#
330 173
331# SCRIPT_PERL += perf-add--interactive.perl 174SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
332
333SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
334 $(patsubst %.perl,%,$(SCRIPT_PERL))
335
336# Empty...
337EXTRA_PROGRAMS =
338
339# ... and all the rest that could be moved out of bindir to perfexecdir
340PROGRAMS += $(EXTRA_PROGRAMS)
341 175
342# 176#
343# Single 'perf' binary right now: 177# Single 'perf' binary right now:
344# 178#
345PROGRAMS += $(OUTPUT)perf 179PROGRAMS += $(OUTPUT)perf
346 180
347# List built-in command $C whose implementation cmd_$C() is not in 181LANG_BINDINGS =
348# builtin-$C.o but is linked in as part of some other command.
349#
350 182
351# what 'all' will build and 'install' will install, in perfexecdir 183# what 'all' will build and 'install' will install, in perfexecdir
352ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) 184ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
353 185
354# what 'all' will build but not install in perfexecdir 186# what 'all' will build but not install in perfexecdir
355OTHER_PROGRAMS = $(OUTPUT)perf$X 187OTHER_PROGRAMS = $(OUTPUT)perf
356 188
357# Set paths to tools early so that they can be used for version tests. 189# Set paths to tools early so that they can be used for version tests.
358ifndef SHELL_PATH 190ifndef SHELL_PATH
@@ -395,6 +227,7 @@ LIB_H += util/include/dwarf-regs.h
395LIB_H += util/include/asm/dwarf2.h 227LIB_H += util/include/asm/dwarf2.h
396LIB_H += util/include/asm/cpufeature.h 228LIB_H += util/include/asm/cpufeature.h
397LIB_H += perf.h 229LIB_H += perf.h
230LIB_H += util/annotate.h
398LIB_H += util/cache.h 231LIB_H += util/cache.h
399LIB_H += util/callchain.h 232LIB_H += util/callchain.h
400LIB_H += util/build-id.h 233LIB_H += util/build-id.h
@@ -402,6 +235,7 @@ LIB_H += util/debug.h
402LIB_H += util/debugfs.h 235LIB_H += util/debugfs.h
403LIB_H += util/event.h 236LIB_H += util/event.h
404LIB_H += util/evsel.h 237LIB_H += util/evsel.h
238LIB_H += util/evlist.h
405LIB_H += util/exec_cmd.h 239LIB_H += util/exec_cmd.h
406LIB_H += util/types.h 240LIB_H += util/types.h
407LIB_H += util/levenshtein.h 241LIB_H += util/levenshtein.h
@@ -416,6 +250,7 @@ LIB_H += util/help.h
416LIB_H += util/session.h 250LIB_H += util/session.h
417LIB_H += util/strbuf.h 251LIB_H += util/strbuf.h
418LIB_H += util/strlist.h 252LIB_H += util/strlist.h
253LIB_H += util/strfilter.h
419LIB_H += util/svghelper.h 254LIB_H += util/svghelper.h
420LIB_H += util/run-command.h 255LIB_H += util/run-command.h
421LIB_H += util/sigchain.h 256LIB_H += util/sigchain.h
@@ -425,21 +260,26 @@ LIB_H += util/values.h
425LIB_H += util/sort.h 260LIB_H += util/sort.h
426LIB_H += util/hist.h 261LIB_H += util/hist.h
427LIB_H += util/thread.h 262LIB_H += util/thread.h
263LIB_H += util/thread_map.h
428LIB_H += util/trace-event.h 264LIB_H += util/trace-event.h
429LIB_H += util/probe-finder.h 265LIB_H += util/probe-finder.h
430LIB_H += util/probe-event.h 266LIB_H += util/probe-event.h
431LIB_H += util/pstack.h 267LIB_H += util/pstack.h
432LIB_H += util/cpumap.h 268LIB_H += util/cpumap.h
269LIB_H += util/top.h
433LIB_H += $(ARCH_INCLUDE) 270LIB_H += $(ARCH_INCLUDE)
271LIB_H += util/cgroup.h
434 272
435LIB_OBJS += $(OUTPUT)util/abspath.o 273LIB_OBJS += $(OUTPUT)util/abspath.o
436LIB_OBJS += $(OUTPUT)util/alias.o 274LIB_OBJS += $(OUTPUT)util/alias.o
275LIB_OBJS += $(OUTPUT)util/annotate.o
437LIB_OBJS += $(OUTPUT)util/build-id.o 276LIB_OBJS += $(OUTPUT)util/build-id.o
438LIB_OBJS += $(OUTPUT)util/config.o 277LIB_OBJS += $(OUTPUT)util/config.o
439LIB_OBJS += $(OUTPUT)util/ctype.o 278LIB_OBJS += $(OUTPUT)util/ctype.o
440LIB_OBJS += $(OUTPUT)util/debugfs.o 279LIB_OBJS += $(OUTPUT)util/debugfs.o
441LIB_OBJS += $(OUTPUT)util/environment.o 280LIB_OBJS += $(OUTPUT)util/environment.o
442LIB_OBJS += $(OUTPUT)util/event.o 281LIB_OBJS += $(OUTPUT)util/event.o
282LIB_OBJS += $(OUTPUT)util/evlist.o
443LIB_OBJS += $(OUTPUT)util/evsel.o 283LIB_OBJS += $(OUTPUT)util/evsel.o
444LIB_OBJS += $(OUTPUT)util/exec_cmd.o 284LIB_OBJS += $(OUTPUT)util/exec_cmd.o
445LIB_OBJS += $(OUTPUT)util/help.o 285LIB_OBJS += $(OUTPUT)util/help.o
@@ -455,6 +295,8 @@ LIB_OBJS += $(OUTPUT)util/quote.o
455LIB_OBJS += $(OUTPUT)util/strbuf.o 295LIB_OBJS += $(OUTPUT)util/strbuf.o
456LIB_OBJS += $(OUTPUT)util/string.o 296LIB_OBJS += $(OUTPUT)util/string.o
457LIB_OBJS += $(OUTPUT)util/strlist.o 297LIB_OBJS += $(OUTPUT)util/strlist.o
298LIB_OBJS += $(OUTPUT)util/strfilter.o
299LIB_OBJS += $(OUTPUT)util/top.o
458LIB_OBJS += $(OUTPUT)util/usage.o 300LIB_OBJS += $(OUTPUT)util/usage.o
459LIB_OBJS += $(OUTPUT)util/wrapper.o 301LIB_OBJS += $(OUTPUT)util/wrapper.o
460LIB_OBJS += $(OUTPUT)util/sigchain.o 302LIB_OBJS += $(OUTPUT)util/sigchain.o
@@ -469,6 +311,7 @@ LIB_OBJS += $(OUTPUT)util/map.o
469LIB_OBJS += $(OUTPUT)util/pstack.o 311LIB_OBJS += $(OUTPUT)util/pstack.o
470LIB_OBJS += $(OUTPUT)util/session.o 312LIB_OBJS += $(OUTPUT)util/session.o
471LIB_OBJS += $(OUTPUT)util/thread.o 313LIB_OBJS += $(OUTPUT)util/thread.o
314LIB_OBJS += $(OUTPUT)util/thread_map.o
472LIB_OBJS += $(OUTPUT)util/trace-event-parse.o 315LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
473LIB_OBJS += $(OUTPUT)util/trace-event-read.o 316LIB_OBJS += $(OUTPUT)util/trace-event-read.o
474LIB_OBJS += $(OUTPUT)util/trace-event-info.o 317LIB_OBJS += $(OUTPUT)util/trace-event-info.o
@@ -480,6 +323,7 @@ LIB_OBJS += $(OUTPUT)util/probe-event.o
480LIB_OBJS += $(OUTPUT)util/util.o 323LIB_OBJS += $(OUTPUT)util/util.o
481LIB_OBJS += $(OUTPUT)util/xyarray.o 324LIB_OBJS += $(OUTPUT)util/xyarray.o
482LIB_OBJS += $(OUTPUT)util/cpumap.o 325LIB_OBJS += $(OUTPUT)util/cpumap.o
326LIB_OBJS += $(OUTPUT)util/cgroup.o
483 327
484BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 328BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
485 329
@@ -514,6 +358,20 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
514 358
515PERFLIBS = $(LIB_FILE) 359PERFLIBS = $(LIB_FILE)
516 360
361# Files needed for the python binding, perf.so
362# pyrf is just an internal name needed for all those wrappers.
363# This has to be in sync with what is in the 'sources' variable in
364# tools/perf/util/setup.py
365
366PYRF_OBJS += $(OUTPUT)util/cpumap.o
367PYRF_OBJS += $(OUTPUT)util/ctype.o
368PYRF_OBJS += $(OUTPUT)util/evlist.o
369PYRF_OBJS += $(OUTPUT)util/evsel.o
370PYRF_OBJS += $(OUTPUT)util/python.o
371PYRF_OBJS += $(OUTPUT)util/thread_map.o
372PYRF_OBJS += $(OUTPUT)util/util.o
373PYRF_OBJS += $(OUTPUT)util/xyarray.o
374
517# 375#
518# Platform specific tweaks 376# Platform specific tweaks
519# 377#
@@ -535,22 +393,6 @@ endif # NO_DWARF
535 393
536-include arch/$(ARCH)/Makefile 394-include arch/$(ARCH)/Makefile
537 395
538ifeq ($(uname_S),Darwin)
539 ifndef NO_FINK
540 ifeq ($(shell test -d /sw/lib && echo y),y)
541 BASIC_CFLAGS += -I/sw/include
542 BASIC_LDFLAGS += -L/sw/lib
543 endif
544 endif
545 ifndef NO_DARWIN_PORTS
546 ifeq ($(shell test -d /opt/local/lib && echo y),y)
547 BASIC_CFLAGS += -I/opt/local/include
548 BASIC_LDFLAGS += -L/opt/local/lib
549 endif
550 endif
551 PTHREAD_LIBS =
552endif
553
554ifneq ($(OUTPUT),) 396ifneq ($(OUTPUT),)
555 BASIC_CFLAGS += -I$(OUTPUT) 397 BASIC_CFLAGS += -I$(OUTPUT)
556endif 398endif
@@ -595,6 +437,7 @@ else
595 LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o 437 LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o
596 LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o 438 LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o
597 LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o 439 LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o
440 LIB_OBJS += $(OUTPUT)util/ui/browsers/top.o
598 LIB_OBJS += $(OUTPUT)util/ui/helpline.o 441 LIB_OBJS += $(OUTPUT)util/ui/helpline.o
599 LIB_OBJS += $(OUTPUT)util/ui/progress.o 442 LIB_OBJS += $(OUTPUT)util/ui/progress.o
600 LIB_OBJS += $(OUTPUT)util/ui/util.o 443 LIB_OBJS += $(OUTPUT)util/ui/util.o
@@ -604,6 +447,7 @@ else
604 LIB_H += util/ui/libslang.h 447 LIB_H += util/ui/libslang.h
605 LIB_H += util/ui/progress.h 448 LIB_H += util/ui/progress.h
606 LIB_H += util/ui/util.h 449 LIB_H += util/ui/util.h
450 LIB_H += util/ui/ui.h
607 endif 451 endif
608endif 452endif
609 453
@@ -635,12 +479,14 @@ else
635 PYTHON_EMBED_CCOPTS = `python-config --cflags 2>/dev/null` 479 PYTHON_EMBED_CCOPTS = `python-config --cflags 2>/dev/null`
636 FLAGS_PYTHON_EMBED=$(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 480 FLAGS_PYTHON_EMBED=$(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
637 ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y) 481 ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y)
482 msg := $(warning No Python.h found, install python-dev[el] to have python support in 'perf script' and to build the python bindings)
638 BASIC_CFLAGS += -DNO_LIBPYTHON 483 BASIC_CFLAGS += -DNO_LIBPYTHON
639 else 484 else
640 ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS) 485 ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
641 EXTLIBS += $(PYTHON_EMBED_LIBADD) 486 EXTLIBS += $(PYTHON_EMBED_LIBADD)
642 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o 487 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
643 LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o 488 LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
489 LANG_BINDINGS += $(OUTPUT)python/perf.so
644 endif 490 endif
645endif 491endif
646 492
@@ -690,201 +536,13 @@ else
690 endif 536 endif
691endif 537endif
692 538
693ifndef CC_LD_DYNPATH
694 ifdef NO_R_TO_GCC_LINKER
695 # Some gcc does not accept and pass -R to the linker to specify
696 # the runtime dynamic library path.
697 CC_LD_DYNPATH = -Wl,-rpath,
698 else
699 CC_LD_DYNPATH = -R
700 endif
701endif
702
703ifdef NEEDS_SOCKET
704 EXTLIBS += -lsocket
705endif
706ifdef NEEDS_NSL
707 EXTLIBS += -lnsl
708endif
709ifdef NO_D_TYPE_IN_DIRENT
710 BASIC_CFLAGS += -DNO_D_TYPE_IN_DIRENT
711endif
712ifdef NO_D_INO_IN_DIRENT
713 BASIC_CFLAGS += -DNO_D_INO_IN_DIRENT
714endif
715ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
716 BASIC_CFLAGS += -DNO_ST_BLOCKS_IN_STRUCT_STAT
717endif
718ifdef USE_NSEC
719 BASIC_CFLAGS += -DUSE_NSEC
720endif
721ifdef USE_ST_TIMESPEC
722 BASIC_CFLAGS += -DUSE_ST_TIMESPEC
723endif
724ifdef NO_NSEC
725 BASIC_CFLAGS += -DNO_NSEC
726endif
727ifdef NO_C99_FORMAT
728 BASIC_CFLAGS += -DNO_C99_FORMAT
729endif
730ifdef SNPRINTF_RETURNS_BOGUS
731 COMPAT_CFLAGS += -DSNPRINTF_RETURNS_BOGUS
732 COMPAT_OBJS += $(OUTPUT)compat/snprintf.o
733endif
734ifdef FREAD_READS_DIRECTORIES
735 COMPAT_CFLAGS += -DFREAD_READS_DIRECTORIES
736 COMPAT_OBJS += $(OUTPUT)compat/fopen.o
737endif
738ifdef NO_SYMLINK_HEAD
739 BASIC_CFLAGS += -DNO_SYMLINK_HEAD
740endif
741ifdef NO_STRCASESTR
742 COMPAT_CFLAGS += -DNO_STRCASESTR
743 COMPAT_OBJS += $(OUTPUT)compat/strcasestr.o
744endif
745ifdef NO_STRTOUMAX
746 COMPAT_CFLAGS += -DNO_STRTOUMAX
747 COMPAT_OBJS += $(OUTPUT)compat/strtoumax.o
748endif
749ifdef NO_STRTOULL
750 COMPAT_CFLAGS += -DNO_STRTOULL
751endif
752ifdef NO_SETENV
753 COMPAT_CFLAGS += -DNO_SETENV
754 COMPAT_OBJS += $(OUTPUT)compat/setenv.o
755endif
756ifdef NO_MKDTEMP
757 COMPAT_CFLAGS += -DNO_MKDTEMP
758 COMPAT_OBJS += $(OUTPUT)compat/mkdtemp.o
759endif
760ifdef NO_UNSETENV
761 COMPAT_CFLAGS += -DNO_UNSETENV
762 COMPAT_OBJS += $(OUTPUT)compat/unsetenv.o
763endif
764ifdef NO_SYS_SELECT_H
765 BASIC_CFLAGS += -DNO_SYS_SELECT_H
766endif
767ifdef NO_MMAP
768 COMPAT_CFLAGS += -DNO_MMAP
769 COMPAT_OBJS += $(OUTPUT)compat/mmap.o
770else
771 ifdef USE_WIN32_MMAP
772 COMPAT_CFLAGS += -DUSE_WIN32_MMAP
773 COMPAT_OBJS += $(OUTPUT)compat/win32mmap.o
774 endif
775endif
776ifdef NO_PREAD
777 COMPAT_CFLAGS += -DNO_PREAD
778 COMPAT_OBJS += $(OUTPUT)compat/pread.o
779endif
780ifdef NO_FAST_WORKING_DIRECTORY
781 BASIC_CFLAGS += -DNO_FAST_WORKING_DIRECTORY
782endif
783ifdef NO_TRUSTABLE_FILEMODE
784 BASIC_CFLAGS += -DNO_TRUSTABLE_FILEMODE
785endif
786ifdef NO_IPV6
787 BASIC_CFLAGS += -DNO_IPV6
788endif
789ifdef NO_UINTMAX_T
790 BASIC_CFLAGS += -Duintmax_t=uint32_t
791endif
792ifdef NO_SOCKADDR_STORAGE
793ifdef NO_IPV6
794 BASIC_CFLAGS += -Dsockaddr_storage=sockaddr_in
795else
796 BASIC_CFLAGS += -Dsockaddr_storage=sockaddr_in6
797endif
798endif
799ifdef NO_INET_NTOP
800 LIB_OBJS += $(OUTPUT)compat/inet_ntop.o
801endif
802ifdef NO_INET_PTON
803 LIB_OBJS += $(OUTPUT)compat/inet_pton.o
804endif
805
806ifdef NO_ICONV
807 BASIC_CFLAGS += -DNO_ICONV
808endif
809
810ifdef OLD_ICONV
811 BASIC_CFLAGS += -DOLD_ICONV
812endif
813
814ifdef NO_DEFLATE_BOUND
815 BASIC_CFLAGS += -DNO_DEFLATE_BOUND
816endif
817
818ifdef PPC_SHA1
819 SHA1_HEADER = "ppc/sha1.h"
820 LIB_OBJS += $(OUTPUT)ppc/sha1.o ppc/sha1ppc.o
821else
822ifdef ARM_SHA1
823 SHA1_HEADER = "arm/sha1.h"
824 LIB_OBJS += $(OUTPUT)arm/sha1.o $(OUTPUT)arm/sha1_arm.o
825else
826ifdef MOZILLA_SHA1
827 SHA1_HEADER = "mozilla-sha1/sha1.h"
828 LIB_OBJS += $(OUTPUT)mozilla-sha1/sha1.o
829else
830 SHA1_HEADER = <openssl/sha.h>
831 EXTLIBS += $(LIB_4_CRYPTO)
832endif
833endif
834endif
835ifdef NO_PERL_MAKEMAKER
836 export NO_PERL_MAKEMAKER
837endif
838ifdef NO_HSTRERROR
839 COMPAT_CFLAGS += -DNO_HSTRERROR
840 COMPAT_OBJS += $(OUTPUT)compat/hstrerror.o
841endif
842ifdef NO_MEMMEM
843 COMPAT_CFLAGS += -DNO_MEMMEM
844 COMPAT_OBJS += $(OUTPUT)compat/memmem.o
845endif
846ifdef INTERNAL_QSORT
847 COMPAT_CFLAGS += -DINTERNAL_QSORT
848 COMPAT_OBJS += $(OUTPUT)compat/qsort.o
849endif
850ifdef RUNTIME_PREFIX
851 COMPAT_CFLAGS += -DRUNTIME_PREFIX
852endif
853
854ifdef DIR_HAS_BSD_GROUP_SEMANTICS
855 COMPAT_CFLAGS += -DDIR_HAS_BSD_GROUP_SEMANTICS
856endif
857ifdef NO_EXTERNAL_GREP
858 BASIC_CFLAGS += -DNO_EXTERNAL_GREP
859endif
860
861ifeq ($(PERL_PATH),)
862NO_PERL=NoThanks
863endif
864
865QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
866QUIET_SUBDIR1 =
867
868ifneq ($(findstring $(MAKEFLAGS),w),w)
869PRINT_DIR = --no-print-directory
870else # "make -w"
871NO_SUBDIR = :
872endif
873
874ifneq ($(findstring $(MAKEFLAGS),s),s) 539ifneq ($(findstring $(MAKEFLAGS),s),s)
875ifndef V 540ifndef V
876 QUIET_CC = @echo ' ' CC $@; 541 QUIET_CC = @echo ' ' CC $@;
877 QUIET_AR = @echo ' ' AR $@; 542 QUIET_AR = @echo ' ' AR $@;
878 QUIET_LINK = @echo ' ' LINK $@; 543 QUIET_LINK = @echo ' ' LINK $@;
879 QUIET_MKDIR = @echo ' ' MKDIR $@; 544 QUIET_MKDIR = @echo ' ' MKDIR $@;
880 QUIET_BUILT_IN = @echo ' ' BUILTIN $@;
881 QUIET_GEN = @echo ' ' GEN $@; 545 QUIET_GEN = @echo ' ' GEN $@;
882 QUIET_SUBDIR0 = +@subdir=
883 QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
884 $(MAKE) $(PRINT_DIR) -C $$subdir
885 export V
886 export QUIET_GEN
887 export QUIET_BUILT_IN
888endif 546endif
889endif 547endif
890 548
@@ -894,7 +552,6 @@ endif
894 552
895# Shell quote (do not use $(call) to accommodate ancient setups); 553# Shell quote (do not use $(call) to accommodate ancient setups);
896 554
897SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER))
898ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG)) 555ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
899 556
900DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) 557DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
@@ -908,46 +565,36 @@ htmldir_SQ = $(subst ','\'',$(htmldir))
908prefix_SQ = $(subst ','\'',$(prefix)) 565prefix_SQ = $(subst ','\'',$(prefix))
909 566
910SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) 567SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
911PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
912 568
913LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive $(EXTLIBS) 569LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive $(EXTLIBS)
914 570
915BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
916 $(COMPAT_CFLAGS)
917LIB_OBJS += $(COMPAT_OBJS)
918
919ALL_CFLAGS += $(BASIC_CFLAGS) 571ALL_CFLAGS += $(BASIC_CFLAGS)
920ALL_CFLAGS += $(ARCH_CFLAGS) 572ALL_CFLAGS += $(ARCH_CFLAGS)
921ALL_LDFLAGS += $(BASIC_LDFLAGS) 573ALL_LDFLAGS += $(BASIC_LDFLAGS)
922 574
923export TAR INSTALL DESTDIR SHELL_PATH 575export INSTALL SHELL_PATH
924 576
925 577
926### Build rules 578### Build rules
927 579
928SHELL = $(SHELL_PATH) 580SHELL = $(SHELL_PATH)
929 581
930all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) $(OUTPUT)PERF-BUILD-OPTIONS 582all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
931ifneq (,$X)
932 $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) perf$X)), test '$p' -ef '$p$X' || $(RM) '$p';)
933endif
934
935all::
936 583
937please_set_SHELL_PATH_to_a_more_modern_shell: 584please_set_SHELL_PATH_to_a_more_modern_shell:
938 @$$(:) 585 @$$(:)
939 586
940shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell 587shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
941 588
942strip: $(PROGRAMS) $(OUTPUT)perf$X 589strip: $(PROGRAMS) $(OUTPUT)perf
943 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf$X 590 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
944 591
945$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS 592$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
946 $(QUIET_CC)$(CC) -DPERF_VERSION='"$(PERF_VERSION)"' \ 593 $(QUIET_CC)$(CC) -DPERF_VERSION='"$(PERF_VERSION)"' \
947 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \ 594 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
948 $(ALL_CFLAGS) -c $(filter %.c,$^) -o $@ 595 $(ALL_CFLAGS) -c $(filter %.c,$^) -o $@
949 596
950$(OUTPUT)perf$X: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS) 597$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
951 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(OUTPUT)perf.o \ 598 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(OUTPUT)perf.o \
952 $(BUILTIN_OBJS) $(LIBS) -o $@ 599 $(BUILTIN_OBJS) $(LIBS) -o $@
953 600
@@ -963,39 +610,17 @@ $(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPU
963 '-DPERF_MAN_PATH="$(mandir_SQ)"' \ 610 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
964 '-DPERF_INFO_PATH="$(infodir_SQ)"' $< 611 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
965 612
966$(BUILT_INS): $(OUTPUT)perf$X
967 $(QUIET_BUILT_IN)$(RM) $@ && \
968 ln perf$X $@ 2>/dev/null || \
969 ln -s perf$X $@ 2>/dev/null || \
970 cp perf$X $@
971
972$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt 613$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
973 614
974$(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt) 615$(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
975 $(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@ 616 $(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
976 617
977$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh 618$(SCRIPTS) : % : %.sh
978 $(QUIET_GEN)$(RM) $(OUTPUT)$@ $(OUTPUT)$@+ && \ 619 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
979 sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
980 -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
981 -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
982 -e 's/@@PERF_VERSION@@/$(PERF_VERSION)/g' \
983 -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
984 $@.sh > $(OUTPUT)$@+ && \
985 chmod +x $(OUTPUT)$@+ && \
986 mv $(OUTPUT)$@+ $(OUTPUT)$@
987
988configure: configure.ac
989 $(QUIET_GEN)$(RM) $@ $<+ && \
990 sed -e 's/@@PERF_VERSION@@/$(PERF_VERSION)/g' \
991 $< > $<+ && \
992 autoconf -o $@ $<+ && \
993 $(RM) $<+
994 620
995# These can record PERF_VERSION 621# These can record PERF_VERSION
996$(OUTPUT)perf.o perf.spec \ 622$(OUTPUT)perf.o perf.spec \
997 $(patsubst %.sh,%,$(SCRIPT_SH)) \ 623 $(SCRIPTS) \
998 $(patsubst %.perl,%,$(SCRIPT_PERL)) \
999 : $(OUTPUT)PERF-VERSION-FILE 624 : $(OUTPUT)PERF-VERSION-FILE
1000 625
1001$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS 626$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
@@ -1012,9 +637,6 @@ $(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
1012 '-DPREFIX="$(prefix_SQ)"' \ 637 '-DPREFIX="$(prefix_SQ)"' \
1013 $< 638 $<
1014 639
1015$(OUTPUT)builtin-init-db.o: builtin-init-db.c $(OUTPUT)PERF-CFLAGS
1016 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DDEFAULT_PERF_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
1017
1018$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS 640$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
1019 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 641 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
1020 642
@@ -1024,6 +646,9 @@ $(OUTPUT)util/ui/browser.o: util/ui/browser.c $(OUTPUT)PERF-CFLAGS
1024$(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS 646$(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
1025 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 647 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
1026 648
649$(OUTPUT)util/ui/browsers/top.o: util/ui/browsers/top.c $(OUTPUT)PERF-CFLAGS
650 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
651
1027$(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS 652$(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
1028 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 653 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
1029 654
@@ -1045,12 +670,11 @@ $(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/tra
1045$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS 670$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
1046 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $< 671 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
1047 672
1048$(OUTPUT)perf-%$X: %.o $(PERFLIBS) 673$(OUTPUT)perf-%: %.o $(PERFLIBS)
1049 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) 674 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
1050 675
1051$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) 676$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
1052$(patsubst perf-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) 677$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
1053builtin-revert.o wt-status.o: wt-status.h
1054 678
1055# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So 679# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
1056# we depend the various files onto their directories. 680# we depend the various files onto their directories.
@@ -1063,6 +687,36 @@ $(sort $(dir $(DIRECTORY_DEPS))):
1063$(LIB_FILE): $(LIB_OBJS) 687$(LIB_FILE): $(LIB_OBJS)
1064 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS) 688 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
1065 689
690help:
691 @echo 'Perf make targets:'
692 @echo ' doc - make *all* documentation (see below)'
693 @echo ' man - make manpage documentation (access with man <foo>)'
694 @echo ' html - make html documentation'
695 @echo ' info - make GNU info documentation (access with info <foo>)'
696 @echo ' pdf - make pdf documentation'
697 @echo ' TAGS - use etags to make tag information for source browsing'
698 @echo ' tags - use ctags to make tag information for source browsing'
699 @echo ' cscope - use cscope to make interactive browsing database'
700 @echo ''
701 @echo 'Perf install targets:'
702 @echo ' NOTE: documentation build requires asciidoc, xmlto packages to be installed'
703 @echo ' HINT: use "make prefix=<path> <install target>" to install to a particular'
704 @echo ' path like make prefix=/usr/local install install-doc'
705 @echo ' install - install compiled binaries'
706 @echo ' install-doc - install *all* documentation'
707 @echo ' install-man - install manpage documentation'
708 @echo ' install-html - install html documentation'
709 @echo ' install-info - install GNU info documentation'
710 @echo ' install-pdf - install pdf documentation'
711 @echo ''
712 @echo ' quick-install-doc - alias for quick-install-man'
713 @echo ' quick-install-man - install the documentation quickly'
714 @echo ' quick-install-html - install the html documentation quickly'
715 @echo ''
716 @echo 'Perf maintainer targets:'
717 @echo ' distclean - alias to clean'
718 @echo ' clean - clean all binary objects and build output'
719
1066doc: 720doc:
1067 $(MAKE) -C Documentation all 721 $(MAKE) -C Documentation all
1068 722
@@ -1101,30 +755,12 @@ $(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
1101 echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \ 755 echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
1102 fi 756 fi
1103 757
1104# We need to apply sq twice, once to protect from the shell
1105# that runs $(OUTPUT)PERF-BUILD-OPTIONS, and then again to protect it
1106# and the first level quoting from the shell that runs "echo".
1107$(OUTPUT)PERF-BUILD-OPTIONS: .FORCE-PERF-BUILD-OPTIONS
1108 @echo SHELL_PATH=\''$(subst ','\'',$(SHELL_PATH_SQ))'\' >$@
1109 @echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@
1110 @echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@
1111 @echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@
1112
1113### Testing rules 758### Testing rules
1114 759
1115#
1116# None right now:
1117#
1118# TEST_PROGRAMS += test-something$X
1119
1120all:: $(TEST_PROGRAMS)
1121
1122# GNU make supports exporting all variables by "export" without parameters. 760# GNU make supports exporting all variables by "export" without parameters.
1123# However, the environment gets quite big, and some programs have problems 761# However, the environment gets quite big, and some programs have problems
1124# with that. 762# with that.
1125 763
1126export NO_SVN_TESTS
1127
1128check: $(OUTPUT)common-cmds.h 764check: $(OUTPUT)common-cmds.h
1129 if sparse; \ 765 if sparse; \
1130 then \ 766 then \
@@ -1133,33 +769,21 @@ check: $(OUTPUT)common-cmds.h
1133 sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; \ 769 sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
1134 done; \ 770 done; \
1135 else \ 771 else \
1136 echo 2>&1 "Did you mean 'make test'?"; \
1137 exit 1; \ 772 exit 1; \
1138 fi 773 fi
1139 774
1140remove-dashes:
1141 ./fixup-builtins $(BUILT_INS) $(PROGRAMS) $(SCRIPTS)
1142
1143### Installation rules 775### Installation rules
1144 776
1145ifneq ($(filter /%,$(firstword $(template_dir))),)
1146template_instdir = $(template_dir)
1147else
1148template_instdir = $(prefix)/$(template_dir)
1149endif
1150export template_instdir
1151
1152ifneq ($(filter /%,$(firstword $(perfexecdir))),) 777ifneq ($(filter /%,$(firstword $(perfexecdir))),)
1153perfexec_instdir = $(perfexecdir) 778perfexec_instdir = $(perfexecdir)
1154else 779else
1155perfexec_instdir = $(prefix)/$(perfexecdir) 780perfexec_instdir = $(prefix)/$(perfexecdir)
1156endif 781endif
1157perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) 782perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
1158export perfexec_instdir
1159 783
1160install: all 784install: all
1161 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' 785 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
1162 $(INSTALL) $(OUTPUT)perf$X '$(DESTDIR_SQ)$(bindir_SQ)' 786 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'
1163 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace' 787 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
1164 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin' 788 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
1165 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 789 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
@@ -1172,14 +796,6 @@ install: all
1172 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python' 796 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'
1173 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' 797 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
1174 798
1175ifdef BUILT_INS
1176 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
1177 $(INSTALL) $(BUILT_INS) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
1178ifneq (,$X)
1179 $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) $(OUTPUT)perf$X)), $(RM) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$p';)
1180endif
1181endif
1182
1183install-doc: 799install-doc:
1184 $(MAKE) -C Documentation install 800 $(MAKE) -C Documentation install
1185 801
@@ -1204,104 +820,17 @@ quick-install-man:
1204quick-install-html: 820quick-install-html:
1205 $(MAKE) -C Documentation quick-install-html 821 $(MAKE) -C Documentation quick-install-html
1206 822
1207
1208### Maintainer's dist rules
1209#
1210# None right now
1211#
1212#
1213# perf.spec: perf.spec.in
1214# sed -e 's/@@VERSION@@/$(PERF_VERSION)/g' < $< > $@+
1215# mv $@+ $@
1216#
1217# PERF_TARNAME=perf-$(PERF_VERSION)
1218# dist: perf.spec perf-archive$(X) configure
1219# ./perf-archive --format=tar \
1220# --prefix=$(PERF_TARNAME)/ HEAD^{tree} > $(PERF_TARNAME).tar
1221# @mkdir -p $(PERF_TARNAME)
1222# @cp perf.spec configure $(PERF_TARNAME)
1223# @echo $(PERF_VERSION) > $(PERF_TARNAME)/version
1224# $(TAR) rf $(PERF_TARNAME).tar \
1225# $(PERF_TARNAME)/perf.spec \
1226# $(PERF_TARNAME)/configure \
1227# $(PERF_TARNAME)/version
1228# @$(RM) -r $(PERF_TARNAME)
1229# gzip -f -9 $(PERF_TARNAME).tar
1230#
1231# htmldocs = perf-htmldocs-$(PERF_VERSION)
1232# manpages = perf-manpages-$(PERF_VERSION)
1233# dist-doc:
1234# $(RM) -r .doc-tmp-dir
1235# mkdir .doc-tmp-dir
1236# $(MAKE) -C Documentation WEBDOC_DEST=../.doc-tmp-dir install-webdoc
1237# cd .doc-tmp-dir && $(TAR) cf ../$(htmldocs).tar .
1238# gzip -n -9 -f $(htmldocs).tar
1239# :
1240# $(RM) -r .doc-tmp-dir
1241# mkdir -p .doc-tmp-dir/man1 .doc-tmp-dir/man5 .doc-tmp-dir/man7
1242# $(MAKE) -C Documentation DESTDIR=./ \
1243# man1dir=../.doc-tmp-dir/man1 \
1244# man5dir=../.doc-tmp-dir/man5 \
1245# man7dir=../.doc-tmp-dir/man7 \
1246# install
1247# cd .doc-tmp-dir && $(TAR) cf ../$(manpages).tar .
1248# gzip -n -9 -f $(manpages).tar
1249# $(RM) -r .doc-tmp-dir
1250#
1251# rpm: dist
1252# $(RPMBUILD) -ta $(PERF_TARNAME).tar.gz
1253
1254### Cleaning rules 823### Cleaning rules
1255 824
1256distclean: clean
1257# $(RM) configure
1258
1259clean: 825clean:
1260 $(RM) *.o */*.o */*/*.o */*/*/*.o $(LIB_FILE) 826 $(RM) $(OUTPUT){*.o,*/*.o,*/*/*.o,*/*/*/*.o,$(LIB_FILE),perf-archive}
1261 $(RM) $(ALL_PROGRAMS) $(BUILT_INS) perf$X 827 $(RM) $(ALL_PROGRAMS) perf
1262 $(RM) $(TEST_PROGRAMS)
1263 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* 828 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
1264 $(RM) -r autom4te.cache
1265 $(RM) config.log config.mak.autogen config.mak.append config.status config.cache
1266 $(RM) -r $(PERF_TARNAME) .doc-tmp-dir
1267 $(RM) $(PERF_TARNAME).tar.gz perf-core_$(PERF_VERSION)-*.tar.gz
1268 $(RM) $(htmldocs).tar.gz $(manpages).tar.gz
1269 $(MAKE) -C Documentation/ clean 829 $(MAKE) -C Documentation/ clean
1270 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-BUILD-OPTIONS 830 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
831 @python util/setup.py clean --build-lib='$(OUTPUT)python' \
832 --build-temp='$(OUTPUT)python/temp'
1271 833
1272.PHONY: all install clean strip 834.PHONY: all install clean strip
1273.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell 835.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
1274.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS 836.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS
1275.PHONY: .FORCE-PERF-BUILD-OPTIONS
1276
1277### Make sure built-ins do not have dups and listed in perf.c
1278#
1279check-builtins::
1280 ./check-builtins.sh
1281
1282### Test suite coverage testing
1283#
1284# None right now
1285#
1286# .PHONY: coverage coverage-clean coverage-build coverage-report
1287#
1288# coverage:
1289# $(MAKE) coverage-build
1290# $(MAKE) coverage-report
1291#
1292# coverage-clean:
1293# rm -f *.gcda *.gcno
1294#
1295# COVERAGE_CFLAGS = $(CFLAGS) -O0 -ftest-coverage -fprofile-arcs
1296# COVERAGE_LDFLAGS = $(CFLAGS) -O0 -lgcov
1297#
1298# coverage-build: coverage-clean
1299# $(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" all
1300# $(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" \
1301# -j1 test
1302#
1303# coverage-report:
1304# gcov -b *.c */*.c
1305# grep '^function.*called 0 ' *.c.gcov */*.c.gcov \
1306# | sed -e 's/\([^:]*\)\.gcov: *function \([^ ]*\) called.*/\1: \2/' \
1307# | tee coverage-untested-functions
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index d9ab3ce446ac..0c7454f8b8a9 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -55,7 +55,7 @@ int bench_sched_pipe(int argc, const char **argv,
55 * discarding returned value of read(), write() 55 * discarding returned value of read(), write()
56 * causes error in building environment for perf 56 * causes error in building environment for perf
57 */ 57 */
58 int ret, wait_stat; 58 int __used ret, wait_stat;
59 pid_t pid, retpid; 59 pid_t pid, retpid;
60 60
61 argc = parse_options(argc, argv, options, 61 argc = parse_options(argc, argv, options,
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 8879463807e4..695de4b5ae63 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -9,6 +9,7 @@
9 9
10#include "util/util.h" 10#include "util/util.h"
11 11
12#include "util/util.h"
12#include "util/color.h" 13#include "util/color.h"
13#include <linux/list.h> 14#include <linux/list.h>
14#include "util/cache.h" 15#include "util/cache.h"
@@ -18,6 +19,9 @@
18#include "perf.h" 19#include "perf.h"
19#include "util/debug.h" 20#include "util/debug.h"
20 21
22#include "util/evlist.h"
23#include "util/evsel.h"
24#include "util/annotate.h"
21#include "util/event.h" 25#include "util/event.h"
22#include "util/parse-options.h" 26#include "util/parse-options.h"
23#include "util/parse-events.h" 27#include "util/parse-events.h"
@@ -36,9 +40,13 @@ static bool print_line;
36 40
37static const char *sym_hist_filter; 41static const char *sym_hist_filter;
38 42
39static int hists__add_entry(struct hists *self, struct addr_location *al) 43static int perf_evlist__add_sample(struct perf_evlist *evlist,
44 struct perf_sample *sample,
45 struct addr_location *al)
40{ 46{
47 struct perf_evsel *evsel;
41 struct hist_entry *he; 48 struct hist_entry *he;
49 int ret;
42 50
43 if (sym_hist_filter != NULL && 51 if (sym_hist_filter != NULL &&
44 (al->sym == NULL || strcmp(sym_hist_filter, al->sym->name) != 0)) { 52 (al->sym == NULL || strcmp(sym_hist_filter, al->sym->name) != 0)) {
@@ -51,25 +59,51 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
51 return 0; 59 return 0;
52 } 60 }
53 61
54 he = __hists__add_entry(self, al, NULL, 1); 62 evsel = perf_evlist__id2evsel(evlist, sample->id);
63 if (evsel == NULL) {
64 /*
65 * FIXME: Propagate this back, but at least we're in a builtin,
66 * where exit() is allowed. ;-)
67 */
68 ui__warning("Invalid %s file, contains samples with id not in "
69 "its header!\n", input_name);
70 exit_browser(0);
71 exit(1);
72 }
73
74 he = __hists__add_entry(&evsel->hists, al, NULL, 1);
55 if (he == NULL) 75 if (he == NULL)
56 return -ENOMEM; 76 return -ENOMEM;
57 77
58 return hist_entry__inc_addr_samples(he, al->addr); 78 ret = 0;
79 if (he->ms.sym != NULL) {
80 struct annotation *notes = symbol__annotation(he->ms.sym);
81 if (notes->src == NULL &&
82 symbol__alloc_hist(he->ms.sym, evlist->nr_entries) < 0)
83 return -ENOMEM;
84
85 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
86 }
87
88 evsel->hists.stats.total_period += sample->period;
89 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
90 return ret;
59} 91}
60 92
61static int process_sample_event(event_t *event, struct sample_data *sample, 93static int process_sample_event(union perf_event *event,
94 struct perf_sample *sample,
62 struct perf_session *session) 95 struct perf_session *session)
63{ 96{
64 struct addr_location al; 97 struct addr_location al;
65 98
66 if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) { 99 if (perf_event__preprocess_sample(event, session, &al, sample,
100 symbol__annotate_init) < 0) {
67 pr_warning("problem processing %d event, skipping it.\n", 101 pr_warning("problem processing %d event, skipping it.\n",
68 event->header.type); 102 event->header.type);
69 return -1; 103 return -1;
70 } 104 }
71 105
72 if (!al.filtered && hists__add_entry(&session->hists, &al)) { 106 if (!al.filtered && perf_evlist__add_sample(session->evlist, sample, &al)) {
73 pr_warning("problem incrementing symbol count, " 107 pr_warning("problem incrementing symbol count, "
74 "skipping event\n"); 108 "skipping event\n");
75 return -1; 109 return -1;
@@ -78,261 +112,26 @@ static int process_sample_event(event_t *event, struct sample_data *sample,
78 return 0; 112 return 0;
79} 113}
80 114
81static int objdump_line__print(struct objdump_line *self, 115static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
82 struct list_head *head,
83 struct hist_entry *he, u64 len)
84{
85 struct symbol *sym = he->ms.sym;
86 static const char *prev_line;
87 static const char *prev_color;
88
89 if (self->offset != -1) {
90 const char *path = NULL;
91 unsigned int hits = 0;
92 double percent = 0.0;
93 const char *color;
94 struct sym_priv *priv = symbol__priv(sym);
95 struct sym_ext *sym_ext = priv->ext;
96 struct sym_hist *h = priv->hist;
97 s64 offset = self->offset;
98 struct objdump_line *next = objdump__get_next_ip_line(head, self);
99
100 while (offset < (s64)len &&
101 (next == NULL || offset < next->offset)) {
102 if (sym_ext) {
103 if (path == NULL)
104 path = sym_ext[offset].path;
105 percent += sym_ext[offset].percent;
106 } else
107 hits += h->ip[offset];
108
109 ++offset;
110 }
111
112 if (sym_ext == NULL && h->sum)
113 percent = 100.0 * hits / h->sum;
114
115 color = get_percent_color(percent);
116
117 /*
118 * Also color the filename and line if needed, with
119 * the same color than the percentage. Don't print it
120 * twice for close colored ip with the same filename:line
121 */
122 if (path) {
123 if (!prev_line || strcmp(prev_line, path)
124 || color != prev_color) {
125 color_fprintf(stdout, color, " %s", path);
126 prev_line = path;
127 prev_color = color;
128 }
129 }
130
131 color_fprintf(stdout, color, " %7.2f", percent);
132 printf(" : ");
133 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", self->line);
134 } else {
135 if (!*self->line)
136 printf(" :\n");
137 else
138 printf(" : %s\n", self->line);
139 }
140
141 return 0;
142}
143
144static struct rb_root root_sym_ext;
145
146static void insert_source_line(struct sym_ext *sym_ext)
147{
148 struct sym_ext *iter;
149 struct rb_node **p = &root_sym_ext.rb_node;
150 struct rb_node *parent = NULL;
151
152 while (*p != NULL) {
153 parent = *p;
154 iter = rb_entry(parent, struct sym_ext, node);
155
156 if (sym_ext->percent > iter->percent)
157 p = &(*p)->rb_left;
158 else
159 p = &(*p)->rb_right;
160 }
161
162 rb_link_node(&sym_ext->node, parent, p);
163 rb_insert_color(&sym_ext->node, &root_sym_ext);
164}
165
166static void free_source_line(struct hist_entry *he, int len)
167{
168 struct sym_priv *priv = symbol__priv(he->ms.sym);
169 struct sym_ext *sym_ext = priv->ext;
170 int i;
171
172 if (!sym_ext)
173 return;
174
175 for (i = 0; i < len; i++)
176 free(sym_ext[i].path);
177 free(sym_ext);
178
179 priv->ext = NULL;
180 root_sym_ext = RB_ROOT;
181}
182
183/* Get the filename:line for the colored entries */
184static void
185get_source_line(struct hist_entry *he, int len, const char *filename)
186{
187 struct symbol *sym = he->ms.sym;
188 u64 start;
189 int i;
190 char cmd[PATH_MAX * 2];
191 struct sym_ext *sym_ext;
192 struct sym_priv *priv = symbol__priv(sym);
193 struct sym_hist *h = priv->hist;
194
195 if (!h->sum)
196 return;
197
198 sym_ext = priv->ext = calloc(len, sizeof(struct sym_ext));
199 if (!priv->ext)
200 return;
201
202 start = he->ms.map->unmap_ip(he->ms.map, sym->start);
203
204 for (i = 0; i < len; i++) {
205 char *path = NULL;
206 size_t line_len;
207 u64 offset;
208 FILE *fp;
209
210 sym_ext[i].percent = 100.0 * h->ip[i] / h->sum;
211 if (sym_ext[i].percent <= 0.5)
212 continue;
213
214 offset = start + i;
215 sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
216 fp = popen(cmd, "r");
217 if (!fp)
218 continue;
219
220 if (getline(&path, &line_len, fp) < 0 || !line_len)
221 goto next;
222
223 sym_ext[i].path = malloc(sizeof(char) * line_len + 1);
224 if (!sym_ext[i].path)
225 goto next;
226
227 strcpy(sym_ext[i].path, path);
228 insert_source_line(&sym_ext[i]);
229
230 next:
231 pclose(fp);
232 }
233}
234
235static void print_summary(const char *filename)
236{
237 struct sym_ext *sym_ext;
238 struct rb_node *node;
239
240 printf("\nSorted summary for file %s\n", filename);
241 printf("----------------------------------------------\n\n");
242
243 if (RB_EMPTY_ROOT(&root_sym_ext)) {
244 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
245 return;
246 }
247
248 node = rb_first(&root_sym_ext);
249 while (node) {
250 double percent;
251 const char *color;
252 char *path;
253
254 sym_ext = rb_entry(node, struct sym_ext, node);
255 percent = sym_ext->percent;
256 color = get_percent_color(percent);
257 path = sym_ext->path;
258
259 color_fprintf(stdout, color, " %7.2f %s", percent, path);
260 node = rb_next(node);
261 }
262}
263
264static void hist_entry__print_hits(struct hist_entry *self)
265{
266 struct symbol *sym = self->ms.sym;
267 struct sym_priv *priv = symbol__priv(sym);
268 struct sym_hist *h = priv->hist;
269 u64 len = sym->end - sym->start, offset;
270
271 for (offset = 0; offset < len; ++offset)
272 if (h->ip[offset] != 0)
273 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
274 sym->start + offset, h->ip[offset]);
275 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
276}
277
278static int hist_entry__tty_annotate(struct hist_entry *he)
279{ 116{
280 struct map *map = he->ms.map; 117 return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx,
281 struct dso *dso = map->dso; 118 print_line, full_paths, 0, 0);
282 struct symbol *sym = he->ms.sym;
283 const char *filename = dso->long_name, *d_filename;
284 u64 len;
285 LIST_HEAD(head);
286 struct objdump_line *pos, *n;
287
288 if (hist_entry__annotate(he, &head, 0) < 0)
289 return -1;
290
291 if (full_paths)
292 d_filename = filename;
293 else
294 d_filename = basename(filename);
295
296 len = sym->end - sym->start;
297
298 if (print_line) {
299 get_source_line(he, len, filename);
300 print_summary(filename);
301 }
302
303 printf("\n\n------------------------------------------------\n");
304 printf(" Percent | Source code & Disassembly of %s\n", d_filename);
305 printf("------------------------------------------------\n");
306
307 if (verbose)
308 hist_entry__print_hits(he);
309
310 list_for_each_entry_safe(pos, n, &head, node) {
311 objdump_line__print(pos, &head, he, len);
312 list_del(&pos->node);
313 objdump_line__free(pos);
314 }
315
316 if (print_line)
317 free_source_line(he, len);
318
319 return 0;
320} 119}
321 120
322static void hists__find_annotations(struct hists *self) 121static void hists__find_annotations(struct hists *self, int evidx)
323{ 122{
324 struct rb_node *nd = rb_first(&self->entries), *next; 123 struct rb_node *nd = rb_first(&self->entries), *next;
325 int key = KEY_RIGHT; 124 int key = KEY_RIGHT;
326 125
327 while (nd) { 126 while (nd) {
328 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); 127 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
329 struct sym_priv *priv; 128 struct annotation *notes;
330 129
331 if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned) 130 if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned)
332 goto find_next; 131 goto find_next;
333 132
334 priv = symbol__priv(he->ms.sym); 133 notes = symbol__annotation(he->ms.sym);
335 if (priv->hist == NULL) { 134 if (notes->src == NULL) {
336find_next: 135find_next:
337 if (key == KEY_LEFT) 136 if (key == KEY_LEFT)
338 nd = rb_prev(nd); 137 nd = rb_prev(nd);
@@ -342,7 +141,7 @@ find_next:
342 } 141 }
343 142
344 if (use_browser > 0) { 143 if (use_browser > 0) {
345 key = hist_entry__tui_annotate(he); 144 key = hist_entry__tui_annotate(he, evidx);
346 switch (key) { 145 switch (key) {
347 case KEY_RIGHT: 146 case KEY_RIGHT:
348 next = rb_next(nd); 147 next = rb_next(nd);
@@ -357,24 +156,24 @@ find_next:
357 if (next != NULL) 156 if (next != NULL)
358 nd = next; 157 nd = next;
359 } else { 158 } else {
360 hist_entry__tty_annotate(he); 159 hist_entry__tty_annotate(he, evidx);
361 nd = rb_next(nd); 160 nd = rb_next(nd);
362 /* 161 /*
363 * Since we have a hist_entry per IP for the same 162 * Since we have a hist_entry per IP for the same
364 * symbol, free he->ms.sym->hist to signal we already 163 * symbol, free he->ms.sym->src to signal we already
365 * processed this symbol. 164 * processed this symbol.
366 */ 165 */
367 free(priv->hist); 166 free(notes->src);
368 priv->hist = NULL; 167 notes->src = NULL;
369 } 168 }
370 } 169 }
371} 170}
372 171
373static struct perf_event_ops event_ops = { 172static struct perf_event_ops event_ops = {
374 .sample = process_sample_event, 173 .sample = process_sample_event,
375 .mmap = event__process_mmap, 174 .mmap = perf_event__process_mmap,
376 .comm = event__process_comm, 175 .comm = perf_event__process_comm,
377 .fork = event__process_task, 176 .fork = perf_event__process_task,
378 .ordered_samples = true, 177 .ordered_samples = true,
379 .ordering_requires_timestamps = true, 178 .ordering_requires_timestamps = true,
380}; 179};
@@ -383,6 +182,8 @@ static int __cmd_annotate(void)
383{ 182{
384 int ret; 183 int ret;
385 struct perf_session *session; 184 struct perf_session *session;
185 struct perf_evsel *pos;
186 u64 total_nr_samples;
386 187
387 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops); 188 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
388 if (session == NULL) 189 if (session == NULL)
@@ -403,12 +204,36 @@ static int __cmd_annotate(void)
403 if (verbose > 2) 204 if (verbose > 2)
404 perf_session__fprintf_dsos(session, stdout); 205 perf_session__fprintf_dsos(session, stdout);
405 206
406 hists__collapse_resort(&session->hists); 207 total_nr_samples = 0;
407 hists__output_resort(&session->hists); 208 list_for_each_entry(pos, &session->evlist->entries, node) {
408 hists__find_annotations(&session->hists); 209 struct hists *hists = &pos->hists;
409out_delete: 210 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
410 perf_session__delete(session); 211
212 if (nr_samples > 0) {
213 total_nr_samples += nr_samples;
214 hists__collapse_resort(hists);
215 hists__output_resort(hists);
216 hists__find_annotations(hists, pos->idx);
217 }
218 }
411 219
220 if (total_nr_samples == 0) {
221 ui__warning("The %s file has no samples!\n", input_name);
222 goto out_delete;
223 }
224out_delete:
225 /*
226 * Speed up the exit process, for large files this can
227 * take quite a while.
228 *
229 * XXX Enable this when using valgrind or if we ever
230 * librarize this command.
231 *
232 * Also experiment with obstacks to see how much speed
233 * up we'll get here.
234 *
235 * perf_session__delete(session);
236 */
412 return ret; 237 return ret;
413} 238}
414 239
@@ -451,9 +276,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
451 else if (use_tui) 276 else if (use_tui)
452 use_browser = 1; 277 use_browser = 1;
453 278
454 setup_browser(); 279 setup_browser(true);
455 280
456 symbol_conf.priv_size = sizeof(struct sym_priv); 281 symbol_conf.priv_size = sizeof(struct annotation);
457 symbol_conf.try_vmlinux_path = true; 282 symbol_conf.try_vmlinux_path = true;
458 283
459 if (symbol__init() < 0) 284 if (symbol__init() < 0)
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 3153e492dbcc..6b7d91160ecb 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -30,13 +30,13 @@ static int hists__add_entry(struct hists *self,
30 return -ENOMEM; 30 return -ENOMEM;
31} 31}
32 32
33static int diff__process_sample_event(event_t *event, 33static int diff__process_sample_event(union perf_event *event,
34 struct sample_data *sample, 34 struct perf_sample *sample,
35 struct perf_session *session) 35 struct perf_session *session)
36{ 36{
37 struct addr_location al; 37 struct addr_location al;
38 38
39 if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) { 39 if (perf_event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
40 pr_warning("problem processing %d event, skipping it.\n", 40 pr_warning("problem processing %d event, skipping it.\n",
41 event->header.type); 41 event->header.type);
42 return -1; 42 return -1;
@@ -56,11 +56,11 @@ static int diff__process_sample_event(event_t *event,
56 56
57static struct perf_event_ops event_ops = { 57static struct perf_event_ops event_ops = {
58 .sample = diff__process_sample_event, 58 .sample = diff__process_sample_event,
59 .mmap = event__process_mmap, 59 .mmap = perf_event__process_mmap,
60 .comm = event__process_comm, 60 .comm = perf_event__process_comm,
61 .exit = event__process_task, 61 .exit = perf_event__process_task,
62 .fork = event__process_task, 62 .fork = perf_event__process_task,
63 .lost = event__process_lost, 63 .lost = perf_event__process_lost,
64 .ordered_samples = true, 64 .ordered_samples = true,
65 .ordering_requires_timestamps = true, 65 .ordering_requires_timestamps = true,
66}; 66};
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 0c78ffa7bf67..e29f04ed3396 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -16,8 +16,8 @@
16static char const *input_name = "-"; 16static char const *input_name = "-";
17static bool inject_build_ids; 17static bool inject_build_ids;
18 18
19static int event__repipe_synth(event_t *event, 19static int perf_event__repipe_synth(union perf_event *event,
20 struct perf_session *session __used) 20 struct perf_session *session __used)
21{ 21{
22 uint32_t size; 22 uint32_t size;
23 void *buf = event; 23 void *buf = event;
@@ -36,41 +36,44 @@ static int event__repipe_synth(event_t *event,
36 return 0; 36 return 0;
37} 37}
38 38
39static int event__repipe(event_t *event, struct sample_data *sample __used, 39static int perf_event__repipe(union perf_event *event,
40 struct perf_session *session) 40 struct perf_sample *sample __used,
41 struct perf_session *session)
41{ 42{
42 return event__repipe_synth(event, session); 43 return perf_event__repipe_synth(event, session);
43} 44}
44 45
45static int event__repipe_mmap(event_t *self, struct sample_data *sample, 46static int perf_event__repipe_mmap(union perf_event *event,
46 struct perf_session *session) 47 struct perf_sample *sample,
48 struct perf_session *session)
47{ 49{
48 int err; 50 int err;
49 51
50 err = event__process_mmap(self, sample, session); 52 err = perf_event__process_mmap(event, sample, session);
51 event__repipe(self, sample, session); 53 perf_event__repipe(event, sample, session);
52 54
53 return err; 55 return err;
54} 56}
55 57
56static int event__repipe_task(event_t *self, struct sample_data *sample, 58static int perf_event__repipe_task(union perf_event *event,
57 struct perf_session *session) 59 struct perf_sample *sample,
60 struct perf_session *session)
58{ 61{
59 int err; 62 int err;
60 63
61 err = event__process_task(self, sample, session); 64 err = perf_event__process_task(event, sample, session);
62 event__repipe(self, sample, session); 65 perf_event__repipe(event, sample, session);
63 66
64 return err; 67 return err;
65} 68}
66 69
67static int event__repipe_tracing_data(event_t *self, 70static int perf_event__repipe_tracing_data(union perf_event *event,
68 struct perf_session *session) 71 struct perf_session *session)
69{ 72{
70 int err; 73 int err;
71 74
72 event__repipe_synth(self, session); 75 perf_event__repipe_synth(event, session);
73 err = event__process_tracing_data(self, session); 76 err = perf_event__process_tracing_data(event, session);
74 77
75 return err; 78 return err;
76} 79}
@@ -109,8 +112,8 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
109 if (self->kernel) 112 if (self->kernel)
110 misc = PERF_RECORD_MISC_KERNEL; 113 misc = PERF_RECORD_MISC_KERNEL;
111 114
112 err = event__synthesize_build_id(self, misc, event__repipe, 115 err = perf_event__synthesize_build_id(self, misc, perf_event__repipe,
113 machine, session); 116 machine, session);
114 if (err) { 117 if (err) {
115 pr_err("Can't synthesize build_id event for %s\n", self->long_name); 118 pr_err("Can't synthesize build_id event for %s\n", self->long_name);
116 return -1; 119 return -1;
@@ -119,8 +122,9 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
119 return 0; 122 return 0;
120} 123}
121 124
122static int event__inject_buildid(event_t *event, struct sample_data *sample, 125static int perf_event__inject_buildid(union perf_event *event,
123 struct perf_session *session) 126 struct perf_sample *sample,
127 struct perf_session *session)
124{ 128{
125 struct addr_location al; 129 struct addr_location al;
126 struct thread *thread; 130 struct thread *thread;
@@ -155,24 +159,24 @@ static int event__inject_buildid(event_t *event, struct sample_data *sample,
155 } 159 }
156 160
157repipe: 161repipe:
158 event__repipe(event, sample, session); 162 perf_event__repipe(event, sample, session);
159 return 0; 163 return 0;
160} 164}
161 165
162struct perf_event_ops inject_ops = { 166struct perf_event_ops inject_ops = {
163 .sample = event__repipe, 167 .sample = perf_event__repipe,
164 .mmap = event__repipe, 168 .mmap = perf_event__repipe,
165 .comm = event__repipe, 169 .comm = perf_event__repipe,
166 .fork = event__repipe, 170 .fork = perf_event__repipe,
167 .exit = event__repipe, 171 .exit = perf_event__repipe,
168 .lost = event__repipe, 172 .lost = perf_event__repipe,
169 .read = event__repipe, 173 .read = perf_event__repipe,
170 .throttle = event__repipe, 174 .throttle = perf_event__repipe,
171 .unthrottle = event__repipe, 175 .unthrottle = perf_event__repipe,
172 .attr = event__repipe_synth, 176 .attr = perf_event__repipe_synth,
173 .event_type = event__repipe_synth, 177 .event_type = perf_event__repipe_synth,
174 .tracing_data = event__repipe_synth, 178 .tracing_data = perf_event__repipe_synth,
175 .build_id = event__repipe_synth, 179 .build_id = perf_event__repipe_synth,
176}; 180};
177 181
178extern volatile int session_done; 182extern volatile int session_done;
@@ -190,10 +194,10 @@ static int __cmd_inject(void)
190 signal(SIGINT, sig_handler); 194 signal(SIGINT, sig_handler);
191 195
192 if (inject_build_ids) { 196 if (inject_build_ids) {
193 inject_ops.sample = event__inject_buildid; 197 inject_ops.sample = perf_event__inject_buildid;
194 inject_ops.mmap = event__repipe_mmap; 198 inject_ops.mmap = perf_event__repipe_mmap;
195 inject_ops.fork = event__repipe_task; 199 inject_ops.fork = perf_event__repipe_task;
196 inject_ops.tracing_data = event__repipe_tracing_data; 200 inject_ops.tracing_data = perf_event__repipe_tracing_data;
197 } 201 }
198 202
199 session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops); 203 session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops);
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index d97256d65980..7f618f4e7b79 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -275,9 +275,8 @@ static void process_free_event(void *data,
275 s_alloc->alloc_cpu = -1; 275 s_alloc->alloc_cpu = -1;
276} 276}
277 277
278static void 278static void process_raw_event(union perf_event *raw_event __used, void *data,
279process_raw_event(event_t *raw_event __used, void *data, 279 int cpu, u64 timestamp, struct thread *thread)
280 int cpu, u64 timestamp, struct thread *thread)
281{ 280{
282 struct event *event; 281 struct event *event;
283 int type; 282 int type;
@@ -304,7 +303,8 @@ process_raw_event(event_t *raw_event __used, void *data,
304 } 303 }
305} 304}
306 305
307static int process_sample_event(event_t *event, struct sample_data *sample, 306static int process_sample_event(union perf_event *event,
307 struct perf_sample *sample,
308 struct perf_session *session) 308 struct perf_session *session)
309{ 309{
310 struct thread *thread = perf_session__findnew(session, event->ip.pid); 310 struct thread *thread = perf_session__findnew(session, event->ip.pid);
@@ -325,7 +325,7 @@ static int process_sample_event(event_t *event, struct sample_data *sample,
325 325
326static struct perf_event_ops event_ops = { 326static struct perf_event_ops event_ops = {
327 .sample = process_sample_event, 327 .sample = process_sample_event,
328 .comm = event__process_comm, 328 .comm = perf_event__process_comm,
329 .ordered_samples = true, 329 .ordered_samples = true,
330}; 330};
331 331
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index d88c6961274c..6313b6eb3ebb 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (C) 2009, Thomas Gleixner <tglx@linutronix.de> 6 * Copyright (C) 2009, Thomas Gleixner <tglx@linutronix.de>
7 * Copyright (C) 2008-2009, Red Hat Inc, Ingo Molnar <mingo@redhat.com> 7 * Copyright (C) 2008-2009, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
8 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
8 */ 9 */
9#include "builtin.h" 10#include "builtin.h"
10 11
@@ -13,9 +14,47 @@
13#include "util/parse-events.h" 14#include "util/parse-events.h"
14#include "util/cache.h" 15#include "util/cache.h"
15 16
16int cmd_list(int argc __used, const char **argv __used, const char *prefix __used) 17int cmd_list(int argc, const char **argv, const char *prefix __used)
17{ 18{
18 setup_pager(); 19 setup_pager();
19 print_events(); 20
21 if (argc == 1)
22 print_events(NULL);
23 else {
24 int i;
25
26 for (i = 1; i < argc; ++i) {
27 if (i > 1)
28 putchar('\n');
29 if (strncmp(argv[i], "tracepoint", 10) == 0)
30 print_tracepoint_events(NULL, NULL);
31 else if (strcmp(argv[i], "hw") == 0 ||
32 strcmp(argv[i], "hardware") == 0)
33 print_events_type(PERF_TYPE_HARDWARE);
34 else if (strcmp(argv[i], "sw") == 0 ||
35 strcmp(argv[i], "software") == 0)
36 print_events_type(PERF_TYPE_SOFTWARE);
37 else if (strcmp(argv[i], "cache") == 0 ||
38 strcmp(argv[i], "hwcache") == 0)
39 print_hwcache_events(NULL);
40 else {
41 char *sep = strchr(argv[i], ':'), *s;
42 int sep_idx;
43
44 if (sep == NULL) {
45 print_events(argv[i]);
46 continue;
47 }
48 sep_idx = sep - argv[i];
49 s = strdup(argv[i]);
50 if (s == NULL)
51 return -1;
52
53 s[sep_idx] = '\0';
54 print_tracepoint_events(s, s + sep_idx + 1);
55 free(s);
56 }
57 }
58 }
20 return 0; 59 return 0;
21} 60}
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 2b36defc5d73..2e93f99b1480 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -834,14 +834,14 @@ static void dump_info(void)
834 die("Unknown type of information\n"); 834 die("Unknown type of information\n");
835} 835}
836 836
837static int process_sample_event(event_t *self, struct sample_data *sample, 837static int process_sample_event(union perf_event *event, struct perf_sample *sample,
838 struct perf_session *s) 838 struct perf_session *s)
839{ 839{
840 struct thread *thread = perf_session__findnew(s, sample->tid); 840 struct thread *thread = perf_session__findnew(s, sample->tid);
841 841
842 if (thread == NULL) { 842 if (thread == NULL) {
843 pr_debug("problem processing %d event, skipping it.\n", 843 pr_debug("problem processing %d event, skipping it.\n",
844 self->header.type); 844 event->header.type);
845 return -1; 845 return -1;
846 } 846 }
847 847
@@ -852,7 +852,7 @@ static int process_sample_event(event_t *self, struct sample_data *sample,
852 852
853static struct perf_event_ops eops = { 853static struct perf_event_ops eops = {
854 .sample = process_sample_event, 854 .sample = process_sample_event,
855 .comm = event__process_comm, 855 .comm = perf_event__process_comm,
856 .ordered_samples = true, 856 .ordered_samples = true,
857}; 857};
858 858
@@ -893,7 +893,7 @@ static const char * const report_usage[] = {
893 893
894static const struct option report_options[] = { 894static const struct option report_options[] = {
895 OPT_STRING('k', "key", &sort_key, "acquired", 895 OPT_STRING('k', "key", &sort_key, "acquired",
896 "key for sorting"), 896 "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
897 /* TODO: type */ 897 /* TODO: type */
898 OPT_END() 898 OPT_END()
899}; 899};
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index add163c9f0e7..2c0e64d0b4aa 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -36,6 +36,7 @@
36#include "builtin.h" 36#include "builtin.h"
37#include "util/util.h" 37#include "util/util.h"
38#include "util/strlist.h" 38#include "util/strlist.h"
39#include "util/strfilter.h"
39#include "util/symbol.h" 40#include "util/symbol.h"
40#include "util/debug.h" 41#include "util/debug.h"
41#include "util/debugfs.h" 42#include "util/debugfs.h"
@@ -43,6 +44,8 @@
43#include "util/probe-finder.h" 44#include "util/probe-finder.h"
44#include "util/probe-event.h" 45#include "util/probe-event.h"
45 46
47#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
48#define DEFAULT_FUNC_FILTER "!_*"
46#define MAX_PATH_LEN 256 49#define MAX_PATH_LEN 256
47 50
48/* Session management structure */ 51/* Session management structure */
@@ -52,6 +55,7 @@ static struct {
52 bool show_lines; 55 bool show_lines;
53 bool show_vars; 56 bool show_vars;
54 bool show_ext_vars; 57 bool show_ext_vars;
58 bool show_funcs;
55 bool mod_events; 59 bool mod_events;
56 int nevents; 60 int nevents;
57 struct perf_probe_event events[MAX_PROBES]; 61 struct perf_probe_event events[MAX_PROBES];
@@ -59,6 +63,7 @@ static struct {
59 struct line_range line_range; 63 struct line_range line_range;
60 const char *target_module; 64 const char *target_module;
61 int max_probe_points; 65 int max_probe_points;
66 struct strfilter *filter;
62} params; 67} params;
63 68
64/* Parse an event definition. Note that any error must die. */ 69/* Parse an event definition. Note that any error must die. */
@@ -157,6 +162,27 @@ static int opt_show_vars(const struct option *opt __used,
157} 162}
158#endif 163#endif
159 164
165static int opt_set_filter(const struct option *opt __used,
166 const char *str, int unset __used)
167{
168 const char *err;
169
170 if (str) {
171 pr_debug2("Set filter: %s\n", str);
172 if (params.filter)
173 strfilter__delete(params.filter);
174 params.filter = strfilter__new(str, &err);
175 if (!params.filter) {
176 pr_err("Filter parse error at %td.\n", err - str + 1);
177 pr_err("Source: \"%s\"\n", str);
178 pr_err(" %*c\n", (int)(err - str + 1), '^');
179 return -EINVAL;
180 }
181 }
182
183 return 0;
184}
185
160static const char * const probe_usage[] = { 186static const char * const probe_usage[] = {
161 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", 187 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
162 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 188 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
@@ -221,6 +247,13 @@ static const struct option options[] = {
221 OPT__DRY_RUN(&probe_event_dry_run), 247 OPT__DRY_RUN(&probe_event_dry_run),
222 OPT_INTEGER('\0', "max-probes", &params.max_probe_points, 248 OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
223 "Set how many probe points can be found for a probe."), 249 "Set how many probe points can be found for a probe."),
250 OPT_BOOLEAN('F', "funcs", &params.show_funcs,
251 "Show potential probe-able functions."),
252 OPT_CALLBACK('\0', "filter", NULL,
253 "[!]FILTER", "Set a filter (with --vars/funcs only)\n"
254 "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
255 "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)",
256 opt_set_filter),
224 OPT_END() 257 OPT_END()
225}; 258};
226 259
@@ -246,7 +279,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
246 params.max_probe_points = MAX_PROBES; 279 params.max_probe_points = MAX_PROBES;
247 280
248 if ((!params.nevents && !params.dellist && !params.list_events && 281 if ((!params.nevents && !params.dellist && !params.list_events &&
249 !params.show_lines)) 282 !params.show_lines && !params.show_funcs))
250 usage_with_options(probe_usage, options); 283 usage_with_options(probe_usage, options);
251 284
252 /* 285 /*
@@ -267,12 +300,41 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
267 pr_err(" Error: Don't use --list with --vars.\n"); 300 pr_err(" Error: Don't use --list with --vars.\n");
268 usage_with_options(probe_usage, options); 301 usage_with_options(probe_usage, options);
269 } 302 }
303 if (params.show_funcs) {
304 pr_err(" Error: Don't use --list with --funcs.\n");
305 usage_with_options(probe_usage, options);
306 }
270 ret = show_perf_probe_events(); 307 ret = show_perf_probe_events();
271 if (ret < 0) 308 if (ret < 0)
272 pr_err(" Error: Failed to show event list. (%d)\n", 309 pr_err(" Error: Failed to show event list. (%d)\n",
273 ret); 310 ret);
274 return ret; 311 return ret;
275 } 312 }
313 if (params.show_funcs) {
314 if (params.nevents != 0 || params.dellist) {
315 pr_err(" Error: Don't use --funcs with"
316 " --add/--del.\n");
317 usage_with_options(probe_usage, options);
318 }
319 if (params.show_lines) {
320 pr_err(" Error: Don't use --funcs with --line.\n");
321 usage_with_options(probe_usage, options);
322 }
323 if (params.show_vars) {
324 pr_err(" Error: Don't use --funcs with --vars.\n");
325 usage_with_options(probe_usage, options);
326 }
327 if (!params.filter)
328 params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
329 NULL);
330 ret = show_available_funcs(params.target_module,
331 params.filter);
332 strfilter__delete(params.filter);
333 if (ret < 0)
334 pr_err(" Error: Failed to show functions."
335 " (%d)\n", ret);
336 return ret;
337 }
276 338
277#ifdef DWARF_SUPPORT 339#ifdef DWARF_SUPPORT
278 if (params.show_lines) { 340 if (params.show_lines) {
@@ -297,10 +359,16 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
297 " --add/--del.\n"); 359 " --add/--del.\n");
298 usage_with_options(probe_usage, options); 360 usage_with_options(probe_usage, options);
299 } 361 }
362 if (!params.filter)
363 params.filter = strfilter__new(DEFAULT_VAR_FILTER,
364 NULL);
365
300 ret = show_available_vars(params.events, params.nevents, 366 ret = show_available_vars(params.events, params.nevents,
301 params.max_probe_points, 367 params.max_probe_points,
302 params.target_module, 368 params.target_module,
369 params.filter,
303 params.show_ext_vars); 370 params.show_ext_vars);
371 strfilter__delete(params.filter);
304 if (ret < 0) 372 if (ret < 0)
305 pr_err(" Error: Failed to show vars. (%d)\n", ret); 373 pr_err(" Error: Failed to show vars. (%d)\n", ret);
306 return ret; 374 return ret;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 60cac6f92e8b..6febcc168a8c 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -18,11 +18,13 @@
18 18
19#include "util/header.h" 19#include "util/header.h"
20#include "util/event.h" 20#include "util/event.h"
21#include "util/evlist.h"
21#include "util/evsel.h" 22#include "util/evsel.h"
22#include "util/debug.h" 23#include "util/debug.h"
23#include "util/session.h" 24#include "util/session.h"
24#include "util/symbol.h" 25#include "util/symbol.h"
25#include "util/cpumap.h" 26#include "util/cpumap.h"
27#include "util/thread_map.h"
26 28
27#include <unistd.h> 29#include <unistd.h>
28#include <sched.h> 30#include <sched.h>
@@ -37,16 +39,14 @@ enum write_mode_t {
37 39
38static u64 user_interval = ULLONG_MAX; 40static u64 user_interval = ULLONG_MAX;
39static u64 default_interval = 0; 41static u64 default_interval = 0;
40static u64 sample_type;
41 42
42static struct cpu_map *cpus;
43static unsigned int page_size; 43static unsigned int page_size;
44static unsigned int mmap_pages = 128; 44static unsigned int mmap_pages = 128;
45static unsigned int user_freq = UINT_MAX; 45static unsigned int user_freq = UINT_MAX;
46static int freq = 1000; 46static int freq = 1000;
47static int output; 47static int output;
48static int pipe_output = 0; 48static int pipe_output = 0;
49static const char *output_name = "perf.data"; 49static const char *output_name = NULL;
50static int group = 0; 50static int group = 0;
51static int realtime_prio = 0; 51static int realtime_prio = 0;
52static bool nodelay = false; 52static bool nodelay = false;
@@ -55,7 +55,6 @@ static bool sample_id_all_avail = true;
55static bool system_wide = false; 55static bool system_wide = false;
56static pid_t target_pid = -1; 56static pid_t target_pid = -1;
57static pid_t target_tid = -1; 57static pid_t target_tid = -1;
58static struct thread_map *threads;
59static pid_t child_pid = -1; 58static pid_t child_pid = -1;
60static bool no_inherit = false; 59static bool no_inherit = false;
61static enum write_mode_t write_mode = WRITE_FORCE; 60static enum write_mode_t write_mode = WRITE_FORCE;
@@ -66,51 +65,17 @@ static bool sample_address = false;
66static bool sample_time = false; 65static bool sample_time = false;
67static bool no_buildid = false; 66static bool no_buildid = false;
68static bool no_buildid_cache = false; 67static bool no_buildid_cache = false;
68static struct perf_evlist *evsel_list;
69 69
70static long samples = 0; 70static long samples = 0;
71static u64 bytes_written = 0; 71static u64 bytes_written = 0;
72 72
73static struct pollfd *event_array;
74
75static int nr_poll = 0;
76static int nr_cpu = 0;
77
78static int file_new = 1; 73static int file_new = 1;
79static off_t post_processing_offset; 74static off_t post_processing_offset;
80 75
81static struct perf_session *session; 76static struct perf_session *session;
82static const char *cpu_list; 77static const char *cpu_list;
83 78
84struct mmap_data {
85 void *base;
86 unsigned int mask;
87 unsigned int prev;
88};
89
90static struct mmap_data mmap_array[MAX_NR_CPUS];
91
92static unsigned long mmap_read_head(struct mmap_data *md)
93{
94 struct perf_event_mmap_page *pc = md->base;
95 long head;
96
97 head = pc->data_head;
98 rmb();
99
100 return head;
101}
102
103static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
104{
105 struct perf_event_mmap_page *pc = md->base;
106
107 /*
108 * ensure all reads are done before we write the tail out.
109 */
110 /* mb(); */
111 pc->data_tail = tail;
112}
113
114static void advance_output(size_t size) 79static void advance_output(size_t size)
115{ 80{
116 bytes_written += size; 81 bytes_written += size;
@@ -131,42 +96,26 @@ static void write_output(void *buf, size_t size)
131 } 96 }
132} 97}
133 98
134static int process_synthesized_event(event_t *event, 99static int process_synthesized_event(union perf_event *event,
135 struct sample_data *sample __used, 100 struct perf_sample *sample __used,
136 struct perf_session *self __used) 101 struct perf_session *self __used)
137{ 102{
138 write_output(event, event->header.size); 103 write_output(event, event->header.size);
139 return 0; 104 return 0;
140} 105}
141 106
142static void mmap_read(struct mmap_data *md) 107static void mmap_read(struct perf_mmap *md)
143{ 108{
144 unsigned int head = mmap_read_head(md); 109 unsigned int head = perf_mmap__read_head(md);
145 unsigned int old = md->prev; 110 unsigned int old = md->prev;
146 unsigned char *data = md->base + page_size; 111 unsigned char *data = md->base + page_size;
147 unsigned long size; 112 unsigned long size;
148 void *buf; 113 void *buf;
149 int diff;
150 114
151 /* 115 if (old == head)
152 * If we're further behind than half the buffer, there's a chance 116 return;
153 * the writer will bite our tail and mess up the samples under us.
154 *
155 * If we somehow ended up ahead of the head, we got messed up.
156 *
157 * In either case, truncate and restart at head.
158 */
159 diff = head - old;
160 if (diff < 0) {
161 fprintf(stderr, "WARNING: failed to keep up with mmap data\n");
162 /*
163 * head points to a known good entry, start there.
164 */
165 old = head;
166 }
167 117
168 if (old != head) 118 samples++;
169 samples++;
170 119
171 size = head - old; 120 size = head - old;
172 121
@@ -185,7 +134,7 @@ static void mmap_read(struct mmap_data *md)
185 write_output(buf, size); 134 write_output(buf, size);
186 135
187 md->prev = old; 136 md->prev = old;
188 mmap_write_tail(md, old); 137 perf_mmap__write_tail(md, old);
189} 138}
190 139
191static volatile int done = 0; 140static volatile int done = 0;
@@ -209,53 +158,10 @@ static void sig_atexit(void)
209 kill(getpid(), signr); 158 kill(getpid(), signr);
210} 159}
211 160
212static int group_fd; 161static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
213
214static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr)
215{
216 struct perf_header_attr *h_attr;
217
218 if (nr < session->header.attrs) {
219 h_attr = session->header.attr[nr];
220 } else {
221 h_attr = perf_header_attr__new(a);
222 if (h_attr != NULL)
223 if (perf_header__add_attr(&session->header, h_attr) < 0) {
224 perf_header_attr__delete(h_attr);
225 h_attr = NULL;
226 }
227 }
228
229 return h_attr;
230}
231
232static void create_counter(struct perf_evsel *evsel, int cpu)
233{ 162{
234 char *filter = evsel->filter;
235 struct perf_event_attr *attr = &evsel->attr; 163 struct perf_event_attr *attr = &evsel->attr;
236 struct perf_header_attr *h_attr;
237 int track = !evsel->idx; /* only the first counter needs these */ 164 int track = !evsel->idx; /* only the first counter needs these */
238 int thread_index;
239 int ret;
240 struct {
241 u64 count;
242 u64 time_enabled;
243 u64 time_running;
244 u64 id;
245 } read_data;
246 /*
247 * Check if parse_single_tracepoint_event has already asked for
248 * PERF_SAMPLE_TIME.
249 *
250 * XXX this is kludgy but short term fix for problems introduced by
251 * eac23d1c that broke 'perf script' by having different sample_types
252 * when using multiple tracepoint events when we use a perf binary
253 * that tries to use sample_id_all on an older kernel.
254 *
255 * We need to move counter creation to perf_session, support
256 * different sample_types, etc.
257 */
258 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
259 165
260 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 166 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
261 PERF_FORMAT_TOTAL_TIME_RUNNING | 167 PERF_FORMAT_TOTAL_TIME_RUNNING |
@@ -263,7 +169,7 @@ static void create_counter(struct perf_evsel *evsel, int cpu)
263 169
264 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; 170 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
265 171
266 if (nr_counters > 1) 172 if (evlist->nr_entries > 1)
267 attr->sample_type |= PERF_SAMPLE_ID; 173 attr->sample_type |= PERF_SAMPLE_ID;
268 174
269 /* 175 /*
@@ -315,19 +221,58 @@ static void create_counter(struct perf_evsel *evsel, int cpu)
315 221
316 attr->mmap = track; 222 attr->mmap = track;
317 attr->comm = track; 223 attr->comm = track;
318 attr->inherit = !no_inherit; 224
319 if (target_pid == -1 && target_tid == -1 && !system_wide) { 225 if (target_pid == -1 && target_tid == -1 && !system_wide) {
320 attr->disabled = 1; 226 attr->disabled = 1;
321 attr->enable_on_exec = 1; 227 attr->enable_on_exec = 1;
322 } 228 }
323retry_sample_id: 229}
324 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
325 230
326 for (thread_index = 0; thread_index < threads->nr; thread_index++) { 231static bool perf_evlist__equal(struct perf_evlist *evlist,
327try_again: 232 struct perf_evlist *other)
328 FD(evsel, nr_cpu, thread_index) = sys_perf_event_open(attr, threads->map[thread_index], cpu, group_fd, 0); 233{
234 struct perf_evsel *pos, *pair;
235
236 if (evlist->nr_entries != other->nr_entries)
237 return false;
238
239 pair = list_entry(other->entries.next, struct perf_evsel, node);
329 240
330 if (FD(evsel, nr_cpu, thread_index) < 0) { 241 list_for_each_entry(pos, &evlist->entries, node) {
242 if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
243 return false;
244 pair = list_entry(pair->node.next, struct perf_evsel, node);
245 }
246
247 return true;
248}
249
250static void open_counters(struct perf_evlist *evlist)
251{
252 struct perf_evsel *pos;
253
254 list_for_each_entry(pos, &evlist->entries, node) {
255 struct perf_event_attr *attr = &pos->attr;
256 /*
257 * Check if parse_single_tracepoint_event has already asked for
258 * PERF_SAMPLE_TIME.
259 *
260 * XXX this is kludgy but short term fix for problems introduced by
261 * eac23d1c that broke 'perf script' by having different sample_types
262 * when using multiple tracepoint events when we use a perf binary
263 * that tries to use sample_id_all on an older kernel.
264 *
265 * We need to move counter creation to perf_session, support
266 * different sample_types, etc.
267 */
268 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
269
270 config_attr(pos, evlist);
271retry_sample_id:
272 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
273try_again:
274 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
275 !no_inherit) < 0) {
331 int err = errno; 276 int err = errno;
332 277
333 if (err == EPERM || err == EACCES) 278 if (err == EPERM || err == EACCES)
@@ -364,7 +309,7 @@ try_again:
364 } 309 }
365 printf("\n"); 310 printf("\n");
366 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 311 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
367 FD(evsel, nr_cpu, thread_index), strerror(err)); 312 err, strerror(err));
368 313
369#if defined(__i386__) || defined(__x86_64__) 314#if defined(__i386__) || defined(__x86_64__)
370 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 315 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
@@ -375,90 +320,28 @@ try_again:
375#endif 320#endif
376 321
377 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 322 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
378 exit(-1);
379 } 323 }
324 }
380 325
381 h_attr = get_header_attr(attr, evsel->idx); 326 if (perf_evlist__set_filters(evlist)) {
382 if (h_attr == NULL) 327 error("failed to set filter with %d (%s)\n", errno,
383 die("nomem\n"); 328 strerror(errno));
329 exit(-1);
330 }
384 331
385 if (!file_new) { 332 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
386 if (memcmp(&h_attr->attr, attr, sizeof(*attr))) { 333 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
387 fprintf(stderr, "incompatible append\n");
388 exit(-1);
389 }
390 }
391 334
392 if (read(FD(evsel, nr_cpu, thread_index), &read_data, sizeof(read_data)) == -1) { 335 if (file_new)
393 perror("Unable to read perf file descriptor"); 336 session->evlist = evlist;
337 else {
338 if (!perf_evlist__equal(session->evlist, evlist)) {
339 fprintf(stderr, "incompatible append\n");
394 exit(-1); 340 exit(-1);
395 } 341 }
342 }
396 343
397 if (perf_header_attr__add_id(h_attr, read_data.id) < 0) { 344 perf_session__update_sample_type(session);
398 pr_warning("Not enough memory to add id\n");
399 exit(-1);
400 }
401
402 assert(FD(evsel, nr_cpu, thread_index) >= 0);
403 fcntl(FD(evsel, nr_cpu, thread_index), F_SETFL, O_NONBLOCK);
404
405 /*
406 * First counter acts as the group leader:
407 */
408 if (group && group_fd == -1)
409 group_fd = FD(evsel, nr_cpu, thread_index);
410
411 if (evsel->idx || thread_index) {
412 struct perf_evsel *first;
413 first = list_entry(evsel_list.next, struct perf_evsel, node);
414 ret = ioctl(FD(evsel, nr_cpu, thread_index),
415 PERF_EVENT_IOC_SET_OUTPUT,
416 FD(first, nr_cpu, 0));
417 if (ret) {
418 error("failed to set output: %d (%s)\n", errno,
419 strerror(errno));
420 exit(-1);
421 }
422 } else {
423 mmap_array[nr_cpu].prev = 0;
424 mmap_array[nr_cpu].mask = mmap_pages*page_size - 1;
425 mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size,
426 PROT_READ | PROT_WRITE, MAP_SHARED, FD(evsel, nr_cpu, thread_index), 0);
427 if (mmap_array[nr_cpu].base == MAP_FAILED) {
428 error("failed to mmap with %d (%s)\n", errno, strerror(errno));
429 exit(-1);
430 }
431
432 event_array[nr_poll].fd = FD(evsel, nr_cpu, thread_index);
433 event_array[nr_poll].events = POLLIN;
434 nr_poll++;
435 }
436
437 if (filter != NULL) {
438 ret = ioctl(FD(evsel, nr_cpu, thread_index),
439 PERF_EVENT_IOC_SET_FILTER, filter);
440 if (ret) {
441 error("failed to set filter with %d (%s)\n", errno,
442 strerror(errno));
443 exit(-1);
444 }
445 }
446 }
447
448 if (!sample_type)
449 sample_type = attr->sample_type;
450}
451
452static void open_counters(int cpu)
453{
454 struct perf_evsel *pos;
455
456 group_fd = -1;
457
458 list_for_each_entry(pos, &evsel_list, node)
459 create_counter(pos, cpu);
460
461 nr_cpu++;
462} 345}
463 346
464static int process_buildids(void) 347static int process_buildids(void)
@@ -481,14 +364,14 @@ static void atexit_header(void)
481 364
482 if (!no_buildid) 365 if (!no_buildid)
483 process_buildids(); 366 process_buildids();
484 perf_header__write(&session->header, output, true); 367 perf_session__write_header(session, evsel_list, output, true);
485 perf_session__delete(session); 368 perf_session__delete(session);
486 perf_evsel_list__delete(); 369 perf_evlist__delete(evsel_list);
487 symbol__exit(); 370 symbol__exit();
488 } 371 }
489} 372}
490 373
491static void event__synthesize_guest_os(struct machine *machine, void *data) 374static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
492{ 375{
493 int err; 376 int err;
494 struct perf_session *psession = data; 377 struct perf_session *psession = data;
@@ -504,8 +387,8 @@ static void event__synthesize_guest_os(struct machine *machine, void *data)
504 *method is used to avoid symbol missing when the first addr is 387 *method is used to avoid symbol missing when the first addr is
505 *in module instead of in guest kernel. 388 *in module instead of in guest kernel.
506 */ 389 */
507 err = event__synthesize_modules(process_synthesized_event, 390 err = perf_event__synthesize_modules(process_synthesized_event,
508 psession, machine); 391 psession, machine);
509 if (err < 0) 392 if (err < 0)
510 pr_err("Couldn't record guest kernel [%d]'s reference" 393 pr_err("Couldn't record guest kernel [%d]'s reference"
511 " relocation symbol.\n", machine->pid); 394 " relocation symbol.\n", machine->pid);
@@ -514,11 +397,12 @@ static void event__synthesize_guest_os(struct machine *machine, void *data)
514 * We use _stext for guest kernel because guest kernel's /proc/kallsyms 397 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
515 * have no _text sometimes. 398 * have no _text sometimes.
516 */ 399 */
517 err = event__synthesize_kernel_mmap(process_synthesized_event, 400 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
518 psession, machine, "_text"); 401 psession, machine, "_text");
519 if (err < 0) 402 if (err < 0)
520 err = event__synthesize_kernel_mmap(process_synthesized_event, 403 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
521 psession, machine, "_stext"); 404 psession, machine,
405 "_stext");
522 if (err < 0) 406 if (err < 0)
523 pr_err("Couldn't record guest kernel [%d]'s reference" 407 pr_err("Couldn't record guest kernel [%d]'s reference"
524 " relocation symbol.\n", machine->pid); 408 " relocation symbol.\n", machine->pid);
@@ -533,9 +417,9 @@ static void mmap_read_all(void)
533{ 417{
534 int i; 418 int i;
535 419
536 for (i = 0; i < nr_cpu; i++) { 420 for (i = 0; i < evsel_list->cpus->nr; i++) {
537 if (mmap_array[i].base) 421 if (evsel_list->mmap[i].base)
538 mmap_read(&mmap_array[i]); 422 mmap_read(&evsel_list->mmap[i]);
539 } 423 }
540 424
541 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) 425 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
@@ -566,18 +450,26 @@ static int __cmd_record(int argc, const char **argv)
566 exit(-1); 450 exit(-1);
567 } 451 }
568 452
569 if (!strcmp(output_name, "-")) 453 if (!output_name) {
570 pipe_output = 1; 454 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
571 else if (!stat(output_name, &st) && st.st_size) { 455 pipe_output = 1;
572 if (write_mode == WRITE_FORCE) { 456 else
573 char oldname[PATH_MAX]; 457 output_name = "perf.data";
574 snprintf(oldname, sizeof(oldname), "%s.old", 458 }
575 output_name); 459 if (output_name) {
576 unlink(oldname); 460 if (!strcmp(output_name, "-"))
577 rename(output_name, oldname); 461 pipe_output = 1;
462 else if (!stat(output_name, &st) && st.st_size) {
463 if (write_mode == WRITE_FORCE) {
464 char oldname[PATH_MAX];
465 snprintf(oldname, sizeof(oldname), "%s.old",
466 output_name);
467 unlink(oldname);
468 rename(output_name, oldname);
469 }
470 } else if (write_mode == WRITE_APPEND) {
471 write_mode = WRITE_FORCE;
578 } 472 }
579 } else if (write_mode == WRITE_APPEND) {
580 write_mode = WRITE_FORCE;
581 } 473 }
582 474
583 flags = O_CREAT|O_RDWR; 475 flags = O_CREAT|O_RDWR;
@@ -606,19 +498,14 @@ static int __cmd_record(int argc, const char **argv)
606 perf_header__set_feat(&session->header, HEADER_BUILD_ID); 498 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
607 499
608 if (!file_new) { 500 if (!file_new) {
609 err = perf_header__read(session, output); 501 err = perf_session__read_header(session, output);
610 if (err < 0) 502 if (err < 0)
611 goto out_delete_session; 503 goto out_delete_session;
612 } 504 }
613 505
614 if (have_tracepoints(&evsel_list)) 506 if (have_tracepoints(&evsel_list->entries))
615 perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 507 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
616 508
617 /*
618 * perf_session__delete(session) will be called at atexit_header()
619 */
620 atexit(atexit_header);
621
622 if (forks) { 509 if (forks) {
623 child_pid = fork(); 510 child_pid = fork();
624 if (child_pid < 0) { 511 if (child_pid < 0) {
@@ -659,7 +546,7 @@ static int __cmd_record(int argc, const char **argv)
659 } 546 }
660 547
661 if (!system_wide && target_tid == -1 && target_pid == -1) 548 if (!system_wide && target_tid == -1 && target_pid == -1)
662 threads->map[0] = child_pid; 549 evsel_list->threads->map[0] = child_pid;
663 550
664 close(child_ready_pipe[1]); 551 close(child_ready_pipe[1]);
665 close(go_pipe[0]); 552 close(go_pipe[0]);
@@ -673,46 +560,42 @@ static int __cmd_record(int argc, const char **argv)
673 close(child_ready_pipe[0]); 560 close(child_ready_pipe[0]);
674 } 561 }
675 562
676 if (!system_wide && no_inherit && !cpu_list) { 563 open_counters(evsel_list);
677 open_counters(-1);
678 } else {
679 for (i = 0; i < cpus->nr; i++)
680 open_counters(cpus->map[i]);
681 }
682 564
683 perf_session__set_sample_type(session, sample_type); 565 /*
566 * perf_session__delete(session) will be called at atexit_header()
567 */
568 atexit(atexit_header);
684 569
685 if (pipe_output) { 570 if (pipe_output) {
686 err = perf_header__write_pipe(output); 571 err = perf_header__write_pipe(output);
687 if (err < 0) 572 if (err < 0)
688 return err; 573 return err;
689 } else if (file_new) { 574 } else if (file_new) {
690 err = perf_header__write(&session->header, output, false); 575 err = perf_session__write_header(session, evsel_list,
576 output, false);
691 if (err < 0) 577 if (err < 0)
692 return err; 578 return err;
693 } 579 }
694 580
695 post_processing_offset = lseek(output, 0, SEEK_CUR); 581 post_processing_offset = lseek(output, 0, SEEK_CUR);
696 582
697 perf_session__set_sample_id_all(session, sample_id_all_avail);
698
699 if (pipe_output) { 583 if (pipe_output) {
700 err = event__synthesize_attrs(&session->header, 584 err = perf_session__synthesize_attrs(session,
701 process_synthesized_event, 585 process_synthesized_event);
702 session);
703 if (err < 0) { 586 if (err < 0) {
704 pr_err("Couldn't synthesize attrs.\n"); 587 pr_err("Couldn't synthesize attrs.\n");
705 return err; 588 return err;
706 } 589 }
707 590
708 err = event__synthesize_event_types(process_synthesized_event, 591 err = perf_event__synthesize_event_types(process_synthesized_event,
709 session); 592 session);
710 if (err < 0) { 593 if (err < 0) {
711 pr_err("Couldn't synthesize event_types.\n"); 594 pr_err("Couldn't synthesize event_types.\n");
712 return err; 595 return err;
713 } 596 }
714 597
715 if (have_tracepoints(&evsel_list)) { 598 if (have_tracepoints(&evsel_list->entries)) {
716 /* 599 /*
717 * FIXME err <= 0 here actually means that 600 * FIXME err <= 0 here actually means that
718 * there were no tracepoints so its not really 601 * there were no tracepoints so its not really
@@ -721,9 +604,9 @@ static int __cmd_record(int argc, const char **argv)
721 * return this more properly and also 604 * return this more properly and also
722 * propagate errors that now are calling die() 605 * propagate errors that now are calling die()
723 */ 606 */
724 err = event__synthesize_tracing_data(output, &evsel_list, 607 err = perf_event__synthesize_tracing_data(output, evsel_list,
725 process_synthesized_event, 608 process_synthesized_event,
726 session); 609 session);
727 if (err <= 0) { 610 if (err <= 0) {
728 pr_err("Couldn't record tracing data.\n"); 611 pr_err("Couldn't record tracing data.\n");
729 return err; 612 return err;
@@ -738,31 +621,34 @@ static int __cmd_record(int argc, const char **argv)
738 return -1; 621 return -1;
739 } 622 }
740 623
741 err = event__synthesize_kernel_mmap(process_synthesized_event, 624 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
742 session, machine, "_text"); 625 session, machine, "_text");
743 if (err < 0) 626 if (err < 0)
744 err = event__synthesize_kernel_mmap(process_synthesized_event, 627 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
745 session, machine, "_stext"); 628 session, machine, "_stext");
746 if (err < 0) 629 if (err < 0)
747 pr_err("Couldn't record kernel reference relocation symbol\n" 630 pr_err("Couldn't record kernel reference relocation symbol\n"
748 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 631 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
749 "Check /proc/kallsyms permission or run as root.\n"); 632 "Check /proc/kallsyms permission or run as root.\n");
750 633
751 err = event__synthesize_modules(process_synthesized_event, 634 err = perf_event__synthesize_modules(process_synthesized_event,
752 session, machine); 635 session, machine);
753 if (err < 0) 636 if (err < 0)
754 pr_err("Couldn't record kernel module information.\n" 637 pr_err("Couldn't record kernel module information.\n"
755 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 638 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
756 "Check /proc/modules permission or run as root.\n"); 639 "Check /proc/modules permission or run as root.\n");
757 640
758 if (perf_guest) 641 if (perf_guest)
759 perf_session__process_machines(session, event__synthesize_guest_os); 642 perf_session__process_machines(session,
643 perf_event__synthesize_guest_os);
760 644
761 if (!system_wide) 645 if (!system_wide)
762 event__synthesize_thread_map(threads, process_synthesized_event, 646 perf_event__synthesize_thread_map(evsel_list->threads,
763 session); 647 process_synthesized_event,
648 session);
764 else 649 else
765 event__synthesize_threads(process_synthesized_event, session); 650 perf_event__synthesize_threads(process_synthesized_event,
651 session);
766 652
767 if (realtime_prio) { 653 if (realtime_prio) {
768 struct sched_param param; 654 struct sched_param param;
@@ -789,17 +675,17 @@ static int __cmd_record(int argc, const char **argv)
789 if (hits == samples) { 675 if (hits == samples) {
790 if (done) 676 if (done)
791 break; 677 break;
792 err = poll(event_array, nr_poll, -1); 678 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
793 waking++; 679 waking++;
794 } 680 }
795 681
796 if (done) { 682 if (done) {
797 for (i = 0; i < nr_cpu; i++) { 683 for (i = 0; i < evsel_list->cpus->nr; i++) {
798 struct perf_evsel *pos; 684 struct perf_evsel *pos;
799 685
800 list_for_each_entry(pos, &evsel_list, node) { 686 list_for_each_entry(pos, &evsel_list->entries, node) {
801 for (thread = 0; 687 for (thread = 0;
802 thread < threads->nr; 688 thread < evsel_list->threads->nr;
803 thread++) 689 thread++)
804 ioctl(FD(pos, i, thread), 690 ioctl(FD(pos, i, thread),
805 PERF_EVENT_IOC_DISABLE); 691 PERF_EVENT_IOC_DISABLE);
@@ -838,10 +724,10 @@ static const char * const record_usage[] = {
838static bool force, append_file; 724static bool force, append_file;
839 725
840const struct option record_options[] = { 726const struct option record_options[] = {
841 OPT_CALLBACK('e', "event", NULL, "event", 727 OPT_CALLBACK('e', "event", &evsel_list, "event",
842 "event selector. use 'perf list' to list available events", 728 "event selector. use 'perf list' to list available events",
843 parse_events), 729 parse_events),
844 OPT_CALLBACK(0, "filter", NULL, "filter", 730 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
845 "event filter", parse_filter), 731 "event filter", parse_filter),
846 OPT_INTEGER('p', "pid", &target_pid, 732 OPT_INTEGER('p', "pid", &target_pid,
847 "record events on existing process id"), 733 "record events on existing process id"),
@@ -884,6 +770,9 @@ const struct option record_options[] = {
884 "do not update the buildid cache"), 770 "do not update the buildid cache"),
885 OPT_BOOLEAN('B', "no-buildid", &no_buildid, 771 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
886 "do not collect buildids in perf.data"), 772 "do not collect buildids in perf.data"),
773 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
774 "monitor event in cgroup name only",
775 parse_cgroups),
887 OPT_END() 776 OPT_END()
888}; 777};
889 778
@@ -892,6 +781,10 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
892 int err = -ENOMEM; 781 int err = -ENOMEM;
893 struct perf_evsel *pos; 782 struct perf_evsel *pos;
894 783
784 evsel_list = perf_evlist__new(NULL, NULL);
785 if (evsel_list == NULL)
786 return -ENOMEM;
787
895 argc = parse_options(argc, argv, record_options, record_usage, 788 argc = parse_options(argc, argv, record_options, record_usage,
896 PARSE_OPT_STOP_AT_NON_OPTION); 789 PARSE_OPT_STOP_AT_NON_OPTION);
897 if (!argc && target_pid == -1 && target_tid == -1 && 790 if (!argc && target_pid == -1 && target_tid == -1 &&
@@ -908,12 +801,19 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
908 write_mode = WRITE_FORCE; 801 write_mode = WRITE_FORCE;
909 } 802 }
910 803
804 if (nr_cgroups && !system_wide) {
805 fprintf(stderr, "cgroup monitoring only available in"
806 " system-wide mode\n");
807 usage_with_options(record_usage, record_options);
808 }
809
911 symbol__init(); 810 symbol__init();
912 811
913 if (no_buildid_cache || no_buildid) 812 if (no_buildid_cache || no_buildid)
914 disable_buildid_cache(); 813 disable_buildid_cache();
915 814
916 if (list_empty(&evsel_list) && perf_evsel_list__create_default() < 0) { 815 if (evsel_list->nr_entries == 0 &&
816 perf_evlist__add_default(evsel_list) < 0) {
917 pr_err("Not enough memory for event selector list\n"); 817 pr_err("Not enough memory for event selector list\n");
918 goto out_symbol_exit; 818 goto out_symbol_exit;
919 } 819 }
@@ -921,27 +821,19 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
921 if (target_pid != -1) 821 if (target_pid != -1)
922 target_tid = target_pid; 822 target_tid = target_pid;
923 823
924 threads = thread_map__new(target_pid, target_tid); 824 if (perf_evlist__create_maps(evsel_list, target_pid,
925 if (threads == NULL) { 825 target_tid, cpu_list) < 0)
926 pr_err("Problems finding threads of monitor\n");
927 usage_with_options(record_usage, record_options); 826 usage_with_options(record_usage, record_options);
928 }
929 827
930 cpus = cpu_map__new(cpu_list); 828 list_for_each_entry(pos, &evsel_list->entries, node) {
931 if (cpus == NULL) { 829 if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
932 perror("failed to parse CPUs map"); 830 evsel_list->threads->nr) < 0)
933 return -1;
934 }
935
936 list_for_each_entry(pos, &evsel_list, node) {
937 if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
938 goto out_free_fd; 831 goto out_free_fd;
939 if (perf_header__push_event(pos->attr.config, event_name(pos))) 832 if (perf_header__push_event(pos->attr.config, event_name(pos)))
940 goto out_free_fd; 833 goto out_free_fd;
941 } 834 }
942 event_array = malloc((sizeof(struct pollfd) * MAX_NR_CPUS * 835
943 MAX_COUNTERS * threads->nr)); 836 if (perf_evlist__alloc_pollfd(evsel_list) < 0)
944 if (!event_array)
945 goto out_free_fd; 837 goto out_free_fd;
946 838
947 if (user_interval != ULLONG_MAX) 839 if (user_interval != ULLONG_MAX)
@@ -959,16 +851,12 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
959 } else { 851 } else {
960 fprintf(stderr, "frequency and count are zero, aborting\n"); 852 fprintf(stderr, "frequency and count are zero, aborting\n");
961 err = -EINVAL; 853 err = -EINVAL;
962 goto out_free_event_array; 854 goto out_free_fd;
963 } 855 }
964 856
965 err = __cmd_record(argc, argv); 857 err = __cmd_record(argc, argv);
966
967out_free_event_array:
968 free(event_array);
969out_free_fd: 858out_free_fd:
970 thread_map__delete(threads); 859 perf_evlist__delete_maps(evsel_list);
971 threads = NULL;
972out_symbol_exit: 860out_symbol_exit:
973 symbol__exit(); 861 symbol__exit();
974 return err; 862 return err;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index c27e31f289e6..b1b82009ab9b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -9,6 +9,7 @@
9 9
10#include "util/util.h" 10#include "util/util.h"
11 11
12#include "util/annotate.h"
12#include "util/color.h" 13#include "util/color.h"
13#include <linux/list.h> 14#include <linux/list.h>
14#include "util/cache.h" 15#include "util/cache.h"
@@ -20,6 +21,8 @@
20 21
21#include "perf.h" 22#include "perf.h"
22#include "util/debug.h" 23#include "util/debug.h"
24#include "util/evlist.h"
25#include "util/evsel.h"
23#include "util/header.h" 26#include "util/header.h"
24#include "util/session.h" 27#include "util/session.h"
25 28
@@ -43,120 +46,79 @@ static const char default_pretty_printing_style[] = "normal";
43static const char *pretty_printing_style = default_pretty_printing_style; 46static const char *pretty_printing_style = default_pretty_printing_style;
44 47
45static char callchain_default_opt[] = "fractal,0.5"; 48static char callchain_default_opt[] = "fractal,0.5";
49static symbol_filter_t annotate_init;
46 50
47static struct hists *perf_session__hists_findnew(struct perf_session *self, 51static int perf_session__add_hist_entry(struct perf_session *session,
48 u64 event_stream, u32 type,
49 u64 config)
50{
51 struct rb_node **p = &self->hists_tree.rb_node;
52 struct rb_node *parent = NULL;
53 struct hists *iter, *new;
54
55 while (*p != NULL) {
56 parent = *p;
57 iter = rb_entry(parent, struct hists, rb_node);
58 if (iter->config == config)
59 return iter;
60
61
62 if (config > iter->config)
63 p = &(*p)->rb_right;
64 else
65 p = &(*p)->rb_left;
66 }
67
68 new = malloc(sizeof(struct hists));
69 if (new == NULL)
70 return NULL;
71 memset(new, 0, sizeof(struct hists));
72 new->event_stream = event_stream;
73 new->config = config;
74 new->type = type;
75 rb_link_node(&new->rb_node, parent, p);
76 rb_insert_color(&new->rb_node, &self->hists_tree);
77 return new;
78}
79
80static int perf_session__add_hist_entry(struct perf_session *self,
81 struct addr_location *al, 52 struct addr_location *al,
82 struct sample_data *data) 53 struct perf_sample *sample)
83{ 54{
84 struct map_symbol *syms = NULL;
85 struct symbol *parent = NULL; 55 struct symbol *parent = NULL;
86 int err = -ENOMEM; 56 int err = 0;
87 struct hist_entry *he; 57 struct hist_entry *he;
88 struct hists *hists; 58 struct perf_evsel *evsel;
89 struct perf_event_attr *attr; 59
90 60 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
91 if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) { 61 err = perf_session__resolve_callchain(session, al->thread,
92 syms = perf_session__resolve_callchain(self, al->thread, 62 sample->callchain, &parent);
93 data->callchain, &parent); 63 if (err)
94 if (syms == NULL) 64 return err;
95 return -ENOMEM;
96 } 65 }
97 66
98 attr = perf_header__find_attr(data->id, &self->header); 67 evsel = perf_evlist__id2evsel(session->evlist, sample->id);
99 if (attr) 68 if (evsel == NULL) {
100 hists = perf_session__hists_findnew(self, data->id, attr->type, attr->config); 69 /*
101 else 70 * FIXME: Propagate this back, but at least we're in a builtin,
102 hists = perf_session__hists_findnew(self, data->id, 0, 0); 71 * where exit() is allowed. ;-)
103 if (hists == NULL) 72 */
104 goto out_free_syms; 73 ui__warning("Invalid %s file, contains samples with id %" PRIu64 " not in "
105 he = __hists__add_entry(hists, al, parent, data->period); 74 "its header!\n", input_name, sample->id);
75 exit_browser(0);
76 exit(1);
77 }
78
79 he = __hists__add_entry(&evsel->hists, al, parent, sample->period);
106 if (he == NULL) 80 if (he == NULL)
107 goto out_free_syms; 81 return -ENOMEM;
108 err = 0; 82
109 if (symbol_conf.use_callchain) { 83 if (symbol_conf.use_callchain) {
110 err = callchain_append(he->callchain, data->callchain, syms, 84 err = callchain_append(he->callchain, &session->callchain_cursor,
111 data->period); 85 sample->period);
112 if (err) 86 if (err)
113 goto out_free_syms; 87 return err;
114 } 88 }
115 /* 89 /*
116 * Only in the newt browser we are doing integrated annotation, 90 * Only in the newt browser we are doing integrated annotation,
117 * so we don't allocated the extra space needed because the stdio 91 * so we don't allocated the extra space needed because the stdio
118 * code will not use it. 92 * code will not use it.
119 */ 93 */
120 if (use_browser > 0) 94 if (al->sym != NULL && use_browser > 0) {
121 err = hist_entry__inc_addr_samples(he, al->addr); 95 struct annotation *notes = symbol__annotation(he->ms.sym);
122out_free_syms:
123 free(syms);
124 return err;
125}
126 96
127static int add_event_total(struct perf_session *session, 97 assert(evsel != NULL);
128 struct sample_data *data,
129 struct perf_event_attr *attr)
130{
131 struct hists *hists;
132 98
133 if (attr) 99 err = -ENOMEM;
134 hists = perf_session__hists_findnew(session, data->id, 100 if (notes->src == NULL &&
135 attr->type, attr->config); 101 symbol__alloc_hist(he->ms.sym, session->evlist->nr_entries) < 0)
136 else 102 goto out;
137 hists = perf_session__hists_findnew(session, data->id, 0, 0);
138 103
139 if (!hists) 104 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
140 return -ENOMEM; 105 }
141 106
142 hists->stats.total_period += data->period; 107 evsel->hists.stats.total_period += sample->period;
143 /* 108 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
144 * FIXME: add_event_total should be moved from here to 109out:
145 * perf_session__process_event so that the proper hist is passed to 110 return err;
146 * the event_op methods.
147 */
148 hists__inc_nr_events(hists, PERF_RECORD_SAMPLE);
149 session->hists.stats.total_period += data->period;
150 return 0;
151} 111}
152 112
153static int process_sample_event(event_t *event, struct sample_data *sample, 113
114static int process_sample_event(union perf_event *event,
115 struct perf_sample *sample,
154 struct perf_session *session) 116 struct perf_session *session)
155{ 117{
156 struct addr_location al; 118 struct addr_location al;
157 struct perf_event_attr *attr;
158 119
159 if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) { 120 if (perf_event__preprocess_sample(event, session, &al, sample,
121 annotate_init) < 0) {
160 fprintf(stderr, "problem processing %d event, skipping it.\n", 122 fprintf(stderr, "problem processing %d event, skipping it.\n",
161 event->header.type); 123 event->header.type);
162 return -1; 124 return -1;
@@ -170,26 +132,17 @@ static int process_sample_event(event_t *event, struct sample_data *sample,
170 return -1; 132 return -1;
171 } 133 }
172 134
173 attr = perf_header__find_attr(sample->id, &session->header);
174
175 if (add_event_total(session, sample, attr)) {
176 pr_debug("problem adding event period\n");
177 return -1;
178 }
179
180 return 0; 135 return 0;
181} 136}
182 137
183static int process_read_event(event_t *event, struct sample_data *sample __used, 138static int process_read_event(union perf_event *event,
184 struct perf_session *session __used) 139 struct perf_sample *sample __used,
140 struct perf_session *session)
185{ 141{
186 struct perf_event_attr *attr; 142 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist,
187 143 event->read.id);
188 attr = perf_header__find_attr(event->read.id, &session->header);
189
190 if (show_threads) { 144 if (show_threads) {
191 const char *name = attr ? __event_name(attr->type, attr->config) 145 const char *name = evsel ? event_name(evsel) : "unknown";
192 : "unknown";
193 perf_read_values_add_value(&show_threads_values, 146 perf_read_values_add_value(&show_threads_values,
194 event->read.pid, event->read.tid, 147 event->read.pid, event->read.tid,
195 event->read.id, 148 event->read.id,
@@ -198,7 +151,7 @@ static int process_read_event(event_t *event, struct sample_data *sample __used,
198 } 151 }
199 152
200 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid, 153 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
201 attr ? __event_name(attr->type, attr->config) : "FAIL", 154 evsel ? event_name(evsel) : "FAIL",
202 event->read.value); 155 event->read.value);
203 156
204 return 0; 157 return 0;
@@ -222,7 +175,7 @@ static int perf_session__setup_sample_type(struct perf_session *self)
222 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE && 175 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE &&
223 !symbol_conf.use_callchain) { 176 !symbol_conf.use_callchain) {
224 symbol_conf.use_callchain = true; 177 symbol_conf.use_callchain = true;
225 if (register_callchain_param(&callchain_param) < 0) { 178 if (callchain_register_param(&callchain_param) < 0) {
226 fprintf(stderr, "Can't register callchain" 179 fprintf(stderr, "Can't register callchain"
227 " params\n"); 180 " params\n");
228 return -EINVAL; 181 return -EINVAL;
@@ -233,17 +186,17 @@ static int perf_session__setup_sample_type(struct perf_session *self)
233} 186}
234 187
235static struct perf_event_ops event_ops = { 188static struct perf_event_ops event_ops = {
236 .sample = process_sample_event, 189 .sample = process_sample_event,
237 .mmap = event__process_mmap, 190 .mmap = perf_event__process_mmap,
238 .comm = event__process_comm, 191 .comm = perf_event__process_comm,
239 .exit = event__process_task, 192 .exit = perf_event__process_task,
240 .fork = event__process_task, 193 .fork = perf_event__process_task,
241 .lost = event__process_lost, 194 .lost = perf_event__process_lost,
242 .read = process_read_event, 195 .read = process_read_event,
243 .attr = event__process_attr, 196 .attr = perf_event__process_attr,
244 .event_type = event__process_event_type, 197 .event_type = perf_event__process_event_type,
245 .tracing_data = event__process_tracing_data, 198 .tracing_data = perf_event__process_tracing_data,
246 .build_id = event__process_build_id, 199 .build_id = perf_event__process_build_id,
247 .ordered_samples = true, 200 .ordered_samples = true,
248 .ordering_requires_timestamps = true, 201 .ordering_requires_timestamps = true,
249}; 202};
@@ -269,21 +222,21 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
269 return ret + fprintf(fp, "\n#\n"); 222 return ret + fprintf(fp, "\n#\n");
270} 223}
271 224
272static int hists__tty_browse_tree(struct rb_root *tree, const char *help) 225static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
226 const char *help)
273{ 227{
274 struct rb_node *next = rb_first(tree); 228 struct perf_evsel *pos;
275 229
276 while (next) { 230 list_for_each_entry(pos, &evlist->entries, node) {
277 struct hists *hists = rb_entry(next, struct hists, rb_node); 231 struct hists *hists = &pos->hists;
278 const char *evname = NULL; 232 const char *evname = NULL;
279 233
280 if (rb_first(&hists->entries) != rb_last(&hists->entries)) 234 if (rb_first(&hists->entries) != rb_last(&hists->entries))
281 evname = __event_name(hists->type, hists->config); 235 evname = event_name(pos);
282 236
283 hists__fprintf_nr_sample_events(hists, evname, stdout); 237 hists__fprintf_nr_sample_events(hists, evname, stdout);
284 hists__fprintf(hists, NULL, false, stdout); 238 hists__fprintf(hists, NULL, false, stdout);
285 fprintf(stdout, "\n\n"); 239 fprintf(stdout, "\n\n");
286 next = rb_next(&hists->rb_node);
287 } 240 }
288 241
289 if (sort_order == default_sort_order && 242 if (sort_order == default_sort_order &&
@@ -304,8 +257,9 @@ static int hists__tty_browse_tree(struct rb_root *tree, const char *help)
304static int __cmd_report(void) 257static int __cmd_report(void)
305{ 258{
306 int ret = -EINVAL; 259 int ret = -EINVAL;
260 u64 nr_samples;
307 struct perf_session *session; 261 struct perf_session *session;
308 struct rb_node *next; 262 struct perf_evsel *pos;
309 const char *help = "For a higher level overview, try: perf report --sort comm,dso"; 263 const char *help = "For a higher level overview, try: perf report --sort comm,dso";
310 264
311 signal(SIGINT, sig_handler); 265 signal(SIGINT, sig_handler);
@@ -336,20 +290,24 @@ static int __cmd_report(void)
336 if (verbose > 2) 290 if (verbose > 2)
337 perf_session__fprintf_dsos(session, stdout); 291 perf_session__fprintf_dsos(session, stdout);
338 292
339 next = rb_first(&session->hists_tree); 293 nr_samples = 0;
340 while (next) { 294 list_for_each_entry(pos, &session->evlist->entries, node) {
341 struct hists *hists; 295 struct hists *hists = &pos->hists;
342 296
343 hists = rb_entry(next, struct hists, rb_node);
344 hists__collapse_resort(hists); 297 hists__collapse_resort(hists);
345 hists__output_resort(hists); 298 hists__output_resort(hists);
346 next = rb_next(&hists->rb_node); 299 nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];
300 }
301
302 if (nr_samples == 0) {
303 ui__warning("The %s file has no samples!\n", input_name);
304 goto out_delete;
347 } 305 }
348 306
349 if (use_browser > 0) 307 if (use_browser > 0)
350 hists__tui_browse_tree(&session->hists_tree, help); 308 perf_evlist__tui_browse_hists(session->evlist, help);
351 else 309 else
352 hists__tty_browse_tree(&session->hists_tree, help); 310 perf_evlist__tty_browse_hists(session->evlist, help);
353 311
354out_delete: 312out_delete:
355 /* 313 /*
@@ -424,7 +382,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
424 if (tok2) 382 if (tok2)
425 callchain_param.print_limit = strtod(tok2, &endptr); 383 callchain_param.print_limit = strtod(tok2, &endptr);
426setup: 384setup:
427 if (register_callchain_param(&callchain_param) < 0) { 385 if (callchain_register_param(&callchain_param) < 0) {
428 fprintf(stderr, "Can't register callchain params\n"); 386 fprintf(stderr, "Can't register callchain params\n");
429 return -1; 387 return -1;
430 } 388 }
@@ -498,7 +456,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
498 use_browser = 1; 456 use_browser = 1;
499 457
500 if (strcmp(input_name, "-") != 0) 458 if (strcmp(input_name, "-") != 0)
501 setup_browser(); 459 setup_browser(true);
502 else 460 else
503 use_browser = 0; 461 use_browser = 0;
504 /* 462 /*
@@ -507,7 +465,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
507 * implementation. 465 * implementation.
508 */ 466 */
509 if (use_browser > 0) { 467 if (use_browser > 0) {
510 symbol_conf.priv_size = sizeof(struct sym_priv); 468 symbol_conf.priv_size = sizeof(struct annotation);
469 annotate_init = symbol__annotate_init;
511 /* 470 /*
512 * For searching by name on the "Browse map details". 471 * For searching by name on the "Browse map details".
513 * providing it only in verbose mode not to bloat too 472 * providing it only in verbose mode not to bloat too
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 29acb894e035..a32f411faeac 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -369,11 +369,6 @@ static void
369process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom) 369process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom)
370{ 370{
371 int ret = 0; 371 int ret = 0;
372 u64 now;
373 long long delta;
374
375 now = get_nsecs();
376 delta = start_time + atom->timestamp - now;
377 372
378 switch (atom->type) { 373 switch (atom->type) {
379 case SCHED_EVENT_RUN: 374 case SCHED_EVENT_RUN:
@@ -562,7 +557,7 @@ static void wait_for_tasks(void)
562 557
563static void run_one_test(void) 558static void run_one_test(void)
564{ 559{
565 u64 T0, T1, delta, avg_delta, fluct, std_dev; 560 u64 T0, T1, delta, avg_delta, fluct;
566 561
567 T0 = get_nsecs(); 562 T0 = get_nsecs();
568 wait_for_tasks(); 563 wait_for_tasks();
@@ -578,7 +573,6 @@ static void run_one_test(void)
578 else 573 else
579 fluct = delta - avg_delta; 574 fluct = delta - avg_delta;
580 sum_fluct += fluct; 575 sum_fluct += fluct;
581 std_dev = sum_fluct / nr_runs / sqrt(nr_runs);
582 if (!run_avg) 576 if (!run_avg)
583 run_avg = delta; 577 run_avg = delta;
584 run_avg = (run_avg*9 + delta)/10; 578 run_avg = (run_avg*9 + delta)/10;
@@ -799,7 +793,7 @@ replay_switch_event(struct trace_switch_event *switch_event,
799 u64 timestamp, 793 u64 timestamp,
800 struct thread *thread __used) 794 struct thread *thread __used)
801{ 795{
802 struct task_desc *prev, *next; 796 struct task_desc *prev, __used *next;
803 u64 timestamp0; 797 u64 timestamp0;
804 s64 delta; 798 s64 delta;
805 799
@@ -1404,7 +1398,7 @@ map_switch_event(struct trace_switch_event *switch_event,
1404 u64 timestamp, 1398 u64 timestamp,
1405 struct thread *thread __used) 1399 struct thread *thread __used)
1406{ 1400{
1407 struct thread *sched_out, *sched_in; 1401 struct thread *sched_out __used, *sched_in;
1408 int new_shortname; 1402 int new_shortname;
1409 u64 timestamp0; 1403 u64 timestamp0;
1410 s64 delta; 1404 s64 delta;
@@ -1580,9 +1574,9 @@ process_sched_migrate_task_event(void *data, struct perf_session *session,
1580 event, cpu, timestamp, thread); 1574 event, cpu, timestamp, thread);
1581} 1575}
1582 1576
1583static void 1577static void process_raw_event(union perf_event *raw_event __used,
1584process_raw_event(event_t *raw_event __used, struct perf_session *session, 1578 struct perf_session *session, void *data, int cpu,
1585 void *data, int cpu, u64 timestamp, struct thread *thread) 1579 u64 timestamp, struct thread *thread)
1586{ 1580{
1587 struct event *event; 1581 struct event *event;
1588 int type; 1582 int type;
@@ -1607,7 +1601,8 @@ process_raw_event(event_t *raw_event __used, struct perf_session *session,
1607 process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread); 1601 process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread);
1608} 1602}
1609 1603
1610static int process_sample_event(event_t *event, struct sample_data *sample, 1604static int process_sample_event(union perf_event *event,
1605 struct perf_sample *sample,
1611 struct perf_session *session) 1606 struct perf_session *session)
1612{ 1607{
1613 struct thread *thread; 1608 struct thread *thread;
@@ -1635,9 +1630,9 @@ static int process_sample_event(event_t *event, struct sample_data *sample,
1635 1630
1636static struct perf_event_ops event_ops = { 1631static struct perf_event_ops event_ops = {
1637 .sample = process_sample_event, 1632 .sample = process_sample_event,
1638 .comm = event__process_comm, 1633 .comm = perf_event__process_comm,
1639 .lost = event__process_lost, 1634 .lost = perf_event__process_lost,
1640 .fork = event__process_task, 1635 .fork = perf_event__process_task,
1641 .ordered_samples = true, 1636 .ordered_samples = true,
1642}; 1637};
1643 1638
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index b766c2a9ac97..5f40df635dcb 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -63,7 +63,8 @@ static int cleanup_scripting(void)
63 63
64static char const *input_name = "perf.data"; 64static char const *input_name = "perf.data";
65 65
66static int process_sample_event(event_t *event, struct sample_data *sample, 66static int process_sample_event(union perf_event *event,
67 struct perf_sample *sample,
67 struct perf_session *session) 68 struct perf_session *session)
68{ 69{
69 struct thread *thread = perf_session__findnew(session, event->ip.pid); 70 struct thread *thread = perf_session__findnew(session, event->ip.pid);
@@ -100,14 +101,14 @@ static int process_sample_event(event_t *event, struct sample_data *sample,
100} 101}
101 102
102static struct perf_event_ops event_ops = { 103static struct perf_event_ops event_ops = {
103 .sample = process_sample_event, 104 .sample = process_sample_event,
104 .comm = event__process_comm, 105 .comm = perf_event__process_comm,
105 .attr = event__process_attr, 106 .attr = perf_event__process_attr,
106 .event_type = event__process_event_type, 107 .event_type = perf_event__process_event_type,
107 .tracing_data = event__process_tracing_data, 108 .tracing_data = perf_event__process_tracing_data,
108 .build_id = event__process_build_id, 109 .build_id = perf_event__process_build_id,
109 .ordering_requires_timestamps = true,
110 .ordered_samples = true, 110 .ordered_samples = true,
111 .ordering_requires_timestamps = true,
111}; 112};
112 113
113extern volatile int session_done; 114extern volatile int session_done;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a482a191a0ca..21c025222496 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -43,11 +43,13 @@
43#include "util/parse-options.h" 43#include "util/parse-options.h"
44#include "util/parse-events.h" 44#include "util/parse-events.h"
45#include "util/event.h" 45#include "util/event.h"
46#include "util/evlist.h"
46#include "util/evsel.h" 47#include "util/evsel.h"
47#include "util/debug.h" 48#include "util/debug.h"
48#include "util/header.h" 49#include "util/header.h"
49#include "util/cpumap.h" 50#include "util/cpumap.h"
50#include "util/thread.h" 51#include "util/thread.h"
52#include "util/thread_map.h"
51 53
52#include <sys/prctl.h> 54#include <sys/prctl.h>
53#include <math.h> 55#include <math.h>
@@ -71,8 +73,9 @@ static struct perf_event_attr default_attrs[] = {
71 73
72}; 74};
73 75
76struct perf_evlist *evsel_list;
77
74static bool system_wide = false; 78static bool system_wide = false;
75static struct cpu_map *cpus;
76static int run_idx = 0; 79static int run_idx = 0;
77 80
78static int run_count = 1; 81static int run_count = 1;
@@ -81,7 +84,6 @@ static bool scale = true;
81static bool no_aggr = false; 84static bool no_aggr = false;
82static pid_t target_pid = -1; 85static pid_t target_pid = -1;
83static pid_t target_tid = -1; 86static pid_t target_tid = -1;
84static struct thread_map *threads;
85static pid_t child_pid = -1; 87static pid_t child_pid = -1;
86static bool null_run = false; 88static bool null_run = false;
87static bool big_num = true; 89static bool big_num = true;
@@ -166,7 +168,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
166 PERF_FORMAT_TOTAL_TIME_RUNNING; 168 PERF_FORMAT_TOTAL_TIME_RUNNING;
167 169
168 if (system_wide) 170 if (system_wide)
169 return perf_evsel__open_per_cpu(evsel, cpus); 171 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false, false);
170 172
171 attr->inherit = !no_inherit; 173 attr->inherit = !no_inherit;
172 if (target_pid == -1 && target_tid == -1) { 174 if (target_pid == -1 && target_tid == -1) {
@@ -174,7 +176,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
174 attr->enable_on_exec = 1; 176 attr->enable_on_exec = 1;
175 } 177 }
176 178
177 return perf_evsel__open_per_thread(evsel, threads); 179 return perf_evsel__open_per_thread(evsel, evsel_list->threads, false, false);
178} 180}
179 181
180/* 182/*
@@ -199,7 +201,8 @@ static int read_counter_aggr(struct perf_evsel *counter)
199 u64 *count = counter->counts->aggr.values; 201 u64 *count = counter->counts->aggr.values;
200 int i; 202 int i;
201 203
202 if (__perf_evsel__read(counter, cpus->nr, threads->nr, scale) < 0) 204 if (__perf_evsel__read(counter, evsel_list->cpus->nr,
205 evsel_list->threads->nr, scale) < 0)
203 return -1; 206 return -1;
204 207
205 for (i = 0; i < 3; i++) 208 for (i = 0; i < 3; i++)
@@ -232,7 +235,7 @@ static int read_counter(struct perf_evsel *counter)
232 u64 *count; 235 u64 *count;
233 int cpu; 236 int cpu;
234 237
235 for (cpu = 0; cpu < cpus->nr; cpu++) { 238 for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
236 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) 239 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
237 return -1; 240 return -1;
238 241
@@ -297,7 +300,7 @@ static int run_perf_stat(int argc __used, const char **argv)
297 } 300 }
298 301
299 if (target_tid == -1 && target_pid == -1 && !system_wide) 302 if (target_tid == -1 && target_pid == -1 && !system_wide)
300 threads->map[0] = child_pid; 303 evsel_list->threads->map[0] = child_pid;
301 304
302 /* 305 /*
303 * Wait for the child to be ready to exec. 306 * Wait for the child to be ready to exec.
@@ -309,7 +312,7 @@ static int run_perf_stat(int argc __used, const char **argv)
309 close(child_ready_pipe[0]); 312 close(child_ready_pipe[0]);
310 } 313 }
311 314
312 list_for_each_entry(counter, &evsel_list, node) { 315 list_for_each_entry(counter, &evsel_list->entries, node) {
313 if (create_perf_stat_counter(counter) < 0) { 316 if (create_perf_stat_counter(counter) < 0) {
314 if (errno == -EPERM || errno == -EACCES) { 317 if (errno == -EPERM || errno == -EACCES) {
315 error("You may not have permission to collect %sstats.\n" 318 error("You may not have permission to collect %sstats.\n"
@@ -347,14 +350,15 @@ static int run_perf_stat(int argc __used, const char **argv)
347 update_stats(&walltime_nsecs_stats, t1 - t0); 350 update_stats(&walltime_nsecs_stats, t1 - t0);
348 351
349 if (no_aggr) { 352 if (no_aggr) {
350 list_for_each_entry(counter, &evsel_list, node) { 353 list_for_each_entry(counter, &evsel_list->entries, node) {
351 read_counter(counter); 354 read_counter(counter);
352 perf_evsel__close_fd(counter, cpus->nr, 1); 355 perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1);
353 } 356 }
354 } else { 357 } else {
355 list_for_each_entry(counter, &evsel_list, node) { 358 list_for_each_entry(counter, &evsel_list->entries, node) {
356 read_counter_aggr(counter); 359 read_counter_aggr(counter);
357 perf_evsel__close_fd(counter, cpus->nr, threads->nr); 360 perf_evsel__close_fd(counter, evsel_list->cpus->nr,
361 evsel_list->threads->nr);
358 } 362 }
359 } 363 }
360 364
@@ -382,10 +386,13 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
382 if (no_aggr) 386 if (no_aggr)
383 sprintf(cpustr, "CPU%*d%s", 387 sprintf(cpustr, "CPU%*d%s",
384 csv_output ? 0 : -4, 388 csv_output ? 0 : -4,
385 cpus->map[cpu], csv_sep); 389 evsel_list->cpus->map[cpu], csv_sep);
386 390
387 fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel)); 391 fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel));
388 392
393 if (evsel->cgrp)
394 fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name);
395
389 if (csv_output) 396 if (csv_output)
390 return; 397 return;
391 398
@@ -410,12 +417,15 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
410 if (no_aggr) 417 if (no_aggr)
411 sprintf(cpustr, "CPU%*d%s", 418 sprintf(cpustr, "CPU%*d%s",
412 csv_output ? 0 : -4, 419 csv_output ? 0 : -4,
413 cpus->map[cpu], csv_sep); 420 evsel_list->cpus->map[cpu], csv_sep);
414 else 421 else
415 cpu = 0; 422 cpu = 0;
416 423
417 fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel)); 424 fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel));
418 425
426 if (evsel->cgrp)
427 fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name);
428
419 if (csv_output) 429 if (csv_output)
420 return; 430 return;
421 431
@@ -456,9 +466,17 @@ static void print_counter_aggr(struct perf_evsel *counter)
456 int scaled = counter->counts->scaled; 466 int scaled = counter->counts->scaled;
457 467
458 if (scaled == -1) { 468 if (scaled == -1) {
459 fprintf(stderr, "%*s%s%-24s\n", 469 fprintf(stderr, "%*s%s%*s",
460 csv_output ? 0 : 18, 470 csv_output ? 0 : 18,
461 "<not counted>", csv_sep, event_name(counter)); 471 "<not counted>",
472 csv_sep,
473 csv_output ? 0 : -24,
474 event_name(counter));
475
476 if (counter->cgrp)
477 fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name);
478
479 fputc('\n', stderr);
462 return; 480 return;
463 } 481 }
464 482
@@ -483,7 +501,6 @@ static void print_counter_aggr(struct perf_evsel *counter)
483 fprintf(stderr, " (scaled from %.2f%%)", 501 fprintf(stderr, " (scaled from %.2f%%)",
484 100 * avg_running / avg_enabled); 502 100 * avg_running / avg_enabled);
485 } 503 }
486
487 fprintf(stderr, "\n"); 504 fprintf(stderr, "\n");
488} 505}
489 506
@@ -496,19 +513,23 @@ static void print_counter(struct perf_evsel *counter)
496 u64 ena, run, val; 513 u64 ena, run, val;
497 int cpu; 514 int cpu;
498 515
499 for (cpu = 0; cpu < cpus->nr; cpu++) { 516 for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
500 val = counter->counts->cpu[cpu].val; 517 val = counter->counts->cpu[cpu].val;
501 ena = counter->counts->cpu[cpu].ena; 518 ena = counter->counts->cpu[cpu].ena;
502 run = counter->counts->cpu[cpu].run; 519 run = counter->counts->cpu[cpu].run;
503 if (run == 0 || ena == 0) { 520 if (run == 0 || ena == 0) {
504 fprintf(stderr, "CPU%*d%s%*s%s%-24s", 521 fprintf(stderr, "CPU%*d%s%*s%s%*s",
505 csv_output ? 0 : -4, 522 csv_output ? 0 : -4,
506 cpus->map[cpu], csv_sep, 523 evsel_list->cpus->map[cpu], csv_sep,
507 csv_output ? 0 : 18, 524 csv_output ? 0 : 18,
508 "<not counted>", csv_sep, 525 "<not counted>", csv_sep,
526 csv_output ? 0 : -24,
509 event_name(counter)); 527 event_name(counter));
510 528
511 fprintf(stderr, "\n"); 529 if (counter->cgrp)
530 fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name);
531
532 fputc('\n', stderr);
512 continue; 533 continue;
513 } 534 }
514 535
@@ -525,7 +546,7 @@ static void print_counter(struct perf_evsel *counter)
525 100.0 * run / ena); 546 100.0 * run / ena);
526 } 547 }
527 } 548 }
528 fprintf(stderr, "\n"); 549 fputc('\n', stderr);
529 } 550 }
530} 551}
531 552
@@ -555,10 +576,10 @@ static void print_stat(int argc, const char **argv)
555 } 576 }
556 577
557 if (no_aggr) { 578 if (no_aggr) {
558 list_for_each_entry(counter, &evsel_list, node) 579 list_for_each_entry(counter, &evsel_list->entries, node)
559 print_counter(counter); 580 print_counter(counter);
560 } else { 581 } else {
561 list_for_each_entry(counter, &evsel_list, node) 582 list_for_each_entry(counter, &evsel_list->entries, node)
562 print_counter_aggr(counter); 583 print_counter_aggr(counter);
563 } 584 }
564 585
@@ -610,7 +631,7 @@ static int stat__set_big_num(const struct option *opt __used,
610} 631}
611 632
612static const struct option options[] = { 633static const struct option options[] = {
613 OPT_CALLBACK('e', "event", NULL, "event", 634 OPT_CALLBACK('e', "event", &evsel_list, "event",
614 "event selector. use 'perf list' to list available events", 635 "event selector. use 'perf list' to list available events",
615 parse_events), 636 parse_events),
616 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 637 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
@@ -638,6 +659,9 @@ static const struct option options[] = {
638 "disable CPU count aggregation"), 659 "disable CPU count aggregation"),
639 OPT_STRING('x', "field-separator", &csv_sep, "separator", 660 OPT_STRING('x', "field-separator", &csv_sep, "separator",
640 "print counts with custom separator"), 661 "print counts with custom separator"),
662 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
663 "monitor event in cgroup name only",
664 parse_cgroups),
641 OPT_END() 665 OPT_END()
642}; 666};
643 667
@@ -648,6 +672,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
648 672
649 setlocale(LC_ALL, ""); 673 setlocale(LC_ALL, "");
650 674
675 evsel_list = perf_evlist__new(NULL, NULL);
676 if (evsel_list == NULL)
677 return -ENOMEM;
678
651 argc = parse_options(argc, argv, options, stat_usage, 679 argc = parse_options(argc, argv, options, stat_usage,
652 PARSE_OPT_STOP_AT_NON_OPTION); 680 PARSE_OPT_STOP_AT_NON_OPTION);
653 681
@@ -674,49 +702,50 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
674 if (run_count <= 0) 702 if (run_count <= 0)
675 usage_with_options(stat_usage, options); 703 usage_with_options(stat_usage, options);
676 704
677 /* no_aggr is for system-wide only */ 705 /* no_aggr, cgroup are for system-wide only */
678 if (no_aggr && !system_wide) 706 if ((no_aggr || nr_cgroups) && !system_wide) {
707 fprintf(stderr, "both cgroup and no-aggregation "
708 "modes only available in system-wide mode\n");
709
679 usage_with_options(stat_usage, options); 710 usage_with_options(stat_usage, options);
711 }
680 712
681 /* Set attrs and nr_counters if no event is selected and !null_run */ 713 /* Set attrs and nr_counters if no event is selected and !null_run */
682 if (!null_run && !nr_counters) { 714 if (!null_run && !evsel_list->nr_entries) {
683 size_t c; 715 size_t c;
684 716
685 nr_counters = ARRAY_SIZE(default_attrs);
686
687 for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) { 717 for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) {
688 pos = perf_evsel__new(&default_attrs[c], 718 pos = perf_evsel__new(&default_attrs[c], c);
689 nr_counters);
690 if (pos == NULL) 719 if (pos == NULL)
691 goto out; 720 goto out;
692 list_add(&pos->node, &evsel_list); 721 perf_evlist__add(evsel_list, pos);
693 } 722 }
694 } 723 }
695 724
696 if (target_pid != -1) 725 if (target_pid != -1)
697 target_tid = target_pid; 726 target_tid = target_pid;
698 727
699 threads = thread_map__new(target_pid, target_tid); 728 evsel_list->threads = thread_map__new(target_pid, target_tid);
700 if (threads == NULL) { 729 if (evsel_list->threads == NULL) {
701 pr_err("Problems finding threads of monitor\n"); 730 pr_err("Problems finding threads of monitor\n");
702 usage_with_options(stat_usage, options); 731 usage_with_options(stat_usage, options);
703 } 732 }
704 733
705 if (system_wide) 734 if (system_wide)
706 cpus = cpu_map__new(cpu_list); 735 evsel_list->cpus = cpu_map__new(cpu_list);
707 else 736 else
708 cpus = cpu_map__dummy_new(); 737 evsel_list->cpus = cpu_map__dummy_new();
709 738
710 if (cpus == NULL) { 739 if (evsel_list->cpus == NULL) {
711 perror("failed to parse CPUs map"); 740 perror("failed to parse CPUs map");
712 usage_with_options(stat_usage, options); 741 usage_with_options(stat_usage, options);
713 return -1; 742 return -1;
714 } 743 }
715 744
716 list_for_each_entry(pos, &evsel_list, node) { 745 list_for_each_entry(pos, &evsel_list->entries, node) {
717 if (perf_evsel__alloc_stat_priv(pos) < 0 || 746 if (perf_evsel__alloc_stat_priv(pos) < 0 ||
718 perf_evsel__alloc_counts(pos, cpus->nr) < 0 || 747 perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0 ||
719 perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0) 748 perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, evsel_list->threads->nr) < 0)
720 goto out_free_fd; 749 goto out_free_fd;
721 } 750 }
722 751
@@ -741,11 +770,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
741 if (status != -1) 770 if (status != -1)
742 print_stat(argc, argv); 771 print_stat(argc, argv);
743out_free_fd: 772out_free_fd:
744 list_for_each_entry(pos, &evsel_list, node) 773 list_for_each_entry(pos, &evsel_list->entries, node)
745 perf_evsel__free_stat_priv(pos); 774 perf_evsel__free_stat_priv(pos);
746 perf_evsel_list__delete(); 775 perf_evlist__delete_maps(evsel_list);
747out: 776out:
748 thread_map__delete(threads); 777 perf_evlist__delete(evsel_list);
749 threads = NULL;
750 return status; 778 return status;
751} 779}
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 5dcdba653d70..1b2106c58f66 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -7,10 +7,11 @@
7 7
8#include "util/cache.h" 8#include "util/cache.h"
9#include "util/debug.h" 9#include "util/debug.h"
10#include "util/evlist.h"
10#include "util/parse-options.h" 11#include "util/parse-options.h"
11#include "util/session.h" 12#include "util/parse-events.h"
12#include "util/symbol.h" 13#include "util/symbol.h"
13#include "util/thread.h" 14#include "util/thread_map.h"
14 15
15static long page_size; 16static long page_size;
16 17
@@ -238,14 +239,14 @@ out:
238#include "util/evsel.h" 239#include "util/evsel.h"
239#include <sys/types.h> 240#include <sys/types.h>
240 241
241static int trace_event__id(const char *event_name) 242static int trace_event__id(const char *evname)
242{ 243{
243 char *filename; 244 char *filename;
244 int err = -1, fd; 245 int err = -1, fd;
245 246
246 if (asprintf(&filename, 247 if (asprintf(&filename,
247 "/sys/kernel/debug/tracing/events/syscalls/%s/id", 248 "/sys/kernel/debug/tracing/events/syscalls/%s/id",
248 event_name) < 0) 249 evname) < 0)
249 return -1; 250 return -1;
250 251
251 fd = open(filename, O_RDONLY); 252 fd = open(filename, O_RDONLY);
@@ -289,7 +290,7 @@ static int test__open_syscall_event(void)
289 goto out_thread_map_delete; 290 goto out_thread_map_delete;
290 } 291 }
291 292
292 if (perf_evsel__open_per_thread(evsel, threads) < 0) { 293 if (perf_evsel__open_per_thread(evsel, threads, false, false) < 0) {
293 pr_debug("failed to open counter: %s, " 294 pr_debug("failed to open counter: %s, "
294 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 295 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
295 strerror(errno)); 296 strerror(errno));
@@ -347,9 +348,9 @@ static int test__open_syscall_event_on_all_cpus(void)
347 } 348 }
348 349
349 cpus = cpu_map__new(NULL); 350 cpus = cpu_map__new(NULL);
350 if (threads == NULL) { 351 if (cpus == NULL) {
351 pr_debug("thread_map__new\n"); 352 pr_debug("cpu_map__new\n");
352 return -1; 353 goto out_thread_map_delete;
353 } 354 }
354 355
355 356
@@ -364,7 +365,7 @@ static int test__open_syscall_event_on_all_cpus(void)
364 goto out_thread_map_delete; 365 goto out_thread_map_delete;
365 } 366 }
366 367
367 if (perf_evsel__open(evsel, cpus, threads) < 0) { 368 if (perf_evsel__open(evsel, cpus, threads, false, false) < 0) {
368 pr_debug("failed to open counter: %s, " 369 pr_debug("failed to open counter: %s, "
369 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 370 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
370 strerror(errno)); 371 strerror(errno));
@@ -408,6 +409,8 @@ static int test__open_syscall_event_on_all_cpus(void)
408 goto out_close_fd; 409 goto out_close_fd;
409 } 410 }
410 411
412 err = 0;
413
411 for (cpu = 0; cpu < cpus->nr; ++cpu) { 414 for (cpu = 0; cpu < cpus->nr; ++cpu) {
412 unsigned int expected; 415 unsigned int expected;
413 416
@@ -416,18 +419,18 @@ static int test__open_syscall_event_on_all_cpus(void)
416 419
417 if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) { 420 if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
418 pr_debug("perf_evsel__open_read_on_cpu\n"); 421 pr_debug("perf_evsel__open_read_on_cpu\n");
419 goto out_close_fd; 422 err = -1;
423 break;
420 } 424 }
421 425
422 expected = nr_open_calls + cpu; 426 expected = nr_open_calls + cpu;
423 if (evsel->counts->cpu[cpu].val != expected) { 427 if (evsel->counts->cpu[cpu].val != expected) {
424 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n", 428 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
425 expected, cpus->map[cpu], evsel->counts->cpu[cpu].val); 429 expected, cpus->map[cpu], evsel->counts->cpu[cpu].val);
426 goto out_close_fd; 430 err = -1;
427 } 431 }
428 } 432 }
429 433
430 err = 0;
431out_close_fd: 434out_close_fd:
432 perf_evsel__close_fd(evsel, 1, threads->nr); 435 perf_evsel__close_fd(evsel, 1, threads->nr);
433out_evsel_delete: 436out_evsel_delete:
@@ -437,6 +440,159 @@ out_thread_map_delete:
437 return err; 440 return err;
438} 441}
439 442
443/*
444 * This test will generate random numbers of calls to some getpid syscalls,
445 * then establish an mmap for a group of events that are created to monitor
446 * the syscalls.
447 *
448 * It will receive the events, using mmap, use its PERF_SAMPLE_ID generated
449 * sample.id field to map back to its respective perf_evsel instance.
450 *
451 * Then it checks if the number of syscalls reported as perf events by
452 * the kernel corresponds to the number of syscalls made.
453 */
454static int test__basic_mmap(void)
455{
456 int err = -1;
457 union perf_event *event;
458 struct thread_map *threads;
459 struct cpu_map *cpus;
460 struct perf_evlist *evlist;
461 struct perf_event_attr attr = {
462 .type = PERF_TYPE_TRACEPOINT,
463 .read_format = PERF_FORMAT_ID,
464 .sample_type = PERF_SAMPLE_ID,
465 .watermark = 0,
466 };
467 cpu_set_t cpu_set;
468 const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
469 "getpgid", };
470 pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
471 (void*)getpgid };
472#define nsyscalls ARRAY_SIZE(syscall_names)
473 int ids[nsyscalls];
474 unsigned int nr_events[nsyscalls],
475 expected_nr_events[nsyscalls], i, j;
476 struct perf_evsel *evsels[nsyscalls], *evsel;
477
478 for (i = 0; i < nsyscalls; ++i) {
479 char name[64];
480
481 snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
482 ids[i] = trace_event__id(name);
483 if (ids[i] < 0) {
484 pr_debug("Is debugfs mounted on /sys/kernel/debug?\n");
485 return -1;
486 }
487 nr_events[i] = 0;
488 expected_nr_events[i] = random() % 257;
489 }
490
491 threads = thread_map__new(-1, getpid());
492 if (threads == NULL) {
493 pr_debug("thread_map__new\n");
494 return -1;
495 }
496
497 cpus = cpu_map__new(NULL);
498 if (cpus == NULL) {
499 pr_debug("cpu_map__new\n");
500 goto out_free_threads;
501 }
502
503 CPU_ZERO(&cpu_set);
504 CPU_SET(cpus->map[0], &cpu_set);
505 sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
506 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
507 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
508 cpus->map[0], strerror(errno));
509 goto out_free_cpus;
510 }
511
512 evlist = perf_evlist__new(cpus, threads);
513 if (evlist == NULL) {
514 pr_debug("perf_evlist__new\n");
515 goto out_free_cpus;
516 }
517
518 /* anonymous union fields, can't be initialized above */
519 attr.wakeup_events = 1;
520 attr.sample_period = 1;
521
522 for (i = 0; i < nsyscalls; ++i) {
523 attr.config = ids[i];
524 evsels[i] = perf_evsel__new(&attr, i);
525 if (evsels[i] == NULL) {
526 pr_debug("perf_evsel__new\n");
527 goto out_free_evlist;
528 }
529
530 perf_evlist__add(evlist, evsels[i]);
531
532 if (perf_evsel__open(evsels[i], cpus, threads, false, false) < 0) {
533 pr_debug("failed to open counter: %s, "
534 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
535 strerror(errno));
536 goto out_close_fd;
537 }
538 }
539
540 if (perf_evlist__mmap(evlist, 128, true) < 0) {
541 pr_debug("failed to mmap events: %d (%s)\n", errno,
542 strerror(errno));
543 goto out_close_fd;
544 }
545
546 for (i = 0; i < nsyscalls; ++i)
547 for (j = 0; j < expected_nr_events[i]; ++j) {
548 int foo = syscalls[i]();
549 ++foo;
550 }
551
552 while ((event = perf_evlist__read_on_cpu(evlist, 0)) != NULL) {
553 struct perf_sample sample;
554
555 if (event->header.type != PERF_RECORD_SAMPLE) {
556 pr_debug("unexpected %s event\n",
557 perf_event__name(event->header.type));
558 goto out_munmap;
559 }
560
561 perf_event__parse_sample(event, attr.sample_type, false, &sample);
562 evsel = perf_evlist__id2evsel(evlist, sample.id);
563 if (evsel == NULL) {
564 pr_debug("event with id %" PRIu64
565 " doesn't map to an evsel\n", sample.id);
566 goto out_munmap;
567 }
568 nr_events[evsel->idx]++;
569 }
570
571 list_for_each_entry(evsel, &evlist->entries, node) {
572 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
573 pr_debug("expected %d %s events, got %d\n",
574 expected_nr_events[evsel->idx],
575 event_name(evsel), nr_events[evsel->idx]);
576 goto out_munmap;
577 }
578 }
579
580 err = 0;
581out_munmap:
582 perf_evlist__munmap(evlist);
583out_close_fd:
584 for (i = 0; i < nsyscalls; ++i)
585 perf_evsel__close_fd(evsels[i], 1, threads->nr);
586out_free_evlist:
587 perf_evlist__delete(evlist);
588out_free_cpus:
589 cpu_map__delete(cpus);
590out_free_threads:
591 thread_map__delete(threads);
592 return err;
593#undef nsyscalls
594}
595
440static struct test { 596static struct test {
441 const char *desc; 597 const char *desc;
442 int (*func)(void); 598 int (*func)(void);
@@ -454,6 +610,10 @@ static struct test {
454 .func = test__open_syscall_event_on_all_cpus, 610 .func = test__open_syscall_event_on_all_cpus,
455 }, 611 },
456 { 612 {
613 .desc = "read samples using the mmap interface",
614 .func = test__basic_mmap,
615 },
616 {
457 .func = NULL, 617 .func = NULL,
458 }, 618 },
459}; 619};
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 0ace786e83e0..67c0459dc325 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -273,21 +273,24 @@ static int cpus_cstate_state[MAX_CPUS];
273static u64 cpus_pstate_start_times[MAX_CPUS]; 273static u64 cpus_pstate_start_times[MAX_CPUS];
274static u64 cpus_pstate_state[MAX_CPUS]; 274static u64 cpus_pstate_state[MAX_CPUS];
275 275
276static int process_comm_event(event_t *event, struct sample_data *sample __used, 276static int process_comm_event(union perf_event *event,
277 struct perf_sample *sample __used,
277 struct perf_session *session __used) 278 struct perf_session *session __used)
278{ 279{
279 pid_set_comm(event->comm.tid, event->comm.comm); 280 pid_set_comm(event->comm.tid, event->comm.comm);
280 return 0; 281 return 0;
281} 282}
282 283
283static int process_fork_event(event_t *event, struct sample_data *sample __used, 284static int process_fork_event(union perf_event *event,
285 struct perf_sample *sample __used,
284 struct perf_session *session __used) 286 struct perf_session *session __used)
285{ 287{
286 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); 288 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
287 return 0; 289 return 0;
288} 290}
289 291
290static int process_exit_event(event_t *event, struct sample_data *sample __used, 292static int process_exit_event(union perf_event *event,
293 struct perf_sample *sample __used,
291 struct perf_session *session __used) 294 struct perf_session *session __used)
292{ 295{
293 pid_exit(event->fork.pid, event->fork.time); 296 pid_exit(event->fork.pid, event->fork.time);
@@ -483,8 +486,8 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
483} 486}
484 487
485 488
486static int process_sample_event(event_t *event __used, 489static int process_sample_event(union perf_event *event __used,
487 struct sample_data *sample, 490 struct perf_sample *sample,
488 struct perf_session *session) 491 struct perf_session *session)
489{ 492{
490 struct trace_entry *te; 493 struct trace_entry *te;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5a29d9cd9486..80c9e062bd5b 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -20,11 +20,16 @@
20 20
21#include "perf.h" 21#include "perf.h"
22 22
23#include "util/annotate.h"
24#include "util/cache.h"
23#include "util/color.h" 25#include "util/color.h"
26#include "util/evlist.h"
24#include "util/evsel.h" 27#include "util/evsel.h"
25#include "util/session.h" 28#include "util/session.h"
26#include "util/symbol.h" 29#include "util/symbol.h"
27#include "util/thread.h" 30#include "util/thread.h"
31#include "util/thread_map.h"
32#include "util/top.h"
28#include "util/util.h" 33#include "util/util.h"
29#include <linux/rbtree.h> 34#include <linux/rbtree.h>
30#include "util/parse-options.h" 35#include "util/parse-options.h"
@@ -45,7 +50,6 @@
45#include <errno.h> 50#include <errno.h>
46#include <time.h> 51#include <time.h>
47#include <sched.h> 52#include <sched.h>
48#include <pthread.h>
49 53
50#include <sys/syscall.h> 54#include <sys/syscall.h>
51#include <sys/ioctl.h> 55#include <sys/ioctl.h>
@@ -60,85 +64,42 @@
60 64
61#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 65#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
62 66
67static struct perf_top top = {
68 .count_filter = 5,
69 .delay_secs = 2,
70 .display_weighted = -1,
71 .target_pid = -1,
72 .target_tid = -1,
73 .active_symbols = LIST_HEAD_INIT(top.active_symbols),
74 .active_symbols_lock = PTHREAD_MUTEX_INITIALIZER,
75 .active_symbols_cond = PTHREAD_COND_INITIALIZER,
76 .freq = 1000, /* 1 KHz */
77};
78
63static bool system_wide = false; 79static bool system_wide = false;
64 80
65static int default_interval = 0; 81static bool use_tui, use_stdio;
66 82
67static int count_filter = 5; 83static int default_interval = 0;
68static int print_entries;
69 84
70static int target_pid = -1;
71static int target_tid = -1;
72static struct thread_map *threads;
73static bool inherit = false; 85static bool inherit = false;
74static struct cpu_map *cpus;
75static int realtime_prio = 0; 86static int realtime_prio = 0;
76static bool group = false; 87static bool group = false;
77static unsigned int page_size; 88static unsigned int page_size;
78static unsigned int mmap_pages = 16; 89static unsigned int mmap_pages = 128;
79static int freq = 1000; /* 1 KHz */
80 90
81static int delay_secs = 2;
82static bool zero = false;
83static bool dump_symtab = false; 91static bool dump_symtab = false;
84 92
85static bool hide_kernel_symbols = false;
86static bool hide_user_symbols = false;
87static struct winsize winsize; 93static struct winsize winsize;
88 94
89/*
90 * Source
91 */
92
93struct source_line {
94 u64 eip;
95 unsigned long count[MAX_COUNTERS];
96 char *line;
97 struct source_line *next;
98};
99
100static const char *sym_filter = NULL; 95static const char *sym_filter = NULL;
101struct sym_entry *sym_filter_entry = NULL;
102struct sym_entry *sym_filter_entry_sched = NULL; 96struct sym_entry *sym_filter_entry_sched = NULL;
103static int sym_pcnt_filter = 5; 97static int sym_pcnt_filter = 5;
104static int sym_counter = 0;
105static struct perf_evsel *sym_evsel = NULL;
106static int display_weighted = -1;
107static const char *cpu_list;
108
109/*
110 * Symbols
111 */
112
113struct sym_entry_source {
114 struct source_line *source;
115 struct source_line *lines;
116 struct source_line **lines_tail;
117 pthread_mutex_t lock;
118};
119
120struct sym_entry {
121 struct rb_node rb_node;
122 struct list_head node;
123 unsigned long snap_count;
124 double weight;
125 int skip;
126 u16 name_len;
127 u8 origin;
128 struct map *map;
129 struct sym_entry_source *src;
130 unsigned long count[0];
131};
132 98
133/* 99/*
134 * Source functions 100 * Source functions
135 */ 101 */
136 102
137static inline struct symbol *sym_entry__symbol(struct sym_entry *self)
138{
139 return ((void *)self) + symbol_conf.priv_size;
140}
141
142void get_term_dimensions(struct winsize *ws) 103void get_term_dimensions(struct winsize *ws)
143{ 104{
144 char *s = getenv("LINES"); 105 char *s = getenv("LINES");
@@ -163,10 +124,10 @@ void get_term_dimensions(struct winsize *ws)
163 124
164static void update_print_entries(struct winsize *ws) 125static void update_print_entries(struct winsize *ws)
165{ 126{
166 print_entries = ws->ws_row; 127 top.print_entries = ws->ws_row;
167 128
168 if (print_entries > 9) 129 if (top.print_entries > 9)
169 print_entries -= 9; 130 top.print_entries -= 9;
170} 131}
171 132
172static void sig_winch_handler(int sig __used) 133static void sig_winch_handler(int sig __used)
@@ -178,12 +139,9 @@ static void sig_winch_handler(int sig __used)
178static int parse_source(struct sym_entry *syme) 139static int parse_source(struct sym_entry *syme)
179{ 140{
180 struct symbol *sym; 141 struct symbol *sym;
181 struct sym_entry_source *source; 142 struct annotation *notes;
182 struct map *map; 143 struct map *map;
183 FILE *file; 144 int err = -1;
184 char command[PATH_MAX*2];
185 const char *path;
186 u64 len;
187 145
188 if (!syme) 146 if (!syme)
189 return -1; 147 return -1;
@@ -194,411 +152,137 @@ static int parse_source(struct sym_entry *syme)
194 /* 152 /*
195 * We can't annotate with just /proc/kallsyms 153 * We can't annotate with just /proc/kallsyms
196 */ 154 */
197 if (map->dso->origin == DSO__ORIG_KERNEL) 155 if (map->dso->origin == DSO__ORIG_KERNEL) {
156 pr_err("Can't annotate %s: No vmlinux file was found in the "
157 "path\n", sym->name);
158 sleep(1);
198 return -1; 159 return -1;
199
200 if (syme->src == NULL) {
201 syme->src = zalloc(sizeof(*source));
202 if (syme->src == NULL)
203 return -1;
204 pthread_mutex_init(&syme->src->lock, NULL);
205 } 160 }
206 161
207 source = syme->src; 162 notes = symbol__annotation(sym);
208 163 if (notes->src != NULL) {
209 if (source->lines) { 164 pthread_mutex_lock(&notes->lock);
210 pthread_mutex_lock(&source->lock);
211 goto out_assign; 165 goto out_assign;
212 } 166 }
213 path = map->dso->long_name;
214
215 len = sym->end - sym->start;
216
217 sprintf(command,
218 "objdump --start-address=%#0*" PRIx64 " --stop-address=%#0*" PRIx64 " -dS %s",
219 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start),
220 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->end), path);
221
222 file = popen(command, "r");
223 if (!file)
224 return -1;
225
226 pthread_mutex_lock(&source->lock);
227 source->lines_tail = &source->lines;
228 while (!feof(file)) {
229 struct source_line *src;
230 size_t dummy = 0;
231 char *c, *sep;
232 167
233 src = malloc(sizeof(struct source_line)); 168 pthread_mutex_lock(&notes->lock);
234 assert(src != NULL);
235 memset(src, 0, sizeof(struct source_line));
236 169
237 if (getline(&src->line, &dummy, file) < 0) 170 if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
238 break; 171 pthread_mutex_unlock(&notes->lock);
239 if (!src->line) 172 pr_err("Not enough memory for annotating '%s' symbol!\n",
240 break; 173 sym->name);
241 174 sleep(1);
242 c = strchr(src->line, '\n'); 175 return err;
243 if (c)
244 *c = 0;
245
246 src->next = NULL;
247 *source->lines_tail = src;
248 source->lines_tail = &src->next;
249
250 src->eip = strtoull(src->line, &sep, 16);
251 if (*sep == ':')
252 src->eip = map__objdump_2ip(map, src->eip);
253 else /* this line has no ip info (e.g. source line) */
254 src->eip = 0;
255 } 176 }
256 pclose(file); 177
178 err = symbol__annotate(sym, syme->map, 0);
179 if (err == 0) {
257out_assign: 180out_assign:
258 sym_filter_entry = syme; 181 top.sym_filter_entry = syme;
259 pthread_mutex_unlock(&source->lock); 182 }
260 return 0; 183
184 pthread_mutex_unlock(&notes->lock);
185 return err;
261} 186}
262 187
263static void __zero_source_counters(struct sym_entry *syme) 188static void __zero_source_counters(struct sym_entry *syme)
264{ 189{
265 int i; 190 struct symbol *sym = sym_entry__symbol(syme);
266 struct source_line *line; 191 symbol__annotate_zero_histograms(sym);
267
268 line = syme->src->lines;
269 while (line) {
270 for (i = 0; i < nr_counters; i++)
271 line->count[i] = 0;
272 line = line->next;
273 }
274} 192}
275 193
276static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) 194static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
277{ 195{
278 struct source_line *line; 196 struct annotation *notes;
279 197 struct symbol *sym;
280 if (syme != sym_filter_entry)
281 return;
282 198
283 if (pthread_mutex_trylock(&syme->src->lock)) 199 if (syme != top.sym_filter_entry)
284 return; 200 return;
285 201
286 if (syme->src == NULL || syme->src->source == NULL) 202 sym = sym_entry__symbol(syme);
287 goto out_unlock; 203 notes = symbol__annotation(sym);
288
289 for (line = syme->src->lines; line; line = line->next) {
290 /* skip lines without IP info */
291 if (line->eip == 0)
292 continue;
293 if (line->eip == ip) {
294 line->count[counter]++;
295 break;
296 }
297 if (line->eip > ip)
298 break;
299 }
300out_unlock:
301 pthread_mutex_unlock(&syme->src->lock);
302}
303
304#define PATTERN_LEN (BITS_PER_LONG / 4 + 2)
305
306static void lookup_sym_source(struct sym_entry *syme)
307{
308 struct symbol *symbol = sym_entry__symbol(syme);
309 struct source_line *line;
310 char pattern[PATTERN_LEN + 1];
311
312 sprintf(pattern, "%0*" PRIx64 " <", BITS_PER_LONG / 4,
313 map__rip_2objdump(syme->map, symbol->start));
314
315 pthread_mutex_lock(&syme->src->lock);
316 for (line = syme->src->lines; line; line = line->next) {
317 if (memcmp(line->line, pattern, PATTERN_LEN) == 0) {
318 syme->src->source = line;
319 break;
320 }
321 }
322 pthread_mutex_unlock(&syme->src->lock);
323}
324 204
325static void show_lines(struct source_line *queue, int count, int total) 205 if (pthread_mutex_trylock(&notes->lock))
326{ 206 return;
327 int i;
328 struct source_line *line;
329 207
330 line = queue; 208 ip = syme->map->map_ip(syme->map, ip);
331 for (i = 0; i < count; i++) { 209 symbol__inc_addr_samples(sym, syme->map, counter, ip);
332 float pcnt = 100.0*(float)line->count[sym_counter]/(float)total;
333 210
334 printf("%8li %4.1f%%\t%s\n", line->count[sym_counter], pcnt, line->line); 211 pthread_mutex_unlock(&notes->lock);
335 line = line->next;
336 }
337} 212}
338 213
339#define TRACE_COUNT 3
340
341static void show_details(struct sym_entry *syme) 214static void show_details(struct sym_entry *syme)
342{ 215{
216 struct annotation *notes;
343 struct symbol *symbol; 217 struct symbol *symbol;
344 struct source_line *line; 218 int more;
345 struct source_line *line_queue = NULL;
346 int displayed = 0;
347 int line_queue_count = 0, total = 0, more = 0;
348 219
349 if (!syme) 220 if (!syme)
350 return; 221 return;
351 222
352 if (!syme->src->source)
353 lookup_sym_source(syme);
354
355 if (!syme->src->source)
356 return;
357
358 symbol = sym_entry__symbol(syme); 223 symbol = sym_entry__symbol(syme);
359 printf("Showing %s for %s\n", event_name(sym_evsel), symbol->name); 224 notes = symbol__annotation(symbol);
360 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
361
362 pthread_mutex_lock(&syme->src->lock);
363 line = syme->src->source;
364 while (line) {
365 total += line->count[sym_counter];
366 line = line->next;
367 }
368
369 line = syme->src->source;
370 while (line) {
371 float pcnt = 0.0;
372
373 if (!line_queue_count)
374 line_queue = line;
375 line_queue_count++;
376
377 if (line->count[sym_counter])
378 pcnt = 100.0 * line->count[sym_counter] / (float)total;
379 if (pcnt >= (float)sym_pcnt_filter) {
380 if (displayed <= print_entries)
381 show_lines(line_queue, line_queue_count, total);
382 else more++;
383 displayed += line_queue_count;
384 line_queue_count = 0;
385 line_queue = NULL;
386 } else if (line_queue_count > TRACE_COUNT) {
387 line_queue = line_queue->next;
388 line_queue_count--;
389 }
390
391 line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8;
392 line = line->next;
393 }
394 pthread_mutex_unlock(&syme->src->lock);
395 if (more)
396 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
397}
398 225
399/* 226 pthread_mutex_lock(&notes->lock);
400 * Symbols will be added here in event__process_sample and will get out
401 * after decayed.
402 */
403static LIST_HEAD(active_symbols);
404static pthread_mutex_t active_symbols_lock = PTHREAD_MUTEX_INITIALIZER;
405
406/*
407 * Ordering weight: count-1 * count-2 * ... / count-n
408 */
409static double sym_weight(const struct sym_entry *sym)
410{
411 double weight = sym->snap_count;
412 int counter;
413
414 if (!display_weighted)
415 return weight;
416 227
417 for (counter = 1; counter < nr_counters-1; counter++) 228 if (notes->src == NULL)
418 weight *= sym->count[counter]; 229 goto out_unlock;
419 230
420 weight /= (sym->count[counter] + 1); 231 printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name);
232 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
421 233
422 return weight; 234 more = symbol__annotate_printf(symbol, syme->map, top.sym_evsel->idx,
235 0, sym_pcnt_filter, top.print_entries, 4);
236 if (top.zero)
237 symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx);
238 else
239 symbol__annotate_decay_histogram(symbol, top.sym_evsel->idx);
240 if (more != 0)
241 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
242out_unlock:
243 pthread_mutex_unlock(&notes->lock);
423} 244}
424 245
425static long samples;
426static long kernel_samples, us_samples;
427static long exact_samples;
428static long guest_us_samples, guest_kernel_samples;
429static const char CONSOLE_CLEAR[] = ""; 246static const char CONSOLE_CLEAR[] = "";
430 247
431static void __list_insert_active_sym(struct sym_entry *syme) 248static void __list_insert_active_sym(struct sym_entry *syme)
432{ 249{
433 list_add(&syme->node, &active_symbols); 250 list_add(&syme->node, &top.active_symbols);
434}
435
436static void list_remove_active_sym(struct sym_entry *syme)
437{
438 pthread_mutex_lock(&active_symbols_lock);
439 list_del_init(&syme->node);
440 pthread_mutex_unlock(&active_symbols_lock);
441} 251}
442 252
443static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se) 253static void print_sym_table(struct perf_session *session)
444{ 254{
445 struct rb_node **p = &tree->rb_node; 255 char bf[160];
446 struct rb_node *parent = NULL; 256 int printed = 0;
447 struct sym_entry *iter;
448
449 while (*p != NULL) {
450 parent = *p;
451 iter = rb_entry(parent, struct sym_entry, rb_node);
452
453 if (se->weight > iter->weight)
454 p = &(*p)->rb_left;
455 else
456 p = &(*p)->rb_right;
457 }
458
459 rb_link_node(&se->rb_node, parent, p);
460 rb_insert_color(&se->rb_node, tree);
461}
462
463static void print_sym_table(void)
464{
465 int printed = 0, j;
466 struct perf_evsel *counter;
467 int snap = !display_weighted ? sym_counter : 0;
468 float samples_per_sec = samples/delay_secs;
469 float ksamples_per_sec = kernel_samples/delay_secs;
470 float us_samples_per_sec = (us_samples)/delay_secs;
471 float guest_kernel_samples_per_sec = (guest_kernel_samples)/delay_secs;
472 float guest_us_samples_per_sec = (guest_us_samples)/delay_secs;
473 float esamples_percent = (100.0*exact_samples)/samples;
474 float sum_ksamples = 0.0;
475 struct sym_entry *syme, *n;
476 struct rb_root tmp = RB_ROOT;
477 struct rb_node *nd; 257 struct rb_node *nd;
478 int sym_width = 0, dso_width = 0, dso_short_width = 0; 258 struct sym_entry *syme;
259 struct rb_root tmp = RB_ROOT;
479 const int win_width = winsize.ws_col - 1; 260 const int win_width = winsize.ws_col - 1;
480 261 int sym_width, dso_width, dso_short_width;
481 samples = us_samples = kernel_samples = exact_samples = 0; 262 float sum_ksamples = perf_top__decay_samples(&top, &tmp);
482 guest_kernel_samples = guest_us_samples = 0;
483
484 /* Sort the active symbols */
485 pthread_mutex_lock(&active_symbols_lock);
486 syme = list_entry(active_symbols.next, struct sym_entry, node);
487 pthread_mutex_unlock(&active_symbols_lock);
488
489 list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
490 syme->snap_count = syme->count[snap];
491 if (syme->snap_count != 0) {
492
493 if ((hide_user_symbols &&
494 syme->origin == PERF_RECORD_MISC_USER) ||
495 (hide_kernel_symbols &&
496 syme->origin == PERF_RECORD_MISC_KERNEL)) {
497 list_remove_active_sym(syme);
498 continue;
499 }
500 syme->weight = sym_weight(syme);
501 rb_insert_active_sym(&tmp, syme);
502 sum_ksamples += syme->snap_count;
503
504 for (j = 0; j < nr_counters; j++)
505 syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8;
506 } else
507 list_remove_active_sym(syme);
508 }
509 263
510 puts(CONSOLE_CLEAR); 264 puts(CONSOLE_CLEAR);
511 265
512 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 266 perf_top__header_snprintf(&top, bf, sizeof(bf));
513 if (!perf_guest) { 267 printf("%s\n", bf);
514 printf(" PerfTop:%8.0f irqs/sec kernel:%4.1f%%"
515 " exact: %4.1f%% [",
516 samples_per_sec,
517 100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) /
518 samples_per_sec)),
519 esamples_percent);
520 } else {
521 printf(" PerfTop:%8.0f irqs/sec kernel:%4.1f%% us:%4.1f%%"
522 " guest kernel:%4.1f%% guest us:%4.1f%%"
523 " exact: %4.1f%% [",
524 samples_per_sec,
525 100.0 - (100.0 * ((samples_per_sec-ksamples_per_sec) /
526 samples_per_sec)),
527 100.0 - (100.0 * ((samples_per_sec-us_samples_per_sec) /
528 samples_per_sec)),
529 100.0 - (100.0 * ((samples_per_sec -
530 guest_kernel_samples_per_sec) /
531 samples_per_sec)),
532 100.0 - (100.0 * ((samples_per_sec -
533 guest_us_samples_per_sec) /
534 samples_per_sec)),
535 esamples_percent);
536 }
537
538 if (nr_counters == 1 || !display_weighted) {
539 struct perf_evsel *first;
540 first = list_entry(evsel_list.next, struct perf_evsel, node);
541 printf("%" PRIu64, (uint64_t)first->attr.sample_period);
542 if (freq)
543 printf("Hz ");
544 else
545 printf(" ");
546 }
547
548 if (!display_weighted)
549 printf("%s", event_name(sym_evsel));
550 else list_for_each_entry(counter, &evsel_list, node) {
551 if (counter->idx)
552 printf("/");
553
554 printf("%s", event_name(counter));
555 }
556 268
557 printf( "], "); 269 perf_top__reset_sample_counters(&top);
558
559 if (target_pid != -1)
560 printf(" (target_pid: %d", target_pid);
561 else if (target_tid != -1)
562 printf(" (target_tid: %d", target_tid);
563 else
564 printf(" (all");
565
566 if (cpu_list)
567 printf(", CPU%s: %s)\n", cpus->nr > 1 ? "s" : "", cpu_list);
568 else {
569 if (target_tid != -1)
570 printf(")\n");
571 else
572 printf(", %d CPU%s)\n", cpus->nr, cpus->nr > 1 ? "s" : "");
573 }
574 270
575 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 271 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
576 272
577 if (sym_filter_entry) { 273 if (session->hists.stats.total_lost != 0) {
578 show_details(sym_filter_entry); 274 color_fprintf(stdout, PERF_COLOR_RED, "WARNING:");
579 return; 275 printf(" LOST %" PRIu64 " events, Check IO/CPU overload\n",
276 session->hists.stats.total_lost);
580 } 277 }
581 278
582 /* 279 if (top.sym_filter_entry) {
583 * Find the longest symbol name that will be displayed 280 show_details(top.sym_filter_entry);
584 */ 281 return;
585 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
586 syme = rb_entry(nd, struct sym_entry, rb_node);
587 if (++printed > print_entries ||
588 (int)syme->snap_count < count_filter)
589 continue;
590
591 if (syme->map->dso->long_name_len > dso_width)
592 dso_width = syme->map->dso->long_name_len;
593
594 if (syme->map->dso->short_name_len > dso_short_width)
595 dso_short_width = syme->map->dso->short_name_len;
596
597 if (syme->name_len > sym_width)
598 sym_width = syme->name_len;
599 } 282 }
600 283
601 printed = 0; 284 perf_top__find_widths(&top, &tmp, &dso_width, &dso_short_width,
285 &sym_width);
602 286
603 if (sym_width + dso_width > winsize.ws_col - 29) { 287 if (sym_width + dso_width > winsize.ws_col - 29) {
604 dso_width = dso_short_width; 288 dso_width = dso_short_width;
@@ -606,7 +290,7 @@ static void print_sym_table(void)
606 sym_width = winsize.ws_col - dso_width - 29; 290 sym_width = winsize.ws_col - dso_width - 29;
607 } 291 }
608 putchar('\n'); 292 putchar('\n');
609 if (nr_counters == 1) 293 if (top.evlist->nr_entries == 1)
610 printf(" samples pcnt"); 294 printf(" samples pcnt");
611 else 295 else
612 printf(" weight samples pcnt"); 296 printf(" weight samples pcnt");
@@ -615,7 +299,7 @@ static void print_sym_table(void)
615 printf(" RIP "); 299 printf(" RIP ");
616 printf(" %-*.*s DSO\n", sym_width, sym_width, "function"); 300 printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
617 printf(" %s _______ _____", 301 printf(" %s _______ _____",
618 nr_counters == 1 ? " " : "______"); 302 top.evlist->nr_entries == 1 ? " " : "______");
619 if (verbose) 303 if (verbose)
620 printf(" ________________"); 304 printf(" ________________");
621 printf(" %-*.*s", sym_width, sym_width, graph_line); 305 printf(" %-*.*s", sym_width, sym_width, graph_line);
@@ -628,13 +312,14 @@ static void print_sym_table(void)
628 312
629 syme = rb_entry(nd, struct sym_entry, rb_node); 313 syme = rb_entry(nd, struct sym_entry, rb_node);
630 sym = sym_entry__symbol(syme); 314 sym = sym_entry__symbol(syme);
631 if (++printed > print_entries || (int)syme->snap_count < count_filter) 315 if (++printed > top.print_entries ||
316 (int)syme->snap_count < top.count_filter)
632 continue; 317 continue;
633 318
634 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / 319 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
635 sum_ksamples)); 320 sum_ksamples));
636 321
637 if (nr_counters == 1 || !display_weighted) 322 if (top.evlist->nr_entries == 1 || !top.display_weighted)
638 printf("%20.2f ", syme->weight); 323 printf("%20.2f ", syme->weight);
639 else 324 else
640 printf("%9.1f %10ld ", syme->weight, syme->snap_count); 325 printf("%9.1f %10ld ", syme->weight, syme->snap_count);
@@ -693,10 +378,8 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
693 378
694 /* zero counters of active symbol */ 379 /* zero counters of active symbol */
695 if (syme) { 380 if (syme) {
696 pthread_mutex_lock(&syme->src->lock);
697 __zero_source_counters(syme); 381 __zero_source_counters(syme);
698 *target = NULL; 382 *target = NULL;
699 pthread_mutex_unlock(&syme->src->lock);
700 } 383 }
701 384
702 fprintf(stdout, "\n%s: ", msg); 385 fprintf(stdout, "\n%s: ", msg);
@@ -707,11 +390,11 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
707 if (p) 390 if (p)
708 *p = 0; 391 *p = 0;
709 392
710 pthread_mutex_lock(&active_symbols_lock); 393 pthread_mutex_lock(&top.active_symbols_lock);
711 syme = list_entry(active_symbols.next, struct sym_entry, node); 394 syme = list_entry(top.active_symbols.next, struct sym_entry, node);
712 pthread_mutex_unlock(&active_symbols_lock); 395 pthread_mutex_unlock(&top.active_symbols_lock);
713 396
714 list_for_each_entry_safe_from(syme, n, &active_symbols, node) { 397 list_for_each_entry_safe_from(syme, n, &top.active_symbols, node) {
715 struct symbol *sym = sym_entry__symbol(syme); 398 struct symbol *sym = sym_entry__symbol(syme);
716 399
717 if (!strcmp(buf, sym->name)) { 400 if (!strcmp(buf, sym->name)) {
@@ -735,34 +418,34 @@ static void print_mapped_keys(void)
735{ 418{
736 char *name = NULL; 419 char *name = NULL;
737 420
738 if (sym_filter_entry) { 421 if (top.sym_filter_entry) {
739 struct symbol *sym = sym_entry__symbol(sym_filter_entry); 422 struct symbol *sym = sym_entry__symbol(top.sym_filter_entry);
740 name = sym->name; 423 name = sym->name;
741 } 424 }
742 425
743 fprintf(stdout, "\nMapped keys:\n"); 426 fprintf(stdout, "\nMapped keys:\n");
744 fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", delay_secs); 427 fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", top.delay_secs);
745 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries); 428 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top.print_entries);
746 429
747 if (nr_counters > 1) 430 if (top.evlist->nr_entries > 1)
748 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel)); 431 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(top.sym_evsel));
749 432
750 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 433 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top.count_filter);
751 434
752 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); 435 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter);
753 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 436 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
754 fprintf(stdout, "\t[S] stop annotation.\n"); 437 fprintf(stdout, "\t[S] stop annotation.\n");
755 438
756 if (nr_counters > 1) 439 if (top.evlist->nr_entries > 1)
757 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); 440 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", top.display_weighted ? 1 : 0);
758 441
759 fprintf(stdout, 442 fprintf(stdout,
760 "\t[K] hide kernel_symbols symbols. \t(%s)\n", 443 "\t[K] hide kernel_symbols symbols. \t(%s)\n",
761 hide_kernel_symbols ? "yes" : "no"); 444 top.hide_kernel_symbols ? "yes" : "no");
762 fprintf(stdout, 445 fprintf(stdout,
763 "\t[U] hide user symbols. \t(%s)\n", 446 "\t[U] hide user symbols. \t(%s)\n",
764 hide_user_symbols ? "yes" : "no"); 447 top.hide_user_symbols ? "yes" : "no");
765 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", zero ? 1 : 0); 448 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", top.zero ? 1 : 0);
766 fprintf(stdout, "\t[qQ] quit.\n"); 449 fprintf(stdout, "\t[qQ] quit.\n");
767} 450}
768 451
@@ -783,7 +466,7 @@ static int key_mapped(int c)
783 return 1; 466 return 1;
784 case 'E': 467 case 'E':
785 case 'w': 468 case 'w':
786 return nr_counters > 1 ? 1 : 0; 469 return top.evlist->nr_entries > 1 ? 1 : 0;
787 default: 470 default:
788 break; 471 break;
789 } 472 }
@@ -818,47 +501,47 @@ static void handle_keypress(struct perf_session *session, int c)
818 501
819 switch (c) { 502 switch (c) {
820 case 'd': 503 case 'd':
821 prompt_integer(&delay_secs, "Enter display delay"); 504 prompt_integer(&top.delay_secs, "Enter display delay");
822 if (delay_secs < 1) 505 if (top.delay_secs < 1)
823 delay_secs = 1; 506 top.delay_secs = 1;
824 break; 507 break;
825 case 'e': 508 case 'e':
826 prompt_integer(&print_entries, "Enter display entries (lines)"); 509 prompt_integer(&top.print_entries, "Enter display entries (lines)");
827 if (print_entries == 0) { 510 if (top.print_entries == 0) {
828 sig_winch_handler(SIGWINCH); 511 sig_winch_handler(SIGWINCH);
829 signal(SIGWINCH, sig_winch_handler); 512 signal(SIGWINCH, sig_winch_handler);
830 } else 513 } else
831 signal(SIGWINCH, SIG_DFL); 514 signal(SIGWINCH, SIG_DFL);
832 break; 515 break;
833 case 'E': 516 case 'E':
834 if (nr_counters > 1) { 517 if (top.evlist->nr_entries > 1) {
835 fprintf(stderr, "\nAvailable events:"); 518 fprintf(stderr, "\nAvailable events:");
836 519
837 list_for_each_entry(sym_evsel, &evsel_list, node) 520 list_for_each_entry(top.sym_evsel, &top.evlist->entries, node)
838 fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel)); 521 fprintf(stderr, "\n\t%d %s", top.sym_evsel->idx, event_name(top.sym_evsel));
839 522
840 prompt_integer(&sym_counter, "Enter details event counter"); 523 prompt_integer(&top.sym_counter, "Enter details event counter");
841 524
842 if (sym_counter >= nr_counters) { 525 if (top.sym_counter >= top.evlist->nr_entries) {
843 sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node); 526 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
844 sym_counter = 0; 527 top.sym_counter = 0;
845 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel)); 528 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top.sym_evsel));
846 sleep(1); 529 sleep(1);
847 break; 530 break;
848 } 531 }
849 list_for_each_entry(sym_evsel, &evsel_list, node) 532 list_for_each_entry(top.sym_evsel, &top.evlist->entries, node)
850 if (sym_evsel->idx == sym_counter) 533 if (top.sym_evsel->idx == top.sym_counter)
851 break; 534 break;
852 } else sym_counter = 0; 535 } else top.sym_counter = 0;
853 break; 536 break;
854 case 'f': 537 case 'f':
855 prompt_integer(&count_filter, "Enter display event count filter"); 538 prompt_integer(&top.count_filter, "Enter display event count filter");
856 break; 539 break;
857 case 'F': 540 case 'F':
858 prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)"); 541 prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)");
859 break; 542 break;
860 case 'K': 543 case 'K':
861 hide_kernel_symbols = !hide_kernel_symbols; 544 top.hide_kernel_symbols = !top.hide_kernel_symbols;
862 break; 545 break;
863 case 'q': 546 case 'q':
864 case 'Q': 547 case 'Q':
@@ -867,34 +550,50 @@ static void handle_keypress(struct perf_session *session, int c)
867 perf_session__fprintf_dsos(session, stderr); 550 perf_session__fprintf_dsos(session, stderr);
868 exit(0); 551 exit(0);
869 case 's': 552 case 's':
870 prompt_symbol(&sym_filter_entry, "Enter details symbol"); 553 prompt_symbol(&top.sym_filter_entry, "Enter details symbol");
871 break; 554 break;
872 case 'S': 555 case 'S':
873 if (!sym_filter_entry) 556 if (!top.sym_filter_entry)
874 break; 557 break;
875 else { 558 else {
876 struct sym_entry *syme = sym_filter_entry; 559 struct sym_entry *syme = top.sym_filter_entry;
877 560
878 pthread_mutex_lock(&syme->src->lock); 561 top.sym_filter_entry = NULL;
879 sym_filter_entry = NULL;
880 __zero_source_counters(syme); 562 __zero_source_counters(syme);
881 pthread_mutex_unlock(&syme->src->lock);
882 } 563 }
883 break; 564 break;
884 case 'U': 565 case 'U':
885 hide_user_symbols = !hide_user_symbols; 566 top.hide_user_symbols = !top.hide_user_symbols;
886 break; 567 break;
887 case 'w': 568 case 'w':
888 display_weighted = ~display_weighted; 569 top.display_weighted = ~top.display_weighted;
889 break; 570 break;
890 case 'z': 571 case 'z':
891 zero = !zero; 572 top.zero = !top.zero;
892 break; 573 break;
893 default: 574 default:
894 break; 575 break;
895 } 576 }
896} 577}
897 578
579static void *display_thread_tui(void *arg __used)
580{
581 int err = 0;
582 pthread_mutex_lock(&top.active_symbols_lock);
583 while (list_empty(&top.active_symbols)) {
584 err = pthread_cond_wait(&top.active_symbols_cond,
585 &top.active_symbols_lock);
586 if (err)
587 break;
588 }
589 pthread_mutex_unlock(&top.active_symbols_lock);
590 if (!err)
591 perf_top__tui_browser(&top);
592 exit_browser(0);
593 exit(0);
594 return NULL;
595}
596
898static void *display_thread(void *arg __used) 597static void *display_thread(void *arg __used)
899{ 598{
900 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 599 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
@@ -909,13 +608,13 @@ static void *display_thread(void *arg __used)
909 tc.c_cc[VTIME] = 0; 608 tc.c_cc[VTIME] = 0;
910 609
911repeat: 610repeat:
912 delay_msecs = delay_secs * 1000; 611 delay_msecs = top.delay_secs * 1000;
913 tcsetattr(0, TCSANOW, &tc); 612 tcsetattr(0, TCSANOW, &tc);
914 /* trash return*/ 613 /* trash return*/
915 getc(stdin); 614 getc(stdin);
916 615
917 do { 616 do {
918 print_sym_table(); 617 print_sym_table(session);
919 } while (!poll(&stdin_poll, 1, delay_msecs) == 1); 618 } while (!poll(&stdin_poll, 1, delay_msecs) == 1);
920 619
921 c = getc(stdin); 620 c = getc(stdin);
@@ -930,6 +629,7 @@ repeat:
930/* Tag samples to be skipped. */ 629/* Tag samples to be skipped. */
931static const char *skip_symbols[] = { 630static const char *skip_symbols[] = {
932 "default_idle", 631 "default_idle",
632 "native_safe_halt",
933 "cpu_idle", 633 "cpu_idle",
934 "enter_idle", 634 "enter_idle",
935 "exit_idle", 635 "exit_idle",
@@ -965,9 +665,9 @@ static int symbol_filter(struct map *map, struct symbol *sym)
965 665
966 syme = symbol__priv(sym); 666 syme = symbol__priv(sym);
967 syme->map = map; 667 syme->map = map;
968 syme->src = NULL; 668 symbol__annotate_init(map, sym);
969 669
970 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) { 670 if (!top.sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) {
971 /* schedule initial sym_filter_entry setup */ 671 /* schedule initial sym_filter_entry setup */
972 sym_filter_entry_sched = syme; 672 sym_filter_entry_sched = syme;
973 sym_filter = NULL; 673 sym_filter = NULL;
@@ -980,44 +680,40 @@ static int symbol_filter(struct map *map, struct symbol *sym)
980 } 680 }
981 } 681 }
982 682
983 if (!syme->skip)
984 syme->name_len = strlen(sym->name);
985
986 return 0; 683 return 0;
987} 684}
988 685
989static void event__process_sample(const event_t *self, 686static void perf_event__process_sample(const union perf_event *event,
990 struct sample_data *sample, 687 struct perf_sample *sample,
991 struct perf_session *session, 688 struct perf_session *session)
992 struct perf_evsel *evsel)
993{ 689{
994 u64 ip = self->ip.ip; 690 u64 ip = event->ip.ip;
995 struct sym_entry *syme; 691 struct sym_entry *syme;
996 struct addr_location al; 692 struct addr_location al;
997 struct machine *machine; 693 struct machine *machine;
998 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 694 u8 origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
999 695
1000 ++samples; 696 ++top.samples;
1001 697
1002 switch (origin) { 698 switch (origin) {
1003 case PERF_RECORD_MISC_USER: 699 case PERF_RECORD_MISC_USER:
1004 ++us_samples; 700 ++top.us_samples;
1005 if (hide_user_symbols) 701 if (top.hide_user_symbols)
1006 return; 702 return;
1007 machine = perf_session__find_host_machine(session); 703 machine = perf_session__find_host_machine(session);
1008 break; 704 break;
1009 case PERF_RECORD_MISC_KERNEL: 705 case PERF_RECORD_MISC_KERNEL:
1010 ++kernel_samples; 706 ++top.kernel_samples;
1011 if (hide_kernel_symbols) 707 if (top.hide_kernel_symbols)
1012 return; 708 return;
1013 machine = perf_session__find_host_machine(session); 709 machine = perf_session__find_host_machine(session);
1014 break; 710 break;
1015 case PERF_RECORD_MISC_GUEST_KERNEL: 711 case PERF_RECORD_MISC_GUEST_KERNEL:
1016 ++guest_kernel_samples; 712 ++top.guest_kernel_samples;
1017 machine = perf_session__find_machine(session, self->ip.pid); 713 machine = perf_session__find_machine(session, event->ip.pid);
1018 break; 714 break;
1019 case PERF_RECORD_MISC_GUEST_USER: 715 case PERF_RECORD_MISC_GUEST_USER:
1020 ++guest_us_samples; 716 ++top.guest_us_samples;
1021 /* 717 /*
1022 * TODO: we don't process guest user from host side 718 * TODO: we don't process guest user from host side
1023 * except simple counting. 719 * except simple counting.
@@ -1029,15 +725,15 @@ static void event__process_sample(const event_t *self,
1029 725
1030 if (!machine && perf_guest) { 726 if (!machine && perf_guest) {
1031 pr_err("Can't find guest [%d]'s kernel information\n", 727 pr_err("Can't find guest [%d]'s kernel information\n",
1032 self->ip.pid); 728 event->ip.pid);
1033 return; 729 return;
1034 } 730 }
1035 731
1036 if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) 732 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
1037 exact_samples++; 733 top.exact_samples++;
1038 734
1039 if (event__preprocess_sample(self, session, &al, sample, 735 if (perf_event__preprocess_sample(event, session, &al, sample,
1040 symbol_filter) < 0 || 736 symbol_filter) < 0 ||
1041 al.filtered) 737 al.filtered)
1042 return; 738 return;
1043 739
@@ -1055,8 +751,9 @@ static void event__process_sample(const event_t *self,
1055 */ 751 */
1056 if (al.map == machine->vmlinux_maps[MAP__FUNCTION] && 752 if (al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
1057 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { 753 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
1058 pr_err("The %s file can't be used\n", 754 ui__warning("The %s file can't be used\n",
1059 symbol_conf.vmlinux_name); 755 symbol_conf.vmlinux_name);
756 exit_browser(0);
1060 exit(1); 757 exit(1);
1061 } 758 }
1062 759
@@ -1065,13 +762,13 @@ static void event__process_sample(const event_t *self,
1065 762
1066 /* let's see, whether we need to install initial sym_filter_entry */ 763 /* let's see, whether we need to install initial sym_filter_entry */
1067 if (sym_filter_entry_sched) { 764 if (sym_filter_entry_sched) {
1068 sym_filter_entry = sym_filter_entry_sched; 765 top.sym_filter_entry = sym_filter_entry_sched;
1069 sym_filter_entry_sched = NULL; 766 sym_filter_entry_sched = NULL;
1070 if (parse_source(sym_filter_entry) < 0) { 767 if (parse_source(top.sym_filter_entry) < 0) {
1071 struct symbol *sym = sym_entry__symbol(sym_filter_entry); 768 struct symbol *sym = sym_entry__symbol(top.sym_filter_entry);
1072 769
1073 pr_err("Can't annotate %s", sym->name); 770 pr_err("Can't annotate %s", sym->name);
1074 if (sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) { 771 if (top.sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) {
1075 pr_err(": No vmlinux file was found in the path:\n"); 772 pr_err(": No vmlinux file was found in the path:\n");
1076 machine__fprintf_vmlinux_path(machine, stderr); 773 machine__fprintf_vmlinux_path(machine, stderr);
1077 } else 774 } else
@@ -1082,166 +779,73 @@ static void event__process_sample(const event_t *self,
1082 779
1083 syme = symbol__priv(al.sym); 780 syme = symbol__priv(al.sym);
1084 if (!syme->skip) { 781 if (!syme->skip) {
1085 syme->count[evsel->idx]++; 782 struct perf_evsel *evsel;
783
1086 syme->origin = origin; 784 syme->origin = origin;
785 evsel = perf_evlist__id2evsel(top.evlist, sample->id);
786 assert(evsel != NULL);
787 syme->count[evsel->idx]++;
1087 record_precise_ip(syme, evsel->idx, ip); 788 record_precise_ip(syme, evsel->idx, ip);
1088 pthread_mutex_lock(&active_symbols_lock); 789 pthread_mutex_lock(&top.active_symbols_lock);
1089 if (list_empty(&syme->node) || !syme->node.next) 790 if (list_empty(&syme->node) || !syme->node.next) {
791 static bool first = true;
1090 __list_insert_active_sym(syme); 792 __list_insert_active_sym(syme);
1091 pthread_mutex_unlock(&active_symbols_lock); 793 if (first) {
794 pthread_cond_broadcast(&top.active_symbols_cond);
795 first = false;
796 }
797 }
798 pthread_mutex_unlock(&top.active_symbols_lock);
1092 } 799 }
1093} 800}
1094 801
1095struct mmap_data { 802static void perf_session__mmap_read_cpu(struct perf_session *self, int cpu)
1096 void *base;
1097 int mask;
1098 unsigned int prev;
1099};
1100
1101static int perf_evsel__alloc_mmap_per_thread(struct perf_evsel *evsel,
1102 int ncpus, int nthreads)
1103{
1104 evsel->priv = xyarray__new(ncpus, nthreads, sizeof(struct mmap_data));
1105 return evsel->priv != NULL ? 0 : -ENOMEM;
1106}
1107
1108static void perf_evsel__free_mmap(struct perf_evsel *evsel)
1109{
1110 xyarray__delete(evsel->priv);
1111 evsel->priv = NULL;
1112}
1113
1114static unsigned int mmap_read_head(struct mmap_data *md)
1115{
1116 struct perf_event_mmap_page *pc = md->base;
1117 int head;
1118
1119 head = pc->data_head;
1120 rmb();
1121
1122 return head;
1123}
1124
1125static void perf_session__mmap_read_counter(struct perf_session *self,
1126 struct perf_evsel *evsel,
1127 int cpu, int thread_idx)
1128{ 803{
1129 struct xyarray *mmap_array = evsel->priv; 804 struct perf_sample sample;
1130 struct mmap_data *md = xyarray__entry(mmap_array, cpu, thread_idx); 805 union perf_event *event;
1131 unsigned int head = mmap_read_head(md);
1132 unsigned int old = md->prev;
1133 unsigned char *data = md->base + page_size;
1134 struct sample_data sample;
1135 int diff;
1136
1137 /*
1138 * If we're further behind than half the buffer, there's a chance
1139 * the writer will bite our tail and mess up the samples under us.
1140 *
1141 * If we somehow ended up ahead of the head, we got messed up.
1142 *
1143 * In either case, truncate and restart at head.
1144 */
1145 diff = head - old;
1146 if (diff > md->mask / 2 || diff < 0) {
1147 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
1148
1149 /*
1150 * head points to a known good entry, start there.
1151 */
1152 old = head;
1153 }
1154
1155 for (; old != head;) {
1156 event_t *event = (event_t *)&data[old & md->mask];
1157
1158 event_t event_copy;
1159 806
1160 size_t size = event->header.size; 807 while ((event = perf_evlist__read_on_cpu(top.evlist, cpu)) != NULL) {
808 perf_session__parse_sample(self, event, &sample);
1161 809
1162 /*
1163 * Event straddles the mmap boundary -- header should always
1164 * be inside due to u64 alignment of output.
1165 */
1166 if ((old & md->mask) + size != ((old + size) & md->mask)) {
1167 unsigned int offset = old;
1168 unsigned int len = min(sizeof(*event), size), cpy;
1169 void *dst = &event_copy;
1170
1171 do {
1172 cpy = min(md->mask + 1 - (offset & md->mask), len);
1173 memcpy(dst, &data[offset & md->mask], cpy);
1174 offset += cpy;
1175 dst += cpy;
1176 len -= cpy;
1177 } while (len);
1178
1179 event = &event_copy;
1180 }
1181
1182 event__parse_sample(event, self, &sample);
1183 if (event->header.type == PERF_RECORD_SAMPLE) 810 if (event->header.type == PERF_RECORD_SAMPLE)
1184 event__process_sample(event, &sample, self, evsel); 811 perf_event__process_sample(event, &sample, self);
1185 else 812 else
1186 event__process(event, &sample, self); 813 perf_event__process(event, &sample, self);
1187 old += size;
1188 } 814 }
1189
1190 md->prev = old;
1191} 815}
1192 816
1193static struct pollfd *event_array;
1194
1195static void perf_session__mmap_read(struct perf_session *self) 817static void perf_session__mmap_read(struct perf_session *self)
1196{ 818{
1197 struct perf_evsel *counter; 819 int i;
1198 int i, thread_index;
1199
1200 for (i = 0; i < cpus->nr; i++) {
1201 list_for_each_entry(counter, &evsel_list, node) {
1202 for (thread_index = 0;
1203 thread_index < threads->nr;
1204 thread_index++) {
1205 perf_session__mmap_read_counter(self,
1206 counter, i, thread_index);
1207 }
1208 }
1209 }
1210}
1211 820
1212int nr_poll; 821 for (i = 0; i < top.evlist->cpus->nr; i++)
1213int group_fd; 822 perf_session__mmap_read_cpu(self, i);
823}
1214 824
1215static void start_counter(int i, struct perf_evsel *evsel) 825static void start_counters(struct perf_evlist *evlist)
1216{ 826{
1217 struct xyarray *mmap_array = evsel->priv; 827 struct perf_evsel *counter;
1218 struct mmap_data *mm;
1219 struct perf_event_attr *attr;
1220 int cpu = -1;
1221 int thread_index;
1222
1223 if (target_tid == -1)
1224 cpu = cpus->map[i];
1225 828
1226 attr = &evsel->attr; 829 list_for_each_entry(counter, &evlist->entries, node) {
830 struct perf_event_attr *attr = &counter->attr;
1227 831
1228 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 832 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1229 833
1230 if (freq) { 834 if (top.freq) {
1231 attr->sample_type |= PERF_SAMPLE_PERIOD; 835 attr->sample_type |= PERF_SAMPLE_PERIOD;
1232 attr->freq = 1; 836 attr->freq = 1;
1233 attr->sample_freq = freq; 837 attr->sample_freq = top.freq;
1234 } 838 }
1235 839
1236 attr->inherit = (cpu < 0) && inherit; 840 if (evlist->nr_entries > 1) {
1237 attr->mmap = 1; 841 attr->sample_type |= PERF_SAMPLE_ID;
842 attr->read_format |= PERF_FORMAT_ID;
843 }
1238 844
1239 for (thread_index = 0; thread_index < threads->nr; thread_index++) { 845 attr->mmap = 1;
1240try_again: 846try_again:
1241 FD(evsel, i, thread_index) = sys_perf_event_open(attr, 847 if (perf_evsel__open(counter, top.evlist->cpus,
1242 threads->map[thread_index], cpu, group_fd, 0); 848 top.evlist->threads, group, inherit) < 0) {
1243
1244 if (FD(evsel, i, thread_index) < 0) {
1245 int err = errno; 849 int err = errno;
1246 850
1247 if (err == EPERM || err == EACCES) 851 if (err == EPERM || err == EACCES)
@@ -1253,8 +857,8 @@ try_again:
1253 * based cpu-clock-tick sw counter, which 857 * based cpu-clock-tick sw counter, which
1254 * is always available even if no PMU support: 858 * is always available even if no PMU support:
1255 */ 859 */
1256 if (attr->type == PERF_TYPE_HARDWARE 860 if (attr->type == PERF_TYPE_HARDWARE &&
1257 && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 861 attr->config == PERF_COUNT_HW_CPU_CYCLES) {
1258 862
1259 if (verbose) 863 if (verbose)
1260 warning(" ... trying to fall back to cpu-clock-ticks\n"); 864 warning(" ... trying to fall back to cpu-clock-ticks\n");
@@ -1264,39 +868,22 @@ try_again:
1264 goto try_again; 868 goto try_again;
1265 } 869 }
1266 printf("\n"); 870 printf("\n");
1267 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 871 error("sys_perf_event_open() syscall returned with %d "
1268 FD(evsel, i, thread_index), strerror(err)); 872 "(%s). /bin/dmesg may provide additional information.\n",
873 err, strerror(err));
1269 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 874 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
1270 exit(-1); 875 exit(-1);
1271 } 876 }
1272 assert(FD(evsel, i, thread_index) >= 0);
1273 fcntl(FD(evsel, i, thread_index), F_SETFL, O_NONBLOCK);
1274
1275 /*
1276 * First counter acts as the group leader:
1277 */
1278 if (group && group_fd == -1)
1279 group_fd = FD(evsel, i, thread_index);
1280
1281 event_array[nr_poll].fd = FD(evsel, i, thread_index);
1282 event_array[nr_poll].events = POLLIN;
1283 nr_poll++;
1284
1285 mm = xyarray__entry(mmap_array, i, thread_index);
1286 mm->prev = 0;
1287 mm->mask = mmap_pages*page_size - 1;
1288 mm->base = mmap(NULL, (mmap_pages+1)*page_size,
1289 PROT_READ, MAP_SHARED, FD(evsel, i, thread_index), 0);
1290 if (mm->base == MAP_FAILED)
1291 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
1292 } 877 }
878
879 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
880 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
1293} 881}
1294 882
1295static int __cmd_top(void) 883static int __cmd_top(void)
1296{ 884{
1297 pthread_t thread; 885 pthread_t thread;
1298 struct perf_evsel *counter; 886 int ret __used;
1299 int i, ret;
1300 /* 887 /*
1301 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 888 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
1302 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 889 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
@@ -1305,23 +892,23 @@ static int __cmd_top(void)
1305 if (session == NULL) 892 if (session == NULL)
1306 return -ENOMEM; 893 return -ENOMEM;
1307 894
1308 if (target_tid != -1) 895 if (top.target_tid != -1)
1309 event__synthesize_thread_map(threads, event__process, session); 896 perf_event__synthesize_thread_map(top.evlist->threads,
897 perf_event__process, session);
1310 else 898 else
1311 event__synthesize_threads(event__process, session); 899 perf_event__synthesize_threads(perf_event__process, session);
1312 900
1313 for (i = 0; i < cpus->nr; i++) { 901 start_counters(top.evlist);
1314 group_fd = -1; 902 session->evlist = top.evlist;
1315 list_for_each_entry(counter, &evsel_list, node) 903 perf_session__update_sample_type(session);
1316 start_counter(i, counter);
1317 }
1318 904
1319 /* Wait for a minimal set of events before starting the snapshot */ 905 /* Wait for a minimal set of events before starting the snapshot */
1320 poll(&event_array[0], nr_poll, 100); 906 poll(top.evlist->pollfd, top.evlist->nr_fds, 100);
1321 907
1322 perf_session__mmap_read(session); 908 perf_session__mmap_read(session);
1323 909
1324 if (pthread_create(&thread, NULL, display_thread, session)) { 910 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
911 display_thread), session)) {
1325 printf("Could not create display thread.\n"); 912 printf("Could not create display thread.\n");
1326 exit(-1); 913 exit(-1);
1327 } 914 }
@@ -1337,12 +924,12 @@ static int __cmd_top(void)
1337 } 924 }
1338 925
1339 while (1) { 926 while (1) {
1340 int hits = samples; 927 u64 hits = top.samples;
1341 928
1342 perf_session__mmap_read(session); 929 perf_session__mmap_read(session);
1343 930
1344 if (hits == samples) 931 if (hits == top.samples)
1345 ret = poll(event_array, nr_poll, 100); 932 ret = poll(top.evlist->pollfd, top.evlist->nr_fds, 100);
1346 } 933 }
1347 934
1348 return 0; 935 return 0;
@@ -1354,31 +941,31 @@ static const char * const top_usage[] = {
1354}; 941};
1355 942
1356static const struct option options[] = { 943static const struct option options[] = {
1357 OPT_CALLBACK('e', "event", NULL, "event", 944 OPT_CALLBACK('e', "event", &top.evlist, "event",
1358 "event selector. use 'perf list' to list available events", 945 "event selector. use 'perf list' to list available events",
1359 parse_events), 946 parse_events),
1360 OPT_INTEGER('c', "count", &default_interval, 947 OPT_INTEGER('c', "count", &default_interval,
1361 "event period to sample"), 948 "event period to sample"),
1362 OPT_INTEGER('p', "pid", &target_pid, 949 OPT_INTEGER('p', "pid", &top.target_pid,
1363 "profile events on existing process id"), 950 "profile events on existing process id"),
1364 OPT_INTEGER('t', "tid", &target_tid, 951 OPT_INTEGER('t', "tid", &top.target_tid,
1365 "profile events on existing thread id"), 952 "profile events on existing thread id"),
1366 OPT_BOOLEAN('a', "all-cpus", &system_wide, 953 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1367 "system-wide collection from all CPUs"), 954 "system-wide collection from all CPUs"),
1368 OPT_STRING('C', "cpu", &cpu_list, "cpu", 955 OPT_STRING('C', "cpu", &top.cpu_list, "cpu",
1369 "list of cpus to monitor"), 956 "list of cpus to monitor"),
1370 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 957 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1371 "file", "vmlinux pathname"), 958 "file", "vmlinux pathname"),
1372 OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols, 959 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
1373 "hide kernel symbols"), 960 "hide kernel symbols"),
1374 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 961 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
1375 OPT_INTEGER('r', "realtime", &realtime_prio, 962 OPT_INTEGER('r', "realtime", &realtime_prio,
1376 "collect data with this RT SCHED_FIFO priority"), 963 "collect data with this RT SCHED_FIFO priority"),
1377 OPT_INTEGER('d', "delay", &delay_secs, 964 OPT_INTEGER('d', "delay", &top.delay_secs,
1378 "number of seconds to delay between refreshes"), 965 "number of seconds to delay between refreshes"),
1379 OPT_BOOLEAN('D', "dump-symtab", &dump_symtab, 966 OPT_BOOLEAN('D', "dump-symtab", &dump_symtab,
1380 "dump the symbol table used for profiling"), 967 "dump the symbol table used for profiling"),
1381 OPT_INTEGER('f', "count-filter", &count_filter, 968 OPT_INTEGER('f', "count-filter", &top.count_filter,
1382 "only display functions with more events than this"), 969 "only display functions with more events than this"),
1383 OPT_BOOLEAN('g', "group", &group, 970 OPT_BOOLEAN('g', "group", &group,
1384 "put the counters into a counter group"), 971 "put the counters into a counter group"),
@@ -1386,14 +973,16 @@ static const struct option options[] = {
1386 "child tasks inherit counters"), 973 "child tasks inherit counters"),
1387 OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name", 974 OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name",
1388 "symbol to annotate"), 975 "symbol to annotate"),
1389 OPT_BOOLEAN('z', "zero", &zero, 976 OPT_BOOLEAN('z', "zero", &top.zero,
1390 "zero history across updates"), 977 "zero history across updates"),
1391 OPT_INTEGER('F', "freq", &freq, 978 OPT_INTEGER('F', "freq", &top.freq,
1392 "profile at this frequency"), 979 "profile at this frequency"),
1393 OPT_INTEGER('E', "entries", &print_entries, 980 OPT_INTEGER('E', "entries", &top.print_entries,
1394 "display this many functions"), 981 "display this many functions"),
1395 OPT_BOOLEAN('U', "hide_user_symbols", &hide_user_symbols, 982 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
1396 "hide user symbols"), 983 "hide user symbols"),
984 OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"),
985 OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"),
1397 OPT_INCR('v', "verbose", &verbose, 986 OPT_INCR('v', "verbose", &verbose,
1398 "be more verbose (show counter open errors, etc)"), 987 "be more verbose (show counter open errors, etc)"),
1399 OPT_END() 988 OPT_END()
@@ -1404,64 +993,68 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1404 struct perf_evsel *pos; 993 struct perf_evsel *pos;
1405 int status = -ENOMEM; 994 int status = -ENOMEM;
1406 995
996 top.evlist = perf_evlist__new(NULL, NULL);
997 if (top.evlist == NULL)
998 return -ENOMEM;
999
1407 page_size = sysconf(_SC_PAGE_SIZE); 1000 page_size = sysconf(_SC_PAGE_SIZE);
1408 1001
1409 argc = parse_options(argc, argv, options, top_usage, 0); 1002 argc = parse_options(argc, argv, options, top_usage, 0);
1410 if (argc) 1003 if (argc)
1411 usage_with_options(top_usage, options); 1004 usage_with_options(top_usage, options);
1412 1005
1413 if (target_pid != -1) 1006 /*
1414 target_tid = target_pid; 1007 * XXX For now start disabled, only using TUI if explicitely asked for.
1008 * Change that when handle_keys equivalent gets written, live annotation
1009 * done, etc.
1010 */
1011 use_browser = 0;
1415 1012
1416 threads = thread_map__new(target_pid, target_tid); 1013 if (use_stdio)
1417 if (threads == NULL) { 1014 use_browser = 0;
1418 pr_err("Problems finding threads of monitor\n"); 1015 else if (use_tui)
1419 usage_with_options(top_usage, options); 1016 use_browser = 1;
1420 }
1421 1017
1422 event_array = malloc((sizeof(struct pollfd) * 1018 setup_browser(false);
1423 MAX_NR_CPUS * MAX_COUNTERS * threads->nr));
1424 if (!event_array)
1425 return -ENOMEM;
1426 1019
1427 /* CPU and PID are mutually exclusive */ 1020 /* CPU and PID are mutually exclusive */
1428 if (target_tid > 0 && cpu_list) { 1021 if (top.target_tid > 0 && top.cpu_list) {
1429 printf("WARNING: PID switch overriding CPU\n"); 1022 printf("WARNING: PID switch overriding CPU\n");
1430 sleep(1); 1023 sleep(1);
1431 cpu_list = NULL; 1024 top.cpu_list = NULL;
1432 } 1025 }
1433 1026
1434 if (!nr_counters && perf_evsel_list__create_default() < 0) { 1027 if (top.target_pid != -1)
1028 top.target_tid = top.target_pid;
1029
1030 if (perf_evlist__create_maps(top.evlist, top.target_pid,
1031 top.target_tid, top.cpu_list) < 0)
1032 usage_with_options(top_usage, options);
1033
1034 if (!top.evlist->nr_entries &&
1035 perf_evlist__add_default(top.evlist) < 0) {
1435 pr_err("Not enough memory for event selector list\n"); 1036 pr_err("Not enough memory for event selector list\n");
1436 return -ENOMEM; 1037 return -ENOMEM;
1437 } 1038 }
1438 1039
1439 if (delay_secs < 1) 1040 if (top.delay_secs < 1)
1440 delay_secs = 1; 1041 top.delay_secs = 1;
1441 1042
1442 /* 1043 /*
1443 * User specified count overrides default frequency. 1044 * User specified count overrides default frequency.
1444 */ 1045 */
1445 if (default_interval) 1046 if (default_interval)
1446 freq = 0; 1047 top.freq = 0;
1447 else if (freq) { 1048 else if (top.freq) {
1448 default_interval = freq; 1049 default_interval = top.freq;
1449 } else { 1050 } else {
1450 fprintf(stderr, "frequency and count are zero, aborting\n"); 1051 fprintf(stderr, "frequency and count are zero, aborting\n");
1451 exit(EXIT_FAILURE); 1052 exit(EXIT_FAILURE);
1452 } 1053 }
1453 1054
1454 if (target_tid != -1) 1055 list_for_each_entry(pos, &top.evlist->entries, node) {
1455 cpus = cpu_map__dummy_new(); 1056 if (perf_evsel__alloc_fd(pos, top.evlist->cpus->nr,
1456 else 1057 top.evlist->threads->nr) < 0)
1457 cpus = cpu_map__new(cpu_list);
1458
1459 if (cpus == NULL)
1460 usage_with_options(top_usage, options);
1461
1462 list_for_each_entry(pos, &evsel_list, node) {
1463 if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 ||
1464 perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
1465 goto out_free_fd; 1058 goto out_free_fd;
1466 /* 1059 /*
1467 * Fill in the ones not specifically initialized via -c: 1060 * Fill in the ones not specifically initialized via -c:
@@ -1472,26 +1065,28 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1472 pos->attr.sample_period = default_interval; 1065 pos->attr.sample_period = default_interval;
1473 } 1066 }
1474 1067
1475 sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node); 1068 if (perf_evlist__alloc_pollfd(top.evlist) < 0 ||
1069 perf_evlist__alloc_mmap(top.evlist) < 0)
1070 goto out_free_fd;
1071
1072 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
1476 1073
1477 symbol_conf.priv_size = (sizeof(struct sym_entry) + 1074 symbol_conf.priv_size = (sizeof(struct sym_entry) + sizeof(struct annotation) +
1478 (nr_counters + 1) * sizeof(unsigned long)); 1075 (top.evlist->nr_entries + 1) * sizeof(unsigned long));
1479 1076
1480 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1077 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1481 if (symbol__init() < 0) 1078 if (symbol__init() < 0)
1482 return -1; 1079 return -1;
1483 1080
1484 get_term_dimensions(&winsize); 1081 get_term_dimensions(&winsize);
1485 if (print_entries == 0) { 1082 if (top.print_entries == 0) {
1486 update_print_entries(&winsize); 1083 update_print_entries(&winsize);
1487 signal(SIGWINCH, sig_winch_handler); 1084 signal(SIGWINCH, sig_winch_handler);
1488 } 1085 }
1489 1086
1490 status = __cmd_top(); 1087 status = __cmd_top();
1491out_free_fd: 1088out_free_fd:
1492 list_for_each_entry(pos, &evsel_list, node) 1089 perf_evlist__delete(top.evlist);
1493 perf_evsel__free_mmap(pos);
1494 perf_evsel_list__delete();
1495 1090
1496 return status; 1091 return status;
1497} 1092}
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 95aaf565c704..a5fc660c1f12 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -94,6 +94,32 @@ void get_term_dimensions(struct winsize *ws);
94#include "util/types.h" 94#include "util/types.h"
95#include <stdbool.h> 95#include <stdbool.h>
96 96
97struct perf_mmap {
98 void *base;
99 int mask;
100 unsigned int prev;
101};
102
103static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm)
104{
105 struct perf_event_mmap_page *pc = mm->base;
106 int head = pc->data_head;
107 rmb();
108 return head;
109}
110
111static inline void perf_mmap__write_tail(struct perf_mmap *md,
112 unsigned long tail)
113{
114 struct perf_event_mmap_page *pc = md->base;
115
116 /*
117 * ensure all reads are done before we write the tail out.
118 */
119 /* mb(); */
120 pc->data_tail = tail;
121}
122
97/* 123/*
98 * prctl(PR_TASK_PERF_EVENTS_DISABLE) will (cheaply) disable all 124 * prctl(PR_TASK_PERF_EVENTS_DISABLE) will (cheaply) disable all
99 * counters in the current task. 125 * counters in the current task.
diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py
new file mode 100755
index 000000000000..df638c438a9f
--- /dev/null
+++ b/tools/perf/python/twatch.py
@@ -0,0 +1,41 @@
1#! /usr/bin/python
2# -*- python -*-
3# -*- coding: utf-8 -*-
4# twatch - Experimental use of the perf python interface
5# Copyright (C) 2011 Arnaldo Carvalho de Melo <acme@redhat.com>
6#
7# This application is free software; you can redistribute it and/or
8# modify it under the terms of the GNU General Public License
9# as published by the Free Software Foundation; version 2.
10#
11# This application is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14# General Public License for more details.
15
16import perf
17
18def main():
19 cpus = perf.cpu_map()
20 threads = perf.thread_map()
21 evsel = perf.evsel(task = 1, comm = 1, mmap = 0,
22 wakeup_events = 1, sample_period = 1,
23 sample_id_all = 1,
24 sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU | perf.SAMPLE_TID)
25 evsel.open(cpus = cpus, threads = threads);
26 evlist = perf.evlist(cpus, threads)
27 evlist.add(evsel)
28 evlist.mmap()
29 while True:
30 evlist.poll(timeout = -1)
31 for cpu in cpus:
32 event = evlist.read_on_cpu(cpu)
33 if not event:
34 continue
35 print "cpu: %2d, pid: %4d, tid: %4d" % (event.sample_cpu,
36 event.sample_pid,
37 event.sample_tid),
38 print event
39
40if __name__ == '__main__':
41 main()
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
new file mode 100644
index 000000000000..0d0830c98cd7
--- /dev/null
+++ b/tools/perf/util/annotate.c
@@ -0,0 +1,605 @@
1/*
2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Parts came from builtin-annotate.c, see those files for further
5 * copyright notes.
6 *
7 * Released under the GPL v2. (and only v2, not any later version)
8 */
9
10#include "util.h"
11#include "build-id.h"
12#include "color.h"
13#include "cache.h"
14#include "symbol.h"
15#include "debug.h"
16#include "annotate.h"
17#include <pthread.h>
18
19int symbol__annotate_init(struct map *map __used, struct symbol *sym)
20{
21 struct annotation *notes = symbol__annotation(sym);
22 pthread_mutex_init(&notes->lock, NULL);
23 return 0;
24}
25
26int symbol__alloc_hist(struct symbol *sym, int nevents)
27{
28 struct annotation *notes = symbol__annotation(sym);
29 size_t sizeof_sym_hist = (sizeof(struct sym_hist) +
30 (sym->end - sym->start) * sizeof(u64));
31
32 notes->src = zalloc(sizeof(*notes->src) + nevents * sizeof_sym_hist);
33 if (notes->src == NULL)
34 return -1;
35 notes->src->sizeof_sym_hist = sizeof_sym_hist;
36 notes->src->nr_histograms = nevents;
37 INIT_LIST_HEAD(&notes->src->source);
38 return 0;
39}
40
41void symbol__annotate_zero_histograms(struct symbol *sym)
42{
43 struct annotation *notes = symbol__annotation(sym);
44
45 pthread_mutex_lock(&notes->lock);
46 if (notes->src != NULL)
47 memset(notes->src->histograms, 0,
48 notes->src->nr_histograms * notes->src->sizeof_sym_hist);
49 pthread_mutex_unlock(&notes->lock);
50}
51
52int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
53 int evidx, u64 addr)
54{
55 unsigned offset;
56 struct annotation *notes;
57 struct sym_hist *h;
58
59 notes = symbol__annotation(sym);
60 if (notes->src == NULL)
61 return -ENOMEM;
62
63 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
64
65 if (addr >= sym->end)
66 return 0;
67
68 offset = addr - sym->start;
69 h = annotation__histogram(notes, evidx);
70 h->sum++;
71 h->addr[offset]++;
72
73 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
74 ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name,
75 addr, addr - sym->start, evidx, h->addr[offset]);
76 return 0;
77}
78
79static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize)
80{
81 struct objdump_line *self = malloc(sizeof(*self) + privsize);
82
83 if (self != NULL) {
84 self->offset = offset;
85 self->line = line;
86 }
87
88 return self;
89}
90
91void objdump_line__free(struct objdump_line *self)
92{
93 free(self->line);
94 free(self);
95}
96
97static void objdump__add_line(struct list_head *head, struct objdump_line *line)
98{
99 list_add_tail(&line->node, head);
100}
101
102struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
103 struct objdump_line *pos)
104{
105 list_for_each_entry_continue(pos, head, node)
106 if (pos->offset >= 0)
107 return pos;
108
109 return NULL;
110}
111
112static int objdump_line__print(struct objdump_line *oline, struct symbol *sym,
113 int evidx, u64 len, int min_pcnt,
114 int printed, int max_lines,
115 struct objdump_line *queue)
116{
117 static const char *prev_line;
118 static const char *prev_color;
119
120 if (oline->offset != -1) {
121 const char *path = NULL;
122 unsigned int hits = 0;
123 double percent = 0.0;
124 const char *color;
125 struct annotation *notes = symbol__annotation(sym);
126 struct source_line *src_line = notes->src->lines;
127 struct sym_hist *h = annotation__histogram(notes, evidx);
128 s64 offset = oline->offset;
129 struct objdump_line *next;
130
131 next = objdump__get_next_ip_line(&notes->src->source, oline);
132
133 while (offset < (s64)len &&
134 (next == NULL || offset < next->offset)) {
135 if (src_line) {
136 if (path == NULL)
137 path = src_line[offset].path;
138 percent += src_line[offset].percent;
139 } else
140 hits += h->addr[offset];
141
142 ++offset;
143 }
144
145 if (src_line == NULL && h->sum)
146 percent = 100.0 * hits / h->sum;
147
148 if (percent < min_pcnt)
149 return -1;
150
151 if (max_lines && printed >= max_lines)
152 return 1;
153
154 if (queue != NULL) {
155 list_for_each_entry_from(queue, &notes->src->source, node) {
156 if (queue == oline)
157 break;
158 objdump_line__print(queue, sym, evidx, len,
159 0, 0, 1, NULL);
160 }
161 }
162
163 color = get_percent_color(percent);
164
165 /*
166 * Also color the filename and line if needed, with
167 * the same color than the percentage. Don't print it
168 * twice for close colored addr with the same filename:line
169 */
170 if (path) {
171 if (!prev_line || strcmp(prev_line, path)
172 || color != prev_color) {
173 color_fprintf(stdout, color, " %s", path);
174 prev_line = path;
175 prev_color = color;
176 }
177 }
178
179 color_fprintf(stdout, color, " %7.2f", percent);
180 printf(" : ");
181 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", oline->line);
182 } else if (max_lines && printed >= max_lines)
183 return 1;
184 else {
185 if (queue)
186 return -1;
187
188 if (!*oline->line)
189 printf(" :\n");
190 else
191 printf(" : %s\n", oline->line);
192 }
193
194 return 0;
195}
196
197static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
198 FILE *file, size_t privsize)
199{
200 struct annotation *notes = symbol__annotation(sym);
201 struct objdump_line *objdump_line;
202 char *line = NULL, *tmp, *tmp2, *c;
203 size_t line_len;
204 s64 line_ip, offset = -1;
205
206 if (getline(&line, &line_len, file) < 0)
207 return -1;
208
209 if (!line)
210 return -1;
211
212 while (line_len != 0 && isspace(line[line_len - 1]))
213 line[--line_len] = '\0';
214
215 c = strchr(line, '\n');
216 if (c)
217 *c = 0;
218
219 line_ip = -1;
220
221 /*
222 * Strip leading spaces:
223 */
224 tmp = line;
225 while (*tmp) {
226 if (*tmp != ' ')
227 break;
228 tmp++;
229 }
230
231 if (*tmp) {
232 /*
233 * Parse hexa addresses followed by ':'
234 */
235 line_ip = strtoull(tmp, &tmp2, 16);
236 if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0')
237 line_ip = -1;
238 }
239
240 if (line_ip != -1) {
241 u64 start = map__rip_2objdump(map, sym->start),
242 end = map__rip_2objdump(map, sym->end);
243
244 offset = line_ip - start;
245 if (offset < 0 || (u64)line_ip > end)
246 offset = -1;
247 }
248
249 objdump_line = objdump_line__new(offset, line, privsize);
250 if (objdump_line == NULL) {
251 free(line);
252 return -1;
253 }
254 objdump__add_line(&notes->src->source, objdump_line);
255
256 return 0;
257}
258
259int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
260{
261 struct dso *dso = map->dso;
262 char *filename = dso__build_id_filename(dso, NULL, 0);
263 bool free_filename = true;
264 char command[PATH_MAX * 2];
265 FILE *file;
266 int err = 0;
267 char symfs_filename[PATH_MAX];
268
269 if (filename) {
270 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
271 symbol_conf.symfs, filename);
272 }
273
274 if (filename == NULL) {
275 if (dso->has_build_id) {
276 pr_err("Can't annotate %s: not enough memory\n",
277 sym->name);
278 return -ENOMEM;
279 }
280 goto fallback;
281 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
282 strstr(command, "[kernel.kallsyms]") ||
283 access(symfs_filename, R_OK)) {
284 free(filename);
285fallback:
286 /*
287 * If we don't have build-ids or the build-id file isn't in the
288 * cache, or is just a kallsyms file, well, lets hope that this
289 * DSO is the same as when 'perf record' ran.
290 */
291 filename = dso->long_name;
292 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
293 symbol_conf.symfs, filename);
294 free_filename = false;
295 }
296
297 if (dso->origin == DSO__ORIG_KERNEL) {
298 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";
299 char *build_id_msg = NULL;
300
301 if (dso->annotate_warned)
302 goto out_free_filename;
303
304 if (dso->has_build_id) {
305 build_id__sprintf(dso->build_id,
306 sizeof(dso->build_id), bf + 15);
307 build_id_msg = bf;
308 }
309 err = -ENOENT;
310 dso->annotate_warned = 1;
311 pr_err("Can't annotate %s: No vmlinux file%s was found in the "
312 "path.\nPlease use 'perf buildid-cache -av vmlinux' or "
313 "--vmlinux vmlinux.\n",
314 sym->name, build_id_msg ?: "");
315 goto out_free_filename;
316 }
317
318 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
319 filename, sym->name, map->unmap_ip(map, sym->start),
320 map->unmap_ip(map, sym->end));
321
322 pr_debug("annotating [%p] %30s : [%p] %30s\n",
323 dso, dso->long_name, sym, sym->name);
324
325 snprintf(command, sizeof(command),
326 "objdump --start-address=0x%016" PRIx64
327 " --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand",
328 map__rip_2objdump(map, sym->start),
329 map__rip_2objdump(map, sym->end),
330 symfs_filename, filename);
331
332 pr_debug("Executing: %s\n", command);
333
334 file = popen(command, "r");
335 if (!file)
336 goto out_free_filename;
337
338 while (!feof(file))
339 if (symbol__parse_objdump_line(sym, map, file, privsize) < 0)
340 break;
341
342 pclose(file);
343out_free_filename:
344 if (free_filename)
345 free(filename);
346 return err;
347}
348
349static void insert_source_line(struct rb_root *root, struct source_line *src_line)
350{
351 struct source_line *iter;
352 struct rb_node **p = &root->rb_node;
353 struct rb_node *parent = NULL;
354
355 while (*p != NULL) {
356 parent = *p;
357 iter = rb_entry(parent, struct source_line, node);
358
359 if (src_line->percent > iter->percent)
360 p = &(*p)->rb_left;
361 else
362 p = &(*p)->rb_right;
363 }
364
365 rb_link_node(&src_line->node, parent, p);
366 rb_insert_color(&src_line->node, root);
367}
368
369static void symbol__free_source_line(struct symbol *sym, int len)
370{
371 struct annotation *notes = symbol__annotation(sym);
372 struct source_line *src_line = notes->src->lines;
373 int i;
374
375 for (i = 0; i < len; i++)
376 free(src_line[i].path);
377
378 free(src_line);
379 notes->src->lines = NULL;
380}
381
382/* Get the filename:line for the colored entries */
383static int symbol__get_source_line(struct symbol *sym, struct map *map,
384 int evidx, struct rb_root *root, int len,
385 const char *filename)
386{
387 u64 start;
388 int i;
389 char cmd[PATH_MAX * 2];
390 struct source_line *src_line;
391 struct annotation *notes = symbol__annotation(sym);
392 struct sym_hist *h = annotation__histogram(notes, evidx);
393
394 if (!h->sum)
395 return 0;
396
397 src_line = notes->src->lines = calloc(len, sizeof(struct source_line));
398 if (!notes->src->lines)
399 return -1;
400
401 start = map->unmap_ip(map, sym->start);
402
403 for (i = 0; i < len; i++) {
404 char *path = NULL;
405 size_t line_len;
406 u64 offset;
407 FILE *fp;
408
409 src_line[i].percent = 100.0 * h->addr[i] / h->sum;
410 if (src_line[i].percent <= 0.5)
411 continue;
412
413 offset = start + i;
414 sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
415 fp = popen(cmd, "r");
416 if (!fp)
417 continue;
418
419 if (getline(&path, &line_len, fp) < 0 || !line_len)
420 goto next;
421
422 src_line[i].path = malloc(sizeof(char) * line_len + 1);
423 if (!src_line[i].path)
424 goto next;
425
426 strcpy(src_line[i].path, path);
427 insert_source_line(root, &src_line[i]);
428
429 next:
430 pclose(fp);
431 }
432
433 return 0;
434}
435
436static void print_summary(struct rb_root *root, const char *filename)
437{
438 struct source_line *src_line;
439 struct rb_node *node;
440
441 printf("\nSorted summary for file %s\n", filename);
442 printf("----------------------------------------------\n\n");
443
444 if (RB_EMPTY_ROOT(root)) {
445 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
446 return;
447 }
448
449 node = rb_first(root);
450 while (node) {
451 double percent;
452 const char *color;
453 char *path;
454
455 src_line = rb_entry(node, struct source_line, node);
456 percent = src_line->percent;
457 color = get_percent_color(percent);
458 path = src_line->path;
459
460 color_fprintf(stdout, color, " %7.2f %s", percent, path);
461 node = rb_next(node);
462 }
463}
464
465static void symbol__annotate_hits(struct symbol *sym, int evidx)
466{
467 struct annotation *notes = symbol__annotation(sym);
468 struct sym_hist *h = annotation__histogram(notes, evidx);
469 u64 len = sym->end - sym->start, offset;
470
471 for (offset = 0; offset < len; ++offset)
472 if (h->addr[offset] != 0)
473 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
474 sym->start + offset, h->addr[offset]);
475 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
476}
477
478int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
479 bool full_paths, int min_pcnt, int max_lines,
480 int context)
481{
482 struct dso *dso = map->dso;
483 const char *filename = dso->long_name, *d_filename;
484 struct annotation *notes = symbol__annotation(sym);
485 struct objdump_line *pos, *queue = NULL;
486 int printed = 2, queue_len = 0;
487 int more = 0;
488 u64 len;
489
490 if (full_paths)
491 d_filename = filename;
492 else
493 d_filename = basename(filename);
494
495 len = sym->end - sym->start;
496
497 printf(" Percent | Source code & Disassembly of %s\n", d_filename);
498 printf("------------------------------------------------\n");
499
500 if (verbose)
501 symbol__annotate_hits(sym, evidx);
502
503 list_for_each_entry(pos, &notes->src->source, node) {
504 if (context && queue == NULL) {
505 queue = pos;
506 queue_len = 0;
507 }
508
509 switch (objdump_line__print(pos, sym, evidx, len, min_pcnt,
510 printed, max_lines, queue)) {
511 case 0:
512 ++printed;
513 if (context) {
514 printed += queue_len;
515 queue = NULL;
516 queue_len = 0;
517 }
518 break;
519 case 1:
520 /* filtered by max_lines */
521 ++more;
522 break;
523 case -1:
524 default:
525 /*
526 * Filtered by min_pcnt or non IP lines when
527 * context != 0
528 */
529 if (!context)
530 break;
531 if (queue_len == context)
532 queue = list_entry(queue->node.next, typeof(*queue), node);
533 else
534 ++queue_len;
535 break;
536 }
537 }
538
539 return more;
540}
541
542void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
543{
544 struct annotation *notes = symbol__annotation(sym);
545 struct sym_hist *h = annotation__histogram(notes, evidx);
546
547 memset(h, 0, notes->src->sizeof_sym_hist);
548}
549
550void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
551{
552 struct annotation *notes = symbol__annotation(sym);
553 struct sym_hist *h = annotation__histogram(notes, evidx);
554 struct objdump_line *pos;
555 int len = sym->end - sym->start;
556
557 h->sum = 0;
558
559 list_for_each_entry(pos, &notes->src->source, node) {
560 if (pos->offset != -1 && pos->offset < len) {
561 h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8;
562 h->sum += h->addr[pos->offset];
563 }
564 }
565}
566
567void objdump_line_list__purge(struct list_head *head)
568{
569 struct objdump_line *pos, *n;
570
571 list_for_each_entry_safe(pos, n, head, node) {
572 list_del(&pos->node);
573 objdump_line__free(pos);
574 }
575}
576
577int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
578 bool print_lines, bool full_paths, int min_pcnt,
579 int max_lines)
580{
581 struct dso *dso = map->dso;
582 const char *filename = dso->long_name;
583 struct rb_root source_line = RB_ROOT;
584 u64 len;
585
586 if (symbol__annotate(sym, map, 0) < 0)
587 return -1;
588
589 len = sym->end - sym->start;
590
591 if (print_lines) {
592 symbol__get_source_line(sym, map, evidx, &source_line,
593 len, filename);
594 print_summary(&source_line, filename);
595 }
596
597 symbol__annotate_printf(sym, map, evidx, full_paths,
598 min_pcnt, max_lines, 0);
599 if (print_lines)
600 symbol__free_source_line(sym, len);
601
602 objdump_line_list__purge(&symbol__annotation(sym)->src->source);
603
604 return 0;
605}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
new file mode 100644
index 000000000000..c2c286896801
--- /dev/null
+++ b/tools/perf/util/annotate.h
@@ -0,0 +1,103 @@
1#ifndef __PERF_ANNOTATE_H
2#define __PERF_ANNOTATE_H
3
4#include <stdbool.h>
5#include "types.h"
6#include "symbol.h"
7#include <linux/list.h>
8#include <linux/rbtree.h>
9
10struct objdump_line {
11 struct list_head node;
12 s64 offset;
13 char *line;
14};
15
16void objdump_line__free(struct objdump_line *self);
17struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
18 struct objdump_line *pos);
19
20struct sym_hist {
21 u64 sum;
22 u64 addr[0];
23};
24
25struct source_line {
26 struct rb_node node;
27 double percent;
28 char *path;
29};
30
31/** struct annotated_source - symbols with hits have this attached as in sannotation
32 *
33 * @histogram: Array of addr hit histograms per event being monitored
34 * @lines: If 'print_lines' is specified, per source code line percentages
35 * @source: source parsed from objdump -dS
36 *
37 * lines is allocated, percentages calculated and all sorted by percentage
38 * when the annotation is about to be presented, so the percentages are for
39 * one of the entries in the histogram array, i.e. for the event/counter being
40 * presented. It is deallocated right after symbol__{tui,tty,etc}_annotate
41 * returns.
42 */
43struct annotated_source {
44 struct list_head source;
45 struct source_line *lines;
46 int nr_histograms;
47 int sizeof_sym_hist;
48 struct sym_hist histograms[0];
49};
50
51struct annotation {
52 pthread_mutex_t lock;
53 struct annotated_source *src;
54};
55
56struct sannotation {
57 struct annotation annotation;
58 struct symbol symbol;
59};
60
61static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
62{
63 return (((void *)&notes->src->histograms) +
64 (notes->src->sizeof_sym_hist * idx));
65}
66
67static inline struct annotation *symbol__annotation(struct symbol *sym)
68{
69 struct sannotation *a = container_of(sym, struct sannotation, symbol);
70 return &a->annotation;
71}
72
73int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
74 int evidx, u64 addr);
75int symbol__alloc_hist(struct symbol *sym, int nevents);
76void symbol__annotate_zero_histograms(struct symbol *sym);
77
78int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
79int symbol__annotate_init(struct map *map __used, struct symbol *sym);
80int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
81 bool full_paths, int min_pcnt, int max_lines,
82 int context);
83void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
84void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
85void objdump_line_list__purge(struct list_head *head);
86
87int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
88 bool print_lines, bool full_paths, int min_pcnt,
89 int max_lines);
90
91#ifdef NO_NEWT_SUPPORT
92static inline int symbol__tui_annotate(struct symbol *sym __used,
93 struct map *map __used,
94 int evidx __used, int refresh __used)
95{
96 return 0;
97}
98#else
99int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
100 int refresh);
101#endif
102
103#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index deffb8c96071..31f934af9861 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -14,8 +14,8 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include "debug.h" 15#include "debug.h"
16 16
17static int build_id__mark_dso_hit(event_t *event, 17static int build_id__mark_dso_hit(union perf_event *event,
18 struct sample_data *sample __used, 18 struct perf_sample *sample __used,
19 struct perf_session *session) 19 struct perf_session *session)
20{ 20{
21 struct addr_location al; 21 struct addr_location al;
@@ -37,13 +37,14 @@ static int build_id__mark_dso_hit(event_t *event,
37 return 0; 37 return 0;
38} 38}
39 39
40static int event__exit_del_thread(event_t *self, struct sample_data *sample __used, 40static int perf_event__exit_del_thread(union perf_event *event,
41 struct perf_session *session) 41 struct perf_sample *sample __used,
42 struct perf_session *session)
42{ 43{
43 struct thread *thread = perf_session__findnew(session, self->fork.tid); 44 struct thread *thread = perf_session__findnew(session, event->fork.tid);
44 45
45 dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid, 46 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
46 self->fork.ppid, self->fork.ptid); 47 event->fork.ppid, event->fork.ptid);
47 48
48 if (thread) { 49 if (thread) {
49 rb_erase(&thread->rb_node, &session->threads); 50 rb_erase(&thread->rb_node, &session->threads);
@@ -56,9 +57,9 @@ static int event__exit_del_thread(event_t *self, struct sample_data *sample __us
56 57
57struct perf_event_ops build_id__mark_dso_hit_ops = { 58struct perf_event_ops build_id__mark_dso_hit_ops = {
58 .sample = build_id__mark_dso_hit, 59 .sample = build_id__mark_dso_hit,
59 .mmap = event__process_mmap, 60 .mmap = perf_event__process_mmap,
60 .fork = event__process_task, 61 .fork = perf_event__process_task,
61 .exit = event__exit_del_thread, 62 .exit = perf_event__exit_del_thread,
62}; 63};
63 64
64char *dso__build_id_filename(struct dso *self, char *bf, size_t size) 65char *dso__build_id_filename(struct dso *self, char *bf, size_t size)
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index a7729797fd96..fc5e5a09d5b9 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -34,13 +34,14 @@ extern int pager_use_color;
34extern int use_browser; 34extern int use_browser;
35 35
36#ifdef NO_NEWT_SUPPORT 36#ifdef NO_NEWT_SUPPORT
37static inline void setup_browser(void) 37static inline void setup_browser(bool fallback_to_pager)
38{ 38{
39 setup_pager(); 39 if (fallback_to_pager)
40 setup_pager();
40} 41}
41static inline void exit_browser(bool wait_for_ok __used) {} 42static inline void exit_browser(bool wait_for_ok __used) {}
42#else 43#else
43void setup_browser(void); 44void setup_browser(bool fallback_to_pager);
44void exit_browser(bool wait_for_ok); 45void exit_browser(bool wait_for_ok);
45#endif 46#endif
46 47
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index e12d539417b2..9f7106a8d9a4 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2009-2010, Frederic Weisbecker <fweisbec@gmail.com> 2 * Copyright (C) 2009-2011, Frederic Weisbecker <fweisbec@gmail.com>
3 * 3 *
4 * Handle the callchains from the stream in an ad-hoc radix tree and then 4 * Handle the callchains from the stream in an ad-hoc radix tree and then
5 * sort them in an rbtree. 5 * sort them in an rbtree.
@@ -18,7 +18,8 @@
18#include "util.h" 18#include "util.h"
19#include "callchain.h" 19#include "callchain.h"
20 20
21bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event) 21bool ip_callchain__valid(struct ip_callchain *chain,
22 const union perf_event *event)
22{ 23{
23 unsigned int chain_size = event->header.size; 24 unsigned int chain_size = event->header.size;
24 chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event; 25 chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event;
@@ -26,10 +27,10 @@ bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event)
26} 27}
27 28
28#define chain_for_each_child(child, parent) \ 29#define chain_for_each_child(child, parent) \
29 list_for_each_entry(child, &parent->children, brothers) 30 list_for_each_entry(child, &parent->children, siblings)
30 31
31#define chain_for_each_child_safe(child, next, parent) \ 32#define chain_for_each_child_safe(child, next, parent) \
32 list_for_each_entry_safe(child, next, &parent->children, brothers) 33 list_for_each_entry_safe(child, next, &parent->children, siblings)
33 34
34static void 35static void
35rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, 36rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
@@ -38,14 +39,14 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
38 struct rb_node **p = &root->rb_node; 39 struct rb_node **p = &root->rb_node;
39 struct rb_node *parent = NULL; 40 struct rb_node *parent = NULL;
40 struct callchain_node *rnode; 41 struct callchain_node *rnode;
41 u64 chain_cumul = cumul_hits(chain); 42 u64 chain_cumul = callchain_cumul_hits(chain);
42 43
43 while (*p) { 44 while (*p) {
44 u64 rnode_cumul; 45 u64 rnode_cumul;
45 46
46 parent = *p; 47 parent = *p;
47 rnode = rb_entry(parent, struct callchain_node, rb_node); 48 rnode = rb_entry(parent, struct callchain_node, rb_node);
48 rnode_cumul = cumul_hits(rnode); 49 rnode_cumul = callchain_cumul_hits(rnode);
49 50
50 switch (mode) { 51 switch (mode) {
51 case CHAIN_FLAT: 52 case CHAIN_FLAT:
@@ -104,7 +105,7 @@ static void __sort_chain_graph_abs(struct callchain_node *node,
104 105
105 chain_for_each_child(child, node) { 106 chain_for_each_child(child, node) {
106 __sort_chain_graph_abs(child, min_hit); 107 __sort_chain_graph_abs(child, min_hit);
107 if (cumul_hits(child) >= min_hit) 108 if (callchain_cumul_hits(child) >= min_hit)
108 rb_insert_callchain(&node->rb_root, child, 109 rb_insert_callchain(&node->rb_root, child,
109 CHAIN_GRAPH_ABS); 110 CHAIN_GRAPH_ABS);
110 } 111 }
@@ -129,7 +130,7 @@ static void __sort_chain_graph_rel(struct callchain_node *node,
129 130
130 chain_for_each_child(child, node) { 131 chain_for_each_child(child, node) {
131 __sort_chain_graph_rel(child, min_percent); 132 __sort_chain_graph_rel(child, min_percent);
132 if (cumul_hits(child) >= min_hit) 133 if (callchain_cumul_hits(child) >= min_hit)
133 rb_insert_callchain(&node->rb_root, child, 134 rb_insert_callchain(&node->rb_root, child,
134 CHAIN_GRAPH_REL); 135 CHAIN_GRAPH_REL);
135 } 136 }
@@ -143,7 +144,7 @@ sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
143 rb_root->rb_node = chain_root->node.rb_root.rb_node; 144 rb_root->rb_node = chain_root->node.rb_root.rb_node;
144} 145}
145 146
146int register_callchain_param(struct callchain_param *param) 147int callchain_register_param(struct callchain_param *param)
147{ 148{
148 switch (param->mode) { 149 switch (param->mode) {
149 case CHAIN_GRAPH_ABS: 150 case CHAIN_GRAPH_ABS:
@@ -189,32 +190,27 @@ create_child(struct callchain_node *parent, bool inherit_children)
189 chain_for_each_child(next, new) 190 chain_for_each_child(next, new)
190 next->parent = new; 191 next->parent = new;
191 } 192 }
192 list_add_tail(&new->brothers, &parent->children); 193 list_add_tail(&new->siblings, &parent->children);
193 194
194 return new; 195 return new;
195} 196}
196 197
197 198
198struct resolved_ip {
199 u64 ip;
200 struct map_symbol ms;
201};
202
203struct resolved_chain {
204 u64 nr;
205 struct resolved_ip ips[0];
206};
207
208
209/* 199/*
210 * Fill the node with callchain values 200 * Fill the node with callchain values
211 */ 201 */
212static void 202static void
213fill_node(struct callchain_node *node, struct resolved_chain *chain, int start) 203fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
214{ 204{
215 unsigned int i; 205 struct callchain_cursor_node *cursor_node;
206
207 node->val_nr = cursor->nr - cursor->pos;
208 if (!node->val_nr)
209 pr_warning("Warning: empty node in callchain tree\n");
216 210
217 for (i = start; i < chain->nr; i++) { 211 cursor_node = callchain_cursor_current(cursor);
212
213 while (cursor_node) {
218 struct callchain_list *call; 214 struct callchain_list *call;
219 215
220 call = zalloc(sizeof(*call)); 216 call = zalloc(sizeof(*call));
@@ -222,23 +218,25 @@ fill_node(struct callchain_node *node, struct resolved_chain *chain, int start)
222 perror("not enough memory for the code path tree"); 218 perror("not enough memory for the code path tree");
223 return; 219 return;
224 } 220 }
225 call->ip = chain->ips[i].ip; 221 call->ip = cursor_node->ip;
226 call->ms = chain->ips[i].ms; 222 call->ms.sym = cursor_node->sym;
223 call->ms.map = cursor_node->map;
227 list_add_tail(&call->list, &node->val); 224 list_add_tail(&call->list, &node->val);
225
226 callchain_cursor_advance(cursor);
227 cursor_node = callchain_cursor_current(cursor);
228 } 228 }
229 node->val_nr = chain->nr - start;
230 if (!node->val_nr)
231 pr_warning("Warning: empty node in callchain tree\n");
232} 229}
233 230
234static void 231static void
235add_child(struct callchain_node *parent, struct resolved_chain *chain, 232add_child(struct callchain_node *parent,
236 int start, u64 period) 233 struct callchain_cursor *cursor,
234 u64 period)
237{ 235{
238 struct callchain_node *new; 236 struct callchain_node *new;
239 237
240 new = create_child(parent, false); 238 new = create_child(parent, false);
241 fill_node(new, chain, start); 239 fill_node(new, cursor);
242 240
243 new->children_hit = 0; 241 new->children_hit = 0;
244 new->hit = period; 242 new->hit = period;
@@ -250,9 +248,10 @@ add_child(struct callchain_node *parent, struct resolved_chain *chain,
250 * Then create another child to host the given callchain of new branch 248 * Then create another child to host the given callchain of new branch
251 */ 249 */
252static void 250static void
253split_add_child(struct callchain_node *parent, struct resolved_chain *chain, 251split_add_child(struct callchain_node *parent,
254 struct callchain_list *to_split, int idx_parents, int idx_local, 252 struct callchain_cursor *cursor,
255 u64 period) 253 struct callchain_list *to_split,
254 u64 idx_parents, u64 idx_local, u64 period)
256{ 255{
257 struct callchain_node *new; 256 struct callchain_node *new;
258 struct list_head *old_tail; 257 struct list_head *old_tail;
@@ -272,14 +271,14 @@ split_add_child(struct callchain_node *parent, struct resolved_chain *chain,
272 /* split the hits */ 271 /* split the hits */
273 new->hit = parent->hit; 272 new->hit = parent->hit;
274 new->children_hit = parent->children_hit; 273 new->children_hit = parent->children_hit;
275 parent->children_hit = cumul_hits(new); 274 parent->children_hit = callchain_cumul_hits(new);
276 new->val_nr = parent->val_nr - idx_local; 275 new->val_nr = parent->val_nr - idx_local;
277 parent->val_nr = idx_local; 276 parent->val_nr = idx_local;
278 277
279 /* create a new child for the new branch if any */ 278 /* create a new child for the new branch if any */
280 if (idx_total < chain->nr) { 279 if (idx_total < cursor->nr) {
281 parent->hit = 0; 280 parent->hit = 0;
282 add_child(parent, chain, idx_total, period); 281 add_child(parent, cursor, period);
283 parent->children_hit += period; 282 parent->children_hit += period;
284 } else { 283 } else {
285 parent->hit = period; 284 parent->hit = period;
@@ -287,36 +286,41 @@ split_add_child(struct callchain_node *parent, struct resolved_chain *chain,
287} 286}
288 287
289static int 288static int
290append_chain(struct callchain_node *root, struct resolved_chain *chain, 289append_chain(struct callchain_node *root,
291 unsigned int start, u64 period); 290 struct callchain_cursor *cursor,
291 u64 period);
292 292
293static void 293static void
294append_chain_children(struct callchain_node *root, struct resolved_chain *chain, 294append_chain_children(struct callchain_node *root,
295 unsigned int start, u64 period) 295 struct callchain_cursor *cursor,
296 u64 period)
296{ 297{
297 struct callchain_node *rnode; 298 struct callchain_node *rnode;
298 299
299 /* lookup in childrens */ 300 /* lookup in childrens */
300 chain_for_each_child(rnode, root) { 301 chain_for_each_child(rnode, root) {
301 unsigned int ret = append_chain(rnode, chain, start, period); 302 unsigned int ret = append_chain(rnode, cursor, period);
302 303
303 if (!ret) 304 if (!ret)
304 goto inc_children_hit; 305 goto inc_children_hit;
305 } 306 }
306 /* nothing in children, add to the current node */ 307 /* nothing in children, add to the current node */
307 add_child(root, chain, start, period); 308 add_child(root, cursor, period);
308 309
309inc_children_hit: 310inc_children_hit:
310 root->children_hit += period; 311 root->children_hit += period;
311} 312}
312 313
313static int 314static int
314append_chain(struct callchain_node *root, struct resolved_chain *chain, 315append_chain(struct callchain_node *root,
315 unsigned int start, u64 period) 316 struct callchain_cursor *cursor,
317 u64 period)
316{ 318{
319 struct callchain_cursor_node *curr_snap = cursor->curr;
317 struct callchain_list *cnode; 320 struct callchain_list *cnode;
318 unsigned int i = start; 321 u64 start = cursor->pos;
319 bool found = false; 322 bool found = false;
323 u64 matches;
320 324
321 /* 325 /*
322 * Lookup in the current node 326 * Lookup in the current node
@@ -324,141 +328,134 @@ append_chain(struct callchain_node *root, struct resolved_chain *chain,
324 * anywhere inside a function. 328 * anywhere inside a function.
325 */ 329 */
326 list_for_each_entry(cnode, &root->val, list) { 330 list_for_each_entry(cnode, &root->val, list) {
331 struct callchain_cursor_node *node;
327 struct symbol *sym; 332 struct symbol *sym;
328 333
329 if (i == chain->nr) 334 node = callchain_cursor_current(cursor);
335 if (!node)
330 break; 336 break;
331 337
332 sym = chain->ips[i].ms.sym; 338 sym = node->sym;
333 339
334 if (cnode->ms.sym && sym) { 340 if (cnode->ms.sym && sym) {
335 if (cnode->ms.sym->start != sym->start) 341 if (cnode->ms.sym->start != sym->start)
336 break; 342 break;
337 } else if (cnode->ip != chain->ips[i].ip) 343 } else if (cnode->ip != node->ip)
338 break; 344 break;
339 345
340 if (!found) 346 if (!found)
341 found = true; 347 found = true;
342 i++; 348
349 callchain_cursor_advance(cursor);
343 } 350 }
344 351
345 /* matches not, relay on the parent */ 352 /* matches not, relay on the parent */
346 if (!found) 353 if (!found) {
354 cursor->curr = curr_snap;
355 cursor->pos = start;
347 return -1; 356 return -1;
357 }
358
359 matches = cursor->pos - start;
348 360
349 /* we match only a part of the node. Split it and add the new chain */ 361 /* we match only a part of the node. Split it and add the new chain */
350 if (i - start < root->val_nr) { 362 if (matches < root->val_nr) {
351 split_add_child(root, chain, cnode, start, i - start, period); 363 split_add_child(root, cursor, cnode, start, matches, period);
352 return 0; 364 return 0;
353 } 365 }
354 366
355 /* we match 100% of the path, increment the hit */ 367 /* we match 100% of the path, increment the hit */
356 if (i - start == root->val_nr && i == chain->nr) { 368 if (matches == root->val_nr && cursor->pos == cursor->nr) {
357 root->hit += period; 369 root->hit += period;
358 return 0; 370 return 0;
359 } 371 }
360 372
361 /* We match the node and still have a part remaining */ 373 /* We match the node and still have a part remaining */
362 append_chain_children(root, chain, i, period); 374 append_chain_children(root, cursor, period);
363 375
364 return 0; 376 return 0;
365} 377}
366 378
367static void filter_context(struct ip_callchain *old, struct resolved_chain *new, 379int callchain_append(struct callchain_root *root,
368 struct map_symbol *syms) 380 struct callchain_cursor *cursor,
369{ 381 u64 period)
370 int i, j = 0;
371
372 for (i = 0; i < (int)old->nr; i++) {
373 if (old->ips[i] >= PERF_CONTEXT_MAX)
374 continue;
375
376 new->ips[j].ip = old->ips[i];
377 new->ips[j].ms = syms[i];
378 j++;
379 }
380
381 new->nr = j;
382}
383
384
385int callchain_append(struct callchain_root *root, struct ip_callchain *chain,
386 struct map_symbol *syms, u64 period)
387{ 382{
388 struct resolved_chain *filtered; 383 if (!cursor->nr)
389
390 if (!chain->nr)
391 return 0; 384 return 0;
392 385
393 filtered = zalloc(sizeof(*filtered) + 386 callchain_cursor_commit(cursor);
394 chain->nr * sizeof(struct resolved_ip));
395 if (!filtered)
396 return -ENOMEM;
397
398 filter_context(chain, filtered, syms);
399
400 if (!filtered->nr)
401 goto end;
402 387
403 append_chain_children(&root->node, filtered, 0, period); 388 append_chain_children(&root->node, cursor, period);
404 389
405 if (filtered->nr > root->max_depth) 390 if (cursor->nr > root->max_depth)
406 root->max_depth = filtered->nr; 391 root->max_depth = cursor->nr;
407end:
408 free(filtered);
409 392
410 return 0; 393 return 0;
411} 394}
412 395
413static int 396static int
414merge_chain_branch(struct callchain_node *dst, struct callchain_node *src, 397merge_chain_branch(struct callchain_cursor *cursor,
415 struct resolved_chain *chain) 398 struct callchain_node *dst, struct callchain_node *src)
416{ 399{
400 struct callchain_cursor_node **old_last = cursor->last;
417 struct callchain_node *child, *next_child; 401 struct callchain_node *child, *next_child;
418 struct callchain_list *list, *next_list; 402 struct callchain_list *list, *next_list;
419 int old_pos = chain->nr; 403 int old_pos = cursor->nr;
420 int err = 0; 404 int err = 0;
421 405
422 list_for_each_entry_safe(list, next_list, &src->val, list) { 406 list_for_each_entry_safe(list, next_list, &src->val, list) {
423 chain->ips[chain->nr].ip = list->ip; 407 callchain_cursor_append(cursor, list->ip,
424 chain->ips[chain->nr].ms = list->ms; 408 list->ms.map, list->ms.sym);
425 chain->nr++;
426 list_del(&list->list); 409 list_del(&list->list);
427 free(list); 410 free(list);
428 } 411 }
429 412
430 if (src->hit) 413 if (src->hit) {
431 append_chain_children(dst, chain, 0, src->hit); 414 callchain_cursor_commit(cursor);
415 append_chain_children(dst, cursor, src->hit);
416 }
432 417
433 chain_for_each_child_safe(child, next_child, src) { 418 chain_for_each_child_safe(child, next_child, src) {
434 err = merge_chain_branch(dst, child, chain); 419 err = merge_chain_branch(cursor, dst, child);
435 if (err) 420 if (err)
436 break; 421 break;
437 422
438 list_del(&child->brothers); 423 list_del(&child->siblings);
439 free(child); 424 free(child);
440 } 425 }
441 426
442 chain->nr = old_pos; 427 cursor->nr = old_pos;
428 cursor->last = old_last;
443 429
444 return err; 430 return err;
445} 431}
446 432
447int callchain_merge(struct callchain_root *dst, struct callchain_root *src) 433int callchain_merge(struct callchain_cursor *cursor,
434 struct callchain_root *dst, struct callchain_root *src)
435{
436 return merge_chain_branch(cursor, &dst->node, &src->node);
437}
438
439int callchain_cursor_append(struct callchain_cursor *cursor,
440 u64 ip, struct map *map, struct symbol *sym)
448{ 441{
449 struct resolved_chain *chain; 442 struct callchain_cursor_node *node = *cursor->last;
450 int err;
451 443
452 chain = malloc(sizeof(*chain) + 444 if (!node) {
453 src->max_depth * sizeof(struct resolved_ip)); 445 node = calloc(sizeof(*node), 1);
454 if (!chain) 446 if (!node)
455 return -ENOMEM; 447 return -ENOMEM;
456 448
457 chain->nr = 0; 449 *cursor->last = node;
450 }
458 451
459 err = merge_chain_branch(&dst->node, &src->node, chain); 452 node->ip = ip;
453 node->map = map;
454 node->sym = sym;
460 455
461 free(chain); 456 cursor->nr++;
462 457
463 return err; 458 cursor->last = &node->next;
459
460 return 0;
464} 461}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index c15fb8c24ad2..1a79df9f739f 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -16,7 +16,7 @@ enum chain_mode {
16 16
17struct callchain_node { 17struct callchain_node {
18 struct callchain_node *parent; 18 struct callchain_node *parent;
19 struct list_head brothers; 19 struct list_head siblings;
20 struct list_head children; 20 struct list_head children;
21 struct list_head val; 21 struct list_head val;
22 struct rb_node rb_node; /* to sort nodes in an rbtree */ 22 struct rb_node rb_node; /* to sort nodes in an rbtree */
@@ -49,9 +49,30 @@ struct callchain_list {
49 struct list_head list; 49 struct list_head list;
50}; 50};
51 51
52/*
53 * A callchain cursor is a single linked list that
54 * let one feed a callchain progressively.
55 * It keeps persitent allocated entries to minimize
56 * allocations.
57 */
58struct callchain_cursor_node {
59 u64 ip;
60 struct map *map;
61 struct symbol *sym;
62 struct callchain_cursor_node *next;
63};
64
65struct callchain_cursor {
66 u64 nr;
67 struct callchain_cursor_node *first;
68 struct callchain_cursor_node **last;
69 u64 pos;
70 struct callchain_cursor_node *curr;
71};
72
52static inline void callchain_init(struct callchain_root *root) 73static inline void callchain_init(struct callchain_root *root)
53{ 74{
54 INIT_LIST_HEAD(&root->node.brothers); 75 INIT_LIST_HEAD(&root->node.siblings);
55 INIT_LIST_HEAD(&root->node.children); 76 INIT_LIST_HEAD(&root->node.children);
56 INIT_LIST_HEAD(&root->node.val); 77 INIT_LIST_HEAD(&root->node.val);
57 78
@@ -61,15 +82,54 @@ static inline void callchain_init(struct callchain_root *root)
61 root->max_depth = 0; 82 root->max_depth = 0;
62} 83}
63 84
64static inline u64 cumul_hits(struct callchain_node *node) 85static inline u64 callchain_cumul_hits(struct callchain_node *node)
65{ 86{
66 return node->hit + node->children_hit; 87 return node->hit + node->children_hit;
67} 88}
68 89
69int register_callchain_param(struct callchain_param *param); 90int callchain_register_param(struct callchain_param *param);
70int callchain_append(struct callchain_root *root, struct ip_callchain *chain, 91int callchain_append(struct callchain_root *root,
71 struct map_symbol *syms, u64 period); 92 struct callchain_cursor *cursor,
72int callchain_merge(struct callchain_root *dst, struct callchain_root *src); 93 u64 period);
94
95int callchain_merge(struct callchain_cursor *cursor,
96 struct callchain_root *dst, struct callchain_root *src);
97
98bool ip_callchain__valid(struct ip_callchain *chain,
99 const union perf_event *event);
100/*
101 * Initialize a cursor before adding entries inside, but keep
102 * the previously allocated entries as a cache.
103 */
104static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
105{
106 cursor->nr = 0;
107 cursor->last = &cursor->first;
108}
109
110int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
111 struct map *map, struct symbol *sym);
73 112
74bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event); 113/* Close a cursor writing session. Initialize for the reader */
114static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
115{
116 cursor->curr = cursor->first;
117 cursor->pos = 0;
118}
119
120/* Cursor reading iteration helpers */
121static inline struct callchain_cursor_node *
122callchain_cursor_current(struct callchain_cursor *cursor)
123{
124 if (cursor->pos == cursor->nr)
125 return NULL;
126
127 return cursor->curr;
128}
129
130static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
131{
132 cursor->curr = cursor->curr->next;
133 cursor->pos++;
134}
75#endif /* __PERF_CALLCHAIN_H */ 135#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
new file mode 100644
index 000000000000..9fea75535221
--- /dev/null
+++ b/tools/perf/util/cgroup.c
@@ -0,0 +1,178 @@
1#include "util.h"
2#include "../perf.h"
3#include "parse-options.h"
4#include "evsel.h"
5#include "cgroup.h"
6#include "debugfs.h" /* MAX_PATH, STR() */
7#include "evlist.h"
8
9int nr_cgroups;
10
11static int
12cgroupfs_find_mountpoint(char *buf, size_t maxlen)
13{
14 FILE *fp;
15 char mountpoint[MAX_PATH+1], tokens[MAX_PATH+1], type[MAX_PATH+1];
16 char *token, *saved_ptr;
17 int found = 0;
18
19 fp = fopen("/proc/mounts", "r");
20 if (!fp)
21 return -1;
22
23 /*
24 * in order to handle split hierarchy, we need to scan /proc/mounts
25 * and inspect every cgroupfs mount point to find one that has
26 * perf_event subsystem
27 */
28 while (fscanf(fp, "%*s %"STR(MAX_PATH)"s %"STR(MAX_PATH)"s %"
29 STR(MAX_PATH)"s %*d %*d\n",
30 mountpoint, type, tokens) == 3) {
31
32 if (!strcmp(type, "cgroup")) {
33
34 token = strtok_r(tokens, ",", &saved_ptr);
35
36 while (token != NULL) {
37 if (!strcmp(token, "perf_event")) {
38 found = 1;
39 break;
40 }
41 token = strtok_r(NULL, ",", &saved_ptr);
42 }
43 }
44 if (found)
45 break;
46 }
47 fclose(fp);
48 if (!found)
49 return -1;
50
51 if (strlen(mountpoint) < maxlen) {
52 strcpy(buf, mountpoint);
53 return 0;
54 }
55 return -1;
56}
57
58static int open_cgroup(char *name)
59{
60 char path[MAX_PATH+1];
61 char mnt[MAX_PATH+1];
62 int fd;
63
64
65 if (cgroupfs_find_mountpoint(mnt, MAX_PATH+1))
66 return -1;
67
68 snprintf(path, MAX_PATH, "%s/%s", mnt, name);
69
70 fd = open(path, O_RDONLY);
71 if (fd == -1)
72 fprintf(stderr, "no access to cgroup %s\n", path);
73
74 return fd;
75}
76
77static int add_cgroup(struct perf_evlist *evlist, char *str)
78{
79 struct perf_evsel *counter;
80 struct cgroup_sel *cgrp = NULL;
81 int n;
82 /*
83 * check if cgrp is already defined, if so we reuse it
84 */
85 list_for_each_entry(counter, &evlist->entries, node) {
86 cgrp = counter->cgrp;
87 if (!cgrp)
88 continue;
89 if (!strcmp(cgrp->name, str))
90 break;
91
92 cgrp = NULL;
93 }
94
95 if (!cgrp) {
96 cgrp = zalloc(sizeof(*cgrp));
97 if (!cgrp)
98 return -1;
99
100 cgrp->name = str;
101
102 cgrp->fd = open_cgroup(str);
103 if (cgrp->fd == -1) {
104 free(cgrp);
105 return -1;
106 }
107 }
108
109 /*
110 * find corresponding event
111 * if add cgroup N, then need to find event N
112 */
113 n = 0;
114 list_for_each_entry(counter, &evlist->entries, node) {
115 if (n == nr_cgroups)
116 goto found;
117 n++;
118 }
119 if (cgrp->refcnt == 0)
120 free(cgrp);
121
122 return -1;
123found:
124 cgrp->refcnt++;
125 counter->cgrp = cgrp;
126 return 0;
127}
128
129void close_cgroup(struct cgroup_sel *cgrp)
130{
131 if (!cgrp)
132 return;
133
134 /* XXX: not reentrant */
135 if (--cgrp->refcnt == 0) {
136 close(cgrp->fd);
137 free(cgrp->name);
138 free(cgrp);
139 }
140}
141
142int parse_cgroups(const struct option *opt __used, const char *str,
143 int unset __used)
144{
145 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
146 const char *p, *e, *eos = str + strlen(str);
147 char *s;
148 int ret;
149
150 if (list_empty(&evlist->entries)) {
151 fprintf(stderr, "must define events before cgroups\n");
152 return -1;
153 }
154
155 for (;;) {
156 p = strchr(str, ',');
157 e = p ? p : eos;
158
159 /* allow empty cgroups, i.e., skip */
160 if (e - str) {
161 /* termination added */
162 s = strndup(str, e - str);
163 if (!s)
164 return -1;
165 ret = add_cgroup(evlist, s);
166 if (ret) {
167 free(s);
168 return -1;
169 }
170 }
171 /* nr_cgroups is increased een for empty cgroups */
172 nr_cgroups++;
173 if (!p)
174 break;
175 str = p+1;
176 }
177 return 0;
178}
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
new file mode 100644
index 000000000000..89acd6debdc5
--- /dev/null
+++ b/tools/perf/util/cgroup.h
@@ -0,0 +1,17 @@
1#ifndef __CGROUP_H__
2#define __CGROUP_H__
3
4struct option;
5
6struct cgroup_sel {
7 char *name;
8 int fd;
9 int refcnt;
10};
11
12
13extern int nr_cgroups; /* number of explicit cgroups defined */
14extern void close_cgroup(struct cgroup_sel *cgrp);
15extern int parse_cgroups(const struct option *opt, const char *str, int unset);
16
17#endif /* __CGROUP_H__ */
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 3ccaa1043383..6893eec693ab 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -177,3 +177,8 @@ struct cpu_map *cpu_map__dummy_new(void)
177 177
178 return cpus; 178 return cpus;
179} 179}
180
181void cpu_map__delete(struct cpu_map *map)
182{
183 free(map);
184}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index f7a4f42f6307..072c0a374794 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -8,6 +8,6 @@ struct cpu_map {
8 8
9struct cpu_map *cpu_map__new(const char *cpu_list); 9struct cpu_map *cpu_map__new(const char *cpu_list);
10struct cpu_map *cpu_map__dummy_new(void); 10struct cpu_map *cpu_map__dummy_new(void);
11void *cpu_map__delete(struct cpu_map *map); 11void cpu_map__delete(struct cpu_map *map);
12 12
13#endif /* __PERF_CPUMAP_H */ 13#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 01bbe8ecec3f..d4536a9e0d8c 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -57,7 +57,7 @@ void ui__warning(const char *format, ...)
57} 57}
58#endif 58#endif
59 59
60void trace_event(event_t *event) 60void trace_event(union perf_event *event)
61{ 61{
62 unsigned char *raw_event = (void *)event; 62 unsigned char *raw_event = (void *)event;
63 const char *color = PERF_COLOR_BLUE; 63 const char *color = PERF_COLOR_BLUE;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index ca35fd66b5df..93516cf4682c 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -9,7 +9,7 @@ extern int verbose;
9extern bool quiet, dump_trace; 9extern bool quiet, dump_trace;
10 10
11int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 11int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
12void trace_event(event_t *event); 12void trace_event(union perf_event *event);
13 13
14struct ui_progress; 14struct ui_progress;
15 15
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 50d0a931497a..2b15c362ef56 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -6,8 +6,9 @@
6#include "string.h" 6#include "string.h"
7#include "strlist.h" 7#include "strlist.h"
8#include "thread.h" 8#include "thread.h"
9#include "thread_map.h"
9 10
10static const char *event__name[] = { 11static const char *perf_event__names[] = {
11 [0] = "TOTAL", 12 [0] = "TOTAL",
12 [PERF_RECORD_MMAP] = "MMAP", 13 [PERF_RECORD_MMAP] = "MMAP",
13 [PERF_RECORD_LOST] = "LOST", 14 [PERF_RECORD_LOST] = "LOST",
@@ -25,16 +26,16 @@ static const char *event__name[] = {
25 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", 26 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND",
26}; 27};
27 28
28const char *event__get_event_name(unsigned int id) 29const char *perf_event__name(unsigned int id)
29{ 30{
30 if (id >= ARRAY_SIZE(event__name)) 31 if (id >= ARRAY_SIZE(perf_event__names))
31 return "INVALID"; 32 return "INVALID";
32 if (!event__name[id]) 33 if (!perf_event__names[id])
33 return "UNKNOWN"; 34 return "UNKNOWN";
34 return event__name[id]; 35 return perf_event__names[id];
35} 36}
36 37
37static struct sample_data synth_sample = { 38static struct perf_sample synth_sample = {
38 .pid = -1, 39 .pid = -1,
39 .tid = -1, 40 .tid = -1,
40 .time = -1, 41 .time = -1,
@@ -43,9 +44,9 @@ static struct sample_data synth_sample = {
43 .period = 1, 44 .period = 1,
44}; 45};
45 46
46static pid_t event__synthesize_comm(event_t *event, pid_t pid, int full, 47static pid_t perf_event__synthesize_comm(union perf_event *event, pid_t pid,
47 event__handler_t process, 48 int full, perf_event__handler_t process,
48 struct perf_session *session) 49 struct perf_session *session)
49{ 50{
50 char filename[PATH_MAX]; 51 char filename[PATH_MAX];
51 char bf[BUFSIZ]; 52 char bf[BUFSIZ];
@@ -126,9 +127,10 @@ out:
126 return tgid; 127 return tgid;
127} 128}
128 129
129static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid, 130static int perf_event__synthesize_mmap_events(union perf_event *event,
130 event__handler_t process, 131 pid_t pid, pid_t tgid,
131 struct perf_session *session) 132 perf_event__handler_t process,
133 struct perf_session *session)
132{ 134{
133 char filename[PATH_MAX]; 135 char filename[PATH_MAX];
134 FILE *fp; 136 FILE *fp;
@@ -199,14 +201,14 @@ static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid,
199 return 0; 201 return 0;
200} 202}
201 203
202int event__synthesize_modules(event__handler_t process, 204int perf_event__synthesize_modules(perf_event__handler_t process,
203 struct perf_session *session, 205 struct perf_session *session,
204 struct machine *machine) 206 struct machine *machine)
205{ 207{
206 struct rb_node *nd; 208 struct rb_node *nd;
207 struct map_groups *kmaps = &machine->kmaps; 209 struct map_groups *kmaps = &machine->kmaps;
208 event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size); 210 union perf_event *event = zalloc((sizeof(event->mmap) +
209 211 session->id_hdr_size));
210 if (event == NULL) { 212 if (event == NULL) {
211 pr_debug("Not enough memory synthesizing mmap event " 213 pr_debug("Not enough memory synthesizing mmap event "
212 "for kernel modules\n"); 214 "for kernel modules\n");
@@ -251,23 +253,24 @@ int event__synthesize_modules(event__handler_t process,
251 return 0; 253 return 0;
252} 254}
253 255
254static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event, 256static int __event__synthesize_thread(union perf_event *comm_event,
255 pid_t pid, event__handler_t process, 257 union perf_event *mmap_event,
258 pid_t pid, perf_event__handler_t process,
256 struct perf_session *session) 259 struct perf_session *session)
257{ 260{
258 pid_t tgid = event__synthesize_comm(comm_event, pid, 1, process, 261 pid_t tgid = perf_event__synthesize_comm(comm_event, pid, 1, process,
259 session); 262 session);
260 if (tgid == -1) 263 if (tgid == -1)
261 return -1; 264 return -1;
262 return event__synthesize_mmap_events(mmap_event, pid, tgid, 265 return perf_event__synthesize_mmap_events(mmap_event, pid, tgid,
263 process, session); 266 process, session);
264} 267}
265 268
266int event__synthesize_thread_map(struct thread_map *threads, 269int perf_event__synthesize_thread_map(struct thread_map *threads,
267 event__handler_t process, 270 perf_event__handler_t process,
268 struct perf_session *session) 271 struct perf_session *session)
269{ 272{
270 event_t *comm_event, *mmap_event; 273 union perf_event *comm_event, *mmap_event;
271 int err = -1, thread; 274 int err = -1, thread;
272 275
273 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 276 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
@@ -294,12 +297,12 @@ out:
294 return err; 297 return err;
295} 298}
296 299
297int event__synthesize_threads(event__handler_t process, 300int perf_event__synthesize_threads(perf_event__handler_t process,
298 struct perf_session *session) 301 struct perf_session *session)
299{ 302{
300 DIR *proc; 303 DIR *proc;
301 struct dirent dirent, *next; 304 struct dirent dirent, *next;
302 event_t *comm_event, *mmap_event; 305 union perf_event *comm_event, *mmap_event;
303 int err = -1; 306 int err = -1;
304 307
305 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 308 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
@@ -357,10 +360,10 @@ static int find_symbol_cb(void *arg, const char *name, char type,
357 return 1; 360 return 1;
358} 361}
359 362
360int event__synthesize_kernel_mmap(event__handler_t process, 363int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
361 struct perf_session *session, 364 struct perf_session *session,
362 struct machine *machine, 365 struct machine *machine,
363 const char *symbol_name) 366 const char *symbol_name)
364{ 367{
365 size_t size; 368 size_t size;
366 const char *filename, *mmap_name; 369 const char *filename, *mmap_name;
@@ -374,8 +377,8 @@ int event__synthesize_kernel_mmap(event__handler_t process,
374 * kernels. 377 * kernels.
375 */ 378 */
376 struct process_symbol_args args = { .name = symbol_name, }; 379 struct process_symbol_args args = { .name = symbol_name, };
377 event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size); 380 union perf_event *event = zalloc((sizeof(event->mmap) +
378 381 session->id_hdr_size));
379 if (event == NULL) { 382 if (event == NULL) {
380 pr_debug("Not enough memory synthesizing mmap event " 383 pr_debug("Not enough memory synthesizing mmap event "
381 "for kernel modules\n"); 384 "for kernel modules\n");
@@ -421,42 +424,15 @@ int event__synthesize_kernel_mmap(event__handler_t process,
421 return err; 424 return err;
422} 425}
423 426
424static void thread__comm_adjust(struct thread *self, struct hists *hists) 427int perf_event__process_comm(union perf_event *event,
425{ 428 struct perf_sample *sample __used,
426 char *comm = self->comm; 429 struct perf_session *session)
427
428 if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
429 (!symbol_conf.comm_list ||
430 strlist__has_entry(symbol_conf.comm_list, comm))) {
431 u16 slen = strlen(comm);
432
433 if (hists__new_col_len(hists, HISTC_COMM, slen))
434 hists__set_col_len(hists, HISTC_THREAD, slen + 6);
435 }
436}
437
438static int thread__set_comm_adjust(struct thread *self, const char *comm,
439 struct hists *hists)
440{ 430{
441 int ret = thread__set_comm(self, comm); 431 struct thread *thread = perf_session__findnew(session, event->comm.tid);
442
443 if (ret)
444 return ret;
445
446 thread__comm_adjust(self, hists);
447 432
448 return 0; 433 dump_printf(": %s:%d\n", event->comm.comm, event->comm.tid);
449}
450 434
451int event__process_comm(event_t *self, struct sample_data *sample __used, 435 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
452 struct perf_session *session)
453{
454 struct thread *thread = perf_session__findnew(session, self->comm.tid);
455
456 dump_printf(": %s:%d\n", self->comm.comm, self->comm.tid);
457
458 if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm,
459 &session->hists)) {
460 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 436 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
461 return -1; 437 return -1;
462 } 438 }
@@ -464,19 +440,21 @@ int event__process_comm(event_t *self, struct sample_data *sample __used,
464 return 0; 440 return 0;
465} 441}
466 442
467int event__process_lost(event_t *self, struct sample_data *sample __used, 443int perf_event__process_lost(union perf_event *event,
468 struct perf_session *session) 444 struct perf_sample *sample __used,
445 struct perf_session *session)
469{ 446{
470 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", 447 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
471 self->lost.id, self->lost.lost); 448 event->lost.id, event->lost.lost);
472 session->hists.stats.total_lost += self->lost.lost; 449 session->hists.stats.total_lost += event->lost.lost;
473 return 0; 450 return 0;
474} 451}
475 452
476static void event_set_kernel_mmap_len(struct map **maps, event_t *self) 453static void perf_event__set_kernel_mmap_len(union perf_event *event,
454 struct map **maps)
477{ 455{
478 maps[MAP__FUNCTION]->start = self->mmap.start; 456 maps[MAP__FUNCTION]->start = event->mmap.start;
479 maps[MAP__FUNCTION]->end = self->mmap.start + self->mmap.len; 457 maps[MAP__FUNCTION]->end = event->mmap.start + event->mmap.len;
480 /* 458 /*
481 * Be a bit paranoid here, some perf.data file came with 459 * Be a bit paranoid here, some perf.data file came with
482 * a zero sized synthesized MMAP event for the kernel. 460 * a zero sized synthesized MMAP event for the kernel.
@@ -485,8 +463,8 @@ static void event_set_kernel_mmap_len(struct map **maps, event_t *self)
485 maps[MAP__FUNCTION]->end = ~0ULL; 463 maps[MAP__FUNCTION]->end = ~0ULL;
486} 464}
487 465
488static int event__process_kernel_mmap(event_t *self, 466static int perf_event__process_kernel_mmap(union perf_event *event,
489 struct perf_session *session) 467 struct perf_session *session)
490{ 468{
491 struct map *map; 469 struct map *map;
492 char kmmap_prefix[PATH_MAX]; 470 char kmmap_prefix[PATH_MAX];
@@ -494,9 +472,9 @@ static int event__process_kernel_mmap(event_t *self,
494 enum dso_kernel_type kernel_type; 472 enum dso_kernel_type kernel_type;
495 bool is_kernel_mmap; 473 bool is_kernel_mmap;
496 474
497 machine = perf_session__findnew_machine(session, self->mmap.pid); 475 machine = perf_session__findnew_machine(session, event->mmap.pid);
498 if (!machine) { 476 if (!machine) {
499 pr_err("Can't find id %d's machine\n", self->mmap.pid); 477 pr_err("Can't find id %d's machine\n", event->mmap.pid);
500 goto out_problem; 478 goto out_problem;
501 } 479 }
502 480
@@ -506,17 +484,17 @@ static int event__process_kernel_mmap(event_t *self,
506 else 484 else
507 kernel_type = DSO_TYPE_GUEST_KERNEL; 485 kernel_type = DSO_TYPE_GUEST_KERNEL;
508 486
509 is_kernel_mmap = memcmp(self->mmap.filename, 487 is_kernel_mmap = memcmp(event->mmap.filename,
510 kmmap_prefix, 488 kmmap_prefix,
511 strlen(kmmap_prefix)) == 0; 489 strlen(kmmap_prefix)) == 0;
512 if (self->mmap.filename[0] == '/' || 490 if (event->mmap.filename[0] == '/' ||
513 (!is_kernel_mmap && self->mmap.filename[0] == '[')) { 491 (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
514 492
515 char short_module_name[1024]; 493 char short_module_name[1024];
516 char *name, *dot; 494 char *name, *dot;
517 495
518 if (self->mmap.filename[0] == '/') { 496 if (event->mmap.filename[0] == '/') {
519 name = strrchr(self->mmap.filename, '/'); 497 name = strrchr(event->mmap.filename, '/');
520 if (name == NULL) 498 if (name == NULL)
521 goto out_problem; 499 goto out_problem;
522 500
@@ -528,10 +506,10 @@ static int event__process_kernel_mmap(event_t *self,
528 "[%.*s]", (int)(dot - name), name); 506 "[%.*s]", (int)(dot - name), name);
529 strxfrchar(short_module_name, '-', '_'); 507 strxfrchar(short_module_name, '-', '_');
530 } else 508 } else
531 strcpy(short_module_name, self->mmap.filename); 509 strcpy(short_module_name, event->mmap.filename);
532 510
533 map = machine__new_module(machine, self->mmap.start, 511 map = machine__new_module(machine, event->mmap.start,
534 self->mmap.filename); 512 event->mmap.filename);
535 if (map == NULL) 513 if (map == NULL)
536 goto out_problem; 514 goto out_problem;
537 515
@@ -541,9 +519,9 @@ static int event__process_kernel_mmap(event_t *self,
541 519
542 map->dso->short_name = name; 520 map->dso->short_name = name;
543 map->dso->sname_alloc = 1; 521 map->dso->sname_alloc = 1;
544 map->end = map->start + self->mmap.len; 522 map->end = map->start + event->mmap.len;
545 } else if (is_kernel_mmap) { 523 } else if (is_kernel_mmap) {
546 const char *symbol_name = (self->mmap.filename + 524 const char *symbol_name = (event->mmap.filename +
547 strlen(kmmap_prefix)); 525 strlen(kmmap_prefix));
548 /* 526 /*
549 * Should be there already, from the build-id table in 527 * Should be there already, from the build-id table in
@@ -558,10 +536,10 @@ static int event__process_kernel_mmap(event_t *self,
558 if (__machine__create_kernel_maps(machine, kernel) < 0) 536 if (__machine__create_kernel_maps(machine, kernel) < 0)
559 goto out_problem; 537 goto out_problem;
560 538
561 event_set_kernel_mmap_len(machine->vmlinux_maps, self); 539 perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps);
562 perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, 540 perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
563 symbol_name, 541 symbol_name,
564 self->mmap.pgoff); 542 event->mmap.pgoff);
565 if (machine__is_default_guest(machine)) { 543 if (machine__is_default_guest(machine)) {
566 /* 544 /*
567 * preload dso of guest kernel and modules 545 * preload dso of guest kernel and modules
@@ -575,22 +553,23 @@ out_problem:
575 return -1; 553 return -1;
576} 554}
577 555
578int event__process_mmap(event_t *self, struct sample_data *sample __used, 556int perf_event__process_mmap(union perf_event *event,
579 struct perf_session *session) 557 struct perf_sample *sample __used,
558 struct perf_session *session)
580{ 559{
581 struct machine *machine; 560 struct machine *machine;
582 struct thread *thread; 561 struct thread *thread;
583 struct map *map; 562 struct map *map;
584 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 563 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
585 int ret = 0; 564 int ret = 0;
586 565
587 dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", 566 dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n",
588 self->mmap.pid, self->mmap.tid, self->mmap.start, 567 event->mmap.pid, event->mmap.tid, event->mmap.start,
589 self->mmap.len, self->mmap.pgoff, self->mmap.filename); 568 event->mmap.len, event->mmap.pgoff, event->mmap.filename);
590 569
591 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || 570 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
592 cpumode == PERF_RECORD_MISC_KERNEL) { 571 cpumode == PERF_RECORD_MISC_KERNEL) {
593 ret = event__process_kernel_mmap(self, session); 572 ret = perf_event__process_kernel_mmap(event, session);
594 if (ret < 0) 573 if (ret < 0)
595 goto out_problem; 574 goto out_problem;
596 return 0; 575 return 0;
@@ -599,12 +578,12 @@ int event__process_mmap(event_t *self, struct sample_data *sample __used,
599 machine = perf_session__find_host_machine(session); 578 machine = perf_session__find_host_machine(session);
600 if (machine == NULL) 579 if (machine == NULL)
601 goto out_problem; 580 goto out_problem;
602 thread = perf_session__findnew(session, self->mmap.pid); 581 thread = perf_session__findnew(session, event->mmap.pid);
603 if (thread == NULL) 582 if (thread == NULL)
604 goto out_problem; 583 goto out_problem;
605 map = map__new(&machine->user_dsos, self->mmap.start, 584 map = map__new(&machine->user_dsos, event->mmap.start,
606 self->mmap.len, self->mmap.pgoff, 585 event->mmap.len, event->mmap.pgoff,
607 self->mmap.pid, self->mmap.filename, 586 event->mmap.pid, event->mmap.filename,
608 MAP__FUNCTION); 587 MAP__FUNCTION);
609 if (map == NULL) 588 if (map == NULL)
610 goto out_problem; 589 goto out_problem;
@@ -617,16 +596,17 @@ out_problem:
617 return 0; 596 return 0;
618} 597}
619 598
620int event__process_task(event_t *self, struct sample_data *sample __used, 599int perf_event__process_task(union perf_event *event,
621 struct perf_session *session) 600 struct perf_sample *sample __used,
601 struct perf_session *session)
622{ 602{
623 struct thread *thread = perf_session__findnew(session, self->fork.tid); 603 struct thread *thread = perf_session__findnew(session, event->fork.tid);
624 struct thread *parent = perf_session__findnew(session, self->fork.ptid); 604 struct thread *parent = perf_session__findnew(session, event->fork.ptid);
625 605
626 dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid, 606 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
627 self->fork.ppid, self->fork.ptid); 607 event->fork.ppid, event->fork.ptid);
628 608
629 if (self->header.type == PERF_RECORD_EXIT) { 609 if (event->header.type == PERF_RECORD_EXIT) {
630 perf_session__remove_thread(session, thread); 610 perf_session__remove_thread(session, thread);
631 return 0; 611 return 0;
632 } 612 }
@@ -640,20 +620,22 @@ int event__process_task(event_t *self, struct sample_data *sample __used,
640 return 0; 620 return 0;
641} 621}
642 622
643int event__process(event_t *event, struct sample_data *sample, 623int perf_event__process(union perf_event *event, struct perf_sample *sample,
644 struct perf_session *session) 624 struct perf_session *session)
645{ 625{
646 switch (event->header.type) { 626 switch (event->header.type) {
647 case PERF_RECORD_COMM: 627 case PERF_RECORD_COMM:
648 event__process_comm(event, sample, session); 628 perf_event__process_comm(event, sample, session);
649 break; 629 break;
650 case PERF_RECORD_MMAP: 630 case PERF_RECORD_MMAP:
651 event__process_mmap(event, sample, session); 631 perf_event__process_mmap(event, sample, session);
652 break; 632 break;
653 case PERF_RECORD_FORK: 633 case PERF_RECORD_FORK:
654 case PERF_RECORD_EXIT: 634 case PERF_RECORD_EXIT:
655 event__process_task(event, sample, session); 635 perf_event__process_task(event, sample, session);
656 break; 636 break;
637 case PERF_RECORD_LOST:
638 perf_event__process_lost(event, sample, session);
657 default: 639 default:
658 break; 640 break;
659 } 641 }
@@ -750,24 +732,14 @@ void thread__find_addr_location(struct thread *self,
750 al->sym = NULL; 732 al->sym = NULL;
751} 733}
752 734
753static void dso__calc_col_width(struct dso *self, struct hists *hists) 735int perf_event__preprocess_sample(const union perf_event *event,
754{ 736 struct perf_session *session,
755 if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep && 737 struct addr_location *al,
756 (!symbol_conf.dso_list || 738 struct perf_sample *sample,
757 strlist__has_entry(symbol_conf.dso_list, self->name))) { 739 symbol_filter_t filter)
758 u16 slen = dso__name_len(self);
759 hists__new_col_len(hists, HISTC_DSO, slen);
760 }
761
762 self->slen_calculated = 1;
763}
764
765int event__preprocess_sample(const event_t *self, struct perf_session *session,
766 struct addr_location *al, struct sample_data *data,
767 symbol_filter_t filter)
768{ 740{
769 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 741 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
770 struct thread *thread = perf_session__findnew(session, self->ip.pid); 742 struct thread *thread = perf_session__findnew(session, event->ip.pid);
771 743
772 if (thread == NULL) 744 if (thread == NULL)
773 return -1; 745 return -1;
@@ -789,12 +761,12 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
789 machine__create_kernel_maps(&session->host_machine); 761 machine__create_kernel_maps(&session->host_machine);
790 762
791 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 763 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
792 self->ip.pid, self->ip.ip, al); 764 event->ip.pid, event->ip.ip, al);
793 dump_printf(" ...... dso: %s\n", 765 dump_printf(" ...... dso: %s\n",
794 al->map ? al->map->dso->long_name : 766 al->map ? al->map->dso->long_name :
795 al->level == 'H' ? "[hypervisor]" : "<not found>"); 767 al->level == 'H' ? "[hypervisor]" : "<not found>");
796 al->sym = NULL; 768 al->sym = NULL;
797 al->cpu = data->cpu; 769 al->cpu = sample->cpu;
798 770
799 if (al->map) { 771 if (al->map) {
800 if (symbol_conf.dso_list && 772 if (symbol_conf.dso_list &&
@@ -805,23 +777,8 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
805 strlist__has_entry(symbol_conf.dso_list, 777 strlist__has_entry(symbol_conf.dso_list,
806 al->map->dso->long_name))))) 778 al->map->dso->long_name)))))
807 goto out_filtered; 779 goto out_filtered;
808 /*
809 * We have to do this here as we may have a dso with no symbol
810 * hit that has a name longer than the ones with symbols
811 * sampled.
812 */
813 if (!sort_dso.elide && !al->map->dso->slen_calculated)
814 dso__calc_col_width(al->map->dso, &session->hists);
815 780
816 al->sym = map__find_symbol(al->map, al->addr, filter); 781 al->sym = map__find_symbol(al->map, al->addr, filter);
817 } else {
818 const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
819
820 if (hists__col_len(&session->hists, HISTC_DSO) < unresolved_col_width &&
821 !symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
822 !symbol_conf.dso_list)
823 hists__set_col_len(&session->hists, HISTC_DSO,
824 unresolved_col_width);
825 } 782 }
826 783
827 if (symbol_conf.sym_list && al->sym && 784 if (symbol_conf.sym_list && al->sym &&
@@ -834,128 +791,3 @@ out_filtered:
834 al->filtered = true; 791 al->filtered = true;
835 return 0; 792 return 0;
836} 793}
837
838static int event__parse_id_sample(const event_t *event,
839 struct perf_session *session,
840 struct sample_data *sample)
841{
842 const u64 *array;
843 u64 type;
844
845 sample->cpu = sample->pid = sample->tid = -1;
846 sample->stream_id = sample->id = sample->time = -1ULL;
847
848 if (!session->sample_id_all)
849 return 0;
850
851 array = event->sample.array;
852 array += ((event->header.size -
853 sizeof(event->header)) / sizeof(u64)) - 1;
854 type = session->sample_type;
855
856 if (type & PERF_SAMPLE_CPU) {
857 u32 *p = (u32 *)array;
858 sample->cpu = *p;
859 array--;
860 }
861
862 if (type & PERF_SAMPLE_STREAM_ID) {
863 sample->stream_id = *array;
864 array--;
865 }
866
867 if (type & PERF_SAMPLE_ID) {
868 sample->id = *array;
869 array--;
870 }
871
872 if (type & PERF_SAMPLE_TIME) {
873 sample->time = *array;
874 array--;
875 }
876
877 if (type & PERF_SAMPLE_TID) {
878 u32 *p = (u32 *)array;
879 sample->pid = p[0];
880 sample->tid = p[1];
881 }
882
883 return 0;
884}
885
886int event__parse_sample(const event_t *event, struct perf_session *session,
887 struct sample_data *data)
888{
889 const u64 *array;
890 u64 type;
891
892 if (event->header.type != PERF_RECORD_SAMPLE)
893 return event__parse_id_sample(event, session, data);
894
895 array = event->sample.array;
896 type = session->sample_type;
897
898 if (type & PERF_SAMPLE_IP) {
899 data->ip = event->ip.ip;
900 array++;
901 }
902
903 if (type & PERF_SAMPLE_TID) {
904 u32 *p = (u32 *)array;
905 data->pid = p[0];
906 data->tid = p[1];
907 array++;
908 }
909
910 if (type & PERF_SAMPLE_TIME) {
911 data->time = *array;
912 array++;
913 }
914
915 if (type & PERF_SAMPLE_ADDR) {
916 data->addr = *array;
917 array++;
918 }
919
920 data->id = -1ULL;
921 if (type & PERF_SAMPLE_ID) {
922 data->id = *array;
923 array++;
924 }
925
926 if (type & PERF_SAMPLE_STREAM_ID) {
927 data->stream_id = *array;
928 array++;
929 }
930
931 if (type & PERF_SAMPLE_CPU) {
932 u32 *p = (u32 *)array;
933 data->cpu = *p;
934 array++;
935 } else
936 data->cpu = -1;
937
938 if (type & PERF_SAMPLE_PERIOD) {
939 data->period = *array;
940 array++;
941 }
942
943 if (type & PERF_SAMPLE_READ) {
944 pr_debug("PERF_SAMPLE_READ is unsuported for now\n");
945 return -1;
946 }
947
948 if (type & PERF_SAMPLE_CALLCHAIN) {
949 data->callchain = (struct ip_callchain *)array;
950 array += 1 + data->callchain->nr;
951 }
952
953 if (type & PERF_SAMPLE_RAW) {
954 u32 *p = (u32 *)array;
955 data->raw_size = *p;
956 p++;
957 data->raw_data = p;
958 }
959
960 return 0;
961}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index cc7b52f9b492..9c35170fb379 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -61,7 +61,7 @@ struct sample_event {
61 u64 array[]; 61 u64 array[];
62}; 62};
63 63
64struct sample_data { 64struct perf_sample {
65 u64 ip; 65 u64 ip;
66 u32 pid, tid; 66 u32 pid, tid;
67 u64 time; 67 u64 time;
@@ -117,7 +117,7 @@ struct tracing_data_event {
117 u32 size; 117 u32 size;
118}; 118};
119 119
120typedef union event_union { 120union perf_event {
121 struct perf_event_header header; 121 struct perf_event_header header;
122 struct ip_event ip; 122 struct ip_event ip;
123 struct mmap_event mmap; 123 struct mmap_event mmap;
@@ -130,50 +130,54 @@ typedef union event_union {
130 struct event_type_event event_type; 130 struct event_type_event event_type;
131 struct tracing_data_event tracing_data; 131 struct tracing_data_event tracing_data;
132 struct build_id_event build_id; 132 struct build_id_event build_id;
133} event_t; 133};
134 134
135void event__print_totals(void); 135void perf_event__print_totals(void);
136 136
137struct perf_session; 137struct perf_session;
138struct thread_map; 138struct thread_map;
139 139
140typedef int (*event__handler_synth_t)(event_t *event, 140typedef int (*perf_event__handler_synth_t)(union perf_event *event,
141 struct perf_session *session);
142typedef int (*perf_event__handler_t)(union perf_event *event,
143 struct perf_sample *sample,
141 struct perf_session *session); 144 struct perf_session *session);
142typedef int (*event__handler_t)(event_t *event, struct sample_data *sample, 145
143 struct perf_session *session); 146int perf_event__synthesize_thread_map(struct thread_map *threads,
144 147 perf_event__handler_t process,
145int event__synthesize_thread_map(struct thread_map *threads, 148 struct perf_session *session);
146 event__handler_t process, 149int perf_event__synthesize_threads(perf_event__handler_t process,
147 struct perf_session *session); 150 struct perf_session *session);
148int event__synthesize_threads(event__handler_t process, 151int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
149 struct perf_session *session); 152 struct perf_session *session,
150int event__synthesize_kernel_mmap(event__handler_t process, 153 struct machine *machine,
151 struct perf_session *session, 154 const char *symbol_name);
152 struct machine *machine, 155
153 const char *symbol_name); 156int perf_event__synthesize_modules(perf_event__handler_t process,
154 157 struct perf_session *session,
155int event__synthesize_modules(event__handler_t process, 158 struct machine *machine);
156 struct perf_session *session, 159
157 struct machine *machine); 160int perf_event__process_comm(union perf_event *event, struct perf_sample *sample,
158 161 struct perf_session *session);
159int event__process_comm(event_t *self, struct sample_data *sample, 162int perf_event__process_lost(union perf_event *event, struct perf_sample *sample,
160 struct perf_session *session); 163 struct perf_session *session);
161int event__process_lost(event_t *self, struct sample_data *sample, 164int perf_event__process_mmap(union perf_event *event, struct perf_sample *sample,
162 struct perf_session *session); 165 struct perf_session *session);
163int event__process_mmap(event_t *self, struct sample_data *sample, 166int perf_event__process_task(union perf_event *event, struct perf_sample *sample,
164 struct perf_session *session); 167 struct perf_session *session);
165int event__process_task(event_t *self, struct sample_data *sample, 168int perf_event__process(union perf_event *event, struct perf_sample *sample,
166 struct perf_session *session); 169 struct perf_session *session);
167int event__process(event_t *event, struct sample_data *sample,
168 struct perf_session *session);
169 170
170struct addr_location; 171struct addr_location;
171int event__preprocess_sample(const event_t *self, struct perf_session *session, 172int perf_event__preprocess_sample(const union perf_event *self,
172 struct addr_location *al, struct sample_data *data, 173 struct perf_session *session,
173 symbol_filter_t filter); 174 struct addr_location *al,
174int event__parse_sample(const event_t *event, struct perf_session *session, 175 struct perf_sample *sample,
175 struct sample_data *sample); 176 symbol_filter_t filter);
177
178const char *perf_event__name(unsigned int id);
176 179
177const char *event__get_event_name(unsigned int id); 180int perf_event__parse_sample(const union perf_event *event, u64 type,
181 bool sample_id_all, struct perf_sample *sample);
178 182
179#endif /* __PERF_RECORD_H */ 183#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
new file mode 100644
index 000000000000..d852cefa20de
--- /dev/null
+++ b/tools/perf/util/evlist.c
@@ -0,0 +1,394 @@
1/*
2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Parts came from builtin-{top,stat,record}.c, see those files for further
5 * copyright notes.
6 *
7 * Released under the GPL v2. (and only v2, not any later version)
8 */
9#include <poll.h>
10#include "cpumap.h"
11#include "thread_map.h"
12#include "evlist.h"
13#include "evsel.h"
14#include "util.h"
15
16#include <sys/mman.h>
17
18#include <linux/bitops.h>
19#include <linux/hash.h>
20
21#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
22#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
23
24void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
25 struct thread_map *threads)
26{
27 int i;
28
29 for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i)
30 INIT_HLIST_HEAD(&evlist->heads[i]);
31 INIT_LIST_HEAD(&evlist->entries);
32 perf_evlist__set_maps(evlist, cpus, threads);
33}
34
35struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
36 struct thread_map *threads)
37{
38 struct perf_evlist *evlist = zalloc(sizeof(*evlist));
39
40 if (evlist != NULL)
41 perf_evlist__init(evlist, cpus, threads);
42
43 return evlist;
44}
45
46static void perf_evlist__purge(struct perf_evlist *evlist)
47{
48 struct perf_evsel *pos, *n;
49
50 list_for_each_entry_safe(pos, n, &evlist->entries, node) {
51 list_del_init(&pos->node);
52 perf_evsel__delete(pos);
53 }
54
55 evlist->nr_entries = 0;
56}
57
58void perf_evlist__exit(struct perf_evlist *evlist)
59{
60 free(evlist->mmap);
61 free(evlist->pollfd);
62 evlist->mmap = NULL;
63 evlist->pollfd = NULL;
64}
65
66void perf_evlist__delete(struct perf_evlist *evlist)
67{
68 perf_evlist__purge(evlist);
69 perf_evlist__exit(evlist);
70 free(evlist);
71}
72
73void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
74{
75 list_add_tail(&entry->node, &evlist->entries);
76 ++evlist->nr_entries;
77}
78
79int perf_evlist__add_default(struct perf_evlist *evlist)
80{
81 struct perf_event_attr attr = {
82 .type = PERF_TYPE_HARDWARE,
83 .config = PERF_COUNT_HW_CPU_CYCLES,
84 };
85 struct perf_evsel *evsel = perf_evsel__new(&attr, 0);
86
87 if (evsel == NULL)
88 return -ENOMEM;
89
90 perf_evlist__add(evlist, evsel);
91 return 0;
92}
93
94int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
95{
96 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries;
97 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
98 return evlist->pollfd != NULL ? 0 : -ENOMEM;
99}
100
101void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
102{
103 fcntl(fd, F_SETFL, O_NONBLOCK);
104 evlist->pollfd[evlist->nr_fds].fd = fd;
105 evlist->pollfd[evlist->nr_fds].events = POLLIN;
106 evlist->nr_fds++;
107}
108
109static void perf_evlist__id_hash(struct perf_evlist *evlist,
110 struct perf_evsel *evsel,
111 int cpu, int thread, u64 id)
112{
113 int hash;
114 struct perf_sample_id *sid = SID(evsel, cpu, thread);
115
116 sid->id = id;
117 sid->evsel = evsel;
118 hash = hash_64(sid->id, PERF_EVLIST__HLIST_BITS);
119 hlist_add_head(&sid->node, &evlist->heads[hash]);
120}
121
122void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
123 int cpu, int thread, u64 id)
124{
125 perf_evlist__id_hash(evlist, evsel, cpu, thread, id);
126 evsel->id[evsel->ids++] = id;
127}
128
129static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
130 struct perf_evsel *evsel,
131 int cpu, int thread, int fd)
132{
133 u64 read_data[4] = { 0, };
134 int id_idx = 1; /* The first entry is the counter value */
135
136 if (!(evsel->attr.read_format & PERF_FORMAT_ID) ||
137 read(fd, &read_data, sizeof(read_data)) == -1)
138 return -1;
139
140 if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
141 ++id_idx;
142 if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
143 ++id_idx;
144
145 perf_evlist__id_add(evlist, evsel, cpu, thread, read_data[id_idx]);
146 return 0;
147}
148
149struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
150{
151 struct hlist_head *head;
152 struct hlist_node *pos;
153 struct perf_sample_id *sid;
154 int hash;
155
156 if (evlist->nr_entries == 1)
157 return list_entry(evlist->entries.next, struct perf_evsel, node);
158
159 hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
160 head = &evlist->heads[hash];
161
162 hlist_for_each_entry(sid, pos, head, node)
163 if (sid->id == id)
164 return sid->evsel;
165 return NULL;
166}
167
168union perf_event *perf_evlist__read_on_cpu(struct perf_evlist *evlist, int cpu)
169{
170 /* XXX Move this to perf.c, making it generally available */
171 unsigned int page_size = sysconf(_SC_PAGE_SIZE);
172 struct perf_mmap *md = &evlist->mmap[cpu];
173 unsigned int head = perf_mmap__read_head(md);
174 unsigned int old = md->prev;
175 unsigned char *data = md->base + page_size;
176 union perf_event *event = NULL;
177
178 if (evlist->overwrite) {
179 /*
180 * If we're further behind than half the buffer, there's a chance
181 * the writer will bite our tail and mess up the samples under us.
182 *
183 * If we somehow ended up ahead of the head, we got messed up.
184 *
185 * In either case, truncate and restart at head.
186 */
187 int diff = head - old;
188 if (diff > md->mask / 2 || diff < 0) {
189 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
190
191 /*
192 * head points to a known good entry, start there.
193 */
194 old = head;
195 }
196 }
197
198 if (old != head) {
199 size_t size;
200
201 event = (union perf_event *)&data[old & md->mask];
202 size = event->header.size;
203
204 /*
205 * Event straddles the mmap boundary -- header should always
206 * be inside due to u64 alignment of output.
207 */
208 if ((old & md->mask) + size != ((old + size) & md->mask)) {
209 unsigned int offset = old;
210 unsigned int len = min(sizeof(*event), size), cpy;
211 void *dst = &evlist->event_copy;
212
213 do {
214 cpy = min(md->mask + 1 - (offset & md->mask), len);
215 memcpy(dst, &data[offset & md->mask], cpy);
216 offset += cpy;
217 dst += cpy;
218 len -= cpy;
219 } while (len);
220
221 event = &evlist->event_copy;
222 }
223
224 old += size;
225 }
226
227 md->prev = old;
228
229 if (!evlist->overwrite)
230 perf_mmap__write_tail(md, old);
231
232 return event;
233}
234
235void perf_evlist__munmap(struct perf_evlist *evlist)
236{
237 int cpu;
238
239 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
240 if (evlist->mmap[cpu].base != NULL) {
241 munmap(evlist->mmap[cpu].base, evlist->mmap_len);
242 evlist->mmap[cpu].base = NULL;
243 }
244 }
245}
246
247int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
248{
249 evlist->mmap = zalloc(evlist->cpus->nr * sizeof(struct perf_mmap));
250 return evlist->mmap != NULL ? 0 : -ENOMEM;
251}
252
253static int __perf_evlist__mmap(struct perf_evlist *evlist, int cpu, int prot,
254 int mask, int fd)
255{
256 evlist->mmap[cpu].prev = 0;
257 evlist->mmap[cpu].mask = mask;
258 evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot,
259 MAP_SHARED, fd, 0);
260 if (evlist->mmap[cpu].base == MAP_FAILED)
261 return -1;
262
263 perf_evlist__add_pollfd(evlist, fd);
264 return 0;
265}
266
267/** perf_evlist__mmap - Create per cpu maps to receive events
268 *
269 * @evlist - list of events
270 * @pages - map length in pages
271 * @overwrite - overwrite older events?
272 *
273 * If overwrite is false the user needs to signal event consuption using:
274 *
275 * struct perf_mmap *m = &evlist->mmap[cpu];
276 * unsigned int head = perf_mmap__read_head(m);
277 *
278 * perf_mmap__write_tail(m, head)
279 *
280 * Using perf_evlist__read_on_cpu does this automatically.
281 */
282int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite)
283{
284 unsigned int page_size = sysconf(_SC_PAGE_SIZE);
285 int mask = pages * page_size - 1, cpu;
286 struct perf_evsel *first_evsel, *evsel;
287 const struct cpu_map *cpus = evlist->cpus;
288 const struct thread_map *threads = evlist->threads;
289 int thread, prot = PROT_READ | (overwrite ? 0 : PROT_WRITE);
290
291 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
292 return -ENOMEM;
293
294 if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
295 return -ENOMEM;
296
297 evlist->overwrite = overwrite;
298 evlist->mmap_len = (pages + 1) * page_size;
299 first_evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
300
301 list_for_each_entry(evsel, &evlist->entries, node) {
302 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
303 evsel->sample_id == NULL &&
304 perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0)
305 return -ENOMEM;
306
307 for (cpu = 0; cpu < cpus->nr; cpu++) {
308 for (thread = 0; thread < threads->nr; thread++) {
309 int fd = FD(evsel, cpu, thread);
310
311 if (evsel->idx || thread) {
312 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT,
313 FD(first_evsel, cpu, 0)) != 0)
314 goto out_unmap;
315 } else if (__perf_evlist__mmap(evlist, cpu, prot, mask, fd) < 0)
316 goto out_unmap;
317
318 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
319 perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
320 goto out_unmap;
321 }
322 }
323 }
324
325 return 0;
326
327out_unmap:
328 for (cpu = 0; cpu < cpus->nr; cpu++) {
329 if (evlist->mmap[cpu].base != NULL) {
330 munmap(evlist->mmap[cpu].base, evlist->mmap_len);
331 evlist->mmap[cpu].base = NULL;
332 }
333 }
334 return -1;
335}
336
337int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
338 pid_t target_tid, const char *cpu_list)
339{
340 evlist->threads = thread_map__new(target_pid, target_tid);
341
342 if (evlist->threads == NULL)
343 return -1;
344
345 if (target_tid != -1)
346 evlist->cpus = cpu_map__dummy_new();
347 else
348 evlist->cpus = cpu_map__new(cpu_list);
349
350 if (evlist->cpus == NULL)
351 goto out_delete_threads;
352
353 return 0;
354
355out_delete_threads:
356 thread_map__delete(evlist->threads);
357 return -1;
358}
359
360void perf_evlist__delete_maps(struct perf_evlist *evlist)
361{
362 cpu_map__delete(evlist->cpus);
363 thread_map__delete(evlist->threads);
364 evlist->cpus = NULL;
365 evlist->threads = NULL;
366}
367
368int perf_evlist__set_filters(struct perf_evlist *evlist)
369{
370 const struct thread_map *threads = evlist->threads;
371 const struct cpu_map *cpus = evlist->cpus;
372 struct perf_evsel *evsel;
373 char *filter;
374 int thread;
375 int cpu;
376 int err;
377 int fd;
378
379 list_for_each_entry(evsel, &evlist->entries, node) {
380 filter = evsel->filter;
381 if (!filter)
382 continue;
383 for (cpu = 0; cpu < cpus->nr; cpu++) {
384 for (thread = 0; thread < threads->nr; thread++) {
385 fd = FD(evsel, cpu, thread);
386 err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter);
387 if (err)
388 return err;
389 }
390 }
391 }
392
393 return 0;
394}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
new file mode 100644
index 000000000000..8b1cb7a4c5f1
--- /dev/null
+++ b/tools/perf/util/evlist.h
@@ -0,0 +1,68 @@
1#ifndef __PERF_EVLIST_H
2#define __PERF_EVLIST_H 1
3
4#include <linux/list.h>
5#include "../perf.h"
6#include "event.h"
7
8struct pollfd;
9struct thread_map;
10struct cpu_map;
11
12#define PERF_EVLIST__HLIST_BITS 8
13#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
14
15struct perf_evlist {
16 struct list_head entries;
17 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
18 int nr_entries;
19 int nr_fds;
20 int mmap_len;
21 bool overwrite;
22 union perf_event event_copy;
23 struct perf_mmap *mmap;
24 struct pollfd *pollfd;
25 struct thread_map *threads;
26 struct cpu_map *cpus;
27};
28
29struct perf_evsel;
30
31struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
32 struct thread_map *threads);
33void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
34 struct thread_map *threads);
35void perf_evlist__exit(struct perf_evlist *evlist);
36void perf_evlist__delete(struct perf_evlist *evlist);
37
38void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
39int perf_evlist__add_default(struct perf_evlist *evlist);
40
41void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
42 int cpu, int thread, u64 id);
43
44int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
45void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
46
47struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
48
49union perf_event *perf_evlist__read_on_cpu(struct perf_evlist *self, int cpu);
50
51int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
52int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
53void perf_evlist__munmap(struct perf_evlist *evlist);
54
55static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
56 struct cpu_map *cpus,
57 struct thread_map *threads)
58{
59 evlist->cpus = cpus;
60 evlist->threads = threads;
61}
62
63int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
64 pid_t target_tid, const char *cpu_list);
65void perf_evlist__delete_maps(struct perf_evlist *evlist);
66int perf_evlist__set_filters(struct perf_evlist *evlist);
67
68#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d8575d31ee6c..662596afd7f1 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1,20 +1,34 @@
1/*
2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Parts came from builtin-{top,stat,record}.c, see those files for further
5 * copyright notes.
6 *
7 * Released under the GPL v2. (and only v2, not any later version)
8 */
9
1#include "evsel.h" 10#include "evsel.h"
2#include "../perf.h" 11#include "evlist.h"
3#include "util.h" 12#include "util.h"
4#include "cpumap.h" 13#include "cpumap.h"
5#include "thread.h" 14#include "thread_map.h"
6 15
7#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 16#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
8 17
18void perf_evsel__init(struct perf_evsel *evsel,
19 struct perf_event_attr *attr, int idx)
20{
21 evsel->idx = idx;
22 evsel->attr = *attr;
23 INIT_LIST_HEAD(&evsel->node);
24}
25
9struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) 26struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
10{ 27{
11 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 28 struct perf_evsel *evsel = zalloc(sizeof(*evsel));
12 29
13 if (evsel != NULL) { 30 if (evsel != NULL)
14 evsel->idx = idx; 31 perf_evsel__init(evsel, attr, idx);
15 evsel->attr = *attr;
16 INIT_LIST_HEAD(&evsel->node);
17 }
18 32
19 return evsel; 33 return evsel;
20} 34}
@@ -25,6 +39,22 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
25 return evsel->fd != NULL ? 0 : -ENOMEM; 39 return evsel->fd != NULL ? 0 : -ENOMEM;
26} 40}
27 41
42int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
43{
44 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
45 if (evsel->sample_id == NULL)
46 return -ENOMEM;
47
48 evsel->id = zalloc(ncpus * nthreads * sizeof(u64));
49 if (evsel->id == NULL) {
50 xyarray__delete(evsel->sample_id);
51 evsel->sample_id = NULL;
52 return -ENOMEM;
53 }
54
55 return 0;
56}
57
28int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus) 58int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
29{ 59{
30 evsel->counts = zalloc((sizeof(*evsel->counts) + 60 evsel->counts = zalloc((sizeof(*evsel->counts) +
@@ -38,6 +68,14 @@ void perf_evsel__free_fd(struct perf_evsel *evsel)
38 evsel->fd = NULL; 68 evsel->fd = NULL;
39} 69}
40 70
71void perf_evsel__free_id(struct perf_evsel *evsel)
72{
73 xyarray__delete(evsel->sample_id);
74 evsel->sample_id = NULL;
75 free(evsel->id);
76 evsel->id = NULL;
77}
78
41void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 79void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
42{ 80{
43 int cpu, thread; 81 int cpu, thread;
@@ -49,10 +87,19 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
49 } 87 }
50} 88}
51 89
52void perf_evsel__delete(struct perf_evsel *evsel) 90void perf_evsel__exit(struct perf_evsel *evsel)
53{ 91{
54 assert(list_empty(&evsel->node)); 92 assert(list_empty(&evsel->node));
55 xyarray__delete(evsel->fd); 93 xyarray__delete(evsel->fd);
94 xyarray__delete(evsel->sample_id);
95 free(evsel->id);
96}
97
98void perf_evsel__delete(struct perf_evsel *evsel)
99{
100 perf_evsel__exit(evsel);
101 close_cgroup(evsel->cgrp);
102 free(evsel->name);
56 free(evsel); 103 free(evsel);
57} 104}
58 105
@@ -128,21 +175,51 @@ int __perf_evsel__read(struct perf_evsel *evsel,
128} 175}
129 176
130static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 177static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
131 struct thread_map *threads) 178 struct thread_map *threads, bool group, bool inherit)
132{ 179{
133 int cpu, thread; 180 int cpu, thread;
181 unsigned long flags = 0;
182 int pid = -1;
134 183
135 if (evsel->fd == NULL && 184 if (evsel->fd == NULL &&
136 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 185 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
137 return -1; 186 return -1;
138 187
188 if (evsel->cgrp) {
189 flags = PERF_FLAG_PID_CGROUP;
190 pid = evsel->cgrp->fd;
191 }
192
139 for (cpu = 0; cpu < cpus->nr; cpu++) { 193 for (cpu = 0; cpu < cpus->nr; cpu++) {
194 int group_fd = -1;
195 /*
196 * Don't allow mmap() of inherited per-task counters. This
197 * would create a performance issue due to all children writing
198 * to the same buffer.
199 *
200 * FIXME:
201 * Proper fix is not to pass 'inherit' to perf_evsel__open*,
202 * but a 'flags' parameter, with 'group' folded there as well,
203 * then introduce a PERF_O_{MMAP,GROUP,INHERIT} enum, and if
204 * O_MMAP is set, emit a warning if cpu < 0 and O_INHERIT is
205 * set. Lets go for the minimal fix first tho.
206 */
207 evsel->attr.inherit = (cpus->map[cpu] >= 0) && inherit;
208
140 for (thread = 0; thread < threads->nr; thread++) { 209 for (thread = 0; thread < threads->nr; thread++) {
210
211 if (!evsel->cgrp)
212 pid = threads->map[thread];
213
141 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, 214 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
142 threads->map[thread], 215 pid,
143 cpus->map[cpu], -1, 0); 216 cpus->map[cpu],
217 group_fd, flags);
144 if (FD(evsel, cpu, thread) < 0) 218 if (FD(evsel, cpu, thread) < 0)
145 goto out_close; 219 goto out_close;
220
221 if (group && group_fd == -1)
222 group_fd = FD(evsel, cpu, thread);
146 } 223 }
147 } 224 }
148 225
@@ -175,10 +252,9 @@ static struct {
175 .threads = { -1, }, 252 .threads = { -1, },
176}; 253};
177 254
178int perf_evsel__open(struct perf_evsel *evsel, 255int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
179 struct cpu_map *cpus, struct thread_map *threads) 256 struct thread_map *threads, bool group, bool inherit)
180{ 257{
181
182 if (cpus == NULL) { 258 if (cpus == NULL) {
183 /* Work around old compiler warnings about strict aliasing */ 259 /* Work around old compiler warnings about strict aliasing */
184 cpus = &empty_cpu_map.map; 260 cpus = &empty_cpu_map.map;
@@ -187,15 +263,135 @@ int perf_evsel__open(struct perf_evsel *evsel,
187 if (threads == NULL) 263 if (threads == NULL)
188 threads = &empty_thread_map.map; 264 threads = &empty_thread_map.map;
189 265
190 return __perf_evsel__open(evsel, cpus, threads); 266 return __perf_evsel__open(evsel, cpus, threads, group, inherit);
191} 267}
192 268
193int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus) 269int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
270 struct cpu_map *cpus, bool group, bool inherit)
194{ 271{
195 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map); 272 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, inherit);
273}
274
275int perf_evsel__open_per_thread(struct perf_evsel *evsel,
276 struct thread_map *threads, bool group, bool inherit)
277{
278 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, inherit);
279}
280
281static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
282 struct perf_sample *sample)
283{
284 const u64 *array = event->sample.array;
285
286 array += ((event->header.size -
287 sizeof(event->header)) / sizeof(u64)) - 1;
288
289 if (type & PERF_SAMPLE_CPU) {
290 u32 *p = (u32 *)array;
291 sample->cpu = *p;
292 array--;
293 }
294
295 if (type & PERF_SAMPLE_STREAM_ID) {
296 sample->stream_id = *array;
297 array--;
298 }
299
300 if (type & PERF_SAMPLE_ID) {
301 sample->id = *array;
302 array--;
303 }
304
305 if (type & PERF_SAMPLE_TIME) {
306 sample->time = *array;
307 array--;
308 }
309
310 if (type & PERF_SAMPLE_TID) {
311 u32 *p = (u32 *)array;
312 sample->pid = p[0];
313 sample->tid = p[1];
314 }
315
316 return 0;
196} 317}
197 318
198int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads) 319int perf_event__parse_sample(const union perf_event *event, u64 type,
320 bool sample_id_all, struct perf_sample *data)
199{ 321{
200 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads); 322 const u64 *array;
323
324 data->cpu = data->pid = data->tid = -1;
325 data->stream_id = data->id = data->time = -1ULL;
326
327 if (event->header.type != PERF_RECORD_SAMPLE) {
328 if (!sample_id_all)
329 return 0;
330 return perf_event__parse_id_sample(event, type, data);
331 }
332
333 array = event->sample.array;
334
335 if (type & PERF_SAMPLE_IP) {
336 data->ip = event->ip.ip;
337 array++;
338 }
339
340 if (type & PERF_SAMPLE_TID) {
341 u32 *p = (u32 *)array;
342 data->pid = p[0];
343 data->tid = p[1];
344 array++;
345 }
346
347 if (type & PERF_SAMPLE_TIME) {
348 data->time = *array;
349 array++;
350 }
351
352 if (type & PERF_SAMPLE_ADDR) {
353 data->addr = *array;
354 array++;
355 }
356
357 data->id = -1ULL;
358 if (type & PERF_SAMPLE_ID) {
359 data->id = *array;
360 array++;
361 }
362
363 if (type & PERF_SAMPLE_STREAM_ID) {
364 data->stream_id = *array;
365 array++;
366 }
367
368 if (type & PERF_SAMPLE_CPU) {
369 u32 *p = (u32 *)array;
370 data->cpu = *p;
371 array++;
372 }
373
374 if (type & PERF_SAMPLE_PERIOD) {
375 data->period = *array;
376 array++;
377 }
378
379 if (type & PERF_SAMPLE_READ) {
380 fprintf(stderr, "PERF_SAMPLE_READ is unsuported for now\n");
381 return -1;
382 }
383
384 if (type & PERF_SAMPLE_CALLCHAIN) {
385 data->callchain = (struct ip_callchain *)array;
386 array += 1 + data->callchain->nr;
387 }
388
389 if (type & PERF_SAMPLE_RAW) {
390 u32 *p = (u32 *)array;
391 data->raw_size = *p;
392 p++;
393 data->raw_data = p;
394 }
395
396 return 0;
201} 397}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b2d755fe88a5..6710ab538342 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -6,6 +6,8 @@
6#include "../../../include/linux/perf_event.h" 6#include "../../../include/linux/perf_event.h"
7#include "types.h" 7#include "types.h"
8#include "xyarray.h" 8#include "xyarray.h"
9#include "cgroup.h"
10#include "hist.h"
9 11
10struct perf_counts_values { 12struct perf_counts_values {
11 union { 13 union {
@@ -24,31 +26,66 @@ struct perf_counts {
24 struct perf_counts_values cpu[]; 26 struct perf_counts_values cpu[];
25}; 27};
26 28
29struct perf_evsel;
30
31/*
32 * Per fd, to map back from PERF_SAMPLE_ID to evsel, only used when there are
33 * more than one entry in the evlist.
34 */
35struct perf_sample_id {
36 struct hlist_node node;
37 u64 id;
38 struct perf_evsel *evsel;
39};
40
41/** struct perf_evsel - event selector
42 *
43 * @name - Can be set to retain the original event name passed by the user,
44 * so that when showing results in tools such as 'perf stat', we
45 * show the name used, not some alias.
46 */
27struct perf_evsel { 47struct perf_evsel {
28 struct list_head node; 48 struct list_head node;
29 struct perf_event_attr attr; 49 struct perf_event_attr attr;
30 char *filter; 50 char *filter;
31 struct xyarray *fd; 51 struct xyarray *fd;
52 struct xyarray *sample_id;
53 u64 *id;
32 struct perf_counts *counts; 54 struct perf_counts *counts;
33 int idx; 55 int idx;
34 void *priv; 56 int ids;
57 struct hists hists;
58 char *name;
59 union {
60 void *priv;
61 off_t id_offset;
62 };
63 struct cgroup_sel *cgrp;
35}; 64};
36 65
37struct cpu_map; 66struct cpu_map;
38struct thread_map; 67struct thread_map;
68struct perf_evlist;
39 69
40struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); 70struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
71void perf_evsel__init(struct perf_evsel *evsel,
72 struct perf_event_attr *attr, int idx);
73void perf_evsel__exit(struct perf_evsel *evsel);
41void perf_evsel__delete(struct perf_evsel *evsel); 74void perf_evsel__delete(struct perf_evsel *evsel);
42 75
43int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 76int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
77int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
44int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); 78int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
45void perf_evsel__free_fd(struct perf_evsel *evsel); 79void perf_evsel__free_fd(struct perf_evsel *evsel);
80void perf_evsel__free_id(struct perf_evsel *evsel);
46void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 81void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
47 82
48int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus); 83int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
49int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads); 84 struct cpu_map *cpus, bool group, bool inherit);
50int perf_evsel__open(struct perf_evsel *evsel, 85int perf_evsel__open_per_thread(struct perf_evsel *evsel,
51 struct cpu_map *cpus, struct thread_map *threads); 86 struct thread_map *threads, bool group, bool inherit);
87int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
88 struct thread_map *threads, bool group, bool inherit);
52 89
53#define perf_evsel__match(evsel, t, c) \ 90#define perf_evsel__match(evsel, t, c) \
54 (evsel->attr.type == PERF_TYPE_##t && \ 91 (evsel->attr.type == PERF_TYPE_##t && \
diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
index 67eeff571568..7adf4ad15d8f 100644
--- a/tools/perf/util/exec_cmd.c
+++ b/tools/perf/util/exec_cmd.c
@@ -11,31 +11,12 @@ static const char *argv0_path;
11 11
12const char *system_path(const char *path) 12const char *system_path(const char *path)
13{ 13{
14#ifdef RUNTIME_PREFIX
15 static const char *prefix;
16#else
17 static const char *prefix = PREFIX; 14 static const char *prefix = PREFIX;
18#endif
19 struct strbuf d = STRBUF_INIT; 15 struct strbuf d = STRBUF_INIT;
20 16
21 if (is_absolute_path(path)) 17 if (is_absolute_path(path))
22 return path; 18 return path;
23 19
24#ifdef RUNTIME_PREFIX
25 assert(argv0_path);
26 assert(is_absolute_path(argv0_path));
27
28 if (!prefix &&
29 !(prefix = strip_path_suffix(argv0_path, PERF_EXEC_PATH)) &&
30 !(prefix = strip_path_suffix(argv0_path, BINDIR)) &&
31 !(prefix = strip_path_suffix(argv0_path, "perf"))) {
32 prefix = PREFIX;
33 fprintf(stderr, "RUNTIME_PREFIX requested, "
34 "but prefix computation failed. "
35 "Using static fallback '%s'.\n", prefix);
36 }
37#endif
38
39 strbuf_addf(&d, "%s/%s", prefix, path); 20 strbuf_addf(&d, "%s/%s", prefix, path);
40 path = strbuf_detach(&d, NULL); 21 path = strbuf_detach(&d, NULL);
41 return path; 22 return path;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 0866bcdb5e8e..e5230c0ef95b 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -8,6 +8,8 @@
8#include <linux/list.h> 8#include <linux/list.h>
9#include <linux/kernel.h> 9#include <linux/kernel.h>
10 10
11#include "evlist.h"
12#include "evsel.h"
11#include "util.h" 13#include "util.h"
12#include "header.h" 14#include "header.h"
13#include "../perf.h" 15#include "../perf.h"
@@ -18,89 +20,6 @@
18 20
19static bool no_buildid_cache = false; 21static bool no_buildid_cache = false;
20 22
21/*
22 * Create new perf.data header attribute:
23 */
24struct perf_header_attr *perf_header_attr__new(struct perf_event_attr *attr)
25{
26 struct perf_header_attr *self = malloc(sizeof(*self));
27
28 if (self != NULL) {
29 self->attr = *attr;
30 self->ids = 0;
31 self->size = 1;
32 self->id = malloc(sizeof(u64));
33 if (self->id == NULL) {
34 free(self);
35 self = NULL;
36 }
37 }
38
39 return self;
40}
41
42void perf_header_attr__delete(struct perf_header_attr *self)
43{
44 free(self->id);
45 free(self);
46}
47
48int perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
49{
50 int pos = self->ids;
51
52 self->ids++;
53 if (self->ids > self->size) {
54 int nsize = self->size * 2;
55 u64 *nid = realloc(self->id, nsize * sizeof(u64));
56
57 if (nid == NULL)
58 return -1;
59
60 self->size = nsize;
61 self->id = nid;
62 }
63 self->id[pos] = id;
64 return 0;
65}
66
67int perf_header__init(struct perf_header *self)
68{
69 self->size = 1;
70 self->attr = malloc(sizeof(void *));
71 return self->attr == NULL ? -ENOMEM : 0;
72}
73
74void perf_header__exit(struct perf_header *self)
75{
76 int i;
77 for (i = 0; i < self->attrs; ++i)
78 perf_header_attr__delete(self->attr[i]);
79 free(self->attr);
80}
81
82int perf_header__add_attr(struct perf_header *self,
83 struct perf_header_attr *attr)
84{
85 if (self->frozen)
86 return -1;
87
88 if (self->attrs == self->size) {
89 int nsize = self->size * 2;
90 struct perf_header_attr **nattr;
91
92 nattr = realloc(self->attr, nsize * sizeof(void *));
93 if (nattr == NULL)
94 return -1;
95
96 self->size = nsize;
97 self->attr = nattr;
98 }
99
100 self->attr[self->attrs++] = attr;
101 return 0;
102}
103
104static int event_count; 23static int event_count;
105static struct perf_trace_event_type *events; 24static struct perf_trace_event_type *events;
106 25
@@ -147,19 +66,19 @@ struct perf_file_attr {
147 struct perf_file_section ids; 66 struct perf_file_section ids;
148}; 67};
149 68
150void perf_header__set_feat(struct perf_header *self, int feat) 69void perf_header__set_feat(struct perf_header *header, int feat)
151{ 70{
152 set_bit(feat, self->adds_features); 71 set_bit(feat, header->adds_features);
153} 72}
154 73
155void perf_header__clear_feat(struct perf_header *self, int feat) 74void perf_header__clear_feat(struct perf_header *header, int feat)
156{ 75{
157 clear_bit(feat, self->adds_features); 76 clear_bit(feat, header->adds_features);
158} 77}
159 78
160bool perf_header__has_feat(const struct perf_header *self, int feat) 79bool perf_header__has_feat(const struct perf_header *header, int feat)
161{ 80{
162 return test_bit(feat, self->adds_features); 81 return test_bit(feat, header->adds_features);
163} 82}
164 83
165static int do_write(int fd, const void *buf, size_t size) 84static int do_write(int fd, const void *buf, size_t size)
@@ -228,22 +147,22 @@ static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
228 return 0; 147 return 0;
229} 148}
230 149
231static int machine__write_buildid_table(struct machine *self, int fd) 150static int machine__write_buildid_table(struct machine *machine, int fd)
232{ 151{
233 int err; 152 int err;
234 u16 kmisc = PERF_RECORD_MISC_KERNEL, 153 u16 kmisc = PERF_RECORD_MISC_KERNEL,
235 umisc = PERF_RECORD_MISC_USER; 154 umisc = PERF_RECORD_MISC_USER;
236 155
237 if (!machine__is_host(self)) { 156 if (!machine__is_host(machine)) {
238 kmisc = PERF_RECORD_MISC_GUEST_KERNEL; 157 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
239 umisc = PERF_RECORD_MISC_GUEST_USER; 158 umisc = PERF_RECORD_MISC_GUEST_USER;
240 } 159 }
241 160
242 err = __dsos__write_buildid_table(&self->kernel_dsos, self->pid, 161 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid,
243 kmisc, fd); 162 kmisc, fd);
244 if (err == 0) 163 if (err == 0)
245 err = __dsos__write_buildid_table(&self->user_dsos, 164 err = __dsos__write_buildid_table(&machine->user_dsos,
246 self->pid, umisc, fd); 165 machine->pid, umisc, fd);
247 return err; 166 return err;
248} 167}
249 168
@@ -366,12 +285,12 @@ out_free:
366 return err; 285 return err;
367} 286}
368 287
369static int dso__cache_build_id(struct dso *self, const char *debugdir) 288static int dso__cache_build_id(struct dso *dso, const char *debugdir)
370{ 289{
371 bool is_kallsyms = self->kernel && self->long_name[0] != '/'; 290 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
372 291
373 return build_id_cache__add_b(self->build_id, sizeof(self->build_id), 292 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
374 self->long_name, debugdir, is_kallsyms); 293 dso->long_name, debugdir, is_kallsyms);
375} 294}
376 295
377static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) 296static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
@@ -386,14 +305,14 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
386 return err; 305 return err;
387} 306}
388 307
389static int machine__cache_build_ids(struct machine *self, const char *debugdir) 308static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
390{ 309{
391 int ret = __dsos__cache_build_ids(&self->kernel_dsos, debugdir); 310 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir);
392 ret |= __dsos__cache_build_ids(&self->user_dsos, debugdir); 311 ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir);
393 return ret; 312 return ret;
394} 313}
395 314
396static int perf_session__cache_build_ids(struct perf_session *self) 315static int perf_session__cache_build_ids(struct perf_session *session)
397{ 316{
398 struct rb_node *nd; 317 struct rb_node *nd;
399 int ret; 318 int ret;
@@ -404,28 +323,28 @@ static int perf_session__cache_build_ids(struct perf_session *self)
404 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) 323 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
405 return -1; 324 return -1;
406 325
407 ret = machine__cache_build_ids(&self->host_machine, debugdir); 326 ret = machine__cache_build_ids(&session->host_machine, debugdir);
408 327
409 for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) { 328 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
410 struct machine *pos = rb_entry(nd, struct machine, rb_node); 329 struct machine *pos = rb_entry(nd, struct machine, rb_node);
411 ret |= machine__cache_build_ids(pos, debugdir); 330 ret |= machine__cache_build_ids(pos, debugdir);
412 } 331 }
413 return ret ? -1 : 0; 332 return ret ? -1 : 0;
414} 333}
415 334
416static bool machine__read_build_ids(struct machine *self, bool with_hits) 335static bool machine__read_build_ids(struct machine *machine, bool with_hits)
417{ 336{
418 bool ret = __dsos__read_build_ids(&self->kernel_dsos, with_hits); 337 bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits);
419 ret |= __dsos__read_build_ids(&self->user_dsos, with_hits); 338 ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits);
420 return ret; 339 return ret;
421} 340}
422 341
423static bool perf_session__read_build_ids(struct perf_session *self, bool with_hits) 342static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
424{ 343{
425 struct rb_node *nd; 344 struct rb_node *nd;
426 bool ret = machine__read_build_ids(&self->host_machine, with_hits); 345 bool ret = machine__read_build_ids(&session->host_machine, with_hits);
427 346
428 for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) { 347 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
429 struct machine *pos = rb_entry(nd, struct machine, rb_node); 348 struct machine *pos = rb_entry(nd, struct machine, rb_node);
430 ret |= machine__read_build_ids(pos, with_hits); 349 ret |= machine__read_build_ids(pos, with_hits);
431 } 350 }
@@ -433,7 +352,8 @@ static bool perf_session__read_build_ids(struct perf_session *self, bool with_hi
433 return ret; 352 return ret;
434} 353}
435 354
436static int perf_header__adds_write(struct perf_header *self, int fd) 355static int perf_header__adds_write(struct perf_header *header,
356 struct perf_evlist *evlist, int fd)
437{ 357{
438 int nr_sections; 358 int nr_sections;
439 struct perf_session *session; 359 struct perf_session *session;
@@ -442,13 +362,13 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
442 u64 sec_start; 362 u64 sec_start;
443 int idx = 0, err; 363 int idx = 0, err;
444 364
445 session = container_of(self, struct perf_session, header); 365 session = container_of(header, struct perf_session, header);
446 366
447 if (perf_header__has_feat(self, HEADER_BUILD_ID && 367 if (perf_header__has_feat(header, HEADER_BUILD_ID &&
448 !perf_session__read_build_ids(session, true))) 368 !perf_session__read_build_ids(session, true)))
449 perf_header__clear_feat(self, HEADER_BUILD_ID); 369 perf_header__clear_feat(header, HEADER_BUILD_ID);
450 370
451 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 371 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
452 if (!nr_sections) 372 if (!nr_sections)
453 return 0; 373 return 0;
454 374
@@ -458,28 +378,28 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
458 378
459 sec_size = sizeof(*feat_sec) * nr_sections; 379 sec_size = sizeof(*feat_sec) * nr_sections;
460 380
461 sec_start = self->data_offset + self->data_size; 381 sec_start = header->data_offset + header->data_size;
462 lseek(fd, sec_start + sec_size, SEEK_SET); 382 lseek(fd, sec_start + sec_size, SEEK_SET);
463 383
464 if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { 384 if (perf_header__has_feat(header, HEADER_TRACE_INFO)) {
465 struct perf_file_section *trace_sec; 385 struct perf_file_section *trace_sec;
466 386
467 trace_sec = &feat_sec[idx++]; 387 trace_sec = &feat_sec[idx++];
468 388
469 /* Write trace info */ 389 /* Write trace info */
470 trace_sec->offset = lseek(fd, 0, SEEK_CUR); 390 trace_sec->offset = lseek(fd, 0, SEEK_CUR);
471 read_tracing_data(fd, &evsel_list); 391 read_tracing_data(fd, &evlist->entries);
472 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; 392 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
473 } 393 }
474 394
475 if (perf_header__has_feat(self, HEADER_BUILD_ID)) { 395 if (perf_header__has_feat(header, HEADER_BUILD_ID)) {
476 struct perf_file_section *buildid_sec; 396 struct perf_file_section *buildid_sec;
477 397
478 buildid_sec = &feat_sec[idx++]; 398 buildid_sec = &feat_sec[idx++];
479 399
480 /* Write build-ids */ 400 /* Write build-ids */
481 buildid_sec->offset = lseek(fd, 0, SEEK_CUR); 401 buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
482 err = dsos__write_buildid_table(self, fd); 402 err = dsos__write_buildid_table(header, fd);
483 if (err < 0) { 403 if (err < 0) {
484 pr_debug("failed to write buildid table\n"); 404 pr_debug("failed to write buildid table\n");
485 goto out_free; 405 goto out_free;
@@ -518,32 +438,41 @@ int perf_header__write_pipe(int fd)
518 return 0; 438 return 0;
519} 439}
520 440
521int perf_header__write(struct perf_header *self, int fd, bool at_exit) 441int perf_session__write_header(struct perf_session *session,
442 struct perf_evlist *evlist,
443 int fd, bool at_exit)
522{ 444{
523 struct perf_file_header f_header; 445 struct perf_file_header f_header;
524 struct perf_file_attr f_attr; 446 struct perf_file_attr f_attr;
525 struct perf_header_attr *attr; 447 struct perf_header *header = &session->header;
526 int i, err; 448 struct perf_evsel *attr, *pair = NULL;
449 int err;
527 450
528 lseek(fd, sizeof(f_header), SEEK_SET); 451 lseek(fd, sizeof(f_header), SEEK_SET);
529 452
530 for (i = 0; i < self->attrs; i++) { 453 if (session->evlist != evlist)
531 attr = self->attr[i]; 454 pair = list_entry(session->evlist->entries.next, struct perf_evsel, node);
532 455
456 list_for_each_entry(attr, &evlist->entries, node) {
533 attr->id_offset = lseek(fd, 0, SEEK_CUR); 457 attr->id_offset = lseek(fd, 0, SEEK_CUR);
534 err = do_write(fd, attr->id, attr->ids * sizeof(u64)); 458 err = do_write(fd, attr->id, attr->ids * sizeof(u64));
535 if (err < 0) { 459 if (err < 0) {
460out_err_write:
536 pr_debug("failed to write perf header\n"); 461 pr_debug("failed to write perf header\n");
537 return err; 462 return err;
538 } 463 }
464 if (session->evlist != evlist) {
465 err = do_write(fd, pair->id, pair->ids * sizeof(u64));
466 if (err < 0)
467 goto out_err_write;
468 attr->ids += pair->ids;
469 pair = list_entry(pair->node.next, struct perf_evsel, node);
470 }
539 } 471 }
540 472
473 header->attr_offset = lseek(fd, 0, SEEK_CUR);
541 474
542 self->attr_offset = lseek(fd, 0, SEEK_CUR); 475 list_for_each_entry(attr, &evlist->entries, node) {
543
544 for (i = 0; i < self->attrs; i++) {
545 attr = self->attr[i];
546
547 f_attr = (struct perf_file_attr){ 476 f_attr = (struct perf_file_attr){
548 .attr = attr->attr, 477 .attr = attr->attr,
549 .ids = { 478 .ids = {
@@ -558,20 +487,20 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit)
558 } 487 }
559 } 488 }
560 489
561 self->event_offset = lseek(fd, 0, SEEK_CUR); 490 header->event_offset = lseek(fd, 0, SEEK_CUR);
562 self->event_size = event_count * sizeof(struct perf_trace_event_type); 491 header->event_size = event_count * sizeof(struct perf_trace_event_type);
563 if (events) { 492 if (events) {
564 err = do_write(fd, events, self->event_size); 493 err = do_write(fd, events, header->event_size);
565 if (err < 0) { 494 if (err < 0) {
566 pr_debug("failed to write perf header events\n"); 495 pr_debug("failed to write perf header events\n");
567 return err; 496 return err;
568 } 497 }
569 } 498 }
570 499
571 self->data_offset = lseek(fd, 0, SEEK_CUR); 500 header->data_offset = lseek(fd, 0, SEEK_CUR);
572 501
573 if (at_exit) { 502 if (at_exit) {
574 err = perf_header__adds_write(self, fd); 503 err = perf_header__adds_write(header, evlist, fd);
575 if (err < 0) 504 if (err < 0)
576 return err; 505 return err;
577 } 506 }
@@ -581,20 +510,20 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit)
581 .size = sizeof(f_header), 510 .size = sizeof(f_header),
582 .attr_size = sizeof(f_attr), 511 .attr_size = sizeof(f_attr),
583 .attrs = { 512 .attrs = {
584 .offset = self->attr_offset, 513 .offset = header->attr_offset,
585 .size = self->attrs * sizeof(f_attr), 514 .size = evlist->nr_entries * sizeof(f_attr),
586 }, 515 },
587 .data = { 516 .data = {
588 .offset = self->data_offset, 517 .offset = header->data_offset,
589 .size = self->data_size, 518 .size = header->data_size,
590 }, 519 },
591 .event_types = { 520 .event_types = {
592 .offset = self->event_offset, 521 .offset = header->event_offset,
593 .size = self->event_size, 522 .size = header->event_size,
594 }, 523 },
595 }; 524 };
596 525
597 memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features)); 526 memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features));
598 527
599 lseek(fd, 0, SEEK_SET); 528 lseek(fd, 0, SEEK_SET);
600 err = do_write(fd, &f_header, sizeof(f_header)); 529 err = do_write(fd, &f_header, sizeof(f_header));
@@ -602,26 +531,26 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit)
602 pr_debug("failed to write perf header\n"); 531 pr_debug("failed to write perf header\n");
603 return err; 532 return err;
604 } 533 }
605 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 534 lseek(fd, header->data_offset + header->data_size, SEEK_SET);
606 535
607 self->frozen = 1; 536 header->frozen = 1;
608 return 0; 537 return 0;
609} 538}
610 539
611static int perf_header__getbuffer64(struct perf_header *self, 540static int perf_header__getbuffer64(struct perf_header *header,
612 int fd, void *buf, size_t size) 541 int fd, void *buf, size_t size)
613{ 542{
614 if (readn(fd, buf, size) <= 0) 543 if (readn(fd, buf, size) <= 0)
615 return -1; 544 return -1;
616 545
617 if (self->needs_swap) 546 if (header->needs_swap)
618 mem_bswap_64(buf, size); 547 mem_bswap_64(buf, size);
619 548
620 return 0; 549 return 0;
621} 550}
622 551
623int perf_header__process_sections(struct perf_header *self, int fd, 552int perf_header__process_sections(struct perf_header *header, int fd,
624 int (*process)(struct perf_file_section *self, 553 int (*process)(struct perf_file_section *section,
625 struct perf_header *ph, 554 struct perf_header *ph,
626 int feat, int fd)) 555 int feat, int fd))
627{ 556{
@@ -631,7 +560,7 @@ int perf_header__process_sections(struct perf_header *self, int fd,
631 int idx = 0; 560 int idx = 0;
632 int err = -1, feat = 1; 561 int err = -1, feat = 1;
633 562
634 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 563 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
635 if (!nr_sections) 564 if (!nr_sections)
636 return 0; 565 return 0;
637 566
@@ -641,17 +570,17 @@ int perf_header__process_sections(struct perf_header *self, int fd,
641 570
642 sec_size = sizeof(*feat_sec) * nr_sections; 571 sec_size = sizeof(*feat_sec) * nr_sections;
643 572
644 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 573 lseek(fd, header->data_offset + header->data_size, SEEK_SET);
645 574
646 if (perf_header__getbuffer64(self, fd, feat_sec, sec_size)) 575 if (perf_header__getbuffer64(header, fd, feat_sec, sec_size))
647 goto out_free; 576 goto out_free;
648 577
649 err = 0; 578 err = 0;
650 while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { 579 while (idx < nr_sections && feat < HEADER_LAST_FEATURE) {
651 if (perf_header__has_feat(self, feat)) { 580 if (perf_header__has_feat(header, feat)) {
652 struct perf_file_section *sec = &feat_sec[idx++]; 581 struct perf_file_section *sec = &feat_sec[idx++];
653 582
654 err = process(sec, self, feat, fd); 583 err = process(sec, header, feat, fd);
655 if (err < 0) 584 if (err < 0)
656 break; 585 break;
657 } 586 }
@@ -662,35 +591,35 @@ out_free:
662 return err; 591 return err;
663} 592}
664 593
665int perf_file_header__read(struct perf_file_header *self, 594int perf_file_header__read(struct perf_file_header *header,
666 struct perf_header *ph, int fd) 595 struct perf_header *ph, int fd)
667{ 596{
668 lseek(fd, 0, SEEK_SET); 597 lseek(fd, 0, SEEK_SET);
669 598
670 if (readn(fd, self, sizeof(*self)) <= 0 || 599 if (readn(fd, header, sizeof(*header)) <= 0 ||
671 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 600 memcmp(&header->magic, __perf_magic, sizeof(header->magic)))
672 return -1; 601 return -1;
673 602
674 if (self->attr_size != sizeof(struct perf_file_attr)) { 603 if (header->attr_size != sizeof(struct perf_file_attr)) {
675 u64 attr_size = bswap_64(self->attr_size); 604 u64 attr_size = bswap_64(header->attr_size);
676 605
677 if (attr_size != sizeof(struct perf_file_attr)) 606 if (attr_size != sizeof(struct perf_file_attr))
678 return -1; 607 return -1;
679 608
680 mem_bswap_64(self, offsetof(struct perf_file_header, 609 mem_bswap_64(header, offsetof(struct perf_file_header,
681 adds_features)); 610 adds_features));
682 ph->needs_swap = true; 611 ph->needs_swap = true;
683 } 612 }
684 613
685 if (self->size != sizeof(*self)) { 614 if (header->size != sizeof(*header)) {
686 /* Support the previous format */ 615 /* Support the previous format */
687 if (self->size == offsetof(typeof(*self), adds_features)) 616 if (header->size == offsetof(typeof(*header), adds_features))
688 bitmap_zero(self->adds_features, HEADER_FEAT_BITS); 617 bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
689 else 618 else
690 return -1; 619 return -1;
691 } 620 }
692 621
693 memcpy(&ph->adds_features, &self->adds_features, 622 memcpy(&ph->adds_features, &header->adds_features,
694 sizeof(ph->adds_features)); 623 sizeof(ph->adds_features));
695 /* 624 /*
696 * FIXME: hack that assumes that if we need swap the perf.data file 625 * FIXME: hack that assumes that if we need swap the perf.data file
@@ -704,10 +633,10 @@ int perf_file_header__read(struct perf_file_header *self,
704 perf_header__set_feat(ph, HEADER_BUILD_ID); 633 perf_header__set_feat(ph, HEADER_BUILD_ID);
705 } 634 }
706 635
707 ph->event_offset = self->event_types.offset; 636 ph->event_offset = header->event_types.offset;
708 ph->event_size = self->event_types.size; 637 ph->event_size = header->event_types.size;
709 ph->data_offset = self->data.offset; 638 ph->data_offset = header->data.offset;
710 ph->data_size = self->data.size; 639 ph->data_size = header->data.size;
711 return 0; 640 return 0;
712} 641}
713 642
@@ -766,11 +695,10 @@ out:
766 return err; 695 return err;
767} 696}
768 697
769static int perf_header__read_build_ids(struct perf_header *self, 698static int perf_header__read_build_ids(struct perf_header *header,
770 int input, u64 offset, u64 size) 699 int input, u64 offset, u64 size)
771{ 700{
772 struct perf_session *session = container_of(self, 701 struct perf_session *session = container_of(header, struct perf_session, header);
773 struct perf_session, header);
774 struct build_id_event bev; 702 struct build_id_event bev;
775 char filename[PATH_MAX]; 703 char filename[PATH_MAX];
776 u64 limit = offset + size; 704 u64 limit = offset + size;
@@ -782,7 +710,7 @@ static int perf_header__read_build_ids(struct perf_header *self,
782 if (read(input, &bev, sizeof(bev)) != sizeof(bev)) 710 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
783 goto out; 711 goto out;
784 712
785 if (self->needs_swap) 713 if (header->needs_swap)
786 perf_event_header__bswap(&bev.header); 714 perf_event_header__bswap(&bev.header);
787 715
788 len = bev.header.size - sizeof(bev); 716 len = bev.header.size - sizeof(bev);
@@ -798,13 +726,13 @@ out:
798 return err; 726 return err;
799} 727}
800 728
801static int perf_file_section__process(struct perf_file_section *self, 729static int perf_file_section__process(struct perf_file_section *section,
802 struct perf_header *ph, 730 struct perf_header *ph,
803 int feat, int fd) 731 int feat, int fd)
804{ 732{
805 if (lseek(fd, self->offset, SEEK_SET) == (off_t)-1) { 733 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
806 pr_debug("Failed to lseek to %" PRIu64 " offset for feature " 734 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
807 "%d, continuing...\n", self->offset, feat); 735 "%d, continuing...\n", section->offset, feat);
808 return 0; 736 return 0;
809 } 737 }
810 738
@@ -814,7 +742,7 @@ static int perf_file_section__process(struct perf_file_section *self,
814 break; 742 break;
815 743
816 case HEADER_BUILD_ID: 744 case HEADER_BUILD_ID:
817 if (perf_header__read_build_ids(ph, fd, self->offset, self->size)) 745 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
818 pr_debug("Failed to read buildids, continuing...\n"); 746 pr_debug("Failed to read buildids, continuing...\n");
819 break; 747 break;
820 default: 748 default:
@@ -824,21 +752,21 @@ static int perf_file_section__process(struct perf_file_section *self,
824 return 0; 752 return 0;
825} 753}
826 754
827static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, 755static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
828 struct perf_header *ph, int fd, 756 struct perf_header *ph, int fd,
829 bool repipe) 757 bool repipe)
830{ 758{
831 if (readn(fd, self, sizeof(*self)) <= 0 || 759 if (readn(fd, header, sizeof(*header)) <= 0 ||
832 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 760 memcmp(&header->magic, __perf_magic, sizeof(header->magic)))
833 return -1; 761 return -1;
834 762
835 if (repipe && do_write(STDOUT_FILENO, self, sizeof(*self)) < 0) 763 if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0)
836 return -1; 764 return -1;
837 765
838 if (self->size != sizeof(*self)) { 766 if (header->size != sizeof(*header)) {
839 u64 size = bswap_64(self->size); 767 u64 size = bswap_64(header->size);
840 768
841 if (size != sizeof(*self)) 769 if (size != sizeof(*header))
842 return -1; 770 return -1;
843 771
844 ph->needs_swap = true; 772 ph->needs_swap = true;
@@ -849,10 +777,10 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *self,
849 777
850static int perf_header__read_pipe(struct perf_session *session, int fd) 778static int perf_header__read_pipe(struct perf_session *session, int fd)
851{ 779{
852 struct perf_header *self = &session->header; 780 struct perf_header *header = &session->header;
853 struct perf_pipe_file_header f_header; 781 struct perf_pipe_file_header f_header;
854 782
855 if (perf_file_header__read_pipe(&f_header, self, fd, 783 if (perf_file_header__read_pipe(&f_header, header, fd,
856 session->repipe) < 0) { 784 session->repipe) < 0) {
857 pr_debug("incompatible file format\n"); 785 pr_debug("incompatible file format\n");
858 return -EINVAL; 786 return -EINVAL;
@@ -863,18 +791,22 @@ static int perf_header__read_pipe(struct perf_session *session, int fd)
863 return 0; 791 return 0;
864} 792}
865 793
866int perf_header__read(struct perf_session *session, int fd) 794int perf_session__read_header(struct perf_session *session, int fd)
867{ 795{
868 struct perf_header *self = &session->header; 796 struct perf_header *header = &session->header;
869 struct perf_file_header f_header; 797 struct perf_file_header f_header;
870 struct perf_file_attr f_attr; 798 struct perf_file_attr f_attr;
871 u64 f_id; 799 u64 f_id;
872 int nr_attrs, nr_ids, i, j; 800 int nr_attrs, nr_ids, i, j;
873 801
802 session->evlist = perf_evlist__new(NULL, NULL);
803 if (session->evlist == NULL)
804 return -ENOMEM;
805
874 if (session->fd_pipe) 806 if (session->fd_pipe)
875 return perf_header__read_pipe(session, fd); 807 return perf_header__read_pipe(session, fd);
876 808
877 if (perf_file_header__read(&f_header, self, fd) < 0) { 809 if (perf_file_header__read(&f_header, header, fd) < 0) {
878 pr_debug("incompatible file format\n"); 810 pr_debug("incompatible file format\n");
879 return -EINVAL; 811 return -EINVAL;
880 } 812 }
@@ -883,33 +815,39 @@ int perf_header__read(struct perf_session *session, int fd)
883 lseek(fd, f_header.attrs.offset, SEEK_SET); 815 lseek(fd, f_header.attrs.offset, SEEK_SET);
884 816
885 for (i = 0; i < nr_attrs; i++) { 817 for (i = 0; i < nr_attrs; i++) {
886 struct perf_header_attr *attr; 818 struct perf_evsel *evsel;
887 off_t tmp; 819 off_t tmp;
888 820
889 if (perf_header__getbuffer64(self, fd, &f_attr, sizeof(f_attr))) 821 if (perf_header__getbuffer64(header, fd, &f_attr, sizeof(f_attr)))
890 goto out_errno; 822 goto out_errno;
891 823
892 tmp = lseek(fd, 0, SEEK_CUR); 824 tmp = lseek(fd, 0, SEEK_CUR);
825 evsel = perf_evsel__new(&f_attr.attr, i);
893 826
894 attr = perf_header_attr__new(&f_attr.attr); 827 if (evsel == NULL)
895 if (attr == NULL) 828 goto out_delete_evlist;
896 return -ENOMEM; 829 /*
830 * Do it before so that if perf_evsel__alloc_id fails, this
831 * entry gets purged too at perf_evlist__delete().
832 */
833 perf_evlist__add(session->evlist, evsel);
897 834
898 nr_ids = f_attr.ids.size / sizeof(u64); 835 nr_ids = f_attr.ids.size / sizeof(u64);
836 /*
837 * We don't have the cpu and thread maps on the header, so
838 * for allocating the perf_sample_id table we fake 1 cpu and
839 * hattr->ids threads.
840 */
841 if (perf_evsel__alloc_id(evsel, 1, nr_ids))
842 goto out_delete_evlist;
843
899 lseek(fd, f_attr.ids.offset, SEEK_SET); 844 lseek(fd, f_attr.ids.offset, SEEK_SET);
900 845
901 for (j = 0; j < nr_ids; j++) { 846 for (j = 0; j < nr_ids; j++) {
902 if (perf_header__getbuffer64(self, fd, &f_id, sizeof(f_id))) 847 if (perf_header__getbuffer64(header, fd, &f_id, sizeof(f_id)))
903 goto out_errno; 848 goto out_errno;
904 849
905 if (perf_header_attr__add_id(attr, f_id) < 0) { 850 perf_evlist__id_add(session->evlist, evsel, 0, j, f_id);
906 perf_header_attr__delete(attr);
907 return -ENOMEM;
908 }
909 }
910 if (perf_header__add_attr(self, attr) < 0) {
911 perf_header_attr__delete(attr);
912 return -ENOMEM;
913 } 851 }
914 852
915 lseek(fd, tmp, SEEK_SET); 853 lseek(fd, tmp, SEEK_SET);
@@ -920,93 +858,63 @@ int perf_header__read(struct perf_session *session, int fd)
920 events = malloc(f_header.event_types.size); 858 events = malloc(f_header.event_types.size);
921 if (events == NULL) 859 if (events == NULL)
922 return -ENOMEM; 860 return -ENOMEM;
923 if (perf_header__getbuffer64(self, fd, events, 861 if (perf_header__getbuffer64(header, fd, events,
924 f_header.event_types.size)) 862 f_header.event_types.size))
925 goto out_errno; 863 goto out_errno;
926 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 864 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
927 } 865 }
928 866
929 perf_header__process_sections(self, fd, perf_file_section__process); 867 perf_header__process_sections(header, fd, perf_file_section__process);
930 868
931 lseek(fd, self->data_offset, SEEK_SET); 869 lseek(fd, header->data_offset, SEEK_SET);
932 870
933 self->frozen = 1; 871 header->frozen = 1;
934 return 0; 872 return 0;
935out_errno: 873out_errno:
936 return -errno; 874 return -errno;
875
876out_delete_evlist:
877 perf_evlist__delete(session->evlist);
878 session->evlist = NULL;
879 return -ENOMEM;
937} 880}
938 881
939u64 perf_header__sample_type(struct perf_header *header) 882u64 perf_evlist__sample_type(struct perf_evlist *evlist)
940{ 883{
884 struct perf_evsel *pos;
941 u64 type = 0; 885 u64 type = 0;
942 int i;
943
944 for (i = 0; i < header->attrs; i++) {
945 struct perf_header_attr *attr = header->attr[i];
946 886
887 list_for_each_entry(pos, &evlist->entries, node) {
947 if (!type) 888 if (!type)
948 type = attr->attr.sample_type; 889 type = pos->attr.sample_type;
949 else if (type != attr->attr.sample_type) 890 else if (type != pos->attr.sample_type)
950 die("non matching sample_type"); 891 die("non matching sample_type");
951 } 892 }
952 893
953 return type; 894 return type;
954} 895}
955 896
956bool perf_header__sample_id_all(const struct perf_header *header) 897bool perf_evlist__sample_id_all(const struct perf_evlist *evlist)
957{ 898{
958 bool value = false, first = true; 899 bool value = false, first = true;
959 int i; 900 struct perf_evsel *pos;
960
961 for (i = 0; i < header->attrs; i++) {
962 struct perf_header_attr *attr = header->attr[i];
963 901
902 list_for_each_entry(pos, &evlist->entries, node) {
964 if (first) { 903 if (first) {
965 value = attr->attr.sample_id_all; 904 value = pos->attr.sample_id_all;
966 first = false; 905 first = false;
967 } else if (value != attr->attr.sample_id_all) 906 } else if (value != pos->attr.sample_id_all)
968 die("non matching sample_id_all"); 907 die("non matching sample_id_all");
969 } 908 }
970 909
971 return value; 910 return value;
972} 911}
973 912
974struct perf_event_attr * 913int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
975perf_header__find_attr(u64 id, struct perf_header *header) 914 perf_event__handler_t process,
976{ 915 struct perf_session *session)
977 int i;
978
979 /*
980 * We set id to -1 if the data file doesn't contain sample
981 * ids. This can happen when the data file contains one type
982 * of event and in that case, the header can still store the
983 * event attribute information. Check for this and avoid
984 * walking through the entire list of ids which may be large.
985 */
986 if (id == -1ULL) {
987 if (header->attrs > 0)
988 return &header->attr[0]->attr;
989 return NULL;
990 }
991
992 for (i = 0; i < header->attrs; i++) {
993 struct perf_header_attr *attr = header->attr[i];
994 int j;
995
996 for (j = 0; j < attr->ids; j++) {
997 if (attr->id[j] == id)
998 return &attr->attr;
999 }
1000 }
1001
1002 return NULL;
1003}
1004
1005int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
1006 event__handler_t process,
1007 struct perf_session *session)
1008{ 916{
1009 event_t *ev; 917 union perf_event *ev;
1010 size_t size; 918 size_t size;
1011 int err; 919 int err;
1012 920
@@ -1033,17 +941,15 @@ int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
1033 return err; 941 return err;
1034} 942}
1035 943
1036int event__synthesize_attrs(struct perf_header *self, event__handler_t process, 944int perf_session__synthesize_attrs(struct perf_session *session,
1037 struct perf_session *session) 945 perf_event__handler_t process)
1038{ 946{
1039 struct perf_header_attr *attr; 947 struct perf_evsel *attr;
1040 int i, err = 0; 948 int err = 0;
1041
1042 for (i = 0; i < self->attrs; i++) {
1043 attr = self->attr[i];
1044 949
1045 err = event__synthesize_attr(&attr->attr, attr->ids, attr->id, 950 list_for_each_entry(attr, &session->evlist->entries, node) {
1046 process, session); 951 err = perf_event__synthesize_attr(&attr->attr, attr->ids,
952 attr->id, process, session);
1047 if (err) { 953 if (err) {
1048 pr_debug("failed to create perf header attribute\n"); 954 pr_debug("failed to create perf header attribute\n");
1049 return err; 955 return err;
@@ -1053,29 +959,39 @@ int event__synthesize_attrs(struct perf_header *self, event__handler_t process,
1053 return err; 959 return err;
1054} 960}
1055 961
1056int event__process_attr(event_t *self, struct perf_session *session) 962int perf_event__process_attr(union perf_event *event,
963 struct perf_session *session)
1057{ 964{
1058 struct perf_header_attr *attr;
1059 unsigned int i, ids, n_ids; 965 unsigned int i, ids, n_ids;
966 struct perf_evsel *evsel;
1060 967
1061 attr = perf_header_attr__new(&self->attr.attr); 968 if (session->evlist == NULL) {
1062 if (attr == NULL) 969 session->evlist = perf_evlist__new(NULL, NULL);
970 if (session->evlist == NULL)
971 return -ENOMEM;
972 }
973
974 evsel = perf_evsel__new(&event->attr.attr,
975 session->evlist->nr_entries);
976 if (evsel == NULL)
1063 return -ENOMEM; 977 return -ENOMEM;
1064 978
1065 ids = self->header.size; 979 perf_evlist__add(session->evlist, evsel);
1066 ids -= (void *)&self->attr.id - (void *)self; 980
981 ids = event->header.size;
982 ids -= (void *)&event->attr.id - (void *)event;
1067 n_ids = ids / sizeof(u64); 983 n_ids = ids / sizeof(u64);
984 /*
985 * We don't have the cpu and thread maps on the header, so
986 * for allocating the perf_sample_id table we fake 1 cpu and
987 * hattr->ids threads.
988 */
989 if (perf_evsel__alloc_id(evsel, 1, n_ids))
990 return -ENOMEM;
1068 991
1069 for (i = 0; i < n_ids; i++) { 992 for (i = 0; i < n_ids; i++) {
1070 if (perf_header_attr__add_id(attr, self->attr.id[i]) < 0) { 993 perf_evlist__id_add(session->evlist, evsel, 0, i,
1071 perf_header_attr__delete(attr); 994 event->attr.id[i]);
1072 return -ENOMEM;
1073 }
1074 }
1075
1076 if (perf_header__add_attr(&session->header, attr) < 0) {
1077 perf_header_attr__delete(attr);
1078 return -ENOMEM;
1079 } 995 }
1080 996
1081 perf_session__update_sample_type(session); 997 perf_session__update_sample_type(session);
@@ -1083,11 +999,11 @@ int event__process_attr(event_t *self, struct perf_session *session)
1083 return 0; 999 return 0;
1084} 1000}
1085 1001
1086int event__synthesize_event_type(u64 event_id, char *name, 1002int perf_event__synthesize_event_type(u64 event_id, char *name,
1087 event__handler_t process, 1003 perf_event__handler_t process,
1088 struct perf_session *session) 1004 struct perf_session *session)
1089{ 1005{
1090 event_t ev; 1006 union perf_event ev;
1091 size_t size = 0; 1007 size_t size = 0;
1092 int err = 0; 1008 int err = 0;
1093 1009
@@ -1108,8 +1024,8 @@ int event__synthesize_event_type(u64 event_id, char *name,
1108 return err; 1024 return err;
1109} 1025}
1110 1026
1111int event__synthesize_event_types(event__handler_t process, 1027int perf_event__synthesize_event_types(perf_event__handler_t process,
1112 struct perf_session *session) 1028 struct perf_session *session)
1113{ 1029{
1114 struct perf_trace_event_type *type; 1030 struct perf_trace_event_type *type;
1115 int i, err = 0; 1031 int i, err = 0;
@@ -1117,8 +1033,9 @@ int event__synthesize_event_types(event__handler_t process,
1117 for (i = 0; i < event_count; i++) { 1033 for (i = 0; i < event_count; i++) {
1118 type = &events[i]; 1034 type = &events[i];
1119 1035
1120 err = event__synthesize_event_type(type->event_id, type->name, 1036 err = perf_event__synthesize_event_type(type->event_id,
1121 process, session); 1037 type->name, process,
1038 session);
1122 if (err) { 1039 if (err) {
1123 pr_debug("failed to create perf header event type\n"); 1040 pr_debug("failed to create perf header event type\n");
1124 return err; 1041 return err;
@@ -1128,28 +1045,28 @@ int event__synthesize_event_types(event__handler_t process,
1128 return err; 1045 return err;
1129} 1046}
1130 1047
1131int event__process_event_type(event_t *self, 1048int perf_event__process_event_type(union perf_event *event,
1132 struct perf_session *session __unused) 1049 struct perf_session *session __unused)
1133{ 1050{
1134 if (perf_header__push_event(self->event_type.event_type.event_id, 1051 if (perf_header__push_event(event->event_type.event_type.event_id,
1135 self->event_type.event_type.name) < 0) 1052 event->event_type.event_type.name) < 0)
1136 return -ENOMEM; 1053 return -ENOMEM;
1137 1054
1138 return 0; 1055 return 0;
1139} 1056}
1140 1057
1141int event__synthesize_tracing_data(int fd, struct list_head *pattrs, 1058int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
1142 event__handler_t process, 1059 perf_event__handler_t process,
1143 struct perf_session *session __unused) 1060 struct perf_session *session __unused)
1144{ 1061{
1145 event_t ev; 1062 union perf_event ev;
1146 ssize_t size = 0, aligned_size = 0, padding; 1063 ssize_t size = 0, aligned_size = 0, padding;
1147 int err = 0; 1064 int err __used = 0;
1148 1065
1149 memset(&ev, 0, sizeof(ev)); 1066 memset(&ev, 0, sizeof(ev));
1150 1067
1151 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; 1068 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
1152 size = read_tracing_data_size(fd, pattrs); 1069 size = read_tracing_data_size(fd, &evlist->entries);
1153 if (size <= 0) 1070 if (size <= 0)
1154 return size; 1071 return size;
1155 aligned_size = ALIGN(size, sizeof(u64)); 1072 aligned_size = ALIGN(size, sizeof(u64));
@@ -1159,16 +1076,16 @@ int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
1159 1076
1160 process(&ev, NULL, session); 1077 process(&ev, NULL, session);
1161 1078
1162 err = read_tracing_data(fd, pattrs); 1079 err = read_tracing_data(fd, &evlist->entries);
1163 write_padded(fd, NULL, 0, padding); 1080 write_padded(fd, NULL, 0, padding);
1164 1081
1165 return aligned_size; 1082 return aligned_size;
1166} 1083}
1167 1084
1168int event__process_tracing_data(event_t *self, 1085int perf_event__process_tracing_data(union perf_event *event,
1169 struct perf_session *session) 1086 struct perf_session *session)
1170{ 1087{
1171 ssize_t size_read, padding, size = self->tracing_data.size; 1088 ssize_t size_read, padding, size = event->tracing_data.size;
1172 off_t offset = lseek(session->fd, 0, SEEK_CUR); 1089 off_t offset = lseek(session->fd, 0, SEEK_CUR);
1173 char buf[BUFSIZ]; 1090 char buf[BUFSIZ];
1174 1091
@@ -1194,12 +1111,12 @@ int event__process_tracing_data(event_t *self,
1194 return size_read + padding; 1111 return size_read + padding;
1195} 1112}
1196 1113
1197int event__synthesize_build_id(struct dso *pos, u16 misc, 1114int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
1198 event__handler_t process, 1115 perf_event__handler_t process,
1199 struct machine *machine, 1116 struct machine *machine,
1200 struct perf_session *session) 1117 struct perf_session *session)
1201{ 1118{
1202 event_t ev; 1119 union perf_event ev;
1203 size_t len; 1120 size_t len;
1204 int err = 0; 1121 int err = 0;
1205 1122
@@ -1222,11 +1139,11 @@ int event__synthesize_build_id(struct dso *pos, u16 misc,
1222 return err; 1139 return err;
1223} 1140}
1224 1141
1225int event__process_build_id(event_t *self, 1142int perf_event__process_build_id(union perf_event *event,
1226 struct perf_session *session) 1143 struct perf_session *session)
1227{ 1144{
1228 __event_process_build_id(&self->build_id, 1145 __event_process_build_id(&event->build_id,
1229 self->build_id.filename, 1146 event->build_id.filename,
1230 session); 1147 session);
1231 return 0; 1148 return 0;
1232} 1149}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 33f16be7b72f..456661d7f10e 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -9,13 +9,6 @@
9 9
10#include <linux/bitmap.h> 10#include <linux/bitmap.h>
11 11
12struct perf_header_attr {
13 struct perf_event_attr attr;
14 int ids, size;
15 u64 *id;
16 off_t id_offset;
17};
18
19enum { 12enum {
20 HEADER_TRACE_INFO = 1, 13 HEADER_TRACE_INFO = 1,
21 HEADER_BUILD_ID, 14 HEADER_BUILD_ID,
@@ -46,14 +39,12 @@ struct perf_pipe_file_header {
46 39
47struct perf_header; 40struct perf_header;
48 41
49int perf_file_header__read(struct perf_file_header *self, 42int perf_file_header__read(struct perf_file_header *header,
50 struct perf_header *ph, int fd); 43 struct perf_header *ph, int fd);
51 44
52struct perf_header { 45struct perf_header {
53 int frozen; 46 int frozen;
54 int attrs, size;
55 bool needs_swap; 47 bool needs_swap;
56 struct perf_header_attr **attr;
57 s64 attr_offset; 48 s64 attr_offset;
58 u64 data_offset; 49 u64 data_offset;
59 u64 data_size; 50 u64 data_size;
@@ -62,34 +53,25 @@ struct perf_header {
62 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); 53 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
63}; 54};
64 55
65int perf_header__init(struct perf_header *self); 56struct perf_evlist;
66void perf_header__exit(struct perf_header *self);
67 57
68int perf_header__read(struct perf_session *session, int fd); 58int perf_session__read_header(struct perf_session *session, int fd);
69int perf_header__write(struct perf_header *self, int fd, bool at_exit); 59int perf_session__write_header(struct perf_session *session,
60 struct perf_evlist *evlist,
61 int fd, bool at_exit);
70int perf_header__write_pipe(int fd); 62int perf_header__write_pipe(int fd);
71 63
72int perf_header__add_attr(struct perf_header *self,
73 struct perf_header_attr *attr);
74
75int perf_header__push_event(u64 id, const char *name); 64int perf_header__push_event(u64 id, const char *name);
76char *perf_header__find_event(u64 id); 65char *perf_header__find_event(u64 id);
77 66
78struct perf_header_attr *perf_header_attr__new(struct perf_event_attr *attr); 67u64 perf_evlist__sample_type(struct perf_evlist *evlist);
79void perf_header_attr__delete(struct perf_header_attr *self); 68bool perf_evlist__sample_id_all(const struct perf_evlist *evlist);
69void perf_header__set_feat(struct perf_header *header, int feat);
70void perf_header__clear_feat(struct perf_header *header, int feat);
71bool perf_header__has_feat(const struct perf_header *header, int feat);
80 72
81int perf_header_attr__add_id(struct perf_header_attr *self, u64 id); 73int perf_header__process_sections(struct perf_header *header, int fd,
82 74 int (*process)(struct perf_file_section *section,
83u64 perf_header__sample_type(struct perf_header *header);
84bool perf_header__sample_id_all(const struct perf_header *header);
85struct perf_event_attr *
86perf_header__find_attr(u64 id, struct perf_header *header);
87void perf_header__set_feat(struct perf_header *self, int feat);
88void perf_header__clear_feat(struct perf_header *self, int feat);
89bool perf_header__has_feat(const struct perf_header *self, int feat);
90
91int perf_header__process_sections(struct perf_header *self, int fd,
92 int (*process)(struct perf_file_section *self,
93 struct perf_header *ph, 75 struct perf_header *ph,
94 int feat, int fd)); 76 int feat, int fd));
95 77
@@ -97,32 +79,31 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
97 const char *name, bool is_kallsyms); 79 const char *name, bool is_kallsyms);
98int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); 80int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
99 81
100int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, 82int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
101 event__handler_t process, 83 perf_event__handler_t process,
102 struct perf_session *session);
103int event__synthesize_attrs(struct perf_header *self,
104 event__handler_t process,
105 struct perf_session *session);
106int event__process_attr(event_t *self, struct perf_session *session);
107
108int event__synthesize_event_type(u64 event_id, char *name,
109 event__handler_t process,
110 struct perf_session *session);
111int event__synthesize_event_types(event__handler_t process,
112 struct perf_session *session);
113int event__process_event_type(event_t *self,
114 struct perf_session *session);
115
116int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
117 event__handler_t process,
118 struct perf_session *session);
119int event__process_tracing_data(event_t *self,
120 struct perf_session *session); 84 struct perf_session *session);
85int perf_session__synthesize_attrs(struct perf_session *session,
86 perf_event__handler_t process);
87int perf_event__process_attr(union perf_event *event, struct perf_session *session);
88
89int perf_event__synthesize_event_type(u64 event_id, char *name,
90 perf_event__handler_t process,
91 struct perf_session *session);
92int perf_event__synthesize_event_types(perf_event__handler_t process,
93 struct perf_session *session);
94int perf_event__process_event_type(union perf_event *event,
95 struct perf_session *session);
121 96
122int event__synthesize_build_id(struct dso *pos, u16 misc, 97int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
123 event__handler_t process, 98 perf_event__handler_t process,
124 struct machine *machine, 99 struct perf_session *session);
125 struct perf_session *session); 100int perf_event__process_tracing_data(union perf_event *event,
126int event__process_build_id(event_t *self, struct perf_session *session); 101 struct perf_session *session);
127 102
103int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
104 perf_event__handler_t process,
105 struct machine *machine,
106 struct perf_session *session);
107int perf_event__process_build_id(union perf_event *event,
108 struct perf_session *session);
128#endif /* __PERF_HEADER_H */ 109#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index df51560f16f7..627a02e03c57 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,3 +1,4 @@
1#include "annotate.h"
1#include "util.h" 2#include "util.h"
2#include "build-id.h" 3#include "build-id.h"
3#include "hist.h" 4#include "hist.h"
@@ -49,6 +50,15 @@ static void hists__calc_col_len(struct hists *self, struct hist_entry *h)
49 50
50 if (h->ms.sym) 51 if (h->ms.sym)
51 hists__new_col_len(self, HISTC_SYMBOL, h->ms.sym->namelen); 52 hists__new_col_len(self, HISTC_SYMBOL, h->ms.sym->namelen);
53 else {
54 const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
55
56 if (hists__col_len(self, HISTC_DSO) < unresolved_col_width &&
57 !symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
58 !symbol_conf.dso_list)
59 hists__set_col_len(self, HISTC_DSO,
60 unresolved_col_width);
61 }
52 62
53 len = thread__comm_len(h->thread); 63 len = thread__comm_len(h->thread);
54 if (hists__new_col_len(self, HISTC_COMM, len)) 64 if (hists__new_col_len(self, HISTC_COMM, len))
@@ -211,7 +221,9 @@ void hist_entry__free(struct hist_entry *he)
211 * collapse the histogram 221 * collapse the histogram
212 */ 222 */
213 223
214static bool collapse__insert_entry(struct rb_root *root, struct hist_entry *he) 224static bool hists__collapse_insert_entry(struct hists *self,
225 struct rb_root *root,
226 struct hist_entry *he)
215{ 227{
216 struct rb_node **p = &root->rb_node; 228 struct rb_node **p = &root->rb_node;
217 struct rb_node *parent = NULL; 229 struct rb_node *parent = NULL;
@@ -226,8 +238,11 @@ static bool collapse__insert_entry(struct rb_root *root, struct hist_entry *he)
226 238
227 if (!cmp) { 239 if (!cmp) {
228 iter->period += he->period; 240 iter->period += he->period;
229 if (symbol_conf.use_callchain) 241 if (symbol_conf.use_callchain) {
230 callchain_merge(iter->callchain, he->callchain); 242 callchain_cursor_reset(&self->callchain_cursor);
243 callchain_merge(&self->callchain_cursor, iter->callchain,
244 he->callchain);
245 }
231 hist_entry__free(he); 246 hist_entry__free(he);
232 return false; 247 return false;
233 } 248 }
@@ -262,7 +277,7 @@ void hists__collapse_resort(struct hists *self)
262 next = rb_next(&n->rb_node); 277 next = rb_next(&n->rb_node);
263 278
264 rb_erase(&n->rb_node, &self->entries); 279 rb_erase(&n->rb_node, &self->entries);
265 if (collapse__insert_entry(&tmp, n)) 280 if (hists__collapse_insert_entry(self, &tmp, n))
266 hists__inc_nr_entries(self, n); 281 hists__inc_nr_entries(self, n);
267 } 282 }
268 283
@@ -425,7 +440,7 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
425 u64 cumul; 440 u64 cumul;
426 441
427 child = rb_entry(node, struct callchain_node, rb_node); 442 child = rb_entry(node, struct callchain_node, rb_node);
428 cumul = cumul_hits(child); 443 cumul = callchain_cumul_hits(child);
429 remaining -= cumul; 444 remaining -= cumul;
430 445
431 /* 446 /*
@@ -947,225 +962,14 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread)
947 } 962 }
948} 963}
949 964
950static int symbol__alloc_hist(struct symbol *self) 965int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
951{
952 struct sym_priv *priv = symbol__priv(self);
953 const int size = (sizeof(*priv->hist) +
954 (self->end - self->start) * sizeof(u64));
955
956 priv->hist = zalloc(size);
957 return priv->hist == NULL ? -1 : 0;
958}
959
960int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip)
961{
962 unsigned int sym_size, offset;
963 struct symbol *sym = self->ms.sym;
964 struct sym_priv *priv;
965 struct sym_hist *h;
966
967 if (!sym || !self->ms.map)
968 return 0;
969
970 priv = symbol__priv(sym);
971 if (priv->hist == NULL && symbol__alloc_hist(sym) < 0)
972 return -ENOMEM;
973
974 sym_size = sym->end - sym->start;
975 offset = ip - sym->start;
976
977 pr_debug3("%s: ip=%#" PRIx64 "\n", __func__, self->ms.map->unmap_ip(self->ms.map, ip));
978
979 if (offset >= sym_size)
980 return 0;
981
982 h = priv->hist;
983 h->sum++;
984 h->ip[offset]++;
985
986 pr_debug3("%#" PRIx64 " %s: period++ [ip: %#" PRIx64 ", %#" PRIx64
987 "] => %" PRIu64 "\n", self->ms.sym->start, self->ms.sym->name,
988 ip, ip - self->ms.sym->start, h->ip[offset]);
989 return 0;
990}
991
992static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize)
993{
994 struct objdump_line *self = malloc(sizeof(*self) + privsize);
995
996 if (self != NULL) {
997 self->offset = offset;
998 self->line = line;
999 }
1000
1001 return self;
1002}
1003
1004void objdump_line__free(struct objdump_line *self)
1005{
1006 free(self->line);
1007 free(self);
1008}
1009
1010static void objdump__add_line(struct list_head *head, struct objdump_line *line)
1011{
1012 list_add_tail(&line->node, head);
1013}
1014
1015struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
1016 struct objdump_line *pos)
1017{
1018 list_for_each_entry_continue(pos, head, node)
1019 if (pos->offset >= 0)
1020 return pos;
1021
1022 return NULL;
1023}
1024
1025static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file,
1026 struct list_head *head, size_t privsize)
1027{ 966{
1028 struct symbol *sym = self->ms.sym; 967 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
1029 struct objdump_line *objdump_line;
1030 char *line = NULL, *tmp, *tmp2, *c;
1031 size_t line_len;
1032 s64 line_ip, offset = -1;
1033
1034 if (getline(&line, &line_len, file) < 0)
1035 return -1;
1036
1037 if (!line)
1038 return -1;
1039
1040 while (line_len != 0 && isspace(line[line_len - 1]))
1041 line[--line_len] = '\0';
1042
1043 c = strchr(line, '\n');
1044 if (c)
1045 *c = 0;
1046
1047 line_ip = -1;
1048
1049 /*
1050 * Strip leading spaces:
1051 */
1052 tmp = line;
1053 while (*tmp) {
1054 if (*tmp != ' ')
1055 break;
1056 tmp++;
1057 }
1058
1059 if (*tmp) {
1060 /*
1061 * Parse hexa addresses followed by ':'
1062 */
1063 line_ip = strtoull(tmp, &tmp2, 16);
1064 if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0')
1065 line_ip = -1;
1066 }
1067
1068 if (line_ip != -1) {
1069 u64 start = map__rip_2objdump(self->ms.map, sym->start),
1070 end = map__rip_2objdump(self->ms.map, sym->end);
1071
1072 offset = line_ip - start;
1073 if (offset < 0 || (u64)line_ip > end)
1074 offset = -1;
1075 }
1076
1077 objdump_line = objdump_line__new(offset, line, privsize);
1078 if (objdump_line == NULL) {
1079 free(line);
1080 return -1;
1081 }
1082 objdump__add_line(head, objdump_line);
1083
1084 return 0;
1085} 968}
1086 969
1087int hist_entry__annotate(struct hist_entry *self, struct list_head *head, 970int hist_entry__annotate(struct hist_entry *he, size_t privsize)
1088 size_t privsize)
1089{ 971{
1090 struct symbol *sym = self->ms.sym; 972 return symbol__annotate(he->ms.sym, he->ms.map, privsize);
1091 struct map *map = self->ms.map;
1092 struct dso *dso = map->dso;
1093 char *filename = dso__build_id_filename(dso, NULL, 0);
1094 bool free_filename = true;
1095 char command[PATH_MAX * 2];
1096 FILE *file;
1097 int err = 0;
1098 u64 len;
1099 char symfs_filename[PATH_MAX];
1100
1101 if (filename) {
1102 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
1103 symbol_conf.symfs, filename);
1104 }
1105
1106 if (filename == NULL) {
1107 if (dso->has_build_id) {
1108 pr_err("Can't annotate %s: not enough memory\n",
1109 sym->name);
1110 return -ENOMEM;
1111 }
1112 goto fallback;
1113 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
1114 strstr(command, "[kernel.kallsyms]") ||
1115 access(symfs_filename, R_OK)) {
1116 free(filename);
1117fallback:
1118 /*
1119 * If we don't have build-ids or the build-id file isn't in the
1120 * cache, or is just a kallsyms file, well, lets hope that this
1121 * DSO is the same as when 'perf record' ran.
1122 */
1123 filename = dso->long_name;
1124 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
1125 symbol_conf.symfs, filename);
1126 free_filename = false;
1127 }
1128
1129 if (dso->origin == DSO__ORIG_KERNEL) {
1130 if (dso->annotate_warned)
1131 goto out_free_filename;
1132 err = -ENOENT;
1133 dso->annotate_warned = 1;
1134 pr_err("Can't annotate %s: No vmlinux file was found in the "
1135 "path\n", sym->name);
1136 goto out_free_filename;
1137 }
1138
1139 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
1140 filename, sym->name, map->unmap_ip(map, sym->start),
1141 map->unmap_ip(map, sym->end));
1142
1143 len = sym->end - sym->start;
1144
1145 pr_debug("annotating [%p] %30s : [%p] %30s\n",
1146 dso, dso->long_name, sym, sym->name);
1147
1148 snprintf(command, sizeof(command),
1149 "objdump --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand",
1150 map__rip_2objdump(map, sym->start),
1151 map__rip_2objdump(map, sym->end),
1152 symfs_filename, filename);
1153
1154 pr_debug("Executing: %s\n", command);
1155
1156 file = popen(command, "r");
1157 if (!file)
1158 goto out_free_filename;
1159
1160 while (!feof(file))
1161 if (hist_entry__parse_objdump_line(self, file, head, privsize) < 0)
1162 break;
1163
1164 pclose(file);
1165out_free_filename:
1166 if (free_filename)
1167 free(filename);
1168 return err;
1169} 973}
1170 974
1171void hists__inc_nr_events(struct hists *self, u32 type) 975void hists__inc_nr_events(struct hists *self, u32 type)
@@ -1180,8 +984,12 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
1180 size_t ret = 0; 984 size_t ret = 0;
1181 985
1182 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { 986 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
1183 const char *name = event__get_event_name(i); 987 const char *name;
988
989 if (self->stats.nr_events[i] == 0)
990 continue;
1184 991
992 name = perf_event__name(i);
1185 if (!strcmp(name, "UNKNOWN")) 993 if (!strcmp(name, "UNKNOWN"))
1186 continue; 994 continue;
1187 995
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ee789856a8c9..cb6858a2f9a3 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -9,33 +9,6 @@ extern struct callchain_param callchain_param;
9struct hist_entry; 9struct hist_entry;
10struct addr_location; 10struct addr_location;
11struct symbol; 11struct symbol;
12struct rb_root;
13
14struct objdump_line {
15 struct list_head node;
16 s64 offset;
17 char *line;
18};
19
20void objdump_line__free(struct objdump_line *self);
21struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
22 struct objdump_line *pos);
23
24struct sym_hist {
25 u64 sum;
26 u64 ip[0];
27};
28
29struct sym_ext {
30 struct rb_node node;
31 double percent;
32 char *path;
33};
34
35struct sym_priv {
36 struct sym_hist *hist;
37 struct sym_ext *ext;
38};
39 12
40/* 13/*
41 * The kernel collects the number of events it couldn't send in a stretch and 14 * The kernel collects the number of events it couldn't send in a stretch and
@@ -69,14 +42,13 @@ enum hist_column {
69}; 42};
70 43
71struct hists { 44struct hists {
72 struct rb_node rb_node;
73 struct rb_root entries; 45 struct rb_root entries;
74 u64 nr_entries; 46 u64 nr_entries;
75 struct events_stats stats; 47 struct events_stats stats;
76 u64 config;
77 u64 event_stream; 48 u64 event_stream;
78 u32 type;
79 u16 col_len[HISTC_NR_COLS]; 49 u16 col_len[HISTC_NR_COLS];
50 /* Best would be to reuse the session callchain cursor */
51 struct callchain_cursor callchain_cursor;
80}; 52};
81 53
82struct hist_entry *__hists__add_entry(struct hists *self, 54struct hist_entry *__hists__add_entry(struct hists *self,
@@ -102,9 +74,8 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
102size_t hists__fprintf(struct hists *self, struct hists *pair, 74size_t hists__fprintf(struct hists *self, struct hists *pair,
103 bool show_displacement, FILE *fp); 75 bool show_displacement, FILE *fp);
104 76
105int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip); 77int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
106int hist_entry__annotate(struct hist_entry *self, struct list_head *head, 78int hist_entry__annotate(struct hist_entry *self, size_t privsize);
107 size_t privsize);
108 79
109void hists__filter_by_dso(struct hists *self, const struct dso *dso); 80void hists__filter_by_dso(struct hists *self, const struct dso *dso);
110void hists__filter_by_thread(struct hists *self, const struct thread *thread); 81void hists__filter_by_thread(struct hists *self, const struct thread *thread);
@@ -113,21 +84,18 @@ u16 hists__col_len(struct hists *self, enum hist_column col);
113void hists__set_col_len(struct hists *self, enum hist_column col, u16 len); 84void hists__set_col_len(struct hists *self, enum hist_column col, u16 len);
114bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); 85bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
115 86
116#ifdef NO_NEWT_SUPPORT 87struct perf_evlist;
117static inline int hists__browse(struct hists *self __used,
118 const char *helpline __used,
119 const char *ev_name __used)
120{
121 return 0;
122}
123 88
124static inline int hists__tui_browse_tree(struct rb_root *self __used, 89#ifdef NO_NEWT_SUPPORT
125 const char *help __used) 90static inline
91int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used,
92 const char *help __used)
126{ 93{
127 return 0; 94 return 0;
128} 95}
129 96
130static inline int hist_entry__tui_annotate(struct hist_entry *self __used) 97static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
98 int evidx __used)
131{ 99{
132 return 0; 100 return 0;
133} 101}
@@ -135,14 +103,12 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used)
135#define KEY_RIGHT -2 103#define KEY_RIGHT -2
136#else 104#else
137#include <newt.h> 105#include <newt.h>
138int hists__browse(struct hists *self, const char *helpline, 106int hist_entry__tui_annotate(struct hist_entry *self, int evidx);
139 const char *ev_name);
140int hist_entry__tui_annotate(struct hist_entry *self);
141 107
142#define KEY_LEFT NEWT_KEY_LEFT 108#define KEY_LEFT NEWT_KEY_LEFT
143#define KEY_RIGHT NEWT_KEY_RIGHT 109#define KEY_RIGHT NEWT_KEY_RIGHT
144 110
145int hists__tui_browse_tree(struct rb_root *self, const char *help); 111int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help);
146#endif 112#endif
147 113
148unsigned int hists__sort_list_width(struct hists *self); 114unsigned int hists__sort_list_width(struct hists *self);
diff --git a/tools/perf/util/include/linux/list.h b/tools/perf/util/include/linux/list.h
index f5ca26e53fbb..356c7e467b83 100644
--- a/tools/perf/util/include/linux/list.h
+++ b/tools/perf/util/include/linux/list.h
@@ -1,3 +1,4 @@
1#include <linux/kernel.h>
1#include "../../../../include/linux/list.h" 2#include "../../../../include/linux/list.h"
2 3
3#ifndef PERF_LIST_H 4#ifndef PERF_LIST_H
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 135f69baf966..54a7e2634d58 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,6 +1,7 @@
1#include "../../../include/linux/hw_breakpoint.h" 1#include "../../../include/linux/hw_breakpoint.h"
2#include "util.h" 2#include "util.h"
3#include "../perf.h" 3#include "../perf.h"
4#include "evlist.h"
4#include "evsel.h" 5#include "evsel.h"
5#include "parse-options.h" 6#include "parse-options.h"
6#include "parse-events.h" 7#include "parse-events.h"
@@ -11,10 +12,6 @@
11#include "header.h" 12#include "header.h"
12#include "debugfs.h" 13#include "debugfs.h"
13 14
14int nr_counters;
15
16LIST_HEAD(evsel_list);
17
18struct event_symbol { 15struct event_symbol {
19 u8 type; 16 u8 type;
20 u64 config; 17 u64 config;
@@ -271,6 +268,9 @@ const char *event_name(struct perf_evsel *evsel)
271 u64 config = evsel->attr.config; 268 u64 config = evsel->attr.config;
272 int type = evsel->attr.type; 269 int type = evsel->attr.type;
273 270
271 if (evsel->name)
272 return evsel->name;
273
274 return __event_name(type, config); 274 return __event_name(type, config);
275} 275}
276 276
@@ -449,8 +449,8 @@ parse_single_tracepoint_event(char *sys_name,
449/* sys + ':' + event + ':' + flags*/ 449/* sys + ':' + event + ':' + flags*/
450#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128) 450#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128)
451static enum event_result 451static enum event_result
452parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp, 452parse_multiple_tracepoint_event(const struct option *opt, char *sys_name,
453 char *flags) 453 const char *evt_exp, char *flags)
454{ 454{
455 char evt_path[MAXPATHLEN]; 455 char evt_path[MAXPATHLEN];
456 struct dirent *evt_ent; 456 struct dirent *evt_ent;
@@ -483,15 +483,16 @@ parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp,
483 if (len < 0) 483 if (len < 0)
484 return EVT_FAILED; 484 return EVT_FAILED;
485 485
486 if (parse_events(NULL, event_opt, 0)) 486 if (parse_events(opt, event_opt, 0))
487 return EVT_FAILED; 487 return EVT_FAILED;
488 } 488 }
489 489
490 return EVT_HANDLED_ALL; 490 return EVT_HANDLED_ALL;
491} 491}
492 492
493static enum event_result parse_tracepoint_event(const char **strp, 493static enum event_result
494 struct perf_event_attr *attr) 494parse_tracepoint_event(const struct option *opt, const char **strp,
495 struct perf_event_attr *attr)
495{ 496{
496 const char *evt_name; 497 const char *evt_name;
497 char *flags = NULL, *comma_loc; 498 char *flags = NULL, *comma_loc;
@@ -530,7 +531,7 @@ static enum event_result parse_tracepoint_event(const char **strp,
530 return EVT_FAILED; 531 return EVT_FAILED;
531 if (strpbrk(evt_name, "*?")) { 532 if (strpbrk(evt_name, "*?")) {
532 *strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */ 533 *strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */
533 return parse_multiple_tracepoint_event(sys_name, evt_name, 534 return parse_multiple_tracepoint_event(opt, sys_name, evt_name,
534 flags); 535 flags);
535 } else { 536 } else {
536 return parse_single_tracepoint_event(sys_name, evt_name, 537 return parse_single_tracepoint_event(sys_name, evt_name,
@@ -740,11 +741,12 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr)
740 * Symbolic names are (almost) exactly matched. 741 * Symbolic names are (almost) exactly matched.
741 */ 742 */
742static enum event_result 743static enum event_result
743parse_event_symbols(const char **str, struct perf_event_attr *attr) 744parse_event_symbols(const struct option *opt, const char **str,
745 struct perf_event_attr *attr)
744{ 746{
745 enum event_result ret; 747 enum event_result ret;
746 748
747 ret = parse_tracepoint_event(str, attr); 749 ret = parse_tracepoint_event(opt, str, attr);
748 if (ret != EVT_FAILED) 750 if (ret != EVT_FAILED)
749 goto modifier; 751 goto modifier;
750 752
@@ -778,14 +780,17 @@ modifier:
778 return ret; 780 return ret;
779} 781}
780 782
781int parse_events(const struct option *opt __used, const char *str, int unset __used) 783int parse_events(const struct option *opt, const char *str, int unset __used)
782{ 784{
785 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
783 struct perf_event_attr attr; 786 struct perf_event_attr attr;
784 enum event_result ret; 787 enum event_result ret;
788 const char *ostr;
785 789
786 for (;;) { 790 for (;;) {
791 ostr = str;
787 memset(&attr, 0, sizeof(attr)); 792 memset(&attr, 0, sizeof(attr));
788 ret = parse_event_symbols(&str, &attr); 793 ret = parse_event_symbols(opt, &str, &attr);
789 if (ret == EVT_FAILED) 794 if (ret == EVT_FAILED)
790 return -1; 795 return -1;
791 796
@@ -794,12 +799,15 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
794 799
795 if (ret != EVT_HANDLED_ALL) { 800 if (ret != EVT_HANDLED_ALL) {
796 struct perf_evsel *evsel; 801 struct perf_evsel *evsel;
797 evsel = perf_evsel__new(&attr, 802 evsel = perf_evsel__new(&attr, evlist->nr_entries);
798 nr_counters);
799 if (evsel == NULL) 803 if (evsel == NULL)
800 return -1; 804 return -1;
801 list_add_tail(&evsel->node, &evsel_list); 805 perf_evlist__add(evlist, evsel);
802 ++nr_counters; 806
807 evsel->name = calloc(str - ostr + 1, 1);
808 if (!evsel->name)
809 return -1;
810 strncpy(evsel->name, ostr, str - ostr);
803 } 811 }
804 812
805 if (*str == 0) 813 if (*str == 0)
@@ -813,13 +821,14 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
813 return 0; 821 return 0;
814} 822}
815 823
816int parse_filter(const struct option *opt __used, const char *str, 824int parse_filter(const struct option *opt, const char *str,
817 int unset __used) 825 int unset __used)
818{ 826{
827 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
819 struct perf_evsel *last = NULL; 828 struct perf_evsel *last = NULL;
820 829
821 if (!list_empty(&evsel_list)) 830 if (evlist->nr_entries > 0)
822 last = list_entry(evsel_list.prev, struct perf_evsel, node); 831 last = list_entry(evlist->entries.prev, struct perf_evsel, node);
823 832
824 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { 833 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
825 fprintf(stderr, 834 fprintf(stderr,
@@ -849,7 +858,7 @@ static const char * const event_type_descriptors[] = {
849 * Print the events from <debugfs_mount_point>/tracing/events 858 * Print the events from <debugfs_mount_point>/tracing/events
850 */ 859 */
851 860
852static void print_tracepoint_events(void) 861void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
853{ 862{
854 DIR *sys_dir, *evt_dir; 863 DIR *sys_dir, *evt_dir;
855 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 864 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
@@ -864,6 +873,9 @@ static void print_tracepoint_events(void)
864 return; 873 return;
865 874
866 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 875 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
876 if (subsys_glob != NULL &&
877 !strglobmatch(sys_dirent.d_name, subsys_glob))
878 continue;
867 879
868 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 880 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
869 sys_dirent.d_name); 881 sys_dirent.d_name);
@@ -872,6 +884,10 @@ static void print_tracepoint_events(void)
872 continue; 884 continue;
873 885
874 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 886 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
887 if (event_glob != NULL &&
888 !strglobmatch(evt_dirent.d_name, event_glob))
889 continue;
890
875 snprintf(evt_path, MAXPATHLEN, "%s:%s", 891 snprintf(evt_path, MAXPATHLEN, "%s:%s",
876 sys_dirent.d_name, evt_dirent.d_name); 892 sys_dirent.d_name, evt_dirent.d_name);
877 printf(" %-42s [%s]\n", evt_path, 893 printf(" %-42s [%s]\n", evt_path,
@@ -923,13 +939,61 @@ int is_valid_tracepoint(const char *event_string)
923 return 0; 939 return 0;
924} 940}
925 941
942void print_events_type(u8 type)
943{
944 struct event_symbol *syms = event_symbols;
945 unsigned int i;
946 char name[64];
947
948 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
949 if (type != syms->type)
950 continue;
951
952 if (strlen(syms->alias))
953 snprintf(name, sizeof(name), "%s OR %s",
954 syms->symbol, syms->alias);
955 else
956 snprintf(name, sizeof(name), "%s", syms->symbol);
957
958 printf(" %-42s [%s]\n", name,
959 event_type_descriptors[type]);
960 }
961}
962
963int print_hwcache_events(const char *event_glob)
964{
965 unsigned int type, op, i, printed = 0;
966
967 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
968 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
969 /* skip invalid cache type */
970 if (!is_cache_op_valid(type, op))
971 continue;
972
973 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
974 char *name = event_cache_name(type, op, i);
975
976 if (event_glob != NULL &&
977 !strglobmatch(name, event_glob))
978 continue;
979
980 printf(" %-42s [%s]\n", name,
981 event_type_descriptors[PERF_TYPE_HW_CACHE]);
982 ++printed;
983 }
984 }
985 }
986
987 return printed;
988}
989
926/* 990/*
927 * Print the help text for the event symbols: 991 * Print the help text for the event symbols:
928 */ 992 */
929void print_events(void) 993void print_events(const char *event_glob)
930{ 994{
931 struct event_symbol *syms = event_symbols; 995 struct event_symbol *syms = event_symbols;
932 unsigned int i, type, op, prev_type = -1; 996 unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
933 char name[40]; 997 char name[40];
934 998
935 printf("\n"); 999 printf("\n");
@@ -938,8 +1002,16 @@ void print_events(void)
938 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 1002 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
939 type = syms->type; 1003 type = syms->type;
940 1004
941 if (type != prev_type) 1005 if (type != prev_type && printed) {
942 printf("\n"); 1006 printf("\n");
1007 printed = 0;
1008 ntypes_printed++;
1009 }
1010
1011 if (event_glob != NULL &&
1012 !(strglobmatch(syms->symbol, event_glob) ||
1013 (syms->alias && strglobmatch(syms->alias, event_glob))))
1014 continue;
943 1015
944 if (strlen(syms->alias)) 1016 if (strlen(syms->alias))
945 sprintf(name, "%s OR %s", syms->symbol, syms->alias); 1017 sprintf(name, "%s OR %s", syms->symbol, syms->alias);
@@ -949,22 +1021,17 @@ void print_events(void)
949 event_type_descriptors[type]); 1021 event_type_descriptors[type]);
950 1022
951 prev_type = type; 1023 prev_type = type;
1024 ++printed;
952 } 1025 }
953 1026
954 printf("\n"); 1027 if (ntypes_printed) {
955 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 1028 printed = 0;
956 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 1029 printf("\n");
957 /* skip invalid cache type */
958 if (!is_cache_op_valid(type, op))
959 continue;
960
961 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
962 printf(" %-42s [%s]\n",
963 event_cache_name(type, op, i),
964 event_type_descriptors[PERF_TYPE_HW_CACHE]);
965 }
966 }
967 } 1030 }
1031 print_hwcache_events(event_glob);
1032
1033 if (event_glob != NULL)
1034 return;
968 1035
969 printf("\n"); 1036 printf("\n");
970 printf(" %-42s [%s]\n", 1037 printf(" %-42s [%s]\n",
@@ -977,37 +1044,7 @@ void print_events(void)
977 event_type_descriptors[PERF_TYPE_BREAKPOINT]); 1044 event_type_descriptors[PERF_TYPE_BREAKPOINT]);
978 printf("\n"); 1045 printf("\n");
979 1046
980 print_tracepoint_events(); 1047 print_tracepoint_events(NULL, NULL);
981 1048
982 exit(129); 1049 exit(129);
983} 1050}
984
985int perf_evsel_list__create_default(void)
986{
987 struct perf_evsel *evsel;
988 struct perf_event_attr attr;
989
990 memset(&attr, 0, sizeof(attr));
991 attr.type = PERF_TYPE_HARDWARE;
992 attr.config = PERF_COUNT_HW_CPU_CYCLES;
993
994 evsel = perf_evsel__new(&attr, 0);
995
996 if (evsel == NULL)
997 return -ENOMEM;
998
999 list_add(&evsel->node, &evsel_list);
1000 ++nr_counters;
1001 return 0;
1002}
1003
1004void perf_evsel_list__delete(void)
1005{
1006 struct perf_evsel *pos, *n;
1007
1008 list_for_each_entry_safe(pos, n, &evsel_list, node) {
1009 list_del_init(&pos->node);
1010 perf_evsel__delete(pos);
1011 }
1012 nr_counters = 0;
1013}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 458e3ecf17af..212f88e07a9c 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -9,11 +9,6 @@
9struct list_head; 9struct list_head;
10struct perf_evsel; 10struct perf_evsel;
11 11
12extern struct list_head evsel_list;
13
14int perf_evsel_list__create_default(void);
15void perf_evsel_list__delete(void);
16
17struct option; 12struct option;
18 13
19struct tracepoint_path { 14struct tracepoint_path {
@@ -25,8 +20,6 @@ struct tracepoint_path {
25extern struct tracepoint_path *tracepoint_id_to_path(u64 config); 20extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
26extern bool have_tracepoints(struct list_head *evlist); 21extern bool have_tracepoints(struct list_head *evlist);
27 22
28extern int nr_counters;
29
30const char *event_name(struct perf_evsel *event); 23const char *event_name(struct perf_evsel *event);
31extern const char *__event_name(int type, u64 config); 24extern const char *__event_name(int type, u64 config);
32 25
@@ -35,7 +28,10 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
35 28
36#define EVENTS_HELP_MAX (128*1024) 29#define EVENTS_HELP_MAX (128*1024)
37 30
38extern void print_events(void); 31void print_events(const char *event_glob);
32void print_events_type(u8 type);
33void print_tracepoint_events(const char *subsys_glob, const char *event_glob);
34int print_hwcache_events(const char *event_glob);
39extern int is_valid_tracepoint(const char *event_string); 35extern int is_valid_tracepoint(const char *event_string);
40 36
41extern char debugfs_path[]; 37extern char debugfs_path[];
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 6e29d9c9dccc..5ddee66020a7 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -31,6 +31,7 @@
31#include <string.h> 31#include <string.h>
32#include <stdarg.h> 32#include <stdarg.h>
33#include <limits.h> 33#include <limits.h>
34#include <elf.h>
34 35
35#undef _GNU_SOURCE 36#undef _GNU_SOURCE
36#include "util.h" 37#include "util.h"
@@ -111,7 +112,25 @@ static struct symbol *__find_kernel_function_by_name(const char *name,
111 NULL); 112 NULL);
112} 113}
113 114
114const char *kernel_get_module_path(const char *module) 115static struct map *kernel_get_module_map(const char *module)
116{
117 struct rb_node *nd;
118 struct map_groups *grp = &machine.kmaps;
119
120 if (!module)
121 module = "kernel";
122
123 for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) {
124 struct map *pos = rb_entry(nd, struct map, rb_node);
125 if (strncmp(pos->dso->short_name + 1, module,
126 pos->dso->short_name_len - 2) == 0) {
127 return pos;
128 }
129 }
130 return NULL;
131}
132
133static struct dso *kernel_get_module_dso(const char *module)
115{ 134{
116 struct dso *dso; 135 struct dso *dso;
117 struct map *map; 136 struct map *map;
@@ -141,7 +160,13 @@ const char *kernel_get_module_path(const char *module)
141 } 160 }
142 } 161 }
143found: 162found:
144 return dso->long_name; 163 return dso;
164}
165
166const char *kernel_get_module_path(const char *module)
167{
168 struct dso *dso = kernel_get_module_dso(module);
169 return (dso) ? dso->long_name : NULL;
145} 170}
146 171
147#ifdef DWARF_SUPPORT 172#ifdef DWARF_SUPPORT
@@ -384,7 +409,7 @@ int show_line_range(struct line_range *lr, const char *module)
384 setup_pager(); 409 setup_pager();
385 410
386 if (lr->function) 411 if (lr->function)
387 fprintf(stdout, "<%s:%d>\n", lr->function, 412 fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path,
388 lr->start - lr->offset); 413 lr->start - lr->offset);
389 else 414 else
390 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start); 415 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
@@ -426,12 +451,14 @@ end:
426} 451}
427 452
428static int show_available_vars_at(int fd, struct perf_probe_event *pev, 453static int show_available_vars_at(int fd, struct perf_probe_event *pev,
429 int max_vls, bool externs) 454 int max_vls, struct strfilter *_filter,
455 bool externs)
430{ 456{
431 char *buf; 457 char *buf;
432 int ret, i; 458 int ret, i, nvars;
433 struct str_node *node; 459 struct str_node *node;
434 struct variable_list *vls = NULL, *vl; 460 struct variable_list *vls = NULL, *vl;
461 const char *var;
435 462
436 buf = synthesize_perf_probe_point(&pev->point); 463 buf = synthesize_perf_probe_point(&pev->point);
437 if (!buf) 464 if (!buf)
@@ -439,36 +466,45 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,
439 pr_debug("Searching variables at %s\n", buf); 466 pr_debug("Searching variables at %s\n", buf);
440 467
441 ret = find_available_vars_at(fd, pev, &vls, max_vls, externs); 468 ret = find_available_vars_at(fd, pev, &vls, max_vls, externs);
442 if (ret > 0) { 469 if (ret <= 0) {
443 /* Some variables were found */ 470 pr_err("Failed to find variables at %s (%d)\n", buf, ret);
444 fprintf(stdout, "Available variables at %s\n", buf); 471 goto end;
445 for (i = 0; i < ret; i++) { 472 }
446 vl = &vls[i]; 473 /* Some variables are found */
447 /* 474 fprintf(stdout, "Available variables at %s\n", buf);
448 * A probe point might be converted to 475 for (i = 0; i < ret; i++) {
449 * several trace points. 476 vl = &vls[i];
450 */ 477 /*
451 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, 478 * A probe point might be converted to
452 vl->point.offset); 479 * several trace points.
453 free(vl->point.symbol); 480 */
454 if (vl->vars) { 481 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
455 strlist__for_each(node, vl->vars) 482 vl->point.offset);
483 free(vl->point.symbol);
484 nvars = 0;
485 if (vl->vars) {
486 strlist__for_each(node, vl->vars) {
487 var = strchr(node->s, '\t') + 1;
488 if (strfilter__compare(_filter, var)) {
456 fprintf(stdout, "\t\t%s\n", node->s); 489 fprintf(stdout, "\t\t%s\n", node->s);
457 strlist__delete(vl->vars); 490 nvars++;
458 } else 491 }
459 fprintf(stdout, "(No variables)\n"); 492 }
493 strlist__delete(vl->vars);
460 } 494 }
461 free(vls); 495 if (nvars == 0)
462 } else 496 fprintf(stdout, "\t\t(No matched variables)\n");
463 pr_err("Failed to find variables at %s (%d)\n", buf, ret); 497 }
464 498 free(vls);
499end:
465 free(buf); 500 free(buf);
466 return ret; 501 return ret;
467} 502}
468 503
469/* Show available variables on given probe point */ 504/* Show available variables on given probe point */
470int show_available_vars(struct perf_probe_event *pevs, int npevs, 505int show_available_vars(struct perf_probe_event *pevs, int npevs,
471 int max_vls, const char *module, bool externs) 506 int max_vls, const char *module,
507 struct strfilter *_filter, bool externs)
472{ 508{
473 int i, fd, ret = 0; 509 int i, fd, ret = 0;
474 510
@@ -485,7 +521,8 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
485 setup_pager(); 521 setup_pager();
486 522
487 for (i = 0; i < npevs && ret >= 0; i++) 523 for (i = 0; i < npevs && ret >= 0; i++)
488 ret = show_available_vars_at(fd, &pevs[i], max_vls, externs); 524 ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter,
525 externs);
489 526
490 close(fd); 527 close(fd);
491 return ret; 528 return ret;
@@ -531,7 +568,9 @@ int show_line_range(struct line_range *lr __unused, const char *module __unused)
531 568
532int show_available_vars(struct perf_probe_event *pevs __unused, 569int show_available_vars(struct perf_probe_event *pevs __unused,
533 int npevs __unused, int max_vls __unused, 570 int npevs __unused, int max_vls __unused,
534 const char *module __unused, bool externs __unused) 571 const char *module __unused,
572 struct strfilter *filter __unused,
573 bool externs __unused)
535{ 574{
536 pr_warning("Debuginfo-analysis is not supported.\n"); 575 pr_warning("Debuginfo-analysis is not supported.\n");
537 return -ENOSYS; 576 return -ENOSYS;
@@ -556,11 +595,11 @@ static int parse_line_num(char **ptr, int *val, const char *what)
556 * The line range syntax is described by: 595 * The line range syntax is described by:
557 * 596 *
558 * SRC[:SLN[+NUM|-ELN]] 597 * SRC[:SLN[+NUM|-ELN]]
559 * FNC[:SLN[+NUM|-ELN]] 598 * FNC[@SRC][:SLN[+NUM|-ELN]]
560 */ 599 */
561int parse_line_range_desc(const char *arg, struct line_range *lr) 600int parse_line_range_desc(const char *arg, struct line_range *lr)
562{ 601{
563 char *range, *name = strdup(arg); 602 char *range, *file, *name = strdup(arg);
564 int err; 603 int err;
565 604
566 if (!name) 605 if (!name)
@@ -610,7 +649,16 @@ int parse_line_range_desc(const char *arg, struct line_range *lr)
610 } 649 }
611 } 650 }
612 651
613 if (strchr(name, '.')) 652 file = strchr(name, '@');
653 if (file) {
654 *file = '\0';
655 lr->file = strdup(++file);
656 if (lr->file == NULL) {
657 err = -ENOMEM;
658 goto err;
659 }
660 lr->function = name;
661 } else if (strchr(name, '.'))
614 lr->file = name; 662 lr->file = name;
615 else 663 else
616 lr->function = name; 664 lr->function = name;
@@ -1784,9 +1832,12 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1784 } 1832 }
1785 1833
1786 /* Loop 2: add all events */ 1834 /* Loop 2: add all events */
1787 for (i = 0; i < npevs && ret >= 0; i++) 1835 for (i = 0; i < npevs; i++) {
1788 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, 1836 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
1789 pkgs[i].ntevs, force_add); 1837 pkgs[i].ntevs, force_add);
1838 if (ret < 0)
1839 break;
1840 }
1790end: 1841end:
1791 /* Loop 3: cleanup and free trace events */ 1842 /* Loop 3: cleanup and free trace events */
1792 for (i = 0; i < npevs; i++) { 1843 for (i = 0; i < npevs; i++) {
@@ -1912,4 +1963,46 @@ int del_perf_probe_events(struct strlist *dellist)
1912 1963
1913 return ret; 1964 return ret;
1914} 1965}
1966/* TODO: don't use a global variable for filter ... */
1967static struct strfilter *available_func_filter;
1968
1969/*
1970 * If a symbol corresponds to a function with global binding and
1971 * matches filter return 0. For all others return 1.
1972 */
1973static int filter_available_functions(struct map *map __unused,
1974 struct symbol *sym)
1975{
1976 if (sym->binding == STB_GLOBAL &&
1977 strfilter__compare(available_func_filter, sym->name))
1978 return 0;
1979 return 1;
1980}
1981
1982int show_available_funcs(const char *module, struct strfilter *_filter)
1983{
1984 struct map *map;
1985 int ret;
1986
1987 setup_pager();
1988
1989 ret = init_vmlinux();
1990 if (ret < 0)
1991 return ret;
1915 1992
1993 map = kernel_get_module_map(module);
1994 if (!map) {
1995 pr_err("Failed to find %s map.\n", (module) ? : "kernel");
1996 return -EINVAL;
1997 }
1998 available_func_filter = _filter;
1999 if (map__load(map, filter_available_functions)) {
2000 pr_err("Failed to load map.\n");
2001 return -EINVAL;
2002 }
2003 if (!dso__sorted_by_name(map->dso, map->type))
2004 dso__sort_by_name(map->dso, map->type);
2005
2006 dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2007 return 0;
2008}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 5accbedfea37..3434fc9d79d5 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -3,6 +3,7 @@
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include "strlist.h" 5#include "strlist.h"
6#include "strfilter.h"
6 7
7extern bool probe_event_dry_run; 8extern bool probe_event_dry_run;
8 9
@@ -126,7 +127,8 @@ extern int show_perf_probe_events(void);
126extern int show_line_range(struct line_range *lr, const char *module); 127extern int show_line_range(struct line_range *lr, const char *module);
127extern int show_available_vars(struct perf_probe_event *pevs, int npevs, 128extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
128 int max_probe_points, const char *module, 129 int max_probe_points, const char *module,
129 bool externs); 130 struct strfilter *filter, bool externs);
131extern int show_available_funcs(const char *module, struct strfilter *filter);
130 132
131 133
132/* Maximum index number of event-name postfix */ 134/* Maximum index number of event-name postfix */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ab83b6ac5d65..194f9e2a3285 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -33,6 +33,7 @@
33#include <ctype.h> 33#include <ctype.h>
34#include <dwarf-regs.h> 34#include <dwarf-regs.h>
35 35
36#include <linux/bitops.h>
36#include "event.h" 37#include "event.h"
37#include "debug.h" 38#include "debug.h"
38#include "util.h" 39#include "util.h"
@@ -280,6 +281,19 @@ static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
280 return name ? (strcmp(tname, name) == 0) : false; 281 return name ? (strcmp(tname, name) == 0) : false;
281} 282}
282 283
284/* Get callsite line number of inline-function instance */
285static int die_get_call_lineno(Dwarf_Die *in_die)
286{
287 Dwarf_Attribute attr;
288 Dwarf_Word ret;
289
290 if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
291 return -ENOENT;
292
293 dwarf_formudata(&attr, &ret);
294 return (int)ret;
295}
296
283/* Get type die */ 297/* Get type die */
284static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) 298static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
285{ 299{
@@ -320,13 +334,23 @@ static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
320 return vr_die; 334 return vr_die;
321} 335}
322 336
323static bool die_is_signed_type(Dwarf_Die *tp_die) 337static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
338 Dwarf_Word *result)
324{ 339{
325 Dwarf_Attribute attr; 340 Dwarf_Attribute attr;
341
342 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
343 dwarf_formudata(&attr, result) != 0)
344 return -ENOENT;
345
346 return 0;
347}
348
349static bool die_is_signed_type(Dwarf_Die *tp_die)
350{
326 Dwarf_Word ret; 351 Dwarf_Word ret;
327 352
328 if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL || 353 if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
329 dwarf_formudata(&attr, &ret) != 0)
330 return false; 354 return false;
331 355
332 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed || 356 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
@@ -335,11 +359,29 @@ static bool die_is_signed_type(Dwarf_Die *tp_die)
335 359
336static int die_get_byte_size(Dwarf_Die *tp_die) 360static int die_get_byte_size(Dwarf_Die *tp_die)
337{ 361{
338 Dwarf_Attribute attr;
339 Dwarf_Word ret; 362 Dwarf_Word ret;
340 363
341 if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL || 364 if (die_get_attr_udata(tp_die, DW_AT_byte_size, &ret))
342 dwarf_formudata(&attr, &ret) != 0) 365 return 0;
366
367 return (int)ret;
368}
369
370static int die_get_bit_size(Dwarf_Die *tp_die)
371{
372 Dwarf_Word ret;
373
374 if (die_get_attr_udata(tp_die, DW_AT_bit_size, &ret))
375 return 0;
376
377 return (int)ret;
378}
379
380static int die_get_bit_offset(Dwarf_Die *tp_die)
381{
382 Dwarf_Word ret;
383
384 if (die_get_attr_udata(tp_die, DW_AT_bit_offset, &ret))
343 return 0; 385 return 0;
344 386
345 return (int)ret; 387 return (int)ret;
@@ -458,6 +500,151 @@ static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
458 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem); 500 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
459} 501}
460 502
503/* Walker on lines (Note: line number will not be sorted) */
504typedef int (* line_walk_handler_t) (const char *fname, int lineno,
505 Dwarf_Addr addr, void *data);
506
507struct __line_walk_param {
508 const char *fname;
509 line_walk_handler_t handler;
510 void *data;
511 int retval;
512};
513
514static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
515{
516 struct __line_walk_param *lw = data;
517 Dwarf_Addr addr;
518 int lineno;
519
520 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
521 lineno = die_get_call_lineno(in_die);
522 if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
523 lw->retval = lw->handler(lw->fname, lineno, addr,
524 lw->data);
525 if (lw->retval != 0)
526 return DIE_FIND_CB_FOUND;
527 }
528 }
529 return DIE_FIND_CB_SIBLING;
530}
531
532/* Walk on lines of blocks included in given DIE */
533static int __die_walk_funclines(Dwarf_Die *sp_die,
534 line_walk_handler_t handler, void *data)
535{
536 struct __line_walk_param lw = {
537 .handler = handler,
538 .data = data,
539 .retval = 0,
540 };
541 Dwarf_Die die_mem;
542 Dwarf_Addr addr;
543 int lineno;
544
545 /* Handle function declaration line */
546 lw.fname = dwarf_decl_file(sp_die);
547 if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
548 dwarf_entrypc(sp_die, &addr) == 0) {
549 lw.retval = handler(lw.fname, lineno, addr, data);
550 if (lw.retval != 0)
551 goto done;
552 }
553 die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
554done:
555 return lw.retval;
556}
557
558static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
559{
560 struct __line_walk_param *lw = data;
561
562 lw->retval = __die_walk_funclines(sp_die, lw->handler, lw->data);
563 if (lw->retval != 0)
564 return DWARF_CB_ABORT;
565
566 return DWARF_CB_OK;
567}
568
569/*
570 * Walk on lines inside given PDIE. If the PDIE is subprogram, walk only on
571 * the lines inside the subprogram, otherwise PDIE must be a CU DIE.
572 */
573static int die_walk_lines(Dwarf_Die *pdie, line_walk_handler_t handler,
574 void *data)
575{
576 Dwarf_Lines *lines;
577 Dwarf_Line *line;
578 Dwarf_Addr addr;
579 const char *fname;
580 int lineno, ret = 0;
581 Dwarf_Die die_mem, *cu_die;
582 size_t nlines, i;
583
584 /* Get the CU die */
585 if (dwarf_tag(pdie) == DW_TAG_subprogram)
586 cu_die = dwarf_diecu(pdie, &die_mem, NULL, NULL);
587 else
588 cu_die = pdie;
589 if (!cu_die) {
590 pr_debug2("Failed to get CU from subprogram\n");
591 return -EINVAL;
592 }
593
594 /* Get lines list in the CU */
595 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
596 pr_debug2("Failed to get source lines on this CU.\n");
597 return -ENOENT;
598 }
599 pr_debug2("Get %zd lines from this CU\n", nlines);
600
601 /* Walk on the lines on lines list */
602 for (i = 0; i < nlines; i++) {
603 line = dwarf_onesrcline(lines, i);
604 if (line == NULL ||
605 dwarf_lineno(line, &lineno) != 0 ||
606 dwarf_lineaddr(line, &addr) != 0) {
607 pr_debug2("Failed to get line info. "
608 "Possible error in debuginfo.\n");
609 continue;
610 }
611 /* Filter lines based on address */
612 if (pdie != cu_die)
613 /*
614 * Address filtering
615 * The line is included in given function, and
616 * no inline block includes it.
617 */
618 if (!dwarf_haspc(pdie, addr) ||
619 die_find_inlinefunc(pdie, addr, &die_mem))
620 continue;
621 /* Get source line */
622 fname = dwarf_linesrc(line, NULL, NULL);
623
624 ret = handler(fname, lineno, addr, data);
625 if (ret != 0)
626 return ret;
627 }
628
629 /*
630 * Dwarf lines doesn't include function declarations and inlined
631 * subroutines. We have to check functions list or given function.
632 */
633 if (pdie != cu_die)
634 ret = __die_walk_funclines(pdie, handler, data);
635 else {
636 struct __line_walk_param param = {
637 .handler = handler,
638 .data = data,
639 .retval = 0,
640 };
641 dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
642 ret = param.retval;
643 }
644
645 return ret;
646}
647
461struct __find_variable_param { 648struct __find_variable_param {
462 const char *name; 649 const char *name;
463 Dwarf_Addr addr; 650 Dwarf_Addr addr;
@@ -669,6 +856,8 @@ static_var:
669 return 0; 856 return 0;
670} 857}
671 858
859#define BYTES_TO_BITS(nb) ((nb) * BITS_PER_LONG / sizeof(long))
860
672static int convert_variable_type(Dwarf_Die *vr_die, 861static int convert_variable_type(Dwarf_Die *vr_die,
673 struct probe_trace_arg *tvar, 862 struct probe_trace_arg *tvar,
674 const char *cast) 863 const char *cast)
@@ -685,6 +874,14 @@ static int convert_variable_type(Dwarf_Die *vr_die,
685 return (tvar->type == NULL) ? -ENOMEM : 0; 874 return (tvar->type == NULL) ? -ENOMEM : 0;
686 } 875 }
687 876
877 if (die_get_bit_size(vr_die) != 0) {
878 /* This is a bitfield */
879 ret = snprintf(buf, 16, "b%d@%d/%zd", die_get_bit_size(vr_die),
880 die_get_bit_offset(vr_die),
881 BYTES_TO_BITS(die_get_byte_size(vr_die)));
882 goto formatted;
883 }
884
688 if (die_get_real_type(vr_die, &type) == NULL) { 885 if (die_get_real_type(vr_die, &type) == NULL) {
689 pr_warning("Failed to get a type information of %s.\n", 886 pr_warning("Failed to get a type information of %s.\n",
690 dwarf_diename(vr_die)); 887 dwarf_diename(vr_die));
@@ -729,29 +926,31 @@ static int convert_variable_type(Dwarf_Die *vr_die,
729 return (tvar->type == NULL) ? -ENOMEM : 0; 926 return (tvar->type == NULL) ? -ENOMEM : 0;
730 } 927 }
731 928
732 ret = die_get_byte_size(&type) * 8; 929 ret = BYTES_TO_BITS(die_get_byte_size(&type));
733 if (ret) { 930 if (!ret)
734 /* Check the bitwidth */ 931 /* No size ... try to use default type */
735 if (ret > MAX_BASIC_TYPE_BITS) { 932 return 0;
736 pr_info("%s exceeds max-bitwidth."
737 " Cut down to %d bits.\n",
738 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
739 ret = MAX_BASIC_TYPE_BITS;
740 }
741 933
742 ret = snprintf(buf, 16, "%c%d", 934 /* Check the bitwidth */
743 die_is_signed_type(&type) ? 's' : 'u', ret); 935 if (ret > MAX_BASIC_TYPE_BITS) {
744 if (ret < 0 || ret >= 16) { 936 pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n",
745 if (ret >= 16) 937 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
746 ret = -E2BIG; 938 ret = MAX_BASIC_TYPE_BITS;
747 pr_warning("Failed to convert variable type: %s\n", 939 }
748 strerror(-ret)); 940 ret = snprintf(buf, 16, "%c%d",
749 return ret; 941 die_is_signed_type(&type) ? 's' : 'u', ret);
750 } 942
751 tvar->type = strdup(buf); 943formatted:
752 if (tvar->type == NULL) 944 if (ret < 0 || ret >= 16) {
753 return -ENOMEM; 945 if (ret >= 16)
946 ret = -E2BIG;
947 pr_warning("Failed to convert variable type: %s\n",
948 strerror(-ret));
949 return ret;
754 } 950 }
951 tvar->type = strdup(buf);
952 if (tvar->type == NULL)
953 return -ENOMEM;
755 return 0; 954 return 0;
756} 955}
757 956
@@ -1050,157 +1249,102 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
1050 return ret; 1249 return ret;
1051} 1250}
1052 1251
1053/* Find probe point from its line number */ 1252static int probe_point_line_walker(const char *fname, int lineno,
1054static int find_probe_point_by_line(struct probe_finder *pf) 1253 Dwarf_Addr addr, void *data)
1055{ 1254{
1056 Dwarf_Lines *lines; 1255 struct probe_finder *pf = data;
1057 Dwarf_Line *line; 1256 int ret;
1058 size_t nlines, i;
1059 Dwarf_Addr addr;
1060 int lineno;
1061 int ret = 0;
1062
1063 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1064 pr_warning("No source lines found.\n");
1065 return -ENOENT;
1066 }
1067 1257
1068 for (i = 0; i < nlines && ret == 0; i++) { 1258 if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
1069 line = dwarf_onesrcline(lines, i); 1259 return 0;
1070 if (dwarf_lineno(line, &lineno) != 0 ||
1071 lineno != pf->lno)
1072 continue;
1073 1260
1074 /* TODO: Get fileno from line, but how? */ 1261 pf->addr = addr;
1075 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0) 1262 ret = call_probe_finder(NULL, pf);
1076 continue;
1077 1263
1078 if (dwarf_lineaddr(line, &addr) != 0) { 1264 /* Continue if no error, because the line will be in inline function */
1079 pr_warning("Failed to get the address of the line.\n"); 1265 return ret < 0 ? ret : 0;
1080 return -ENOENT; 1266}
1081 }
1082 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
1083 (int)i, lineno, (uintmax_t)addr);
1084 pf->addr = addr;
1085 1267
1086 ret = call_probe_finder(NULL, pf); 1268/* Find probe point from its line number */
1087 /* Continuing, because target line might be inlined. */ 1269static int find_probe_point_by_line(struct probe_finder *pf)
1088 } 1270{
1089 return ret; 1271 return die_walk_lines(&pf->cu_die, probe_point_line_walker, pf);
1090} 1272}
1091 1273
1092/* Find lines which match lazy pattern */ 1274/* Find lines which match lazy pattern */
1093static int find_lazy_match_lines(struct list_head *head, 1275static int find_lazy_match_lines(struct list_head *head,
1094 const char *fname, const char *pat) 1276 const char *fname, const char *pat)
1095{ 1277{
1096 char *fbuf, *p1, *p2; 1278 FILE *fp;
1097 int fd, line, nlines = -1; 1279 char *line = NULL;
1098 struct stat st; 1280 size_t line_len;
1099 1281 ssize_t len;
1100 fd = open(fname, O_RDONLY); 1282 int count = 0, linenum = 1;
1101 if (fd < 0) { 1283
1102 pr_warning("Failed to open %s: %s\n", fname, strerror(-fd)); 1284 fp = fopen(fname, "r");
1285 if (!fp) {
1286 pr_warning("Failed to open %s: %s\n", fname, strerror(errno));
1103 return -errno; 1287 return -errno;
1104 } 1288 }
1105 1289
1106 if (fstat(fd, &st) < 0) { 1290 while ((len = getline(&line, &line_len, fp)) > 0) {
1107 pr_warning("Failed to get the size of %s: %s\n", 1291
1108 fname, strerror(errno)); 1292 if (line[len - 1] == '\n')
1109 nlines = -errno; 1293 line[len - 1] = '\0';
1110 goto out_close; 1294
1111 } 1295 if (strlazymatch(line, pat)) {
1112 1296 line_list__add_line(head, linenum);
1113 nlines = -ENOMEM; 1297 count++;
1114 fbuf = malloc(st.st_size + 2);
1115 if (fbuf == NULL)
1116 goto out_close;
1117 if (read(fd, fbuf, st.st_size) < 0) {
1118 pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
1119 nlines = -errno;
1120 goto out_free_fbuf;
1121 }
1122 fbuf[st.st_size] = '\n'; /* Dummy line */
1123 fbuf[st.st_size + 1] = '\0';
1124 p1 = fbuf;
1125 line = 1;
1126 nlines = 0;
1127 while ((p2 = strchr(p1, '\n')) != NULL) {
1128 *p2 = '\0';
1129 if (strlazymatch(p1, pat)) {
1130 line_list__add_line(head, line);
1131 nlines++;
1132 } 1298 }
1133 line++; 1299 linenum++;
1134 p1 = p2 + 1;
1135 } 1300 }
1136out_free_fbuf: 1301
1137 free(fbuf); 1302 if (ferror(fp))
1138out_close: 1303 count = -errno;
1139 close(fd); 1304 free(line);
1140 return nlines; 1305 fclose(fp);
1306
1307 if (count == 0)
1308 pr_debug("No matched lines found in %s.\n", fname);
1309 return count;
1310}
1311
1312static int probe_point_lazy_walker(const char *fname, int lineno,
1313 Dwarf_Addr addr, void *data)
1314{
1315 struct probe_finder *pf = data;
1316 int ret;
1317
1318 if (!line_list__has_line(&pf->lcache, lineno) ||
1319 strtailcmp(fname, pf->fname) != 0)
1320 return 0;
1321
1322 pr_debug("Probe line found: line:%d addr:0x%llx\n",
1323 lineno, (unsigned long long)addr);
1324 pf->addr = addr;
1325 ret = call_probe_finder(NULL, pf);
1326
1327 /*
1328 * Continue if no error, because the lazy pattern will match
1329 * to other lines
1330 */
1331 return ret < 0 ? ret : 0;
1141} 1332}
1142 1333
1143/* Find probe points from lazy pattern */ 1334/* Find probe points from lazy pattern */
1144static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) 1335static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
1145{ 1336{
1146 Dwarf_Lines *lines;
1147 Dwarf_Line *line;
1148 size_t nlines, i;
1149 Dwarf_Addr addr;
1150 Dwarf_Die die_mem;
1151 int lineno;
1152 int ret = 0; 1337 int ret = 0;
1153 1338
1154 if (list_empty(&pf->lcache)) { 1339 if (list_empty(&pf->lcache)) {
1155 /* Matching lazy line pattern */ 1340 /* Matching lazy line pattern */
1156 ret = find_lazy_match_lines(&pf->lcache, pf->fname, 1341 ret = find_lazy_match_lines(&pf->lcache, pf->fname,
1157 pf->pev->point.lazy_line); 1342 pf->pev->point.lazy_line);
1158 if (ret == 0) { 1343 if (ret <= 0)
1159 pr_debug("No matched lines found in %s.\n", pf->fname);
1160 return 0;
1161 } else if (ret < 0)
1162 return ret; 1344 return ret;
1163 } 1345 }
1164 1346
1165 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 1347 return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
1166 pr_warning("No source lines found.\n");
1167 return -ENOENT;
1168 }
1169
1170 for (i = 0; i < nlines && ret >= 0; i++) {
1171 line = dwarf_onesrcline(lines, i);
1172
1173 if (dwarf_lineno(line, &lineno) != 0 ||
1174 !line_list__has_line(&pf->lcache, lineno))
1175 continue;
1176
1177 /* TODO: Get fileno from line, but how? */
1178 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
1179 continue;
1180
1181 if (dwarf_lineaddr(line, &addr) != 0) {
1182 pr_debug("Failed to get the address of line %d.\n",
1183 lineno);
1184 continue;
1185 }
1186 if (sp_die) {
1187 /* Address filtering 1: does sp_die include addr? */
1188 if (!dwarf_haspc(sp_die, addr))
1189 continue;
1190 /* Address filtering 2: No child include addr? */
1191 if (die_find_inlinefunc(sp_die, addr, &die_mem))
1192 continue;
1193 }
1194
1195 pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n",
1196 (int)i, lineno, (unsigned long long)addr);
1197 pf->addr = addr;
1198
1199 ret = call_probe_finder(sp_die, pf);
1200 /* Continuing, because target line might be inlined. */
1201 }
1202 /* TODO: deallocate lines, but how? */
1203 return ret;
1204} 1348}
1205 1349
1206/* Callback parameter with return value */ 1350/* Callback parameter with return value */
@@ -1318,8 +1462,7 @@ static int find_probes(int fd, struct probe_finder *pf)
1318 off = 0; 1462 off = 0;
1319 line_list__init(&pf->lcache); 1463 line_list__init(&pf->lcache);
1320 /* Loop on CUs (Compilation Unit) */ 1464 /* Loop on CUs (Compilation Unit) */
1321 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) && 1465 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
1322 ret >= 0) {
1323 /* Get the DIE(Debugging Information Entry) of this CU */ 1466 /* Get the DIE(Debugging Information Entry) of this CU */
1324 diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die); 1467 diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die);
1325 if (!diep) 1468 if (!diep)
@@ -1340,6 +1483,8 @@ static int find_probes(int fd, struct probe_finder *pf)
1340 pf->lno = pp->line; 1483 pf->lno = pp->line;
1341 ret = find_probe_point_by_line(pf); 1484 ret = find_probe_point_by_line(pf);
1342 } 1485 }
1486 if (ret < 0)
1487 break;
1343 } 1488 }
1344 off = noff; 1489 off = noff;
1345 } 1490 }
@@ -1644,91 +1789,28 @@ static int line_range_add_line(const char *src, unsigned int lineno,
1644 return line_list__add_line(&lr->line_list, lineno); 1789 return line_list__add_line(&lr->line_list, lineno);
1645} 1790}
1646 1791
1647/* Search function declaration lines */ 1792static int line_range_walk_cb(const char *fname, int lineno,
1648static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data) 1793 Dwarf_Addr addr __used,
1794 void *data)
1649{ 1795{
1650 struct dwarf_callback_param *param = data; 1796 struct line_finder *lf = data;
1651 struct line_finder *lf = param->data;
1652 const char *src;
1653 int lineno;
1654 1797
1655 src = dwarf_decl_file(sp_die); 1798 if ((strtailcmp(fname, lf->fname) != 0) ||
1656 if (src && strtailcmp(src, lf->fname) != 0)
1657 return DWARF_CB_OK;
1658
1659 if (dwarf_decl_line(sp_die, &lineno) != 0 ||
1660 (lf->lno_s > lineno || lf->lno_e < lineno)) 1799 (lf->lno_s > lineno || lf->lno_e < lineno))
1661 return DWARF_CB_OK; 1800 return 0;
1662 1801
1663 param->retval = line_range_add_line(src, lineno, lf->lr); 1802 if (line_range_add_line(fname, lineno, lf->lr) < 0)
1664 if (param->retval < 0) 1803 return -EINVAL;
1665 return DWARF_CB_ABORT;
1666 return DWARF_CB_OK;
1667}
1668 1804
1669static int find_line_range_func_decl_lines(struct line_finder *lf) 1805 return 0;
1670{
1671 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1672 dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, &param, 0);
1673 return param.retval;
1674} 1806}
1675 1807
1676/* Find line range from its line number */ 1808/* Find line range from its line number */
1677static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) 1809static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1678{ 1810{
1679 Dwarf_Lines *lines; 1811 int ret;
1680 Dwarf_Line *line;
1681 size_t nlines, i;
1682 Dwarf_Addr addr;
1683 int lineno, ret = 0;
1684 const char *src;
1685 Dwarf_Die die_mem;
1686
1687 line_list__init(&lf->lr->line_list);
1688 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
1689 pr_warning("No source lines found.\n");
1690 return -ENOENT;
1691 }
1692
1693 /* Search probable lines on lines list */
1694 for (i = 0; i < nlines; i++) {
1695 line = dwarf_onesrcline(lines, i);
1696 if (dwarf_lineno(line, &lineno) != 0 ||
1697 (lf->lno_s > lineno || lf->lno_e < lineno))
1698 continue;
1699
1700 if (sp_die) {
1701 /* Address filtering 1: does sp_die include addr? */
1702 if (dwarf_lineaddr(line, &addr) != 0 ||
1703 !dwarf_haspc(sp_die, addr))
1704 continue;
1705
1706 /* Address filtering 2: No child include addr? */
1707 if (die_find_inlinefunc(sp_die, addr, &die_mem))
1708 continue;
1709 }
1710
1711 /* TODO: Get fileno from line, but how? */
1712 src = dwarf_linesrc(line, NULL, NULL);
1713 if (strtailcmp(src, lf->fname) != 0)
1714 continue;
1715
1716 ret = line_range_add_line(src, lineno, lf->lr);
1717 if (ret < 0)
1718 return ret;
1719 }
1720 1812
1721 /* 1813 ret = die_walk_lines(sp_die ?: &lf->cu_die, line_range_walk_cb, lf);
1722 * Dwarf lines doesn't include function declarations. We have to
1723 * check functions list or given function.
1724 */
1725 if (sp_die) {
1726 src = dwarf_decl_file(sp_die);
1727 if (src && dwarf_decl_line(sp_die, &lineno) == 0 &&
1728 (lf->lno_s <= lineno && lf->lno_e >= lineno))
1729 ret = line_range_add_line(src, lineno, lf->lr);
1730 } else
1731 ret = find_line_range_func_decl_lines(lf);
1732 1814
1733 /* Update status */ 1815 /* Update status */
1734 if (ret >= 0) 1816 if (ret >= 0)
@@ -1758,9 +1840,6 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1758 struct line_finder *lf = param->data; 1840 struct line_finder *lf = param->data;
1759 struct line_range *lr = lf->lr; 1841 struct line_range *lr = lf->lr;
1760 1842
1761 pr_debug("find (%llx) %s\n",
1762 (unsigned long long)dwarf_dieoffset(sp_die),
1763 dwarf_diename(sp_die));
1764 if (dwarf_tag(sp_die) == DW_TAG_subprogram && 1843 if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
1765 die_compare_name(sp_die, lr->function)) { 1844 die_compare_name(sp_die, lr->function)) {
1766 lf->fname = dwarf_decl_file(sp_die); 1845 lf->fname = dwarf_decl_file(sp_die);
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
new file mode 100644
index 000000000000..a9f2d7e1204d
--- /dev/null
+++ b/tools/perf/util/python.c
@@ -0,0 +1,896 @@
1#include <Python.h>
2#include <structmember.h>
3#include <inttypes.h>
4#include <poll.h>
5#include "evlist.h"
6#include "evsel.h"
7#include "event.h"
8#include "cpumap.h"
9#include "thread_map.h"
10
11/* Define PyVarObject_HEAD_INIT for python 2.5 */
12#ifndef PyVarObject_HEAD_INIT
13# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
14#endif
15
16struct throttle_event {
17 struct perf_event_header header;
18 u64 time;
19 u64 id;
20 u64 stream_id;
21};
22
23PyMODINIT_FUNC initperf(void);
24
25#define member_def(type, member, ptype, help) \
26 { #member, ptype, \
27 offsetof(struct pyrf_event, event) + offsetof(struct type, member), \
28 0, help }
29
30#define sample_member_def(name, member, ptype, help) \
31 { #name, ptype, \
32 offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \
33 0, help }
34
35struct pyrf_event {
36 PyObject_HEAD
37 struct perf_sample sample;
38 union perf_event event;
39};
40
41#define sample_members \
42 sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"), \
43 sample_member_def(sample_pid, pid, T_INT, "event pid"), \
44 sample_member_def(sample_tid, tid, T_INT, "event tid"), \
45 sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \
46 sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"), \
47 sample_member_def(sample_id, id, T_ULONGLONG, "event id"), \
48 sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \
49 sample_member_def(sample_period, period, T_ULONGLONG, "event period"), \
50 sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
51
52static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object.");
53
54static PyMemberDef pyrf_mmap_event__members[] = {
55 sample_members
56 member_def(perf_event_header, type, T_UINT, "event type"),
57 member_def(mmap_event, pid, T_UINT, "event pid"),
58 member_def(mmap_event, tid, T_UINT, "event tid"),
59 member_def(mmap_event, start, T_ULONGLONG, "start of the map"),
60 member_def(mmap_event, len, T_ULONGLONG, "map length"),
61 member_def(mmap_event, pgoff, T_ULONGLONG, "page offset"),
62 member_def(mmap_event, filename, T_STRING_INPLACE, "backing store"),
63 { .name = NULL, },
64};
65
66static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent)
67{
68 PyObject *ret;
69 char *s;
70
71 if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64 ", "
72 "length: %#" PRIx64 ", offset: %#" PRIx64 ", "
73 "filename: %s }",
74 pevent->event.mmap.pid, pevent->event.mmap.tid,
75 pevent->event.mmap.start, pevent->event.mmap.len,
76 pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
77 ret = PyErr_NoMemory();
78 } else {
79 ret = PyString_FromString(s);
80 free(s);
81 }
82 return ret;
83}
84
85static PyTypeObject pyrf_mmap_event__type = {
86 PyVarObject_HEAD_INIT(NULL, 0)
87 .tp_name = "perf.mmap_event",
88 .tp_basicsize = sizeof(struct pyrf_event),
89 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
90 .tp_doc = pyrf_mmap_event__doc,
91 .tp_members = pyrf_mmap_event__members,
92 .tp_repr = (reprfunc)pyrf_mmap_event__repr,
93};
94
95static char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object.");
96
97static PyMemberDef pyrf_task_event__members[] = {
98 sample_members
99 member_def(perf_event_header, type, T_UINT, "event type"),
100 member_def(fork_event, pid, T_UINT, "event pid"),
101 member_def(fork_event, ppid, T_UINT, "event ppid"),
102 member_def(fork_event, tid, T_UINT, "event tid"),
103 member_def(fork_event, ptid, T_UINT, "event ptid"),
104 member_def(fork_event, time, T_ULONGLONG, "timestamp"),
105 { .name = NULL, },
106};
107
108static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent)
109{
110 return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
111 "ptid: %u, time: %" PRIu64 "}",
112 pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
113 pevent->event.fork.pid,
114 pevent->event.fork.ppid,
115 pevent->event.fork.tid,
116 pevent->event.fork.ptid,
117 pevent->event.fork.time);
118}
119
120static PyTypeObject pyrf_task_event__type = {
121 PyVarObject_HEAD_INIT(NULL, 0)
122 .tp_name = "perf.task_event",
123 .tp_basicsize = sizeof(struct pyrf_event),
124 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
125 .tp_doc = pyrf_task_event__doc,
126 .tp_members = pyrf_task_event__members,
127 .tp_repr = (reprfunc)pyrf_task_event__repr,
128};
129
130static char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object.");
131
132static PyMemberDef pyrf_comm_event__members[] = {
133 sample_members
134 member_def(perf_event_header, type, T_UINT, "event type"),
135 member_def(comm_event, pid, T_UINT, "event pid"),
136 member_def(comm_event, tid, T_UINT, "event tid"),
137 member_def(comm_event, comm, T_STRING_INPLACE, "process name"),
138 { .name = NULL, },
139};
140
141static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent)
142{
143 return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
144 pevent->event.comm.pid,
145 pevent->event.comm.tid,
146 pevent->event.comm.comm);
147}
148
149static PyTypeObject pyrf_comm_event__type = {
150 PyVarObject_HEAD_INIT(NULL, 0)
151 .tp_name = "perf.comm_event",
152 .tp_basicsize = sizeof(struct pyrf_event),
153 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
154 .tp_doc = pyrf_comm_event__doc,
155 .tp_members = pyrf_comm_event__members,
156 .tp_repr = (reprfunc)pyrf_comm_event__repr,
157};
158
159static char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object.");
160
161static PyMemberDef pyrf_throttle_event__members[] = {
162 sample_members
163 member_def(perf_event_header, type, T_UINT, "event type"),
164 member_def(throttle_event, time, T_ULONGLONG, "timestamp"),
165 member_def(throttle_event, id, T_ULONGLONG, "event id"),
166 member_def(throttle_event, stream_id, T_ULONGLONG, "event stream id"),
167 { .name = NULL, },
168};
169
170static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent)
171{
172 struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1);
173
174 return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64
175 ", stream_id: %" PRIu64 " }",
176 pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
177 te->time, te->id, te->stream_id);
178}
179
180static PyTypeObject pyrf_throttle_event__type = {
181 PyVarObject_HEAD_INIT(NULL, 0)
182 .tp_name = "perf.throttle_event",
183 .tp_basicsize = sizeof(struct pyrf_event),
184 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
185 .tp_doc = pyrf_throttle_event__doc,
186 .tp_members = pyrf_throttle_event__members,
187 .tp_repr = (reprfunc)pyrf_throttle_event__repr,
188};
189
190static int pyrf_event__setup_types(void)
191{
192 int err;
193 pyrf_mmap_event__type.tp_new =
194 pyrf_task_event__type.tp_new =
195 pyrf_comm_event__type.tp_new =
196 pyrf_throttle_event__type.tp_new = PyType_GenericNew;
197 err = PyType_Ready(&pyrf_mmap_event__type);
198 if (err < 0)
199 goto out;
200 err = PyType_Ready(&pyrf_task_event__type);
201 if (err < 0)
202 goto out;
203 err = PyType_Ready(&pyrf_comm_event__type);
204 if (err < 0)
205 goto out;
206 err = PyType_Ready(&pyrf_throttle_event__type);
207 if (err < 0)
208 goto out;
209out:
210 return err;
211}
212
213static PyTypeObject *pyrf_event__type[] = {
214 [PERF_RECORD_MMAP] = &pyrf_mmap_event__type,
215 [PERF_RECORD_LOST] = &pyrf_mmap_event__type,
216 [PERF_RECORD_COMM] = &pyrf_comm_event__type,
217 [PERF_RECORD_EXIT] = &pyrf_task_event__type,
218 [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type,
219 [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
220 [PERF_RECORD_FORK] = &pyrf_task_event__type,
221 [PERF_RECORD_READ] = &pyrf_mmap_event__type,
222 [PERF_RECORD_SAMPLE] = &pyrf_mmap_event__type,
223};
224
225static PyObject *pyrf_event__new(union perf_event *event)
226{
227 struct pyrf_event *pevent;
228 PyTypeObject *ptype;
229
230 if (event->header.type < PERF_RECORD_MMAP ||
231 event->header.type > PERF_RECORD_SAMPLE)
232 return NULL;
233
234 ptype = pyrf_event__type[event->header.type];
235 pevent = PyObject_New(struct pyrf_event, ptype);
236 if (pevent != NULL)
237 memcpy(&pevent->event, event, event->header.size);
238 return (PyObject *)pevent;
239}
240
241struct pyrf_cpu_map {
242 PyObject_HEAD
243
244 struct cpu_map *cpus;
245};
246
247static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
248 PyObject *args, PyObject *kwargs)
249{
250 static char *kwlist[] = { "cpustr", NULL, NULL, };
251 char *cpustr = NULL;
252
253 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
254 kwlist, &cpustr))
255 return -1;
256
257 pcpus->cpus = cpu_map__new(cpustr);
258 if (pcpus->cpus == NULL)
259 return -1;
260 return 0;
261}
262
263static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
264{
265 cpu_map__delete(pcpus->cpus);
266 pcpus->ob_type->tp_free((PyObject*)pcpus);
267}
268
269static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
270{
271 struct pyrf_cpu_map *pcpus = (void *)obj;
272
273 return pcpus->cpus->nr;
274}
275
276static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i)
277{
278 struct pyrf_cpu_map *pcpus = (void *)obj;
279
280 if (i >= pcpus->cpus->nr)
281 return NULL;
282
283 return Py_BuildValue("i", pcpus->cpus->map[i]);
284}
285
286static PySequenceMethods pyrf_cpu_map__sequence_methods = {
287 .sq_length = pyrf_cpu_map__length,
288 .sq_item = pyrf_cpu_map__item,
289};
290
291static char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object.");
292
293static PyTypeObject pyrf_cpu_map__type = {
294 PyVarObject_HEAD_INIT(NULL, 0)
295 .tp_name = "perf.cpu_map",
296 .tp_basicsize = sizeof(struct pyrf_cpu_map),
297 .tp_dealloc = (destructor)pyrf_cpu_map__delete,
298 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
299 .tp_doc = pyrf_cpu_map__doc,
300 .tp_as_sequence = &pyrf_cpu_map__sequence_methods,
301 .tp_init = (initproc)pyrf_cpu_map__init,
302};
303
304static int pyrf_cpu_map__setup_types(void)
305{
306 pyrf_cpu_map__type.tp_new = PyType_GenericNew;
307 return PyType_Ready(&pyrf_cpu_map__type);
308}
309
310struct pyrf_thread_map {
311 PyObject_HEAD
312
313 struct thread_map *threads;
314};
315
316static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
317 PyObject *args, PyObject *kwargs)
318{
319 static char *kwlist[] = { "pid", "tid", NULL, NULL, };
320 int pid = -1, tid = -1;
321
322 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii",
323 kwlist, &pid, &tid))
324 return -1;
325
326 pthreads->threads = thread_map__new(pid, tid);
327 if (pthreads->threads == NULL)
328 return -1;
329 return 0;
330}
331
332static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
333{
334 thread_map__delete(pthreads->threads);
335 pthreads->ob_type->tp_free((PyObject*)pthreads);
336}
337
338static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
339{
340 struct pyrf_thread_map *pthreads = (void *)obj;
341
342 return pthreads->threads->nr;
343}
344
345static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i)
346{
347 struct pyrf_thread_map *pthreads = (void *)obj;
348
349 if (i >= pthreads->threads->nr)
350 return NULL;
351
352 return Py_BuildValue("i", pthreads->threads->map[i]);
353}
354
355static PySequenceMethods pyrf_thread_map__sequence_methods = {
356 .sq_length = pyrf_thread_map__length,
357 .sq_item = pyrf_thread_map__item,
358};
359
360static char pyrf_thread_map__doc[] = PyDoc_STR("thread map object.");
361
362static PyTypeObject pyrf_thread_map__type = {
363 PyVarObject_HEAD_INIT(NULL, 0)
364 .tp_name = "perf.thread_map",
365 .tp_basicsize = sizeof(struct pyrf_thread_map),
366 .tp_dealloc = (destructor)pyrf_thread_map__delete,
367 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
368 .tp_doc = pyrf_thread_map__doc,
369 .tp_as_sequence = &pyrf_thread_map__sequence_methods,
370 .tp_init = (initproc)pyrf_thread_map__init,
371};
372
373static int pyrf_thread_map__setup_types(void)
374{
375 pyrf_thread_map__type.tp_new = PyType_GenericNew;
376 return PyType_Ready(&pyrf_thread_map__type);
377}
378
379struct pyrf_evsel {
380 PyObject_HEAD
381
382 struct perf_evsel evsel;
383};
384
385static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
386 PyObject *args, PyObject *kwargs)
387{
388 struct perf_event_attr attr = {
389 .type = PERF_TYPE_HARDWARE,
390 .config = PERF_COUNT_HW_CPU_CYCLES,
391 .sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID,
392 };
393 static char *kwlist[] = {
394 "type",
395 "config",
396 "sample_freq",
397 "sample_period",
398 "sample_type",
399 "read_format",
400 "disabled",
401 "inherit",
402 "pinned",
403 "exclusive",
404 "exclude_user",
405 "exclude_kernel",
406 "exclude_hv",
407 "exclude_idle",
408 "mmap",
409 "comm",
410 "freq",
411 "inherit_stat",
412 "enable_on_exec",
413 "task",
414 "watermark",
415 "precise_ip",
416 "mmap_data",
417 "sample_id_all",
418 "wakeup_events",
419 "bp_type",
420 "bp_addr",
421 "bp_len", NULL, NULL, };
422 u64 sample_period = 0;
423 u32 disabled = 0,
424 inherit = 0,
425 pinned = 0,
426 exclusive = 0,
427 exclude_user = 0,
428 exclude_kernel = 0,
429 exclude_hv = 0,
430 exclude_idle = 0,
431 mmap = 0,
432 comm = 0,
433 freq = 1,
434 inherit_stat = 0,
435 enable_on_exec = 0,
436 task = 0,
437 watermark = 0,
438 precise_ip = 0,
439 mmap_data = 0,
440 sample_id_all = 1;
441 int idx = 0;
442
443 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
444 "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist,
445 &attr.type, &attr.config, &attr.sample_freq,
446 &sample_period, &attr.sample_type,
447 &attr.read_format, &disabled, &inherit,
448 &pinned, &exclusive, &exclude_user,
449 &exclude_kernel, &exclude_hv, &exclude_idle,
450 &mmap, &comm, &freq, &inherit_stat,
451 &enable_on_exec, &task, &watermark,
452 &precise_ip, &mmap_data, &sample_id_all,
453 &attr.wakeup_events, &attr.bp_type,
454 &attr.bp_addr, &attr.bp_len, &idx))
455 return -1;
456
457 /* union... */
458 if (sample_period != 0) {
459 if (attr.sample_freq != 0)
460 return -1; /* FIXME: throw right exception */
461 attr.sample_period = sample_period;
462 }
463
464 /* Bitfields */
465 attr.disabled = disabled;
466 attr.inherit = inherit;
467 attr.pinned = pinned;
468 attr.exclusive = exclusive;
469 attr.exclude_user = exclude_user;
470 attr.exclude_kernel = exclude_kernel;
471 attr.exclude_hv = exclude_hv;
472 attr.exclude_idle = exclude_idle;
473 attr.mmap = mmap;
474 attr.comm = comm;
475 attr.freq = freq;
476 attr.inherit_stat = inherit_stat;
477 attr.enable_on_exec = enable_on_exec;
478 attr.task = task;
479 attr.watermark = watermark;
480 attr.precise_ip = precise_ip;
481 attr.mmap_data = mmap_data;
482 attr.sample_id_all = sample_id_all;
483
484 perf_evsel__init(&pevsel->evsel, &attr, idx);
485 return 0;
486}
487
488static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
489{
490 perf_evsel__exit(&pevsel->evsel);
491 pevsel->ob_type->tp_free((PyObject*)pevsel);
492}
493
494static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
495 PyObject *args, PyObject *kwargs)
496{
497 struct perf_evsel *evsel = &pevsel->evsel;
498 struct cpu_map *cpus = NULL;
499 struct thread_map *threads = NULL;
500 PyObject *pcpus = NULL, *pthreads = NULL;
501 int group = 0, overwrite = 0;
502 static char *kwlist[] = {"cpus", "threads", "group", "overwrite", NULL, NULL};
503
504 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
505 &pcpus, &pthreads, &group, &overwrite))
506 return NULL;
507
508 if (pthreads != NULL)
509 threads = ((struct pyrf_thread_map *)pthreads)->threads;
510
511 if (pcpus != NULL)
512 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
513
514 if (perf_evsel__open(evsel, cpus, threads, group, overwrite) < 0) {
515 PyErr_SetFromErrno(PyExc_OSError);
516 return NULL;
517 }
518
519 Py_INCREF(Py_None);
520 return Py_None;
521}
522
523static PyMethodDef pyrf_evsel__methods[] = {
524 {
525 .ml_name = "open",
526 .ml_meth = (PyCFunction)pyrf_evsel__open,
527 .ml_flags = METH_VARARGS | METH_KEYWORDS,
528 .ml_doc = PyDoc_STR("open the event selector file descriptor table.")
529 },
530 { .ml_name = NULL, }
531};
532
533static char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object.");
534
535static PyTypeObject pyrf_evsel__type = {
536 PyVarObject_HEAD_INIT(NULL, 0)
537 .tp_name = "perf.evsel",
538 .tp_basicsize = sizeof(struct pyrf_evsel),
539 .tp_dealloc = (destructor)pyrf_evsel__delete,
540 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
541 .tp_doc = pyrf_evsel__doc,
542 .tp_methods = pyrf_evsel__methods,
543 .tp_init = (initproc)pyrf_evsel__init,
544};
545
546static int pyrf_evsel__setup_types(void)
547{
548 pyrf_evsel__type.tp_new = PyType_GenericNew;
549 return PyType_Ready(&pyrf_evsel__type);
550}
551
552struct pyrf_evlist {
553 PyObject_HEAD
554
555 struct perf_evlist evlist;
556};
557
558static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
559 PyObject *args, PyObject *kwargs __used)
560{
561 PyObject *pcpus = NULL, *pthreads = NULL;
562 struct cpu_map *cpus;
563 struct thread_map *threads;
564
565 if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
566 return -1;
567
568 threads = ((struct pyrf_thread_map *)pthreads)->threads;
569 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
570 perf_evlist__init(&pevlist->evlist, cpus, threads);
571 return 0;
572}
573
574static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
575{
576 perf_evlist__exit(&pevlist->evlist);
577 pevlist->ob_type->tp_free((PyObject*)pevlist);
578}
579
580static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
581 PyObject *args, PyObject *kwargs)
582{
583 struct perf_evlist *evlist = &pevlist->evlist;
584 static char *kwlist[] = {"pages", "overwrite",
585 NULL, NULL};
586 int pages = 128, overwrite = false;
587
588 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
589 &pages, &overwrite))
590 return NULL;
591
592 if (perf_evlist__mmap(evlist, pages, overwrite) < 0) {
593 PyErr_SetFromErrno(PyExc_OSError);
594 return NULL;
595 }
596
597 Py_INCREF(Py_None);
598 return Py_None;
599}
600
601static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
602 PyObject *args, PyObject *kwargs)
603{
604 struct perf_evlist *evlist = &pevlist->evlist;
605 static char *kwlist[] = {"timeout", NULL, NULL};
606 int timeout = -1, n;
607
608 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
609 return NULL;
610
611 n = poll(evlist->pollfd, evlist->nr_fds, timeout);
612 if (n < 0) {
613 PyErr_SetFromErrno(PyExc_OSError);
614 return NULL;
615 }
616
617 return Py_BuildValue("i", n);
618}
619
620static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
621 PyObject *args __used, PyObject *kwargs __used)
622{
623 struct perf_evlist *evlist = &pevlist->evlist;
624 PyObject *list = PyList_New(0);
625 int i;
626
627 for (i = 0; i < evlist->nr_fds; ++i) {
628 PyObject *file;
629 FILE *fp = fdopen(evlist->pollfd[i].fd, "r");
630
631 if (fp == NULL)
632 goto free_list;
633
634 file = PyFile_FromFile(fp, "perf", "r", NULL);
635 if (file == NULL)
636 goto free_list;
637
638 if (PyList_Append(list, file) != 0) {
639 Py_DECREF(file);
640 goto free_list;
641 }
642
643 Py_DECREF(file);
644 }
645
646 return list;
647free_list:
648 return PyErr_NoMemory();
649}
650
651
652static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
653 PyObject *args, PyObject *kwargs __used)
654{
655 struct perf_evlist *evlist = &pevlist->evlist;
656 PyObject *pevsel;
657 struct perf_evsel *evsel;
658
659 if (!PyArg_ParseTuple(args, "O", &pevsel))
660 return NULL;
661
662 Py_INCREF(pevsel);
663 evsel = &((struct pyrf_evsel *)pevsel)->evsel;
664 evsel->idx = evlist->nr_entries;
665 perf_evlist__add(evlist, evsel);
666
667 return Py_BuildValue("i", evlist->nr_entries);
668}
669
670static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
671 PyObject *args, PyObject *kwargs)
672{
673 struct perf_evlist *evlist = &pevlist->evlist;
674 union perf_event *event;
675 int sample_id_all = 1, cpu;
676 static char *kwlist[] = {"sample_id_all", NULL, NULL};
677
678 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
679 &cpu, &sample_id_all))
680 return NULL;
681
682 event = perf_evlist__read_on_cpu(evlist, cpu);
683 if (event != NULL) {
684 struct perf_evsel *first;
685 PyObject *pyevent = pyrf_event__new(event);
686 struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
687
688 if (pyevent == NULL)
689 return PyErr_NoMemory();
690
691 first = list_entry(evlist->entries.next, struct perf_evsel, node);
692 perf_event__parse_sample(event, first->attr.sample_type, sample_id_all,
693 &pevent->sample);
694 return pyevent;
695 }
696
697 Py_INCREF(Py_None);
698 return Py_None;
699}
700
701static PyMethodDef pyrf_evlist__methods[] = {
702 {
703 .ml_name = "mmap",
704 .ml_meth = (PyCFunction)pyrf_evlist__mmap,
705 .ml_flags = METH_VARARGS | METH_KEYWORDS,
706 .ml_doc = PyDoc_STR("mmap the file descriptor table.")
707 },
708 {
709 .ml_name = "poll",
710 .ml_meth = (PyCFunction)pyrf_evlist__poll,
711 .ml_flags = METH_VARARGS | METH_KEYWORDS,
712 .ml_doc = PyDoc_STR("poll the file descriptor table.")
713 },
714 {
715 .ml_name = "get_pollfd",
716 .ml_meth = (PyCFunction)pyrf_evlist__get_pollfd,
717 .ml_flags = METH_VARARGS | METH_KEYWORDS,
718 .ml_doc = PyDoc_STR("get the poll file descriptor table.")
719 },
720 {
721 .ml_name = "add",
722 .ml_meth = (PyCFunction)pyrf_evlist__add,
723 .ml_flags = METH_VARARGS | METH_KEYWORDS,
724 .ml_doc = PyDoc_STR("adds an event selector to the list.")
725 },
726 {
727 .ml_name = "read_on_cpu",
728 .ml_meth = (PyCFunction)pyrf_evlist__read_on_cpu,
729 .ml_flags = METH_VARARGS | METH_KEYWORDS,
730 .ml_doc = PyDoc_STR("reads an event.")
731 },
732 { .ml_name = NULL, }
733};
734
735static Py_ssize_t pyrf_evlist__length(PyObject *obj)
736{
737 struct pyrf_evlist *pevlist = (void *)obj;
738
739 return pevlist->evlist.nr_entries;
740}
741
742static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
743{
744 struct pyrf_evlist *pevlist = (void *)obj;
745 struct perf_evsel *pos;
746
747 if (i >= pevlist->evlist.nr_entries)
748 return NULL;
749
750 list_for_each_entry(pos, &pevlist->evlist.entries, node)
751 if (i-- == 0)
752 break;
753
754 return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
755}
756
757static PySequenceMethods pyrf_evlist__sequence_methods = {
758 .sq_length = pyrf_evlist__length,
759 .sq_item = pyrf_evlist__item,
760};
761
762static char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
763
764static PyTypeObject pyrf_evlist__type = {
765 PyVarObject_HEAD_INIT(NULL, 0)
766 .tp_name = "perf.evlist",
767 .tp_basicsize = sizeof(struct pyrf_evlist),
768 .tp_dealloc = (destructor)pyrf_evlist__delete,
769 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
770 .tp_as_sequence = &pyrf_evlist__sequence_methods,
771 .tp_doc = pyrf_evlist__doc,
772 .tp_methods = pyrf_evlist__methods,
773 .tp_init = (initproc)pyrf_evlist__init,
774};
775
776static int pyrf_evlist__setup_types(void)
777{
778 pyrf_evlist__type.tp_new = PyType_GenericNew;
779 return PyType_Ready(&pyrf_evlist__type);
780}
781
782static struct {
783 const char *name;
784 int value;
785} perf__constants[] = {
786 { "TYPE_HARDWARE", PERF_TYPE_HARDWARE },
787 { "TYPE_SOFTWARE", PERF_TYPE_SOFTWARE },
788 { "TYPE_TRACEPOINT", PERF_TYPE_TRACEPOINT },
789 { "TYPE_HW_CACHE", PERF_TYPE_HW_CACHE },
790 { "TYPE_RAW", PERF_TYPE_RAW },
791 { "TYPE_BREAKPOINT", PERF_TYPE_BREAKPOINT },
792
793 { "COUNT_HW_CPU_CYCLES", PERF_COUNT_HW_CPU_CYCLES },
794 { "COUNT_HW_INSTRUCTIONS", PERF_COUNT_HW_INSTRUCTIONS },
795 { "COUNT_HW_CACHE_REFERENCES", PERF_COUNT_HW_CACHE_REFERENCES },
796 { "COUNT_HW_CACHE_MISSES", PERF_COUNT_HW_CACHE_MISSES },
797 { "COUNT_HW_BRANCH_INSTRUCTIONS", PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
798 { "COUNT_HW_BRANCH_MISSES", PERF_COUNT_HW_BRANCH_MISSES },
799 { "COUNT_HW_BUS_CYCLES", PERF_COUNT_HW_BUS_CYCLES },
800 { "COUNT_HW_CACHE_L1D", PERF_COUNT_HW_CACHE_L1D },
801 { "COUNT_HW_CACHE_L1I", PERF_COUNT_HW_CACHE_L1I },
802 { "COUNT_HW_CACHE_LL", PERF_COUNT_HW_CACHE_LL },
803 { "COUNT_HW_CACHE_DTLB", PERF_COUNT_HW_CACHE_DTLB },
804 { "COUNT_HW_CACHE_ITLB", PERF_COUNT_HW_CACHE_ITLB },
805 { "COUNT_HW_CACHE_BPU", PERF_COUNT_HW_CACHE_BPU },
806 { "COUNT_HW_CACHE_OP_READ", PERF_COUNT_HW_CACHE_OP_READ },
807 { "COUNT_HW_CACHE_OP_WRITE", PERF_COUNT_HW_CACHE_OP_WRITE },
808 { "COUNT_HW_CACHE_OP_PREFETCH", PERF_COUNT_HW_CACHE_OP_PREFETCH },
809 { "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS },
810 { "COUNT_HW_CACHE_RESULT_MISS", PERF_COUNT_HW_CACHE_RESULT_MISS },
811
812 { "COUNT_SW_CPU_CLOCK", PERF_COUNT_SW_CPU_CLOCK },
813 { "COUNT_SW_TASK_CLOCK", PERF_COUNT_SW_TASK_CLOCK },
814 { "COUNT_SW_PAGE_FAULTS", PERF_COUNT_SW_PAGE_FAULTS },
815 { "COUNT_SW_CONTEXT_SWITCHES", PERF_COUNT_SW_CONTEXT_SWITCHES },
816 { "COUNT_SW_CPU_MIGRATIONS", PERF_COUNT_SW_CPU_MIGRATIONS },
817 { "COUNT_SW_PAGE_FAULTS_MIN", PERF_COUNT_SW_PAGE_FAULTS_MIN },
818 { "COUNT_SW_PAGE_FAULTS_MAJ", PERF_COUNT_SW_PAGE_FAULTS_MAJ },
819 { "COUNT_SW_ALIGNMENT_FAULTS", PERF_COUNT_SW_ALIGNMENT_FAULTS },
820 { "COUNT_SW_EMULATION_FAULTS", PERF_COUNT_SW_EMULATION_FAULTS },
821
822 { "SAMPLE_IP", PERF_SAMPLE_IP },
823 { "SAMPLE_TID", PERF_SAMPLE_TID },
824 { "SAMPLE_TIME", PERF_SAMPLE_TIME },
825 { "SAMPLE_ADDR", PERF_SAMPLE_ADDR },
826 { "SAMPLE_READ", PERF_SAMPLE_READ },
827 { "SAMPLE_CALLCHAIN", PERF_SAMPLE_CALLCHAIN },
828 { "SAMPLE_ID", PERF_SAMPLE_ID },
829 { "SAMPLE_CPU", PERF_SAMPLE_CPU },
830 { "SAMPLE_PERIOD", PERF_SAMPLE_PERIOD },
831 { "SAMPLE_STREAM_ID", PERF_SAMPLE_STREAM_ID },
832 { "SAMPLE_RAW", PERF_SAMPLE_RAW },
833
834 { "FORMAT_TOTAL_TIME_ENABLED", PERF_FORMAT_TOTAL_TIME_ENABLED },
835 { "FORMAT_TOTAL_TIME_RUNNING", PERF_FORMAT_TOTAL_TIME_RUNNING },
836 { "FORMAT_ID", PERF_FORMAT_ID },
837 { "FORMAT_GROUP", PERF_FORMAT_GROUP },
838
839 { "RECORD_MMAP", PERF_RECORD_MMAP },
840 { "RECORD_LOST", PERF_RECORD_LOST },
841 { "RECORD_COMM", PERF_RECORD_COMM },
842 { "RECORD_EXIT", PERF_RECORD_EXIT },
843 { "RECORD_THROTTLE", PERF_RECORD_THROTTLE },
844 { "RECORD_UNTHROTTLE", PERF_RECORD_UNTHROTTLE },
845 { "RECORD_FORK", PERF_RECORD_FORK },
846 { "RECORD_READ", PERF_RECORD_READ },
847 { "RECORD_SAMPLE", PERF_RECORD_SAMPLE },
848 { .name = NULL, },
849};
850
851static PyMethodDef perf__methods[] = {
852 { .ml_name = NULL, }
853};
854
855PyMODINIT_FUNC initperf(void)
856{
857 PyObject *obj;
858 int i;
859 PyObject *dict, *module = Py_InitModule("perf", perf__methods);
860
861 if (module == NULL ||
862 pyrf_event__setup_types() < 0 ||
863 pyrf_evlist__setup_types() < 0 ||
864 pyrf_evsel__setup_types() < 0 ||
865 pyrf_thread_map__setup_types() < 0 ||
866 pyrf_cpu_map__setup_types() < 0)
867 return;
868
869 Py_INCREF(&pyrf_evlist__type);
870 PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
871
872 Py_INCREF(&pyrf_evsel__type);
873 PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
874
875 Py_INCREF(&pyrf_thread_map__type);
876 PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
877
878 Py_INCREF(&pyrf_cpu_map__type);
879 PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
880
881 dict = PyModule_GetDict(module);
882 if (dict == NULL)
883 goto error;
884
885 for (i = 0; perf__constants[i].name != NULL; i++) {
886 obj = PyInt_FromLong(perf__constants[i].value);
887 if (obj == NULL)
888 goto error;
889 PyDict_SetItemString(dict, perf__constants[i].name, obj);
890 Py_DECREF(obj);
891 }
892
893error:
894 if (PyErr_Occurred())
895 PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
896}
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index c6d99334bdfa..2040b8538527 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -248,8 +248,7 @@ static void python_process_event(int cpu, void *data,
248 context = PyCObject_FromVoidPtr(scripting_context, NULL); 248 context = PyCObject_FromVoidPtr(scripting_context, NULL);
249 249
250 PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); 250 PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
251 PyTuple_SetItem(t, n++, 251 PyTuple_SetItem(t, n++, context);
252 PyCObject_FromVoidPtr(scripting_context, NULL));
253 252
254 if (handler) { 253 if (handler) {
255 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 254 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 105f00bfd555..f26639fa0fb3 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -7,6 +7,8 @@
7#include <sys/types.h> 7#include <sys/types.h>
8#include <sys/mman.h> 8#include <sys/mman.h>
9 9
10#include "evlist.h"
11#include "evsel.h"
10#include "session.h" 12#include "session.h"
11#include "sort.h" 13#include "sort.h"
12#include "util.h" 14#include "util.h"
@@ -19,7 +21,7 @@ static int perf_session__open(struct perf_session *self, bool force)
19 self->fd_pipe = true; 21 self->fd_pipe = true;
20 self->fd = STDIN_FILENO; 22 self->fd = STDIN_FILENO;
21 23
22 if (perf_header__read(self, self->fd) < 0) 24 if (perf_session__read_header(self, self->fd) < 0)
23 pr_err("incompatible file format"); 25 pr_err("incompatible file format");
24 26
25 return 0; 27 return 0;
@@ -51,7 +53,7 @@ static int perf_session__open(struct perf_session *self, bool force)
51 goto out_close; 53 goto out_close;
52 } 54 }
53 55
54 if (perf_header__read(self, self->fd) < 0) { 56 if (perf_session__read_header(self, self->fd) < 0) {
55 pr_err("incompatible file format"); 57 pr_err("incompatible file format");
56 goto out_close; 58 goto out_close;
57 } 59 }
@@ -67,7 +69,7 @@ out_close:
67 69
68static void perf_session__id_header_size(struct perf_session *session) 70static void perf_session__id_header_size(struct perf_session *session)
69{ 71{
70 struct sample_data *data; 72 struct perf_sample *data;
71 u64 sample_type = session->sample_type; 73 u64 sample_type = session->sample_type;
72 u16 size = 0; 74 u16 size = 0;
73 75
@@ -92,21 +94,10 @@ out:
92 session->id_hdr_size = size; 94 session->id_hdr_size = size;
93} 95}
94 96
95void perf_session__set_sample_id_all(struct perf_session *session, bool value)
96{
97 session->sample_id_all = value;
98 perf_session__id_header_size(session);
99}
100
101void perf_session__set_sample_type(struct perf_session *session, u64 type)
102{
103 session->sample_type = type;
104}
105
106void perf_session__update_sample_type(struct perf_session *self) 97void perf_session__update_sample_type(struct perf_session *self)
107{ 98{
108 self->sample_type = perf_header__sample_type(&self->header); 99 self->sample_type = perf_evlist__sample_type(self->evlist);
109 self->sample_id_all = perf_header__sample_id_all(&self->header); 100 self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
110 perf_session__id_header_size(self); 101 perf_session__id_header_size(self);
111} 102}
112 103
@@ -135,13 +126,9 @@ struct perf_session *perf_session__new(const char *filename, int mode,
135 if (self == NULL) 126 if (self == NULL)
136 goto out; 127 goto out;
137 128
138 if (perf_header__init(&self->header) < 0)
139 goto out_free;
140
141 memcpy(self->filename, filename, len); 129 memcpy(self->filename, filename, len);
142 self->threads = RB_ROOT; 130 self->threads = RB_ROOT;
143 INIT_LIST_HEAD(&self->dead_threads); 131 INIT_LIST_HEAD(&self->dead_threads);
144 self->hists_tree = RB_ROOT;
145 self->last_match = NULL; 132 self->last_match = NULL;
146 /* 133 /*
147 * On 64bit we can mmap the data file in one go. No need for tiny mmap 134 * On 64bit we can mmap the data file in one go. No need for tiny mmap
@@ -162,17 +149,16 @@ struct perf_session *perf_session__new(const char *filename, int mode,
162 if (mode == O_RDONLY) { 149 if (mode == O_RDONLY) {
163 if (perf_session__open(self, force) < 0) 150 if (perf_session__open(self, force) < 0)
164 goto out_delete; 151 goto out_delete;
152 perf_session__update_sample_type(self);
165 } else if (mode == O_WRONLY) { 153 } else if (mode == O_WRONLY) {
166 /* 154 /*
167 * In O_RDONLY mode this will be performed when reading the 155 * In O_RDONLY mode this will be performed when reading the
168 * kernel MMAP event, in event__process_mmap(). 156 * kernel MMAP event, in perf_event__process_mmap().
169 */ 157 */
170 if (perf_session__create_kernel_maps(self) < 0) 158 if (perf_session__create_kernel_maps(self) < 0)
171 goto out_delete; 159 goto out_delete;
172 } 160 }
173 161
174 perf_session__update_sample_type(self);
175
176 if (ops && ops->ordering_requires_timestamps && 162 if (ops && ops->ordering_requires_timestamps &&
177 ops->ordered_samples && !self->sample_id_all) { 163 ops->ordered_samples && !self->sample_id_all) {
178 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 164 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
@@ -181,9 +167,6 @@ struct perf_session *perf_session__new(const char *filename, int mode,
181 167
182out: 168out:
183 return self; 169 return self;
184out_free:
185 free(self);
186 return NULL;
187out_delete: 170out_delete:
188 perf_session__delete(self); 171 perf_session__delete(self);
189 return NULL; 172 return NULL;
@@ -214,7 +197,6 @@ static void perf_session__delete_threads(struct perf_session *self)
214 197
215void perf_session__delete(struct perf_session *self) 198void perf_session__delete(struct perf_session *self)
216{ 199{
217 perf_header__exit(&self->header);
218 perf_session__destroy_kernel_maps(self); 200 perf_session__destroy_kernel_maps(self);
219 perf_session__delete_dead_threads(self); 201 perf_session__delete_dead_threads(self);
220 perf_session__delete_threads(self); 202 perf_session__delete_threads(self);
@@ -242,17 +224,16 @@ static bool symbol__match_parent_regex(struct symbol *sym)
242 return 0; 224 return 0;
243} 225}
244 226
245struct map_symbol *perf_session__resolve_callchain(struct perf_session *self, 227int perf_session__resolve_callchain(struct perf_session *self,
246 struct thread *thread, 228 struct thread *thread,
247 struct ip_callchain *chain, 229 struct ip_callchain *chain,
248 struct symbol **parent) 230 struct symbol **parent)
249{ 231{
250 u8 cpumode = PERF_RECORD_MISC_USER; 232 u8 cpumode = PERF_RECORD_MISC_USER;
251 unsigned int i; 233 unsigned int i;
252 struct map_symbol *syms = calloc(chain->nr, sizeof(*syms)); 234 int err;
253 235
254 if (!syms) 236 callchain_cursor_reset(&self->callchain_cursor);
255 return NULL;
256 237
257 for (i = 0; i < chain->nr; i++) { 238 for (i = 0; i < chain->nr; i++) {
258 u64 ip = chain->ips[i]; 239 u64 ip = chain->ips[i];
@@ -281,30 +262,33 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
281 *parent = al.sym; 262 *parent = al.sym;
282 if (!symbol_conf.use_callchain) 263 if (!symbol_conf.use_callchain)
283 break; 264 break;
284 syms[i].map = al.map;
285 syms[i].sym = al.sym;
286 } 265 }
266
267 err = callchain_cursor_append(&self->callchain_cursor,
268 ip, al.map, al.sym);
269 if (err)
270 return err;
287 } 271 }
288 272
289 return syms; 273 return 0;
290} 274}
291 275
292static int process_event_synth_stub(event_t *event __used, 276static int process_event_synth_stub(union perf_event *event __used,
293 struct perf_session *session __used) 277 struct perf_session *session __used)
294{ 278{
295 dump_printf(": unhandled!\n"); 279 dump_printf(": unhandled!\n");
296 return 0; 280 return 0;
297} 281}
298 282
299static int process_event_stub(event_t *event __used, 283static int process_event_stub(union perf_event *event __used,
300 struct sample_data *sample __used, 284 struct perf_sample *sample __used,
301 struct perf_session *session __used) 285 struct perf_session *session __used)
302{ 286{
303 dump_printf(": unhandled!\n"); 287 dump_printf(": unhandled!\n");
304 return 0; 288 return 0;
305} 289}
306 290
307static int process_finished_round_stub(event_t *event __used, 291static int process_finished_round_stub(union perf_event *event __used,
308 struct perf_session *session __used, 292 struct perf_session *session __used,
309 struct perf_event_ops *ops __used) 293 struct perf_event_ops *ops __used)
310{ 294{
@@ -312,7 +296,7 @@ static int process_finished_round_stub(event_t *event __used,
312 return 0; 296 return 0;
313} 297}
314 298
315static int process_finished_round(event_t *event, 299static int process_finished_round(union perf_event *event,
316 struct perf_session *session, 300 struct perf_session *session,
317 struct perf_event_ops *ops); 301 struct perf_event_ops *ops);
318 302
@@ -329,7 +313,7 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
329 if (handler->exit == NULL) 313 if (handler->exit == NULL)
330 handler->exit = process_event_stub; 314 handler->exit = process_event_stub;
331 if (handler->lost == NULL) 315 if (handler->lost == NULL)
332 handler->lost = event__process_lost; 316 handler->lost = perf_event__process_lost;
333 if (handler->read == NULL) 317 if (handler->read == NULL)
334 handler->read = process_event_stub; 318 handler->read = process_event_stub;
335 if (handler->throttle == NULL) 319 if (handler->throttle == NULL)
@@ -363,98 +347,98 @@ void mem_bswap_64(void *src, int byte_size)
363 } 347 }
364} 348}
365 349
366static void event__all64_swap(event_t *self) 350static void perf_event__all64_swap(union perf_event *event)
367{ 351{
368 struct perf_event_header *hdr = &self->header; 352 struct perf_event_header *hdr = &event->header;
369 mem_bswap_64(hdr + 1, self->header.size - sizeof(*hdr)); 353 mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr));
370} 354}
371 355
372static void event__comm_swap(event_t *self) 356static void perf_event__comm_swap(union perf_event *event)
373{ 357{
374 self->comm.pid = bswap_32(self->comm.pid); 358 event->comm.pid = bswap_32(event->comm.pid);
375 self->comm.tid = bswap_32(self->comm.tid); 359 event->comm.tid = bswap_32(event->comm.tid);
376} 360}
377 361
378static void event__mmap_swap(event_t *self) 362static void perf_event__mmap_swap(union perf_event *event)
379{ 363{
380 self->mmap.pid = bswap_32(self->mmap.pid); 364 event->mmap.pid = bswap_32(event->mmap.pid);
381 self->mmap.tid = bswap_32(self->mmap.tid); 365 event->mmap.tid = bswap_32(event->mmap.tid);
382 self->mmap.start = bswap_64(self->mmap.start); 366 event->mmap.start = bswap_64(event->mmap.start);
383 self->mmap.len = bswap_64(self->mmap.len); 367 event->mmap.len = bswap_64(event->mmap.len);
384 self->mmap.pgoff = bswap_64(self->mmap.pgoff); 368 event->mmap.pgoff = bswap_64(event->mmap.pgoff);
385} 369}
386 370
387static void event__task_swap(event_t *self) 371static void perf_event__task_swap(union perf_event *event)
388{ 372{
389 self->fork.pid = bswap_32(self->fork.pid); 373 event->fork.pid = bswap_32(event->fork.pid);
390 self->fork.tid = bswap_32(self->fork.tid); 374 event->fork.tid = bswap_32(event->fork.tid);
391 self->fork.ppid = bswap_32(self->fork.ppid); 375 event->fork.ppid = bswap_32(event->fork.ppid);
392 self->fork.ptid = bswap_32(self->fork.ptid); 376 event->fork.ptid = bswap_32(event->fork.ptid);
393 self->fork.time = bswap_64(self->fork.time); 377 event->fork.time = bswap_64(event->fork.time);
394} 378}
395 379
396static void event__read_swap(event_t *self) 380static void perf_event__read_swap(union perf_event *event)
397{ 381{
398 self->read.pid = bswap_32(self->read.pid); 382 event->read.pid = bswap_32(event->read.pid);
399 self->read.tid = bswap_32(self->read.tid); 383 event->read.tid = bswap_32(event->read.tid);
400 self->read.value = bswap_64(self->read.value); 384 event->read.value = bswap_64(event->read.value);
401 self->read.time_enabled = bswap_64(self->read.time_enabled); 385 event->read.time_enabled = bswap_64(event->read.time_enabled);
402 self->read.time_running = bswap_64(self->read.time_running); 386 event->read.time_running = bswap_64(event->read.time_running);
403 self->read.id = bswap_64(self->read.id); 387 event->read.id = bswap_64(event->read.id);
404} 388}
405 389
406static void event__attr_swap(event_t *self) 390static void perf_event__attr_swap(union perf_event *event)
407{ 391{
408 size_t size; 392 size_t size;
409 393
410 self->attr.attr.type = bswap_32(self->attr.attr.type); 394 event->attr.attr.type = bswap_32(event->attr.attr.type);
411 self->attr.attr.size = bswap_32(self->attr.attr.size); 395 event->attr.attr.size = bswap_32(event->attr.attr.size);
412 self->attr.attr.config = bswap_64(self->attr.attr.config); 396 event->attr.attr.config = bswap_64(event->attr.attr.config);
413 self->attr.attr.sample_period = bswap_64(self->attr.attr.sample_period); 397 event->attr.attr.sample_period = bswap_64(event->attr.attr.sample_period);
414 self->attr.attr.sample_type = bswap_64(self->attr.attr.sample_type); 398 event->attr.attr.sample_type = bswap_64(event->attr.attr.sample_type);
415 self->attr.attr.read_format = bswap_64(self->attr.attr.read_format); 399 event->attr.attr.read_format = bswap_64(event->attr.attr.read_format);
416 self->attr.attr.wakeup_events = bswap_32(self->attr.attr.wakeup_events); 400 event->attr.attr.wakeup_events = bswap_32(event->attr.attr.wakeup_events);
417 self->attr.attr.bp_type = bswap_32(self->attr.attr.bp_type); 401 event->attr.attr.bp_type = bswap_32(event->attr.attr.bp_type);
418 self->attr.attr.bp_addr = bswap_64(self->attr.attr.bp_addr); 402 event->attr.attr.bp_addr = bswap_64(event->attr.attr.bp_addr);
419 self->attr.attr.bp_len = bswap_64(self->attr.attr.bp_len); 403 event->attr.attr.bp_len = bswap_64(event->attr.attr.bp_len);
420 404
421 size = self->header.size; 405 size = event->header.size;
422 size -= (void *)&self->attr.id - (void *)self; 406 size -= (void *)&event->attr.id - (void *)event;
423 mem_bswap_64(self->attr.id, size); 407 mem_bswap_64(event->attr.id, size);
424} 408}
425 409
426static void event__event_type_swap(event_t *self) 410static void perf_event__event_type_swap(union perf_event *event)
427{ 411{
428 self->event_type.event_type.event_id = 412 event->event_type.event_type.event_id =
429 bswap_64(self->event_type.event_type.event_id); 413 bswap_64(event->event_type.event_type.event_id);
430} 414}
431 415
432static void event__tracing_data_swap(event_t *self) 416static void perf_event__tracing_data_swap(union perf_event *event)
433{ 417{
434 self->tracing_data.size = bswap_32(self->tracing_data.size); 418 event->tracing_data.size = bswap_32(event->tracing_data.size);
435} 419}
436 420
437typedef void (*event__swap_op)(event_t *self); 421typedef void (*perf_event__swap_op)(union perf_event *event);
438 422
439static event__swap_op event__swap_ops[] = { 423static perf_event__swap_op perf_event__swap_ops[] = {
440 [PERF_RECORD_MMAP] = event__mmap_swap, 424 [PERF_RECORD_MMAP] = perf_event__mmap_swap,
441 [PERF_RECORD_COMM] = event__comm_swap, 425 [PERF_RECORD_COMM] = perf_event__comm_swap,
442 [PERF_RECORD_FORK] = event__task_swap, 426 [PERF_RECORD_FORK] = perf_event__task_swap,
443 [PERF_RECORD_EXIT] = event__task_swap, 427 [PERF_RECORD_EXIT] = perf_event__task_swap,
444 [PERF_RECORD_LOST] = event__all64_swap, 428 [PERF_RECORD_LOST] = perf_event__all64_swap,
445 [PERF_RECORD_READ] = event__read_swap, 429 [PERF_RECORD_READ] = perf_event__read_swap,
446 [PERF_RECORD_SAMPLE] = event__all64_swap, 430 [PERF_RECORD_SAMPLE] = perf_event__all64_swap,
447 [PERF_RECORD_HEADER_ATTR] = event__attr_swap, 431 [PERF_RECORD_HEADER_ATTR] = perf_event__attr_swap,
448 [PERF_RECORD_HEADER_EVENT_TYPE] = event__event_type_swap, 432 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
449 [PERF_RECORD_HEADER_TRACING_DATA] = event__tracing_data_swap, 433 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
450 [PERF_RECORD_HEADER_BUILD_ID] = NULL, 434 [PERF_RECORD_HEADER_BUILD_ID] = NULL,
451 [PERF_RECORD_HEADER_MAX] = NULL, 435 [PERF_RECORD_HEADER_MAX] = NULL,
452}; 436};
453 437
454struct sample_queue { 438struct sample_queue {
455 u64 timestamp; 439 u64 timestamp;
456 u64 file_offset; 440 u64 file_offset;
457 event_t *event; 441 union perf_event *event;
458 struct list_head list; 442 struct list_head list;
459}; 443};
460 444
@@ -472,8 +456,8 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
472} 456}
473 457
474static int perf_session_deliver_event(struct perf_session *session, 458static int perf_session_deliver_event(struct perf_session *session,
475 event_t *event, 459 union perf_event *event,
476 struct sample_data *sample, 460 struct perf_sample *sample,
477 struct perf_event_ops *ops, 461 struct perf_event_ops *ops,
478 u64 file_offset); 462 u64 file_offset);
479 463
@@ -483,7 +467,7 @@ static void flush_sample_queue(struct perf_session *s,
483 struct ordered_samples *os = &s->ordered_samples; 467 struct ordered_samples *os = &s->ordered_samples;
484 struct list_head *head = &os->samples; 468 struct list_head *head = &os->samples;
485 struct sample_queue *tmp, *iter; 469 struct sample_queue *tmp, *iter;
486 struct sample_data sample; 470 struct perf_sample sample;
487 u64 limit = os->next_flush; 471 u64 limit = os->next_flush;
488 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; 472 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
489 473
@@ -494,7 +478,7 @@ static void flush_sample_queue(struct perf_session *s,
494 if (iter->timestamp > limit) 478 if (iter->timestamp > limit)
495 break; 479 break;
496 480
497 event__parse_sample(iter->event, s, &sample); 481 perf_session__parse_sample(s, iter->event, &sample);
498 perf_session_deliver_event(s, iter->event, &sample, ops, 482 perf_session_deliver_event(s, iter->event, &sample, ops,
499 iter->file_offset); 483 iter->file_offset);
500 484
@@ -550,7 +534,7 @@ static void flush_sample_queue(struct perf_session *s,
550 * Flush every events below timestamp 7 534 * Flush every events below timestamp 7
551 * etc... 535 * etc...
552 */ 536 */
553static int process_finished_round(event_t *event __used, 537static int process_finished_round(union perf_event *event __used,
554 struct perf_session *session, 538 struct perf_session *session,
555 struct perf_event_ops *ops) 539 struct perf_event_ops *ops)
556{ 540{
@@ -607,12 +591,12 @@ static void __queue_event(struct sample_queue *new, struct perf_session *s)
607 591
608#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue)) 592#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
609 593
610static int perf_session_queue_event(struct perf_session *s, event_t *event, 594static int perf_session_queue_event(struct perf_session *s, union perf_event *event,
611 struct sample_data *data, u64 file_offset) 595 struct perf_sample *sample, u64 file_offset)
612{ 596{
613 struct ordered_samples *os = &s->ordered_samples; 597 struct ordered_samples *os = &s->ordered_samples;
614 struct list_head *sc = &os->sample_cache; 598 struct list_head *sc = &os->sample_cache;
615 u64 timestamp = data->time; 599 u64 timestamp = sample->time;
616 struct sample_queue *new; 600 struct sample_queue *new;
617 601
618 if (!timestamp || timestamp == ~0ULL) 602 if (!timestamp || timestamp == ~0ULL)
@@ -648,7 +632,7 @@ static int perf_session_queue_event(struct perf_session *s, event_t *event,
648 return 0; 632 return 0;
649} 633}
650 634
651static void callchain__printf(struct sample_data *sample) 635static void callchain__printf(struct perf_sample *sample)
652{ 636{
653 unsigned int i; 637 unsigned int i;
654 638
@@ -660,8 +644,8 @@ static void callchain__printf(struct sample_data *sample)
660} 644}
661 645
662static void perf_session__print_tstamp(struct perf_session *session, 646static void perf_session__print_tstamp(struct perf_session *session,
663 event_t *event, 647 union perf_event *event,
664 struct sample_data *sample) 648 struct perf_sample *sample)
665{ 649{
666 if (event->header.type != PERF_RECORD_SAMPLE && 650 if (event->header.type != PERF_RECORD_SAMPLE &&
667 !session->sample_id_all) { 651 !session->sample_id_all) {
@@ -676,8 +660,8 @@ static void perf_session__print_tstamp(struct perf_session *session,
676 printf("%" PRIu64 " ", sample->time); 660 printf("%" PRIu64 " ", sample->time);
677} 661}
678 662
679static void dump_event(struct perf_session *session, event_t *event, 663static void dump_event(struct perf_session *session, union perf_event *event,
680 u64 file_offset, struct sample_data *sample) 664 u64 file_offset, struct perf_sample *sample)
681{ 665{
682 if (!dump_trace) 666 if (!dump_trace)
683 return; 667 return;
@@ -691,11 +675,11 @@ static void dump_event(struct perf_session *session, event_t *event,
691 perf_session__print_tstamp(session, event, sample); 675 perf_session__print_tstamp(session, event, sample);
692 676
693 printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset, 677 printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset,
694 event->header.size, event__get_event_name(event->header.type)); 678 event->header.size, perf_event__name(event->header.type));
695} 679}
696 680
697static void dump_sample(struct perf_session *session, event_t *event, 681static void dump_sample(struct perf_session *session, union perf_event *event,
698 struct sample_data *sample) 682 struct perf_sample *sample)
699{ 683{
700 if (!dump_trace) 684 if (!dump_trace)
701 return; 685 return;
@@ -709,8 +693,8 @@ static void dump_sample(struct perf_session *session, event_t *event,
709} 693}
710 694
711static int perf_session_deliver_event(struct perf_session *session, 695static int perf_session_deliver_event(struct perf_session *session,
712 event_t *event, 696 union perf_event *event,
713 struct sample_data *sample, 697 struct perf_sample *sample,
714 struct perf_event_ops *ops, 698 struct perf_event_ops *ops,
715 u64 file_offset) 699 u64 file_offset)
716{ 700{
@@ -743,7 +727,7 @@ static int perf_session_deliver_event(struct perf_session *session,
743} 727}
744 728
745static int perf_session__preprocess_sample(struct perf_session *session, 729static int perf_session__preprocess_sample(struct perf_session *session,
746 event_t *event, struct sample_data *sample) 730 union perf_event *event, struct perf_sample *sample)
747{ 731{
748 if (event->header.type != PERF_RECORD_SAMPLE || 732 if (event->header.type != PERF_RECORD_SAMPLE ||
749 !(session->sample_type & PERF_SAMPLE_CALLCHAIN)) 733 !(session->sample_type & PERF_SAMPLE_CALLCHAIN))
@@ -758,7 +742,7 @@ static int perf_session__preprocess_sample(struct perf_session *session,
758 return 0; 742 return 0;
759} 743}
760 744
761static int perf_session__process_user_event(struct perf_session *session, event_t *event, 745static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
762 struct perf_event_ops *ops, u64 file_offset) 746 struct perf_event_ops *ops, u64 file_offset)
763{ 747{
764 dump_event(session, event, file_offset, NULL); 748 dump_event(session, event, file_offset, NULL);
@@ -783,15 +767,16 @@ static int perf_session__process_user_event(struct perf_session *session, event_
783} 767}
784 768
785static int perf_session__process_event(struct perf_session *session, 769static int perf_session__process_event(struct perf_session *session,
786 event_t *event, 770 union perf_event *event,
787 struct perf_event_ops *ops, 771 struct perf_event_ops *ops,
788 u64 file_offset) 772 u64 file_offset)
789{ 773{
790 struct sample_data sample; 774 struct perf_sample sample;
791 int ret; 775 int ret;
792 776
793 if (session->header.needs_swap && event__swap_ops[event->header.type]) 777 if (session->header.needs_swap &&
794 event__swap_ops[event->header.type](event); 778 perf_event__swap_ops[event->header.type])
779 perf_event__swap_ops[event->header.type](event);
795 780
796 if (event->header.type >= PERF_RECORD_HEADER_MAX) 781 if (event->header.type >= PERF_RECORD_HEADER_MAX)
797 return -EINVAL; 782 return -EINVAL;
@@ -804,7 +789,7 @@ static int perf_session__process_event(struct perf_session *session,
804 /* 789 /*
805 * For all kernel events we get the sample data 790 * For all kernel events we get the sample data
806 */ 791 */
807 event__parse_sample(event, session, &sample); 792 perf_session__parse_sample(session, event, &sample);
808 793
809 /* Preprocess sample records - precheck callchains */ 794 /* Preprocess sample records - precheck callchains */
810 if (perf_session__preprocess_sample(session, event, &sample)) 795 if (perf_session__preprocess_sample(session, event, &sample))
@@ -843,7 +828,7 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
843static void perf_session__warn_about_errors(const struct perf_session *session, 828static void perf_session__warn_about_errors(const struct perf_session *session,
844 const struct perf_event_ops *ops) 829 const struct perf_event_ops *ops)
845{ 830{
846 if (ops->lost == event__process_lost && 831 if (ops->lost == perf_event__process_lost &&
847 session->hists.stats.total_lost != 0) { 832 session->hists.stats.total_lost != 0) {
848 ui__warning("Processed %" PRIu64 " events and LOST %" PRIu64 833 ui__warning("Processed %" PRIu64 " events and LOST %" PRIu64
849 "!\n\nCheck IO/CPU overload!\n\n", 834 "!\n\nCheck IO/CPU overload!\n\n",
@@ -875,7 +860,7 @@ volatile int session_done;
875static int __perf_session__process_pipe_events(struct perf_session *self, 860static int __perf_session__process_pipe_events(struct perf_session *self,
876 struct perf_event_ops *ops) 861 struct perf_event_ops *ops)
877{ 862{
878 event_t event; 863 union perf_event event;
879 uint32_t size; 864 uint32_t size;
880 int skip = 0; 865 int skip = 0;
881 u64 head; 866 u64 head;
@@ -956,7 +941,7 @@ int __perf_session__process_events(struct perf_session *session,
956 struct ui_progress *progress; 941 struct ui_progress *progress;
957 size_t page_size, mmap_size; 942 size_t page_size, mmap_size;
958 char *buf, *mmaps[8]; 943 char *buf, *mmaps[8];
959 event_t *event; 944 union perf_event *event;
960 uint32_t size; 945 uint32_t size;
961 946
962 perf_event_ops__fill_defaults(ops); 947 perf_event_ops__fill_defaults(ops);
@@ -1001,7 +986,7 @@ remap:
1001 file_pos = file_offset + head; 986 file_pos = file_offset + head;
1002 987
1003more: 988more:
1004 event = (event_t *)(buf + head); 989 event = (union perf_event *)(buf + head);
1005 990
1006 if (session->header.needs_swap) 991 if (session->header.needs_swap)
1007 perf_event_header__bswap(&event->header); 992 perf_event_header__bswap(&event->header);
@@ -1134,3 +1119,18 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
1134 size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits); 1119 size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits);
1135 return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits); 1120 return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits);
1136} 1121}
1122
1123size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1124{
1125 struct perf_evsel *pos;
1126 size_t ret = fprintf(fp, "Aggregated stats:\n");
1127
1128 ret += hists__fprintf_nr_events(&session->hists, fp);
1129
1130 list_for_each_entry(pos, &session->evlist->entries, node) {
1131 ret += fprintf(fp, "%s stats:\n", event_name(pos));
1132 ret += hists__fprintf_nr_events(&pos->hists, fp);
1133 }
1134
1135 return ret;
1136}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index decd83f274fd..b5b148b0aaca 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -34,12 +34,12 @@ struct perf_session {
34 struct thread *last_match; 34 struct thread *last_match;
35 struct machine host_machine; 35 struct machine host_machine;
36 struct rb_root machines; 36 struct rb_root machines;
37 struct rb_root hists_tree; 37 struct perf_evlist *evlist;
38 /* 38 /*
39 * FIXME: should point to the first entry in hists_tree and 39 * FIXME: Need to split this up further, we need global
40 * be a hists instance. Right now its only 'report' 40 * stats + per event stats. 'perf diff' also needs
41 * that is using ->hists_tree while all the rest use 41 * to properly support multiple events in a single
42 * ->hists. 42 * perf.data file.
43 */ 43 */
44 struct hists hists; 44 struct hists hists;
45 u64 sample_type; 45 u64 sample_type;
@@ -51,15 +51,17 @@ struct perf_session {
51 int cwdlen; 51 int cwdlen;
52 char *cwd; 52 char *cwd;
53 struct ordered_samples ordered_samples; 53 struct ordered_samples ordered_samples;
54 char filename[0]; 54 struct callchain_cursor callchain_cursor;
55 char filename[0];
55}; 56};
56 57
57struct perf_event_ops; 58struct perf_event_ops;
58 59
59typedef int (*event_op)(event_t *self, struct sample_data *sample, 60typedef int (*event_op)(union perf_event *self, struct perf_sample *sample,
60 struct perf_session *session); 61 struct perf_session *session);
61typedef int (*event_synth_op)(event_t *self, struct perf_session *session); 62typedef int (*event_synth_op)(union perf_event *self,
62typedef int (*event_op2)(event_t *self, struct perf_session *session, 63 struct perf_session *session);
64typedef int (*event_op2)(union perf_event *self, struct perf_session *session,
63 struct perf_event_ops *ops); 65 struct perf_event_ops *ops);
64 66
65struct perf_event_ops { 67struct perf_event_ops {
@@ -94,10 +96,10 @@ int __perf_session__process_events(struct perf_session *self,
94int perf_session__process_events(struct perf_session *self, 96int perf_session__process_events(struct perf_session *self,
95 struct perf_event_ops *event_ops); 97 struct perf_event_ops *event_ops);
96 98
97struct map_symbol *perf_session__resolve_callchain(struct perf_session *self, 99int perf_session__resolve_callchain(struct perf_session *self,
98 struct thread *thread, 100 struct thread *thread,
99 struct ip_callchain *chain, 101 struct ip_callchain *chain,
100 struct symbol **parent); 102 struct symbol **parent);
101 103
102bool perf_session__has_traces(struct perf_session *self, const char *msg); 104bool perf_session__has_traces(struct perf_session *self, const char *msg);
103 105
@@ -110,8 +112,6 @@ void mem_bswap_64(void *src, int byte_size);
110int perf_session__create_kernel_maps(struct perf_session *self); 112int perf_session__create_kernel_maps(struct perf_session *self);
111 113
112void perf_session__update_sample_type(struct perf_session *self); 114void perf_session__update_sample_type(struct perf_session *self);
113void perf_session__set_sample_id_all(struct perf_session *session, bool value);
114void perf_session__set_sample_type(struct perf_session *session, u64 type);
115void perf_session__remove_thread(struct perf_session *self, struct thread *th); 115void perf_session__remove_thread(struct perf_session *self, struct thread *th);
116 116
117static inline 117static inline
@@ -149,9 +149,14 @@ size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
149size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, 149size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,
150 FILE *fp, bool with_hits); 150 FILE *fp, bool with_hits);
151 151
152static inline 152size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
153size_t perf_session__fprintf_nr_events(struct perf_session *self, FILE *fp) 153
154static inline int perf_session__parse_sample(struct perf_session *session,
155 const union perf_event *event,
156 struct perf_sample *sample)
154{ 157{
155 return hists__fprintf_nr_events(&self->hists, fp); 158 return perf_event__parse_sample(event, session->sample_type,
159 session->sample_id_all, sample);
156} 160}
161
157#endif /* __PERF_SESSION_H */ 162#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
new file mode 100644
index 000000000000..e24ffadb20b2
--- /dev/null
+++ b/tools/perf/util/setup.py
@@ -0,0 +1,19 @@
1#!/usr/bin/python2
2
3from distutils.core import setup, Extension
4
5perf = Extension('perf',
6 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c',
7 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
8 'util/util.c', 'util/xyarray.c', 'util/cgroup.c'],
9 include_dirs = ['util/include'],
10 extra_compile_args = ['-fno-strict-aliasing', '-Wno-write-strings'])
11
12setup(name='perf',
13 version='0.1',
14 description='Interface with the Linux profiling infrastructure',
15 author='Arnaldo Carvalho de Melo',
16 author_email='acme@redhat.com',
17 license='GPLv2',
18 url='http://perf.wiki.kernel.org',
19 ext_modules=[perf])
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
new file mode 100644
index 000000000000..834c8ebfe38e
--- /dev/null
+++ b/tools/perf/util/strfilter.c
@@ -0,0 +1,199 @@
1#include "util.h"
2#include "string.h"
3#include "strfilter.h"
4
5/* Operators */
6static const char *OP_and = "&"; /* Logical AND */
7static const char *OP_or = "|"; /* Logical OR */
8static const char *OP_not = "!"; /* Logical NOT */
9
10#define is_operator(c) ((c) == '|' || (c) == '&' || (c) == '!')
11#define is_separator(c) (is_operator(c) || (c) == '(' || (c) == ')')
12
13static void strfilter_node__delete(struct strfilter_node *self)
14{
15 if (self) {
16 if (self->p && !is_operator(*self->p))
17 free((char *)self->p);
18 strfilter_node__delete(self->l);
19 strfilter_node__delete(self->r);
20 free(self);
21 }
22}
23
24void strfilter__delete(struct strfilter *self)
25{
26 if (self) {
27 strfilter_node__delete(self->root);
28 free(self);
29 }
30}
31
32static const char *get_token(const char *s, const char **e)
33{
34 const char *p;
35
36 while (isspace(*s)) /* Skip spaces */
37 s++;
38
39 if (*s == '\0') {
40 p = s;
41 goto end;
42 }
43
44 p = s + 1;
45 if (!is_separator(*s)) {
46 /* End search */
47retry:
48 while (*p && !is_separator(*p) && !isspace(*p))
49 p++;
50 /* Escape and special case: '!' is also used in glob pattern */
51 if (*(p - 1) == '\\' || (*p == '!' && *(p - 1) == '[')) {
52 p++;
53 goto retry;
54 }
55 }
56end:
57 *e = p;
58 return s;
59}
60
61static struct strfilter_node *strfilter_node__alloc(const char *op,
62 struct strfilter_node *l,
63 struct strfilter_node *r)
64{
65 struct strfilter_node *ret = zalloc(sizeof(struct strfilter_node));
66
67 if (ret) {
68 ret->p = op;
69 ret->l = l;
70 ret->r = r;
71 }
72
73 return ret;
74}
75
76static struct strfilter_node *strfilter_node__new(const char *s,
77 const char **ep)
78{
79 struct strfilter_node root, *cur, *last_op;
80 const char *e;
81
82 if (!s)
83 return NULL;
84
85 memset(&root, 0, sizeof(root));
86 last_op = cur = &root;
87
88 s = get_token(s, &e);
89 while (*s != '\0' && *s != ')') {
90 switch (*s) {
91 case '&': /* Exchg last OP->r with AND */
92 if (!cur->r || !last_op->r)
93 goto error;
94 cur = strfilter_node__alloc(OP_and, last_op->r, NULL);
95 if (!cur)
96 goto nomem;
97 last_op->r = cur;
98 last_op = cur;
99 break;
100 case '|': /* Exchg the root with OR */
101 if (!cur->r || !root.r)
102 goto error;
103 cur = strfilter_node__alloc(OP_or, root.r, NULL);
104 if (!cur)
105 goto nomem;
106 root.r = cur;
107 last_op = cur;
108 break;
109 case '!': /* Add NOT as a leaf node */
110 if (cur->r)
111 goto error;
112 cur->r = strfilter_node__alloc(OP_not, NULL, NULL);
113 if (!cur->r)
114 goto nomem;
115 cur = cur->r;
116 break;
117 case '(': /* Recursively parses inside the parenthesis */
118 if (cur->r)
119 goto error;
120 cur->r = strfilter_node__new(s + 1, &s);
121 if (!s)
122 goto nomem;
123 if (!cur->r || *s != ')')
124 goto error;
125 e = s + 1;
126 break;
127 default:
128 if (cur->r)
129 goto error;
130 cur->r = strfilter_node__alloc(NULL, NULL, NULL);
131 if (!cur->r)
132 goto nomem;
133 cur->r->p = strndup(s, e - s);
134 if (!cur->r->p)
135 goto nomem;
136 }
137 s = get_token(e, &e);
138 }
139 if (!cur->r)
140 goto error;
141 *ep = s;
142 return root.r;
143nomem:
144 s = NULL;
145error:
146 *ep = s;
147 strfilter_node__delete(root.r);
148 return NULL;
149}
150
151/*
152 * Parse filter rule and return new strfilter.
153 * Return NULL if fail, and *ep == NULL if memory allocation failed.
154 */
155struct strfilter *strfilter__new(const char *rules, const char **err)
156{
157 struct strfilter *ret = zalloc(sizeof(struct strfilter));
158 const char *ep = NULL;
159
160 if (ret)
161 ret->root = strfilter_node__new(rules, &ep);
162
163 if (!ret || !ret->root || *ep != '\0') {
164 if (err)
165 *err = ep;
166 strfilter__delete(ret);
167 ret = NULL;
168 }
169
170 return ret;
171}
172
173static bool strfilter_node__compare(struct strfilter_node *self,
174 const char *str)
175{
176 if (!self || !self->p)
177 return false;
178
179 switch (*self->p) {
180 case '|': /* OR */
181 return strfilter_node__compare(self->l, str) ||
182 strfilter_node__compare(self->r, str);
183 case '&': /* AND */
184 return strfilter_node__compare(self->l, str) &&
185 strfilter_node__compare(self->r, str);
186 case '!': /* NOT */
187 return !strfilter_node__compare(self->r, str);
188 default:
189 return strglobmatch(str, self->p);
190 }
191}
192
193/* Return true if STR matches the filter rules */
194bool strfilter__compare(struct strfilter *self, const char *str)
195{
196 if (!self)
197 return false;
198 return strfilter_node__compare(self->root, str);
199}
diff --git a/tools/perf/util/strfilter.h b/tools/perf/util/strfilter.h
new file mode 100644
index 000000000000..00f58a7506de
--- /dev/null
+++ b/tools/perf/util/strfilter.h
@@ -0,0 +1,48 @@
1#ifndef __PERF_STRFILTER_H
2#define __PERF_STRFILTER_H
3/* General purpose glob matching filter */
4
5#include <linux/list.h>
6#include <stdbool.h>
7
8/* A node of string filter */
9struct strfilter_node {
10 struct strfilter_node *l; /* Tree left branche (for &,|) */
11 struct strfilter_node *r; /* Tree right branche (for !,&,|) */
12 const char *p; /* Operator or rule */
13};
14
15/* String filter */
16struct strfilter {
17 struct strfilter_node *root;
18};
19
20/**
21 * strfilter__new - Create a new string filter
22 * @rules: Filter rule, which is a combination of glob expressions.
23 * @err: Pointer which points an error detected on @rules
24 *
25 * Parse @rules and return new strfilter. Return NULL if an error detected.
26 * In that case, *@err will indicate where it is detected, and *@err is NULL
27 * if a memory allocation is failed.
28 */
29struct strfilter *strfilter__new(const char *rules, const char **err);
30
31/**
32 * strfilter__compare - compare given string and a string filter
33 * @self: String filter
34 * @str: target string
35 *
36 * Compare @str and @self. Return true if the str match the rule
37 */
38bool strfilter__compare(struct strfilter *self, const char *str);
39
40/**
41 * strfilter__delete - delete a string filter
42 * @self: String filter to delete
43 *
44 * Delete @self.
45 */
46void strfilter__delete(struct strfilter *self);
47
48#endif
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index b1bf490aff88..00014e32c288 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -207,7 +207,6 @@ struct dso *dso__new(const char *name)
207 dso__set_short_name(self, self->name); 207 dso__set_short_name(self, self->name);
208 for (i = 0; i < MAP__NR_TYPES; ++i) 208 for (i = 0; i < MAP__NR_TYPES; ++i)
209 self->symbols[i] = self->symbol_names[i] = RB_ROOT; 209 self->symbols[i] = self->symbol_names[i] = RB_ROOT;
210 self->slen_calculated = 0;
211 self->origin = DSO__ORIG_NOT_FOUND; 210 self->origin = DSO__ORIG_NOT_FOUND;
212 self->loaded = 0; 211 self->loaded = 0;
213 self->sorted_by_name = 0; 212 self->sorted_by_name = 0;
@@ -1525,8 +1524,8 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1525 symbol_conf.symfs, self->long_name); 1524 symbol_conf.symfs, self->long_name);
1526 break; 1525 break;
1527 case DSO__ORIG_GUEST_KMODULE: 1526 case DSO__ORIG_GUEST_KMODULE:
1528 if (map->groups && map->groups->machine) 1527 if (map->groups && machine)
1529 root_dir = map->groups->machine->root_dir; 1528 root_dir = machine->root_dir;
1530 else 1529 else
1531 root_dir = ""; 1530 root_dir = "";
1532 snprintf(name, size, "%s%s%s", symbol_conf.symfs, 1531 snprintf(name, size, "%s%s%s", symbol_conf.symfs,
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 670cd1c88f54..4d7ed09fe332 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -132,7 +132,6 @@ struct dso {
132 struct rb_root symbol_names[MAP__NR_TYPES]; 132 struct rb_root symbol_names[MAP__NR_TYPES];
133 enum dso_kernel_type kernel; 133 enum dso_kernel_type kernel;
134 u8 adjust_symbols:1; 134 u8 adjust_symbols:1;
135 u8 slen_calculated:1;
136 u8 has_build_id:1; 135 u8 has_build_id:1;
137 u8 hit:1; 136 u8 hit:1;
138 u8 annotate_warned:1; 137 u8 annotate_warned:1;
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 00f4eade2e3e..d5d3b22250f3 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -7,61 +7,6 @@
7#include "util.h" 7#include "util.h"
8#include "debug.h" 8#include "debug.h"
9 9
10/* Skip "." and ".." directories */
11static int filter(const struct dirent *dir)
12{
13 if (dir->d_name[0] == '.')
14 return 0;
15 else
16 return 1;
17}
18
19struct thread_map *thread_map__new_by_pid(pid_t pid)
20{
21 struct thread_map *threads;
22 char name[256];
23 int items;
24 struct dirent **namelist = NULL;
25 int i;
26
27 sprintf(name, "/proc/%d/task", pid);
28 items = scandir(name, &namelist, filter, NULL);
29 if (items <= 0)
30 return NULL;
31
32 threads = malloc(sizeof(*threads) + sizeof(pid_t) * items);
33 if (threads != NULL) {
34 for (i = 0; i < items; i++)
35 threads->map[i] = atoi(namelist[i]->d_name);
36 threads->nr = items;
37 }
38
39 for (i=0; i<items; i++)
40 free(namelist[i]);
41 free(namelist);
42
43 return threads;
44}
45
46struct thread_map *thread_map__new_by_tid(pid_t tid)
47{
48 struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
49
50 if (threads != NULL) {
51 threads->map[0] = tid;
52 threads->nr = 1;
53 }
54
55 return threads;
56}
57
58struct thread_map *thread_map__new(pid_t pid, pid_t tid)
59{
60 if (pid != -1)
61 return thread_map__new_by_pid(pid);
62 return thread_map__new_by_tid(tid);
63}
64
65static struct thread *thread__new(pid_t pid) 10static struct thread *thread__new(pid_t pid)
66{ 11{
67 struct thread *self = zalloc(sizeof(*self)); 12 struct thread *self = zalloc(sizeof(*self));
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index d7574101054a..e5f2401c1b5e 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -18,24 +18,10 @@ struct thread {
18 int comm_len; 18 int comm_len;
19}; 19};
20 20
21struct thread_map {
22 int nr;
23 int map[];
24};
25
26struct perf_session; 21struct perf_session;
27 22
28void thread__delete(struct thread *self); 23void thread__delete(struct thread *self);
29 24
30struct thread_map *thread_map__new_by_pid(pid_t pid);
31struct thread_map *thread_map__new_by_tid(pid_t tid);
32struct thread_map *thread_map__new(pid_t pid, pid_t tid);
33
34static inline void thread_map__delete(struct thread_map *threads)
35{
36 free(threads);
37}
38
39int thread__set_comm(struct thread *self, const char *comm); 25int thread__set_comm(struct thread *self, const char *comm);
40int thread__comm_len(struct thread *self); 26int thread__comm_len(struct thread *self);
41struct thread *perf_session__findnew(struct perf_session *self, pid_t pid); 27struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
new file mode 100644
index 000000000000..a5df131b77c3
--- /dev/null
+++ b/tools/perf/util/thread_map.c
@@ -0,0 +1,64 @@
1#include <dirent.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include "thread_map.h"
5
6/* Skip "." and ".." directories */
7static int filter(const struct dirent *dir)
8{
9 if (dir->d_name[0] == '.')
10 return 0;
11 else
12 return 1;
13}
14
15struct thread_map *thread_map__new_by_pid(pid_t pid)
16{
17 struct thread_map *threads;
18 char name[256];
19 int items;
20 struct dirent **namelist = NULL;
21 int i;
22
23 sprintf(name, "/proc/%d/task", pid);
24 items = scandir(name, &namelist, filter, NULL);
25 if (items <= 0)
26 return NULL;
27
28 threads = malloc(sizeof(*threads) + sizeof(pid_t) * items);
29 if (threads != NULL) {
30 for (i = 0; i < items; i++)
31 threads->map[i] = atoi(namelist[i]->d_name);
32 threads->nr = items;
33 }
34
35 for (i=0; i<items; i++)
36 free(namelist[i]);
37 free(namelist);
38
39 return threads;
40}
41
42struct thread_map *thread_map__new_by_tid(pid_t tid)
43{
44 struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
45
46 if (threads != NULL) {
47 threads->map[0] = tid;
48 threads->nr = 1;
49 }
50
51 return threads;
52}
53
54struct thread_map *thread_map__new(pid_t pid, pid_t tid)
55{
56 if (pid != -1)
57 return thread_map__new_by_pid(pid);
58 return thread_map__new_by_tid(tid);
59}
60
61void thread_map__delete(struct thread_map *threads)
62{
63 free(threads);
64}
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
new file mode 100644
index 000000000000..3cb907311409
--- /dev/null
+++ b/tools/perf/util/thread_map.h
@@ -0,0 +1,15 @@
1#ifndef __PERF_THREAD_MAP_H
2#define __PERF_THREAD_MAP_H
3
4#include <sys/types.h>
5
6struct thread_map {
7 int nr;
8 int map[];
9};
10
11struct thread_map *thread_map__new_by_pid(pid_t pid);
12struct thread_map *thread_map__new_by_tid(pid_t tid);
13struct thread_map *thread_map__new(pid_t pid, pid_t tid);
14void thread_map__delete(struct thread_map *threads);
15#endif /* __PERF_THREAD_MAP_H */
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
new file mode 100644
index 000000000000..75cfe4d45119
--- /dev/null
+++ b/tools/perf/util/top.c
@@ -0,0 +1,238 @@
1/*
2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Refactored from builtin-top.c, see that files for further copyright notes.
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */
8
9#include "cpumap.h"
10#include "event.h"
11#include "evlist.h"
12#include "evsel.h"
13#include "parse-events.h"
14#include "symbol.h"
15#include "top.h"
16#include <inttypes.h>
17
18/*
19 * Ordering weight: count-1 * count-2 * ... / count-n
20 */
21static double sym_weight(const struct sym_entry *sym, struct perf_top *top)
22{
23 double weight = sym->snap_count;
24 int counter;
25
26 if (!top->display_weighted)
27 return weight;
28
29 for (counter = 1; counter < top->evlist->nr_entries - 1; counter++)
30 weight *= sym->count[counter];
31
32 weight /= (sym->count[counter] + 1);
33
34 return weight;
35}
36
37static void perf_top__remove_active_sym(struct perf_top *top, struct sym_entry *syme)
38{
39 pthread_mutex_lock(&top->active_symbols_lock);
40 list_del_init(&syme->node);
41 pthread_mutex_unlock(&top->active_symbols_lock);
42}
43
44static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
45{
46 struct rb_node **p = &tree->rb_node;
47 struct rb_node *parent = NULL;
48 struct sym_entry *iter;
49
50 while (*p != NULL) {
51 parent = *p;
52 iter = rb_entry(parent, struct sym_entry, rb_node);
53
54 if (se->weight > iter->weight)
55 p = &(*p)->rb_left;
56 else
57 p = &(*p)->rb_right;
58 }
59
60 rb_link_node(&se->rb_node, parent, p);
61 rb_insert_color(&se->rb_node, tree);
62}
63
64#define SNPRINTF(buf, size, fmt, args...) \
65({ \
66 size_t r = snprintf(buf, size, fmt, ## args); \
67 r > size ? size : r; \
68})
69
70size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
71{
72 struct perf_evsel *counter;
73 float samples_per_sec = top->samples / top->delay_secs;
74 float ksamples_per_sec = top->kernel_samples / top->delay_secs;
75 float esamples_percent = (100.0 * top->exact_samples) / top->samples;
76 size_t ret = 0;
77
78 if (!perf_guest) {
79 ret = SNPRINTF(bf, size,
80 " PerfTop:%8.0f irqs/sec kernel:%4.1f%%"
81 " exact: %4.1f%% [", samples_per_sec,
82 100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) /
83 samples_per_sec)),
84 esamples_percent);
85 } else {
86 float us_samples_per_sec = top->us_samples / top->delay_secs;
87 float guest_kernel_samples_per_sec = top->guest_kernel_samples / top->delay_secs;
88 float guest_us_samples_per_sec = top->guest_us_samples / top->delay_secs;
89
90 ret = SNPRINTF(bf, size,
91 " PerfTop:%8.0f irqs/sec kernel:%4.1f%% us:%4.1f%%"
92 " guest kernel:%4.1f%% guest us:%4.1f%%"
93 " exact: %4.1f%% [", samples_per_sec,
94 100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) /
95 samples_per_sec)),
96 100.0 - (100.0 * ((samples_per_sec - us_samples_per_sec) /
97 samples_per_sec)),
98 100.0 - (100.0 * ((samples_per_sec -
99 guest_kernel_samples_per_sec) /
100 samples_per_sec)),
101 100.0 - (100.0 * ((samples_per_sec -
102 guest_us_samples_per_sec) /
103 samples_per_sec)),
104 esamples_percent);
105 }
106
107 if (top->evlist->nr_entries == 1 || !top->display_weighted) {
108 struct perf_evsel *first;
109 first = list_entry(top->evlist->entries.next, struct perf_evsel, node);
110 ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ",
111 (uint64_t)first->attr.sample_period,
112 top->freq ? "Hz" : "");
113 }
114
115 if (!top->display_weighted) {
116 ret += SNPRINTF(bf + ret, size - ret, "%s",
117 event_name(top->sym_evsel));
118 } else {
119 /*
120 * Don't let events eat all the space. Leaving 30 bytes
121 * for the rest should be enough.
122 */
123 size_t last_pos = size - 30;
124
125 list_for_each_entry(counter, &top->evlist->entries, node) {
126 ret += SNPRINTF(bf + ret, size - ret, "%s%s",
127 counter->idx ? "/" : "",
128 event_name(counter));
129 if (ret > last_pos) {
130 sprintf(bf + last_pos - 3, "..");
131 ret = last_pos - 1;
132 break;
133 }
134 }
135 }
136
137 ret += SNPRINTF(bf + ret, size - ret, "], ");
138
139 if (top->target_pid != -1)
140 ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %d",
141 top->target_pid);
142 else if (top->target_tid != -1)
143 ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %d",
144 top->target_tid);
145 else
146 ret += SNPRINTF(bf + ret, size - ret, " (all");
147
148 if (top->cpu_list)
149 ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)",
150 top->evlist->cpus->nr > 1 ? "s" : "", top->cpu_list);
151 else {
152 if (top->target_tid != -1)
153 ret += SNPRINTF(bf + ret, size - ret, ")");
154 else
155 ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
156 top->evlist->cpus->nr,
157 top->evlist->cpus->nr > 1 ? "s" : "");
158 }
159
160 return ret;
161}
162
163void perf_top__reset_sample_counters(struct perf_top *top)
164{
165 top->samples = top->us_samples = top->kernel_samples =
166 top->exact_samples = top->guest_kernel_samples =
167 top->guest_us_samples = 0;
168}
169
170float perf_top__decay_samples(struct perf_top *top, struct rb_root *root)
171{
172 struct sym_entry *syme, *n;
173 float sum_ksamples = 0.0;
174 int snap = !top->display_weighted ? top->sym_counter : 0, j;
175
176 /* Sort the active symbols */
177 pthread_mutex_lock(&top->active_symbols_lock);
178 syme = list_entry(top->active_symbols.next, struct sym_entry, node);
179 pthread_mutex_unlock(&top->active_symbols_lock);
180
181 top->rb_entries = 0;
182 list_for_each_entry_safe_from(syme, n, &top->active_symbols, node) {
183 syme->snap_count = syme->count[snap];
184 if (syme->snap_count != 0) {
185
186 if ((top->hide_user_symbols &&
187 syme->origin == PERF_RECORD_MISC_USER) ||
188 (top->hide_kernel_symbols &&
189 syme->origin == PERF_RECORD_MISC_KERNEL)) {
190 perf_top__remove_active_sym(top, syme);
191 continue;
192 }
193 syme->weight = sym_weight(syme, top);
194
195 if ((int)syme->snap_count >= top->count_filter) {
196 rb_insert_active_sym(root, syme);
197 ++top->rb_entries;
198 }
199 sum_ksamples += syme->snap_count;
200
201 for (j = 0; j < top->evlist->nr_entries; j++)
202 syme->count[j] = top->zero ? 0 : syme->count[j] * 7 / 8;
203 } else
204 perf_top__remove_active_sym(top, syme);
205 }
206
207 return sum_ksamples;
208}
209
210/*
211 * Find the longest symbol name that will be displayed
212 */
213void perf_top__find_widths(struct perf_top *top, struct rb_root *root,
214 int *dso_width, int *dso_short_width, int *sym_width)
215{
216 struct rb_node *nd;
217 int printed = 0;
218
219 *sym_width = *dso_width = *dso_short_width = 0;
220
221 for (nd = rb_first(root); nd; nd = rb_next(nd)) {
222 struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node);
223 struct symbol *sym = sym_entry__symbol(syme);
224
225 if (++printed > top->print_entries ||
226 (int)syme->snap_count < top->count_filter)
227 continue;
228
229 if (syme->map->dso->long_name_len > *dso_width)
230 *dso_width = syme->map->dso->long_name_len;
231
232 if (syme->map->dso->short_name_len > *dso_short_width)
233 *dso_short_width = syme->map->dso->short_name_len;
234
235 if (sym->namelen > *sym_width)
236 *sym_width = sym->namelen;
237 }
238}
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
new file mode 100644
index 000000000000..96d1cb78af01
--- /dev/null
+++ b/tools/perf/util/top.h
@@ -0,0 +1,66 @@
1#ifndef __PERF_TOP_H
2#define __PERF_TOP_H 1
3
4#include "types.h"
5#include "../perf.h"
6#include <stddef.h>
7#include <pthread.h>
8#include <linux/list.h>
9#include <linux/rbtree.h>
10
11struct perf_evlist;
12struct perf_evsel;
13
14struct sym_entry {
15 struct rb_node rb_node;
16 struct list_head node;
17 unsigned long snap_count;
18 double weight;
19 int skip;
20 u8 origin;
21 struct map *map;
22 unsigned long count[0];
23};
24
25static inline struct symbol *sym_entry__symbol(struct sym_entry *self)
26{
27 return ((void *)self) + symbol_conf.priv_size;
28}
29
30struct perf_top {
31 struct perf_evlist *evlist;
32 /*
33 * Symbols will be added here in perf_event__process_sample and will
34 * get out after decayed.
35 */
36 struct list_head active_symbols;
37 pthread_mutex_t active_symbols_lock;
38 pthread_cond_t active_symbols_cond;
39 u64 samples;
40 u64 kernel_samples, us_samples;
41 u64 exact_samples;
42 u64 guest_us_samples, guest_kernel_samples;
43 int print_entries, count_filter, delay_secs;
44 int display_weighted, freq, rb_entries, sym_counter;
45 pid_t target_pid, target_tid;
46 bool hide_kernel_symbols, hide_user_symbols, zero;
47 const char *cpu_list;
48 struct sym_entry *sym_filter_entry;
49 struct perf_evsel *sym_evsel;
50};
51
52size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
53void perf_top__reset_sample_counters(struct perf_top *top);
54float perf_top__decay_samples(struct perf_top *top, struct rb_root *root);
55void perf_top__find_widths(struct perf_top *top, struct rb_root *root,
56 int *dso_width, int *dso_short_width, int *sym_width);
57
58#ifdef NO_NEWT_SUPPORT
59static inline int perf_top__tui_browser(struct perf_top *top __used)
60{
61 return 0;
62}
63#else
64int perf_top__tui_browser(struct perf_top *top);
65#endif
66#endif /* __PERF_TOP_H */
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 73a02223c629..d8e622dd738a 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -153,7 +153,7 @@ void parse_proc_kallsyms(char *file, unsigned int size __unused)
153 char *next = NULL; 153 char *next = NULL;
154 char *addr_str; 154 char *addr_str;
155 char ch; 155 char ch;
156 int ret; 156 int ret __used;
157 int i; 157 int i;
158 158
159 line = strtok_r(file, "\n", &next); 159 line = strtok_r(file, "\n", &next);
diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c
index 8bc010edca25..611219f80680 100644
--- a/tools/perf/util/ui/browser.c
+++ b/tools/perf/util/ui/browser.c
@@ -1,4 +1,5 @@
1#include "libslang.h" 1#include "libslang.h"
2#include "ui.h"
2#include <linux/compiler.h> 3#include <linux/compiler.h>
3#include <linux/list.h> 4#include <linux/list.h>
4#include <linux/rbtree.h> 5#include <linux/rbtree.h>
@@ -156,6 +157,20 @@ void ui_browser__add_exit_keys(struct ui_browser *self, int keys[])
156 } 157 }
157} 158}
158 159
160void __ui_browser__show_title(struct ui_browser *browser, const char *title)
161{
162 SLsmg_gotorc(0, 0);
163 ui_browser__set_color(browser, NEWT_COLORSET_ROOT);
164 slsmg_write_nstring(title, browser->width);
165}
166
167void ui_browser__show_title(struct ui_browser *browser, const char *title)
168{
169 pthread_mutex_lock(&ui__lock);
170 __ui_browser__show_title(browser, title);
171 pthread_mutex_unlock(&ui__lock);
172}
173
159int ui_browser__show(struct ui_browser *self, const char *title, 174int ui_browser__show(struct ui_browser *self, const char *title,
160 const char *helpline, ...) 175 const char *helpline, ...)
161{ 176{
@@ -178,9 +193,8 @@ int ui_browser__show(struct ui_browser *self, const char *title,
178 if (self->sb == NULL) 193 if (self->sb == NULL)
179 return -1; 194 return -1;
180 195
181 SLsmg_gotorc(0, 0); 196 pthread_mutex_lock(&ui__lock);
182 ui_browser__set_color(self, NEWT_COLORSET_ROOT); 197 __ui_browser__show_title(self, title);
183 slsmg_write_nstring(title, self->width);
184 198
185 ui_browser__add_exit_keys(self, keys); 199 ui_browser__add_exit_keys(self, keys);
186 newtFormAddComponent(self->form, self->sb); 200 newtFormAddComponent(self->form, self->sb);
@@ -188,25 +202,30 @@ int ui_browser__show(struct ui_browser *self, const char *title,
188 va_start(ap, helpline); 202 va_start(ap, helpline);
189 ui_helpline__vpush(helpline, ap); 203 ui_helpline__vpush(helpline, ap);
190 va_end(ap); 204 va_end(ap);
205 pthread_mutex_unlock(&ui__lock);
191 return 0; 206 return 0;
192} 207}
193 208
194void ui_browser__hide(struct ui_browser *self) 209void ui_browser__hide(struct ui_browser *self)
195{ 210{
211 pthread_mutex_lock(&ui__lock);
196 newtFormDestroy(self->form); 212 newtFormDestroy(self->form);
197 self->form = NULL; 213 self->form = NULL;
198 ui_helpline__pop(); 214 ui_helpline__pop();
215 pthread_mutex_unlock(&ui__lock);
199} 216}
200 217
201int ui_browser__refresh(struct ui_browser *self) 218int ui_browser__refresh(struct ui_browser *self)
202{ 219{
203 int row; 220 int row;
204 221
222 pthread_mutex_lock(&ui__lock);
205 newtScrollbarSet(self->sb, self->index, self->nr_entries - 1); 223 newtScrollbarSet(self->sb, self->index, self->nr_entries - 1);
206 row = self->refresh(self); 224 row = self->refresh(self);
207 ui_browser__set_color(self, HE_COLORSET_NORMAL); 225 ui_browser__set_color(self, HE_COLORSET_NORMAL);
208 SLsmg_fill_region(self->y + row, self->x, 226 SLsmg_fill_region(self->y + row, self->x,
209 self->height - row, self->width, ' '); 227 self->height - row, self->width, ' ');
228 pthread_mutex_unlock(&ui__lock);
210 229
211 return 0; 230 return 0;
212} 231}
diff --git a/tools/perf/util/ui/browser.h b/tools/perf/util/ui/browser.h
index 0dc7e4da36f5..fc63dda10910 100644
--- a/tools/perf/util/ui/browser.h
+++ b/tools/perf/util/ui/browser.h
@@ -24,7 +24,6 @@ struct ui_browser {
24 u32 nr_entries; 24 u32 nr_entries;
25}; 25};
26 26
27
28void ui_browser__set_color(struct ui_browser *self, int color); 27void ui_browser__set_color(struct ui_browser *self, int color);
29void ui_browser__set_percent_color(struct ui_browser *self, 28void ui_browser__set_percent_color(struct ui_browser *self,
30 double percent, bool current); 29 double percent, bool current);
@@ -35,6 +34,8 @@ void ui_browser__reset_index(struct ui_browser *self);
35void ui_browser__gotorc(struct ui_browser *self, int y, int x); 34void ui_browser__gotorc(struct ui_browser *self, int y, int x);
36void ui_browser__add_exit_key(struct ui_browser *self, int key); 35void ui_browser__add_exit_key(struct ui_browser *self, int key);
37void ui_browser__add_exit_keys(struct ui_browser *self, int keys[]); 36void ui_browser__add_exit_keys(struct ui_browser *self, int keys[]);
37void __ui_browser__show_title(struct ui_browser *browser, const char *title);
38void ui_browser__show_title(struct ui_browser *browser, const char *title);
38int ui_browser__show(struct ui_browser *self, const char *title, 39int ui_browser__show(struct ui_browser *self, const char *title,
39 const char *helpline, ...); 40 const char *helpline, ...);
40void ui_browser__hide(struct ui_browser *self); 41void ui_browser__hide(struct ui_browser *self);
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 82b78f99251b..8c17a8730e4a 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -1,9 +1,12 @@
1#include "../browser.h" 1#include "../browser.h"
2#include "../helpline.h" 2#include "../helpline.h"
3#include "../libslang.h" 3#include "../libslang.h"
4#include "../../annotate.h"
4#include "../../hist.h" 5#include "../../hist.h"
5#include "../../sort.h" 6#include "../../sort.h"
6#include "../../symbol.h" 7#include "../../symbol.h"
8#include "../../annotate.h"
9#include <pthread.h>
7 10
8static void ui__error_window(const char *fmt, ...) 11static void ui__error_window(const char *fmt, ...)
9{ 12{
@@ -42,8 +45,6 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
42 struct objdump_line_rb_node *olrb = objdump_line__rb(ol); 45 struct objdump_line_rb_node *olrb = objdump_line__rb(ol);
43 ui_browser__set_percent_color(self, olrb->percent, current_entry); 46 ui_browser__set_percent_color(self, olrb->percent, current_entry);
44 slsmg_printf(" %7.2f ", olrb->percent); 47 slsmg_printf(" %7.2f ", olrb->percent);
45 if (!current_entry)
46 ui_browser__set_color(self, HE_COLORSET_CODE);
47 } else { 48 } else {
48 ui_browser__set_percent_color(self, 0, current_entry); 49 ui_browser__set_percent_color(self, 0, current_entry);
49 slsmg_write_nstring(" ", 9); 50 slsmg_write_nstring(" ", 9);
@@ -55,35 +56,40 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
55 slsmg_write_nstring(" ", width - 18); 56 slsmg_write_nstring(" ", width - 18);
56 else 57 else
57 slsmg_write_nstring(ol->line, width - 18); 58 slsmg_write_nstring(ol->line, width - 18);
59
60 if (!current_entry)
61 ui_browser__set_color(self, HE_COLORSET_CODE);
58} 62}
59 63
60static double objdump_line__calc_percent(struct objdump_line *self, 64static double objdump_line__calc_percent(struct objdump_line *self,
61 struct list_head *head, 65 struct symbol *sym, int evidx)
62 struct symbol *sym)
63{ 66{
64 double percent = 0.0; 67 double percent = 0.0;
65 68
66 if (self->offset != -1) { 69 if (self->offset != -1) {
67 int len = sym->end - sym->start; 70 int len = sym->end - sym->start;
68 unsigned int hits = 0; 71 unsigned int hits = 0;
69 struct sym_priv *priv = symbol__priv(sym); 72 struct annotation *notes = symbol__annotation(sym);
70 struct sym_ext *sym_ext = priv->ext; 73 struct source_line *src_line = notes->src->lines;
71 struct sym_hist *h = priv->hist; 74 struct sym_hist *h = annotation__histogram(notes, evidx);
72 s64 offset = self->offset; 75 s64 offset = self->offset;
73 struct objdump_line *next = objdump__get_next_ip_line(head, self); 76 struct objdump_line *next;
74
75 77
78 next = objdump__get_next_ip_line(&notes->src->source, self);
76 while (offset < (s64)len && 79 while (offset < (s64)len &&
77 (next == NULL || offset < next->offset)) { 80 (next == NULL || offset < next->offset)) {
78 if (sym_ext) { 81 if (src_line) {
79 percent += sym_ext[offset].percent; 82 percent += src_line[offset].percent;
80 } else 83 } else
81 hits += h->ip[offset]; 84 hits += h->addr[offset];
82 85
83 ++offset; 86 ++offset;
84 } 87 }
85 88 /*
86 if (sym_ext == NULL && h->sum) 89 * If the percentage wasn't already calculated in
90 * symbol__get_source_line, do it now:
91 */
92 if (src_line == NULL && h->sum)
87 percent = 100.0 * hits / h->sum; 93 percent = 100.0 * hits / h->sum;
88 } 94 }
89 95
@@ -133,103 +139,161 @@ static void annotate_browser__set_top(struct annotate_browser *self,
133 self->curr_hot = nd; 139 self->curr_hot = nd;
134} 140}
135 141
136static int annotate_browser__run(struct annotate_browser *self) 142static void annotate_browser__calc_percent(struct annotate_browser *browser,
143 int evidx)
137{ 144{
138 struct rb_node *nd; 145 struct symbol *sym = browser->b.priv;
139 struct hist_entry *he = self->b.priv; 146 struct annotation *notes = symbol__annotation(sym);
140 int key; 147 struct objdump_line *pos;
141 148
142 if (ui_browser__show(&self->b, he->ms.sym->name, 149 browser->entries = RB_ROOT;
143 "<-, -> or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0) 150
144 return -1; 151 pthread_mutex_lock(&notes->lock);
152
153 list_for_each_entry(pos, &notes->src->source, node) {
154 struct objdump_line_rb_node *rbpos = objdump_line__rb(pos);
155 rbpos->percent = objdump_line__calc_percent(pos, sym, evidx);
156 if (rbpos->percent < 0.01) {
157 RB_CLEAR_NODE(&rbpos->rb_node);
158 continue;
159 }
160 objdump__insert_line(&browser->entries, rbpos);
161 }
162 pthread_mutex_unlock(&notes->lock);
163
164 browser->curr_hot = rb_last(&browser->entries);
165}
166
167static int annotate_browser__run(struct annotate_browser *self, int evidx,
168 int refresh)
169{
170 struct rb_node *nd = NULL;
171 struct symbol *sym = self->b.priv;
145 /* 172 /*
146 * To allow builtin-annotate to cycle thru multiple symbols by 173 * RIGHT To allow builtin-annotate to cycle thru multiple symbols by
147 * examining the exit key for this function. 174 * examining the exit key for this function.
148 */ 175 */
149 ui_browser__add_exit_key(&self->b, NEWT_KEY_RIGHT); 176 int exit_keys[] = { 'H', NEWT_KEY_TAB, NEWT_KEY_UNTAB,
177 NEWT_KEY_RIGHT, 0 };
178 int key;
179
180 if (ui_browser__show(&self->b, sym->name,
181 "<-, -> or ESC: exit, TAB/shift+TAB: "
182 "cycle hottest lines, H: Hottest") < 0)
183 return -1;
184
185 ui_browser__add_exit_keys(&self->b, exit_keys);
186 annotate_browser__calc_percent(self, evidx);
187
188 if (self->curr_hot)
189 annotate_browser__set_top(self, self->curr_hot);
150 190
151 nd = self->curr_hot; 191 nd = self->curr_hot;
152 if (nd) { 192
153 int tabs[] = { NEWT_KEY_TAB, NEWT_KEY_UNTAB, 0 }; 193 if (refresh != 0)
154 ui_browser__add_exit_keys(&self->b, tabs); 194 newtFormSetTimer(self->b.form, refresh);
155 }
156 195
157 while (1) { 196 while (1) {
158 key = ui_browser__run(&self->b); 197 key = ui_browser__run(&self->b);
159 198
199 if (refresh != 0) {
200 annotate_browser__calc_percent(self, evidx);
201 /*
202 * Current line focus got out of the list of most active
203 * lines, NULL it so that if TAB|UNTAB is pressed, we
204 * move to curr_hot (current hottest line).
205 */
206 if (nd != NULL && RB_EMPTY_NODE(nd))
207 nd = NULL;
208 }
209
160 switch (key) { 210 switch (key) {
211 case -1:
212 /*
213 * FIXME we need to check if it was
214 * es.reason == NEWT_EXIT_TIMER
215 */
216 if (refresh != 0)
217 symbol__annotate_decay_histogram(sym, evidx);
218 continue;
161 case NEWT_KEY_TAB: 219 case NEWT_KEY_TAB:
162 nd = rb_prev(nd); 220 if (nd != NULL) {
163 if (nd == NULL) 221 nd = rb_prev(nd);
164 nd = rb_last(&self->entries); 222 if (nd == NULL)
165 annotate_browser__set_top(self, nd); 223 nd = rb_last(&self->entries);
224 } else
225 nd = self->curr_hot;
166 break; 226 break;
167 case NEWT_KEY_UNTAB: 227 case NEWT_KEY_UNTAB:
168 nd = rb_next(nd); 228 if (nd != NULL)
169 if (nd == NULL) 229 nd = rb_next(nd);
170 nd = rb_first(&self->entries); 230 if (nd == NULL)
171 annotate_browser__set_top(self, nd); 231 nd = rb_first(&self->entries);
232 else
233 nd = self->curr_hot;
234 break;
235 case 'H':
236 nd = self->curr_hot;
172 break; 237 break;
173 default: 238 default:
174 goto out; 239 goto out;
175 } 240 }
241
242 if (nd != NULL)
243 annotate_browser__set_top(self, nd);
176 } 244 }
177out: 245out:
178 ui_browser__hide(&self->b); 246 ui_browser__hide(&self->b);
179 return key; 247 return key;
180} 248}
181 249
182int hist_entry__tui_annotate(struct hist_entry *self) 250int hist_entry__tui_annotate(struct hist_entry *he, int evidx)
251{
252 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, 0);
253}
254
255int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
256 int refresh)
183{ 257{
184 struct objdump_line *pos, *n; 258 struct objdump_line *pos, *n;
185 struct objdump_line_rb_node *rbpos; 259 struct annotation *notes = symbol__annotation(sym);
186 LIST_HEAD(head);
187 struct annotate_browser browser = { 260 struct annotate_browser browser = {
188 .b = { 261 .b = {
189 .entries = &head, 262 .entries = &notes->src->source,
190 .refresh = ui_browser__list_head_refresh, 263 .refresh = ui_browser__list_head_refresh,
191 .seek = ui_browser__list_head_seek, 264 .seek = ui_browser__list_head_seek,
192 .write = annotate_browser__write, 265 .write = annotate_browser__write,
193 .priv = self, 266 .priv = sym,
194 }, 267 },
195 }; 268 };
196 int ret; 269 int ret;
197 270
198 if (self->ms.sym == NULL) 271 if (sym == NULL)
199 return -1; 272 return -1;
200 273
201 if (self->ms.map->dso->annotate_warned) 274 if (map->dso->annotate_warned)
202 return -1; 275 return -1;
203 276
204 if (hist_entry__annotate(self, &head, sizeof(*rbpos)) < 0) { 277 if (symbol__annotate(sym, map, sizeof(struct objdump_line_rb_node)) < 0) {
205 ui__error_window(ui_helpline__last_msg); 278 ui__error_window(ui_helpline__last_msg);
206 return -1; 279 return -1;
207 } 280 }
208 281
209 ui_helpline__push("Press <- or ESC to exit"); 282 ui_helpline__push("Press <- or ESC to exit");
210 283
211 list_for_each_entry(pos, &head, node) { 284 list_for_each_entry(pos, &notes->src->source, node) {
285 struct objdump_line_rb_node *rbpos;
212 size_t line_len = strlen(pos->line); 286 size_t line_len = strlen(pos->line);
287
213 if (browser.b.width < line_len) 288 if (browser.b.width < line_len)
214 browser.b.width = line_len; 289 browser.b.width = line_len;
215 rbpos = objdump_line__rb(pos); 290 rbpos = objdump_line__rb(pos);
216 rbpos->idx = browser.b.nr_entries++; 291 rbpos->idx = browser.b.nr_entries++;
217 rbpos->percent = objdump_line__calc_percent(pos, &head, self->ms.sym);
218 if (rbpos->percent < 0.01)
219 continue;
220 objdump__insert_line(&browser.entries, rbpos);
221 } 292 }
222 293
223 /*
224 * Position the browser at the hottest line.
225 */
226 browser.curr_hot = rb_last(&browser.entries);
227 if (browser.curr_hot)
228 annotate_browser__set_top(&browser, browser.curr_hot);
229
230 browser.b.width += 18; /* Percentage */ 294 browser.b.width += 18; /* Percentage */
231 ret = annotate_browser__run(&browser); 295 ret = annotate_browser__run(&browser, evidx, refresh);
232 list_for_each_entry_safe(pos, n, &head, node) { 296 list_for_each_entry_safe(pos, n, &notes->src->source, node) {
233 list_del(&pos->node); 297 list_del(&pos->node);
234 objdump_line__free(pos); 298 objdump_line__free(pos);
235 } 299 }
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index 60c463c16028..798efdca3ead 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -7,6 +7,8 @@
7#include <newt.h> 7#include <newt.h>
8#include <linux/rbtree.h> 8#include <linux/rbtree.h>
9 9
10#include "../../evsel.h"
11#include "../../evlist.h"
10#include "../../hist.h" 12#include "../../hist.h"
11#include "../../pstack.h" 13#include "../../pstack.h"
12#include "../../sort.h" 14#include "../../sort.h"
@@ -292,7 +294,8 @@ static int hist_browser__run(struct hist_browser *self, const char *title)
292{ 294{
293 int key; 295 int key;
294 int exit_keys[] = { 'a', '?', 'h', 'C', 'd', 'D', 'E', 't', 296 int exit_keys[] = { 'a', '?', 'h', 'C', 'd', 'D', 'E', 't',
295 NEWT_KEY_ENTER, NEWT_KEY_RIGHT, NEWT_KEY_LEFT, 0, }; 297 NEWT_KEY_ENTER, NEWT_KEY_RIGHT, NEWT_KEY_LEFT,
298 NEWT_KEY_TAB, NEWT_KEY_UNTAB, 0, };
296 299
297 self->b.entries = &self->hists->entries; 300 self->b.entries = &self->hists->entries;
298 self->b.nr_entries = self->hists->nr_entries; 301 self->b.nr_entries = self->hists->nr_entries;
@@ -377,7 +380,7 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *self,
377 while (node) { 380 while (node) {
378 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); 381 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
379 struct rb_node *next = rb_next(node); 382 struct rb_node *next = rb_next(node);
380 u64 cumul = cumul_hits(child); 383 u64 cumul = callchain_cumul_hits(child);
381 struct callchain_list *chain; 384 struct callchain_list *chain;
382 char folded_sign = ' '; 385 char folded_sign = ' ';
383 int first = true; 386 int first = true;
@@ -638,6 +641,9 @@ static void ui_browser__hists_seek(struct ui_browser *self,
638 struct rb_node *nd; 641 struct rb_node *nd;
639 bool first = true; 642 bool first = true;
640 643
644 if (self->nr_entries == 0)
645 return;
646
641 switch (whence) { 647 switch (whence) {
642 case SEEK_SET: 648 case SEEK_SET:
643 nd = hists__filter_entries(rb_first(self->entries)); 649 nd = hists__filter_entries(rb_first(self->entries));
@@ -797,8 +803,11 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,
797 return printed; 803 return printed;
798} 804}
799 805
800int hists__browse(struct hists *self, const char *helpline, const char *ev_name) 806static int perf_evsel__hists_browse(struct perf_evsel *evsel,
807 const char *helpline, const char *ev_name,
808 bool left_exits)
801{ 809{
810 struct hists *self = &evsel->hists;
802 struct hist_browser *browser = hist_browser__new(self); 811 struct hist_browser *browser = hist_browser__new(self);
803 struct pstack *fstack; 812 struct pstack *fstack;
804 const struct thread *thread_filter = NULL; 813 const struct thread *thread_filter = NULL;
@@ -818,8 +827,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
818 hists__browser_title(self, msg, sizeof(msg), ev_name, 827 hists__browser_title(self, msg, sizeof(msg), ev_name,
819 dso_filter, thread_filter); 828 dso_filter, thread_filter);
820 while (1) { 829 while (1) {
821 const struct thread *thread; 830 const struct thread *thread = NULL;
822 const struct dso *dso; 831 const struct dso *dso = NULL;
823 char *options[16]; 832 char *options[16];
824 int nr_options = 0, choice = 0, i, 833 int nr_options = 0, choice = 0, i,
825 annotate = -2, zoom_dso = -2, zoom_thread = -2, 834 annotate = -2, zoom_dso = -2, zoom_thread = -2,
@@ -827,8 +836,10 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
827 836
828 key = hist_browser__run(browser, msg); 837 key = hist_browser__run(browser, msg);
829 838
830 thread = hist_browser__selected_thread(browser); 839 if (browser->he_selection != NULL) {
831 dso = browser->selection->map ? browser->selection->map->dso : NULL; 840 thread = hist_browser__selected_thread(browser);
841 dso = browser->selection->map ? browser->selection->map->dso : NULL;
842 }
832 843
833 switch (key) { 844 switch (key) {
834 case NEWT_KEY_TAB: 845 case NEWT_KEY_TAB:
@@ -839,7 +850,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
839 */ 850 */
840 goto out_free_stack; 851 goto out_free_stack;
841 case 'a': 852 case 'a':
842 if (browser->selection->map == NULL && 853 if (browser->selection == NULL ||
854 browser->selection->map == NULL ||
843 browser->selection->map->dso->annotate_warned) 855 browser->selection->map->dso->annotate_warned)
844 continue; 856 continue;
845 goto do_annotate; 857 goto do_annotate;
@@ -858,6 +870,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
858 "E Expand all callchains\n" 870 "E Expand all callchains\n"
859 "d Zoom into current DSO\n" 871 "d Zoom into current DSO\n"
860 "t Zoom into current Thread\n" 872 "t Zoom into current Thread\n"
873 "TAB/UNTAB Switch events\n"
861 "q/CTRL+C Exit browser"); 874 "q/CTRL+C Exit browser");
862 continue; 875 continue;
863 case NEWT_KEY_ENTER: 876 case NEWT_KEY_ENTER:
@@ -867,8 +880,14 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
867 case NEWT_KEY_LEFT: { 880 case NEWT_KEY_LEFT: {
868 const void *top; 881 const void *top;
869 882
870 if (pstack__empty(fstack)) 883 if (pstack__empty(fstack)) {
884 /*
885 * Go back to the perf_evsel_menu__run or other user
886 */
887 if (left_exits)
888 goto out_free_stack;
871 continue; 889 continue;
890 }
872 top = pstack__pop(fstack); 891 top = pstack__pop(fstack);
873 if (top == &dso_filter) 892 if (top == &dso_filter)
874 goto zoom_out_dso; 893 goto zoom_out_dso;
@@ -877,14 +896,16 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
877 continue; 896 continue;
878 } 897 }
879 case NEWT_KEY_ESCAPE: 898 case NEWT_KEY_ESCAPE:
880 if (!ui__dialog_yesno("Do you really want to exit?")) 899 if (!left_exits &&
900 !ui__dialog_yesno("Do you really want to exit?"))
881 continue; 901 continue;
882 /* Fall thru */ 902 /* Fall thru */
883 default: 903 default:
884 goto out_free_stack; 904 goto out_free_stack;
885 } 905 }
886 906
887 if (browser->selection->sym != NULL && 907 if (browser->selection != NULL &&
908 browser->selection->sym != NULL &&
888 !browser->selection->map->dso->annotate_warned && 909 !browser->selection->map->dso->annotate_warned &&
889 asprintf(&options[nr_options], "Annotate %s", 910 asprintf(&options[nr_options], "Annotate %s",
890 browser->selection->sym->name) > 0) 911 browser->selection->sym->name) > 0)
@@ -903,7 +924,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
903 (dso->kernel ? "the Kernel" : dso->short_name)) > 0) 924 (dso->kernel ? "the Kernel" : dso->short_name)) > 0)
904 zoom_dso = nr_options++; 925 zoom_dso = nr_options++;
905 926
906 if (browser->selection->map != NULL && 927 if (browser->selection != NULL &&
928 browser->selection->map != NULL &&
907 asprintf(&options[nr_options], "Browse map details") > 0) 929 asprintf(&options[nr_options], "Browse map details") > 0)
908 browse_map = nr_options++; 930 browse_map = nr_options++;
909 931
@@ -923,19 +945,11 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
923 if (choice == annotate) { 945 if (choice == annotate) {
924 struct hist_entry *he; 946 struct hist_entry *he;
925do_annotate: 947do_annotate:
926 if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) {
927 browser->selection->map->dso->annotate_warned = 1;
928 ui_helpline__puts("No vmlinux file found, can't "
929 "annotate with just a "
930 "kallsyms file");
931 continue;
932 }
933
934 he = hist_browser__selected_entry(browser); 948 he = hist_browser__selected_entry(browser);
935 if (he == NULL) 949 if (he == NULL)
936 continue; 950 continue;
937 951
938 hist_entry__tui_annotate(he); 952 hist_entry__tui_annotate(he, evsel->idx);
939 } else if (choice == browse_map) 953 } else if (choice == browse_map)
940 map__browse(browser->selection->map); 954 map__browse(browser->selection->map);
941 else if (choice == zoom_dso) { 955 else if (choice == zoom_dso) {
@@ -984,30 +998,141 @@ out:
984 return key; 998 return key;
985} 999}
986 1000
987int hists__tui_browse_tree(struct rb_root *self, const char *help) 1001struct perf_evsel_menu {
1002 struct ui_browser b;
1003 struct perf_evsel *selection;
1004};
1005
1006static void perf_evsel_menu__write(struct ui_browser *browser,
1007 void *entry, int row)
1008{
1009 struct perf_evsel_menu *menu = container_of(browser,
1010 struct perf_evsel_menu, b);
1011 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
1012 bool current_entry = ui_browser__is_current_entry(browser, row);
1013 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
1014 const char *ev_name = event_name(evsel);
1015 char bf[256], unit;
1016
1017 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
1018 HE_COLORSET_NORMAL);
1019
1020 nr_events = convert_unit(nr_events, &unit);
1021 snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
1022 unit, unit == ' ' ? "" : " ", ev_name);
1023 slsmg_write_nstring(bf, browser->width);
1024
1025 if (current_entry)
1026 menu->selection = evsel;
1027}
1028
1029static int perf_evsel_menu__run(struct perf_evsel_menu *menu, const char *help)
988{ 1030{
989 struct rb_node *first = rb_first(self), *nd = first, *next; 1031 int exit_keys[] = { NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, };
990 int key = 0; 1032 struct perf_evlist *evlist = menu->b.priv;
1033 struct perf_evsel *pos;
1034 const char *ev_name, *title = "Available samples";
1035 int key;
1036
1037 if (ui_browser__show(&menu->b, title,
1038 "ESC: exit, ENTER|->: Browse histograms") < 0)
1039 return -1;
1040
1041 ui_browser__add_exit_keys(&menu->b, exit_keys);
991 1042
992 while (nd) { 1043 while (1) {
993 struct hists *hists = rb_entry(nd, struct hists, rb_node); 1044 key = ui_browser__run(&menu->b);
994 const char *ev_name = __event_name(hists->type, hists->config);
995 1045
996 key = hists__browse(hists, help, ev_name);
997 switch (key) { 1046 switch (key) {
998 case NEWT_KEY_TAB: 1047 case NEWT_KEY_RIGHT:
999 next = rb_next(nd); 1048 case NEWT_KEY_ENTER:
1000 if (next) 1049 if (!menu->selection)
1001 nd = next; 1050 continue;
1051 pos = menu->selection;
1052browse_hists:
1053 ev_name = event_name(pos);
1054 key = perf_evsel__hists_browse(pos, help, ev_name, true);
1055 ui_browser__show_title(&menu->b, title);
1002 break; 1056 break;
1003 case NEWT_KEY_UNTAB: 1057 case NEWT_KEY_LEFT:
1004 if (nd == first) 1058 continue;
1059 case NEWT_KEY_ESCAPE:
1060 if (!ui__dialog_yesno("Do you really want to exit?"))
1005 continue; 1061 continue;
1006 nd = rb_prev(nd); 1062 /* Fall thru */
1063 default:
1064 goto out;
1065 }
1066
1067 switch (key) {
1068 case NEWT_KEY_TAB:
1069 if (pos->node.next == &evlist->entries)
1070 pos = list_entry(evlist->entries.next, struct perf_evsel, node);
1071 else
1072 pos = list_entry(pos->node.next, struct perf_evsel, node);
1073 goto browse_hists;
1074 case NEWT_KEY_UNTAB:
1075 if (pos->node.prev == &evlist->entries)
1076 pos = list_entry(evlist->entries.prev, struct perf_evsel, node);
1077 else
1078 pos = list_entry(pos->node.prev, struct perf_evsel, node);
1079 goto browse_hists;
1080 case 'q':
1081 case CTRL('c'):
1082 goto out;
1007 default: 1083 default:
1008 return key; 1084 break;
1009 } 1085 }
1010 } 1086 }
1011 1087
1088out:
1089 ui_browser__hide(&menu->b);
1012 return key; 1090 return key;
1013} 1091}
1092
1093static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
1094 const char *help)
1095{
1096 struct perf_evsel *pos;
1097 struct perf_evsel_menu menu = {
1098 .b = {
1099 .entries = &evlist->entries,
1100 .refresh = ui_browser__list_head_refresh,
1101 .seek = ui_browser__list_head_seek,
1102 .write = perf_evsel_menu__write,
1103 .nr_entries = evlist->nr_entries,
1104 .priv = evlist,
1105 },
1106 };
1107
1108 ui_helpline__push("Press ESC to exit");
1109
1110 list_for_each_entry(pos, &evlist->entries, node) {
1111 const char *ev_name = event_name(pos);
1112 size_t line_len = strlen(ev_name) + 7;
1113
1114 if (menu.b.width < line_len)
1115 menu.b.width = line_len;
1116 /*
1117 * Cache the evsel name, tracepoints have a _high_ cost per
1118 * event_name() call.
1119 */
1120 if (pos->name == NULL)
1121 pos->name = strdup(ev_name);
1122 }
1123
1124 return perf_evsel_menu__run(&menu, help);
1125}
1126
1127int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help)
1128{
1129
1130 if (evlist->nr_entries == 1) {
1131 struct perf_evsel *first = list_entry(evlist->entries.next,
1132 struct perf_evsel, node);
1133 const char *ev_name = event_name(first);
1134 return perf_evsel__hists_browse(first, help, ev_name, false);
1135 }
1136
1137 return __perf_evlist__tui_browse_hists(evlist, help);
1138}
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c
index e5158369106e..8462bffe20bc 100644
--- a/tools/perf/util/ui/browsers/map.c
+++ b/tools/perf/util/ui/browsers/map.c
@@ -41,7 +41,7 @@ static int ui_entry__read(const char *title, char *bf, size_t size, int width)
41out_free_form: 41out_free_form:
42 newtPopWindow(); 42 newtPopWindow();
43 newtFormDestroy(form); 43 newtFormDestroy(form);
44 return 0; 44 return err;
45} 45}
46 46
47struct map_browser { 47struct map_browser {
diff --git a/tools/perf/util/ui/browsers/top.c b/tools/perf/util/ui/browsers/top.c
new file mode 100644
index 000000000000..5a06538532af
--- /dev/null
+++ b/tools/perf/util/ui/browsers/top.c
@@ -0,0 +1,213 @@
1/*
2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Parts came from builtin-{top,stat,record}.c, see those files for further
5 * copyright notes.
6 *
7 * Released under the GPL v2. (and only v2, not any later version)
8 */
9#include "../browser.h"
10#include "../../annotate.h"
11#include "../helpline.h"
12#include "../libslang.h"
13#include "../util.h"
14#include "../../evlist.h"
15#include "../../hist.h"
16#include "../../sort.h"
17#include "../../symbol.h"
18#include "../../top.h"
19
20struct perf_top_browser {
21 struct ui_browser b;
22 struct rb_root root;
23 struct sym_entry *selection;
24 float sum_ksamples;
25 int dso_width;
26 int dso_short_width;
27 int sym_width;
28};
29
30static void perf_top_browser__write(struct ui_browser *browser, void *entry, int row)
31{
32 struct perf_top_browser *top_browser = container_of(browser, struct perf_top_browser, b);
33 struct sym_entry *syme = rb_entry(entry, struct sym_entry, rb_node);
34 bool current_entry = ui_browser__is_current_entry(browser, row);
35 struct symbol *symbol = sym_entry__symbol(syme);
36 struct perf_top *top = browser->priv;
37 int width = browser->width;
38 double pcnt;
39
40 pcnt = 100.0 - (100.0 * ((top_browser->sum_ksamples - syme->snap_count) /
41 top_browser->sum_ksamples));
42 ui_browser__set_percent_color(browser, pcnt, current_entry);
43
44 if (top->evlist->nr_entries == 1 || !top->display_weighted) {
45 slsmg_printf("%20.2f ", syme->weight);
46 width -= 24;
47 } else {
48 slsmg_printf("%9.1f %10ld ", syme->weight, syme->snap_count);
49 width -= 23;
50 }
51
52 slsmg_printf("%4.1f%%", pcnt);
53 width -= 7;
54
55 if (verbose) {
56 slsmg_printf(" %016" PRIx64, symbol->start);
57 width -= 17;
58 }
59
60 slsmg_printf(" %-*.*s ", top_browser->sym_width, top_browser->sym_width,
61 symbol->name);
62 width -= top_browser->sym_width;
63 slsmg_write_nstring(width >= syme->map->dso->long_name_len ?
64 syme->map->dso->long_name :
65 syme->map->dso->short_name, width);
66
67 if (current_entry)
68 top_browser->selection = syme;
69}
70
71static void perf_top_browser__update_rb_tree(struct perf_top_browser *browser)
72{
73 struct perf_top *top = browser->b.priv;
74 u64 top_idx = browser->b.top_idx;
75
76 browser->root = RB_ROOT;
77 browser->b.top = NULL;
78 browser->sum_ksamples = perf_top__decay_samples(top, &browser->root);
79 /*
80 * No active symbols
81 */
82 if (top->rb_entries == 0)
83 return;
84
85 perf_top__find_widths(top, &browser->root, &browser->dso_width,
86 &browser->dso_short_width,
87 &browser->sym_width);
88 if (browser->sym_width + browser->dso_width > browser->b.width - 29) {
89 browser->dso_width = browser->dso_short_width;
90 if (browser->sym_width + browser->dso_width > browser->b.width - 29)
91 browser->sym_width = browser->b.width - browser->dso_width - 29;
92 }
93
94 /*
95 * Adjust the ui_browser indexes since the entries in the browser->root
96 * rb_tree may have changed, then seek it from start, so that we get a
97 * possible new top of the screen.
98 */
99 browser->b.nr_entries = top->rb_entries;
100
101 if (top_idx >= browser->b.nr_entries) {
102 if (browser->b.height >= browser->b.nr_entries)
103 top_idx = browser->b.nr_entries - browser->b.height;
104 else
105 top_idx = 0;
106 }
107
108 if (browser->b.index >= top_idx + browser->b.height)
109 browser->b.index = top_idx + browser->b.index - browser->b.top_idx;
110
111 if (browser->b.index >= browser->b.nr_entries)
112 browser->b.index = browser->b.nr_entries - 1;
113
114 browser->b.top_idx = top_idx;
115 browser->b.seek(&browser->b, top_idx, SEEK_SET);
116}
117
118static void perf_top_browser__annotate(struct perf_top_browser *browser)
119{
120 struct sym_entry *syme = browser->selection;
121 struct symbol *sym = sym_entry__symbol(syme);
122 struct annotation *notes = symbol__annotation(sym);
123 struct perf_top *top = browser->b.priv;
124
125 if (notes->src != NULL)
126 goto do_annotation;
127
128 pthread_mutex_lock(&notes->lock);
129
130 top->sym_filter_entry = NULL;
131
132 if (symbol__alloc_hist(sym, top->evlist->nr_entries) < 0) {
133 pr_err("Not enough memory for annotating '%s' symbol!\n",
134 sym->name);
135 pthread_mutex_unlock(&notes->lock);
136 return;
137 }
138
139 top->sym_filter_entry = syme;
140
141 pthread_mutex_unlock(&notes->lock);
142do_annotation:
143 symbol__tui_annotate(sym, syme->map, 0, top->delay_secs * 1000);
144}
145
146static int perf_top_browser__run(struct perf_top_browser *browser)
147{
148 int key;
149 char title[160];
150 struct perf_top *top = browser->b.priv;
151 int delay_msecs = top->delay_secs * 1000;
152 int exit_keys[] = { 'a', NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, };
153
154 perf_top_browser__update_rb_tree(browser);
155 perf_top__header_snprintf(top, title, sizeof(title));
156 perf_top__reset_sample_counters(top);
157
158 if (ui_browser__show(&browser->b, title,
159 "ESC: exit, ENTER|->|a: Live Annotate") < 0)
160 return -1;
161
162 newtFormSetTimer(browser->b.form, delay_msecs);
163 ui_browser__add_exit_keys(&browser->b, exit_keys);
164
165 while (1) {
166 key = ui_browser__run(&browser->b);
167
168 switch (key) {
169 case -1:
170 /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */
171 perf_top_browser__update_rb_tree(browser);
172 perf_top__header_snprintf(top, title, sizeof(title));
173 perf_top__reset_sample_counters(top);
174 ui_browser__set_color(&browser->b, NEWT_COLORSET_ROOT);
175 SLsmg_gotorc(0, 0);
176 slsmg_write_nstring(title, browser->b.width);
177 break;
178 case 'a':
179 case NEWT_KEY_RIGHT:
180 case NEWT_KEY_ENTER:
181 if (browser->selection)
182 perf_top_browser__annotate(browser);
183 break;
184 case NEWT_KEY_LEFT:
185 continue;
186 case NEWT_KEY_ESCAPE:
187 if (!ui__dialog_yesno("Do you really want to exit?"))
188 continue;
189 /* Fall thru */
190 default:
191 goto out;
192 }
193 }
194out:
195 ui_browser__hide(&browser->b);
196 return key;
197}
198
199int perf_top__tui_browser(struct perf_top *top)
200{
201 struct perf_top_browser browser = {
202 .b = {
203 .entries = &browser.root,
204 .refresh = ui_browser__rb_tree_refresh,
205 .seek = ui_browser__rb_tree_seek,
206 .write = perf_top_browser__write,
207 .priv = top,
208 },
209 };
210
211 ui_helpline__push("Press <- or ESC to exit");
212 return perf_top_browser__run(&browser);
213}
diff --git a/tools/perf/util/ui/helpline.c b/tools/perf/util/ui/helpline.c
index 8d79daa4458a..f36d2ff509ed 100644
--- a/tools/perf/util/ui/helpline.c
+++ b/tools/perf/util/ui/helpline.c
@@ -5,6 +5,7 @@
5 5
6#include "../debug.h" 6#include "../debug.h"
7#include "helpline.h" 7#include "helpline.h"
8#include "ui.h"
8 9
9void ui_helpline__pop(void) 10void ui_helpline__pop(void)
10{ 11{
@@ -55,7 +56,8 @@ int ui_helpline__show_help(const char *format, va_list ap)
55 int ret; 56 int ret;
56 static int backlog; 57 static int backlog;
57 58
58 ret = vsnprintf(ui_helpline__last_msg + backlog, 59 pthread_mutex_lock(&ui__lock);
60 ret = vsnprintf(ui_helpline__last_msg + backlog,
59 sizeof(ui_helpline__last_msg) - backlog, format, ap); 61 sizeof(ui_helpline__last_msg) - backlog, format, ap);
60 backlog += ret; 62 backlog += ret;
61 63
@@ -64,6 +66,7 @@ int ui_helpline__show_help(const char *format, va_list ap)
64 newtRefresh(); 66 newtRefresh();
65 backlog = 0; 67 backlog = 0;
66 } 68 }
69 pthread_mutex_unlock(&ui__lock);
67 70
68 return ret; 71 return ret;
69} 72}
diff --git a/tools/perf/util/ui/libslang.h b/tools/perf/util/ui/libslang.h
index 5623da8e8080..2b63e1c9b181 100644
--- a/tools/perf/util/ui/libslang.h
+++ b/tools/perf/util/ui/libslang.h
@@ -13,11 +13,11 @@
13 13
14#if SLANG_VERSION < 20104 14#if SLANG_VERSION < 20104
15#define slsmg_printf(msg, args...) \ 15#define slsmg_printf(msg, args...) \
16 SLsmg_printf((char *)msg, ##args) 16 SLsmg_printf((char *)(msg), ##args)
17#define slsmg_write_nstring(msg, len) \ 17#define slsmg_write_nstring(msg, len) \
18 SLsmg_write_nstring((char *)msg, len) 18 SLsmg_write_nstring((char *)(msg), len)
19#define sltt_set_color(obj, name, fg, bg) \ 19#define sltt_set_color(obj, name, fg, bg) \
20 SLtt_set_color(obj,(char *)name, (char *)fg, (char *)bg) 20 SLtt_set_color(obj,(char *)(name), (char *)(fg), (char *)(bg))
21#else 21#else
22#define slsmg_printf SLsmg_printf 22#define slsmg_printf SLsmg_printf
23#define slsmg_write_nstring SLsmg_write_nstring 23#define slsmg_write_nstring SLsmg_write_nstring
diff --git a/tools/perf/util/ui/setup.c b/tools/perf/util/ui/setup.c
index 662085032eb7..ee46d671db59 100644
--- a/tools/perf/util/ui/setup.c
+++ b/tools/perf/util/ui/setup.c
@@ -6,6 +6,9 @@
6#include "../debug.h" 6#include "../debug.h"
7#include "browser.h" 7#include "browser.h"
8#include "helpline.h" 8#include "helpline.h"
9#include "ui.h"
10
11pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
9 12
10static void newt_suspend(void *d __used) 13static void newt_suspend(void *d __used)
11{ 14{
@@ -14,11 +17,12 @@ static void newt_suspend(void *d __used)
14 newtResume(); 17 newtResume();
15} 18}
16 19
17void setup_browser(void) 20void setup_browser(bool fallback_to_pager)
18{ 21{
19 if (!isatty(1) || !use_browser || dump_trace) { 22 if (!isatty(1) || !use_browser || dump_trace) {
20 use_browser = 0; 23 use_browser = 0;
21 setup_pager(); 24 if (fallback_to_pager)
25 setup_pager();
22 return; 26 return;
23 } 27 }
24 28
diff --git a/tools/perf/util/ui/ui.h b/tools/perf/util/ui/ui.h
new file mode 100644
index 000000000000..d264e059c829
--- /dev/null
+++ b/tools/perf/util/ui/ui.h
@@ -0,0 +1,8 @@
1#ifndef _PERF_UI_H_
2#define _PERF_UI_H_ 1
3
4#include <pthread.h>
5
6extern pthread_mutex_t ui__lock;
7
8#endif /* _PERF_UI_H_ */
diff --git a/tools/perf/util/ui/util.c b/tools/perf/util/ui/util.c
index 7b5a8926624e..fdf1fc8f08bc 100644
--- a/tools/perf/util/ui/util.c
+++ b/tools/perf/util/ui/util.c
@@ -9,6 +9,7 @@
9#include "../debug.h" 9#include "../debug.h"
10#include "browser.h" 10#include "browser.h"
11#include "helpline.h" 11#include "helpline.h"
12#include "ui.h"
12#include "util.h" 13#include "util.h"
13 14
14static void newt_form__set_exit_keys(newtComponent self) 15static void newt_form__set_exit_keys(newtComponent self)
@@ -118,10 +119,12 @@ void ui__warning(const char *format, ...)
118 va_list args; 119 va_list args;
119 120
120 va_start(args, format); 121 va_start(args, format);
121 if (use_browser > 0) 122 if (use_browser > 0) {
123 pthread_mutex_lock(&ui__lock);
122 newtWinMessagev((char *)warning_str, (char *)ok, 124 newtWinMessagev((char *)warning_str, (char *)ok,
123 (char *)format, args); 125 (char *)format, args);
124 else 126 pthread_mutex_unlock(&ui__lock);
127 } else
125 vfprintf(stderr, format, args); 128 vfprintf(stderr, format, args);
126 va_end(args); 129 va_end(args);
127} 130}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index e833f26f3bfc..fc784284ac8b 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -70,9 +70,7 @@
70#include <sys/poll.h> 70#include <sys/poll.h>
71#include <sys/socket.h> 71#include <sys/socket.h>
72#include <sys/ioctl.h> 72#include <sys/ioctl.h>
73#ifndef NO_SYS_SELECT_H
74#include <sys/select.h> 73#include <sys/select.h>
75#endif
76#include <netinet/in.h> 74#include <netinet/in.h>
77#include <netinet/tcp.h> 75#include <netinet/tcp.h>
78#include <arpa/inet.h> 76#include <arpa/inet.h>
@@ -83,10 +81,6 @@
83#include "types.h" 81#include "types.h"
84#include <sys/ttydefaults.h> 82#include <sys/ttydefaults.h>
85 83
86#ifndef NO_ICONV
87#include <iconv.h>
88#endif
89
90extern const char *graph_line; 84extern const char *graph_line;
91extern const char *graph_dotted_line; 85extern const char *graph_dotted_line;
92extern char buildid_dir[]; 86extern char buildid_dir[];
@@ -236,26 +230,6 @@ static inline int sane_case(int x, int high)
236 return x; 230 return x;
237} 231}
238 232
239#ifndef DIR_HAS_BSD_GROUP_SEMANTICS
240# define FORCE_DIR_SET_GID S_ISGID
241#else
242# define FORCE_DIR_SET_GID 0
243#endif
244
245#ifdef NO_NSEC
246#undef USE_NSEC
247#define ST_CTIME_NSEC(st) 0
248#define ST_MTIME_NSEC(st) 0
249#else
250#ifdef USE_ST_TIMESPEC
251#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
252#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
253#else
254#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
255#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
256#endif
257#endif
258
259int mkdir_p(char *path, mode_t mode); 233int mkdir_p(char *path, mode_t mode);
260int copyfile(const char *from, const char *to); 234int copyfile(const char *from, const char *to);
261 235
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index e1c62eeb88f5..ba7c63af6f3b 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -1,6 +1,6 @@
1#!/usr/bin/perl -w 1#!/usr/bin/perl -w
2# 2#
3# Copywrite 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. 3# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
4# Licensed under the terms of the GNU GPL License version 2 4# Licensed under the terms of the GNU GPL License version 2
5# 5#
6 6