aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-03-25 07:30:25 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-06 03:30:34 -0400
commitea5d20cf99db5d26d43b6d322d3ace17e08a6552 (patch)
tree287bb37825294d4f3cd943d83b6fb7d4b7009630
parent63e35b25d6b5c3136d22ef249dbbf96716aa08bf (diff)
perf_counter: optionally provide the pid/tid of the sampled task
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>
-rw-r--r--include/linux/perf_counter.h5
-rw-r--r--kernel/perf_counter.c18
2 files changed, 20 insertions, 3 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index c256635377d4..7fdbdf8be775 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -127,8 +127,9 @@ struct perf_counter_hw_event {
127 exclude_kernel : 1, /* ditto kernel */ 127 exclude_kernel : 1, /* ditto kernel */
128 exclude_hv : 1, /* ditto hypervisor */ 128 exclude_hv : 1, /* ditto hypervisor */
129 exclude_idle : 1, /* don't count when idle */ 129 exclude_idle : 1, /* don't count when idle */
130 include_tid : 1, /* include the tid */
130 131
131 __reserved_1 : 55; 132 __reserved_1 : 54;
132 133
133 __u32 extra_config_len; 134 __u32 extra_config_len;
134 __u32 __reserved_4; 135 __u32 __reserved_4;
@@ -164,6 +165,8 @@ struct perf_event_header {
164enum perf_event_type { 165enum perf_event_type {
165 PERF_EVENT_IP = 0, 166 PERF_EVENT_IP = 0,
166 PERF_EVENT_GROUP = 1, 167 PERF_EVENT_GROUP = 1,
168
169 __PERF_EVENT_TID = 0x100,
167}; 170};
168 171
169#ifdef __KERNEL__ 172#ifdef __KERNEL__
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index 7669afe82cc7..f3e1b27bc1b8 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -1528,16 +1528,30 @@ out:
1528static void perf_output_simple(struct perf_counter *counter, 1528static void perf_output_simple(struct perf_counter *counter,
1529 int nmi, struct pt_regs *regs) 1529 int nmi, struct pt_regs *regs)
1530{ 1530{
1531 unsigned int size;
1531 struct { 1532 struct {
1532 struct perf_event_header header; 1533 struct perf_event_header header;
1533 u64 ip; 1534 u64 ip;
1535 u32 pid, tid;
1534 } event; 1536 } event;
1535 1537
1536 event.header.type = PERF_EVENT_IP; 1538 event.header.type = PERF_EVENT_IP;
1537 event.header.size = sizeof(event);
1538 event.ip = instruction_pointer(regs); 1539 event.ip = instruction_pointer(regs);
1539 1540
1540 perf_output_write(counter, nmi, &event, sizeof(event)); 1541 size = sizeof(event);
1542
1543 if (counter->hw_event.include_tid) {
1544 /* namespace issues */
1545 event.pid = current->group_leader->pid;
1546 event.tid = current->pid;
1547
1548 event.header.type |= __PERF_EVENT_TID;
1549 } else
1550 size -= sizeof(u64);
1551
1552 event.header.size = size;
1553
1554 perf_output_write(counter, nmi, &event, size);
1541} 1555}
1542 1556
1543static void perf_output_group(struct perf_counter *counter, int nmi) 1557static void perf_output_group(struct perf_counter *counter, int nmi)