diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-12-03 13:36:35 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-12-04 19:56:48 -0500 |
commit | 6844c09d849aeb00e8ddfe9525e8567a531c22d0 (patch) | |
tree | 6377067b6979199b249596aa6f3c9204d38cb8eb /kernel/perf_event.c | |
parent | 614b6780eb0c393d2fb49ff62d61f29b877bd07e (diff) |
perf events: Separate the routines handling the PERF_SAMPLE_ identity fields
Those will be made available in sample like events like MMAP, EXEC, etc in a
followup patch. So precalculate the extra id header space and have a separate
routine to fill them up.
V2: Thomas noticed that the id header needs to be precalculated at
inherit_events too:
LKML-Reference: <alpine.LFD.2.00.1012031245220.2653@localhost6.localdomain6>
Tested-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Ian Munsie <imunsie@au1.ibm.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Ian Munsie <imunsie@au1.ibm.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <1291318772-30880-2-git-send-email-acme@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r-- | kernel/perf_event.c | 129 |
1 files changed, 75 insertions, 54 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 7961b27acee..a0479976956 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -133,6 +133,28 @@ static void unclone_ctx(struct perf_event_context *ctx) | |||
133 | } | 133 | } |
134 | } | 134 | } |
135 | 135 | ||
136 | static u32 perf_event_pid(struct perf_event *event, struct task_struct *p) | ||
137 | { | ||
138 | /* | ||
139 | * only top level events have the pid namespace they were created in | ||
140 | */ | ||
141 | if (event->parent) | ||
142 | event = event->parent; | ||
143 | |||
144 | return task_tgid_nr_ns(p, event->ns); | ||
145 | } | ||
146 | |||
147 | static u32 perf_event_tid(struct perf_event *event, struct task_struct *p) | ||
148 | { | ||
149 | /* | ||
150 | * only top level events have the pid namespace they were created in | ||
151 | */ | ||
152 | if (event->parent) | ||
153 | event = event->parent; | ||
154 | |||
155 | return task_pid_nr_ns(p, event->ns); | ||
156 | } | ||
157 | |||
136 | /* | 158 | /* |
137 | * If we inherit events we want to return the parent event id | 159 | * If we inherit events we want to return the parent event id |
138 | * to userspace. | 160 | * to userspace. |
@@ -351,15 +373,30 @@ static void perf_event__header_size(struct perf_event *event) | |||
351 | if (sample_type & PERF_SAMPLE_IP) | 373 | if (sample_type & PERF_SAMPLE_IP) |
352 | size += sizeof(data->ip); | 374 | size += sizeof(data->ip); |
353 | 375 | ||
376 | if (sample_type & PERF_SAMPLE_ADDR) | ||
377 | size += sizeof(data->addr); | ||
378 | |||
379 | if (sample_type & PERF_SAMPLE_PERIOD) | ||
380 | size += sizeof(data->period); | ||
381 | |||
382 | if (sample_type & PERF_SAMPLE_READ) | ||
383 | size += event->read_size; | ||
384 | |||
385 | event->header_size = size; | ||
386 | } | ||
387 | |||
388 | static void perf_event__id_header_size(struct perf_event *event) | ||
389 | { | ||
390 | struct perf_sample_data *data; | ||
391 | u64 sample_type = event->attr.sample_type; | ||
392 | u16 size = 0; | ||
393 | |||
354 | if (sample_type & PERF_SAMPLE_TID) | 394 | if (sample_type & PERF_SAMPLE_TID) |
355 | size += sizeof(data->tid_entry); | 395 | size += sizeof(data->tid_entry); |
356 | 396 | ||
357 | if (sample_type & PERF_SAMPLE_TIME) | 397 | if (sample_type & PERF_SAMPLE_TIME) |
358 | size += sizeof(data->time); | 398 | size += sizeof(data->time); |
359 | 399 | ||
360 | if (sample_type & PERF_SAMPLE_ADDR) | ||
361 | size += sizeof(data->addr); | ||
362 | |||
363 | if (sample_type & PERF_SAMPLE_ID) | 400 | if (sample_type & PERF_SAMPLE_ID) |
364 | size += sizeof(data->id); | 401 | size += sizeof(data->id); |
365 | 402 | ||
@@ -369,13 +406,7 @@ static void perf_event__header_size(struct perf_event *event) | |||
369 | if (sample_type & PERF_SAMPLE_CPU) | 406 | if (sample_type & PERF_SAMPLE_CPU) |
370 | size += sizeof(data->cpu_entry); | 407 | size += sizeof(data->cpu_entry); |
371 | 408 | ||
372 | if (sample_type & PERF_SAMPLE_PERIOD) | 409 | event->id_header_size = size; |
373 | size += sizeof(data->period); | ||
374 | |||
375 | if (sample_type & PERF_SAMPLE_READ) | ||
376 | size += event->read_size; | ||
377 | |||
378 | event->header_size = size; | ||
379 | } | 410 | } |
380 | 411 | ||
381 | static void perf_group_attach(struct perf_event *event) | 412 | static void perf_group_attach(struct perf_event *event) |
@@ -3357,6 +3388,36 @@ __always_inline void perf_output_copy(struct perf_output_handle *handle, | |||
3357 | } while (len); | 3388 | } while (len); |
3358 | } | 3389 | } |
3359 | 3390 | ||
3391 | static void perf_event_header__init_id(struct perf_event_header *header, | ||
3392 | struct perf_sample_data *data, | ||
3393 | struct perf_event *event) | ||
3394 | { | ||
3395 | u64 sample_type = event->attr.sample_type; | ||
3396 | |||
3397 | data->type = sample_type; | ||
3398 | header->size += event->id_header_size; | ||
3399 | |||
3400 | if (sample_type & PERF_SAMPLE_TID) { | ||
3401 | /* namespace issues */ | ||
3402 | data->tid_entry.pid = perf_event_pid(event, current); | ||
3403 | data->tid_entry.tid = perf_event_tid(event, current); | ||
3404 | } | ||
3405 | |||
3406 | if (sample_type & PERF_SAMPLE_TIME) | ||
3407 | data->time = perf_clock(); | ||
3408 | |||
3409 | if (sample_type & PERF_SAMPLE_ID) | ||
3410 | data->id = primary_event_id(event); | ||
3411 | |||
3412 | if (sample_type & PERF_SAMPLE_STREAM_ID) | ||
3413 | data->stream_id = event->id; | ||
3414 | |||
3415 | if (sample_type & PERF_SAMPLE_CPU) { | ||
3416 | data->cpu_entry.cpu = raw_smp_processor_id(); | ||
3417 | data->cpu_entry.reserved = 0; | ||
3418 | } | ||
3419 | } | ||
3420 | |||
3360 | int perf_output_begin(struct perf_output_handle *handle, | 3421 | int perf_output_begin(struct perf_output_handle *handle, |
3361 | struct perf_event *event, unsigned int size, | 3422 | struct perf_event *event, unsigned int size, |
3362 | int nmi, int sample) | 3423 | int nmi, int sample) |
@@ -3459,28 +3520,6 @@ void perf_output_end(struct perf_output_handle *handle) | |||
3459 | rcu_read_unlock(); | 3520 | rcu_read_unlock(); |
3460 | } | 3521 | } |
3461 | 3522 | ||
3462 | static u32 perf_event_pid(struct perf_event *event, struct task_struct *p) | ||
3463 | { | ||
3464 | /* | ||
3465 | * only top level events have the pid namespace they were created in | ||
3466 | */ | ||
3467 | if (event->parent) | ||
3468 | event = event->parent; | ||
3469 | |||
3470 | return task_tgid_nr_ns(p, event->ns); | ||
3471 | } | ||
3472 | |||
3473 | static u32 perf_event_tid(struct perf_event *event, struct task_struct *p) | ||
3474 | { | ||
3475 | /* | ||
3476 | * only top level events have the pid namespace they were created in | ||
3477 | */ | ||
3478 | if (event->parent) | ||
3479 | event = event->parent; | ||
3480 | |||
3481 | return task_pid_nr_ns(p, event->ns); | ||
3482 | } | ||
3483 | |||
3484 | static void perf_output_read_one(struct perf_output_handle *handle, | 3523 | static void perf_output_read_one(struct perf_output_handle *handle, |
3485 | struct perf_event *event, | 3524 | struct perf_event *event, |
3486 | u64 enabled, u64 running) | 3525 | u64 enabled, u64 running) |
@@ -3655,37 +3694,17 @@ void perf_prepare_sample(struct perf_event_header *header, | |||
3655 | { | 3694 | { |
3656 | u64 sample_type = event->attr.sample_type; | 3695 | u64 sample_type = event->attr.sample_type; |
3657 | 3696 | ||
3658 | data->type = sample_type; | ||
3659 | |||
3660 | header->type = PERF_RECORD_SAMPLE; | 3697 | header->type = PERF_RECORD_SAMPLE; |
3661 | header->size = sizeof(*header) + event->header_size; | 3698 | header->size = sizeof(*header) + event->header_size; |
3662 | 3699 | ||
3663 | header->misc = 0; | 3700 | header->misc = 0; |
3664 | header->misc |= perf_misc_flags(regs); | 3701 | header->misc |= perf_misc_flags(regs); |
3665 | 3702 | ||
3703 | perf_event_header__init_id(header, data, event); | ||
3704 | |||
3666 | if (sample_type & PERF_SAMPLE_IP) | 3705 | if (sample_type & PERF_SAMPLE_IP) |
3667 | data->ip = perf_instruction_pointer(regs); | 3706 | data->ip = perf_instruction_pointer(regs); |
3668 | 3707 | ||
3669 | if (sample_type & PERF_SAMPLE_TID) { | ||
3670 | /* namespace issues */ | ||
3671 | data->tid_entry.pid = perf_event_pid(event, current); | ||
3672 | data->tid_entry.tid = perf_event_tid(event, current); | ||
3673 | } | ||
3674 | |||
3675 | if (sample_type & PERF_SAMPLE_TIME) | ||
3676 | data->time = perf_clock(); | ||
3677 | |||
3678 | if (sample_type & PERF_SAMPLE_ID) | ||
3679 | data->id = primary_event_id(event); | ||
3680 | |||
3681 | if (sample_type & PERF_SAMPLE_STREAM_ID) | ||
3682 | data->stream_id = event->id; | ||
3683 | |||
3684 | if (sample_type & PERF_SAMPLE_CPU) { | ||
3685 | data->cpu_entry.cpu = raw_smp_processor_id(); | ||
3686 | data->cpu_entry.reserved = 0; | ||
3687 | } | ||
3688 | |||
3689 | if (sample_type & PERF_SAMPLE_CALLCHAIN) { | 3708 | if (sample_type & PERF_SAMPLE_CALLCHAIN) { |
3690 | int size = 1; | 3709 | int size = 1; |
3691 | 3710 | ||
@@ -5745,6 +5764,7 @@ SYSCALL_DEFINE5(perf_event_open, | |||
5745 | * Precalculate sample_data sizes | 5764 | * Precalculate sample_data sizes |
5746 | */ | 5765 | */ |
5747 | perf_event__header_size(event); | 5766 | perf_event__header_size(event); |
5767 | perf_event__id_header_size(event); | ||
5748 | 5768 | ||
5749 | /* | 5769 | /* |
5750 | * Drop the reference on the group_event after placing the | 5770 | * Drop the reference on the group_event after placing the |
@@ -6102,6 +6122,7 @@ inherit_event(struct perf_event *parent_event, | |||
6102 | * Precalculate sample_data sizes | 6122 | * Precalculate sample_data sizes |
6103 | */ | 6123 | */ |
6104 | perf_event__header_size(child_event); | 6124 | perf_event__header_size(child_event); |
6125 | perf_event__id_header_size(child_event); | ||
6105 | 6126 | ||
6106 | /* | 6127 | /* |
6107 | * Link it up in the child's context: | 6128 | * Link it up in the child's context: |