perf_counter: optionally provide the pid/tid of the sampled task
authorPeter Zijlstra <a.p.zijlstra@chello.nl>
Wed, 25 Mar 2009 11:30:25 +0000 (12:30 +0100)
committerIngo Molnar <mingo@elte.hu>
Mon, 6 Apr 2009 07:30:34 +0000 (09:30 +0200)
Allow cpu wide counters to profile userspace by providing what process
the sample belongs to.

This raises the first issue with the output type, lots of these
options: group, tid, callchain, etc.. are non-exclusive and could be
combined, suggesting a bitfield.

However, things like the mmap() data stream doesn't fit in that.

How to split the type field...

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Arjan van de Ven <arjan@infradead.org>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Orig-LKML-Reference: <20090325113317.013775235@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
include/linux/perf_counter.h
kernel/perf_counter.c

index c256635377d4365e23b4beae924fd703cce3423c..7fdbdf8be7753d3c4868607eaafaff3ff1a15c14 100644 (file)
@@ -127,8 +127,9 @@ struct perf_counter_hw_event {
                                exclude_kernel :  1, /* ditto kernel          */
                                exclude_hv     :  1, /* ditto hypervisor      */
                                exclude_idle   :  1, /* don't count when idle */
+                               include_tid    :  1, /* include the tid */
 
-                               __reserved_1   : 55;
+                               __reserved_1   : 54;
 
        __u32                   extra_config_len;
        __u32                   __reserved_4;
@@ -164,6 +165,8 @@ struct perf_event_header {
 enum perf_event_type {
        PERF_EVENT_IP           = 0,
        PERF_EVENT_GROUP        = 1,
+
+       __PERF_EVENT_TID        = 0x100,
 };
 
 #ifdef __KERNEL__
index 7669afe82cc7c6b62aeebde009d0d782ed479f75..f3e1b27bc1b8559126bea89d6f701bfd4061ac61 100644 (file)
@@ -1528,16 +1528,30 @@ out:
 static void perf_output_simple(struct perf_counter *counter,
                               int nmi, struct pt_regs *regs)
 {
+       unsigned int size;
        struct {
                struct perf_event_header header;
                u64 ip;
+               u32 pid, tid;
        } event;
 
        event.header.type = PERF_EVENT_IP;
-       event.header.size = sizeof(event);
        event.ip = instruction_pointer(regs);
 
-       perf_output_write(counter, nmi, &event, sizeof(event));
+       size = sizeof(event);
+
+       if (counter->hw_event.include_tid) {
+               /* namespace issues */
+               event.pid = current->group_leader->pid;
+               event.tid = current->pid;
+
+               event.header.type |= __PERF_EVENT_TID;
+       } else
+               size -= sizeof(u64);
+
+       event.header.size = size;
+
+       perf_output_write(counter, nmi, &event, size);
 }
 
 static void perf_output_group(struct perf_counter *counter, int nmi)