perf: Fix inconsistency between IP and callchain sampling
authorAnton Blanchard <anton@samba.org>
Mon, 18 Jan 2010 05:47:07 +0000 (16:47 +1100)
committerFrederic Weisbecker <fweisbec@gmail.com>
Thu, 28 Jan 2010 13:31:20 +0000 (14:31 +0100)
When running perf across all cpus with backtracing (-a -g), sometimes we
get samples without associated backtraces:

    23.44%         init  [kernel]                     [k] restore
    11.46%         init                       eeba0c  [k] 0x00000000eeba0c
     6.77%      swapper  [kernel]                     [k] .perf_ctx_adjust_freq
     5.73%         init  [kernel]                     [k] .__trace_hcall_entry
     4.69%         perf  libc-2.9.so                  [.] 0x0000000006bb8c
                       |
                       |--11.11%-- 0xfffa941bbbc

It turns out the backtrace code has a check for the idle task and the IP
sampling does not. This creates problems when profiling an interrupt
heavy workload (in my case 10Gbit ethernet) since we get no backtraces
for interrupts received while idle (ie most of the workload).

Right now x86 and sh check that current is not NULL, which should never
happen so remove that too.

Idle task's exclusion must be performed from the core code, on top
of perf_event_attr:exclude_idle.

Signed-off-by: Anton Blanchard <anton@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mundt <lethal@linux-sh.org>
LKML-Reference: <20100118054707.GT12666@kryten>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
arch/powerpc/kernel/perf_callchain.c
arch/sh/kernel/perf_callchain.c
arch/x86/kernel/cpu/perf_event.c

index a3c11cac3d7154d1381d77a83ec513e5c6601c11..95ad9dad298e9d4773117b0406bc4a3378d77e5e 100644 (file)
@@ -495,9 +495,6 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
 
        entry->nr = 0;
 
-       if (current->pid == 0)          /* idle task? */
-               return entry;
-
        if (!user_mode(regs)) {
                perf_callchain_kernel(regs, entry);
                if (current->mm)
index 24ea837eac5bebc4f55018e8940386bb322636bc..a9dd3abde28e3f45bbd7d7654e8717c13aed8f34 100644 (file)
@@ -68,9 +68,6 @@ perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry)
 
        is_user = user_mode(regs);
 
-       if (!current || current->pid == 0)
-               return;
-
        if (is_user && current->state != TASK_RUNNING)
                return;
 
index b1bb8c550526ac36a8e1af514cf3ca74d7dc6c69..ed1998b28a7cab8eed044aeb280228eeab93d529 100644 (file)
@@ -2425,9 +2425,6 @@ perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry)
 
        is_user = user_mode(regs);
 
-       if (!current || current->pid == 0)
-               return;
-
        if (is_user && current->state != TASK_RUNNING)
                return;