diff options
author | Peter Zijlstra <peterz@infradead.org> | 2015-09-03 23:07:48 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-09-13 05:27:27 -0400 |
commit | 0492d4c5b8c4dc3a7591bf6fa0e35d117812cc85 (patch) | |
tree | ccd5edfcd8b444dc4eea0c0ee9e94695f0e48934 /kernel/events | |
parent | b15f495b4e9295cf21065d8569835a2f18cfe41b (diff) |
perf/core: Add group reads to perf_event_read()
Enable perf_event_read() to update entire groups at once, this will be
useful for read transactions.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Link: http://lkml.kernel.org/r/20150723080435.GE25159@twins.programming.kicks-ass.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/events')
-rw-r--r-- | kernel/events/core.c | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index 67b7dba4f0b5..4d89866edd4e 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -3184,12 +3184,18 @@ void perf_event_exec(void) | |||
3184 | rcu_read_unlock(); | 3184 | rcu_read_unlock(); |
3185 | } | 3185 | } |
3186 | 3186 | ||
3187 | struct perf_read_data { | ||
3188 | struct perf_event *event; | ||
3189 | bool group; | ||
3190 | }; | ||
3191 | |||
3187 | /* | 3192 | /* |
3188 | * Cross CPU call to read the hardware event | 3193 | * Cross CPU call to read the hardware event |
3189 | */ | 3194 | */ |
3190 | static void __perf_event_read(void *info) | 3195 | static void __perf_event_read(void *info) |
3191 | { | 3196 | { |
3192 | struct perf_event *event = info; | 3197 | struct perf_read_data *data = info; |
3198 | struct perf_event *sub, *event = data->event; | ||
3193 | struct perf_event_context *ctx = event->ctx; | 3199 | struct perf_event_context *ctx = event->ctx; |
3194 | struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); | 3200 | struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); |
3195 | 3201 | ||
@@ -3208,9 +3214,21 @@ static void __perf_event_read(void *info) | |||
3208 | update_context_time(ctx); | 3214 | update_context_time(ctx); |
3209 | update_cgrp_time_from_event(event); | 3215 | update_cgrp_time_from_event(event); |
3210 | } | 3216 | } |
3217 | |||
3211 | update_event_times(event); | 3218 | update_event_times(event); |
3212 | if (event->state == PERF_EVENT_STATE_ACTIVE) | 3219 | if (event->state == PERF_EVENT_STATE_ACTIVE) |
3213 | event->pmu->read(event); | 3220 | event->pmu->read(event); |
3221 | |||
3222 | if (!data->group) | ||
3223 | goto unlock; | ||
3224 | |||
3225 | list_for_each_entry(sub, &event->sibling_list, group_entry) { | ||
3226 | update_event_times(sub); | ||
3227 | if (sub->state == PERF_EVENT_STATE_ACTIVE) | ||
3228 | sub->pmu->read(sub); | ||
3229 | } | ||
3230 | |||
3231 | unlock: | ||
3214 | raw_spin_unlock(&ctx->lock); | 3232 | raw_spin_unlock(&ctx->lock); |
3215 | } | 3233 | } |
3216 | 3234 | ||
@@ -3275,15 +3293,19 @@ u64 perf_event_read_local(struct perf_event *event) | |||
3275 | return val; | 3293 | return val; |
3276 | } | 3294 | } |
3277 | 3295 | ||
3278 | static void perf_event_read(struct perf_event *event) | 3296 | static void perf_event_read(struct perf_event *event, bool group) |
3279 | { | 3297 | { |
3280 | /* | 3298 | /* |
3281 | * If event is enabled and currently active on a CPU, update the | 3299 | * If event is enabled and currently active on a CPU, update the |
3282 | * value in the event structure: | 3300 | * value in the event structure: |
3283 | */ | 3301 | */ |
3284 | if (event->state == PERF_EVENT_STATE_ACTIVE) { | 3302 | if (event->state == PERF_EVENT_STATE_ACTIVE) { |
3303 | struct perf_read_data data = { | ||
3304 | .event = event, | ||
3305 | .group = group, | ||
3306 | }; | ||
3285 | smp_call_function_single(event->oncpu, | 3307 | smp_call_function_single(event->oncpu, |
3286 | __perf_event_read, event, 1); | 3308 | __perf_event_read, &data, 1); |
3287 | } else if (event->state == PERF_EVENT_STATE_INACTIVE) { | 3309 | } else if (event->state == PERF_EVENT_STATE_INACTIVE) { |
3288 | struct perf_event_context *ctx = event->ctx; | 3310 | struct perf_event_context *ctx = event->ctx; |
3289 | unsigned long flags; | 3311 | unsigned long flags; |
@@ -3298,7 +3320,10 @@ static void perf_event_read(struct perf_event *event) | |||
3298 | update_context_time(ctx); | 3320 | update_context_time(ctx); |
3299 | update_cgrp_time_from_event(event); | 3321 | update_cgrp_time_from_event(event); |
3300 | } | 3322 | } |
3301 | update_event_times(event); | 3323 | if (group) |
3324 | update_group_times(event); | ||
3325 | else | ||
3326 | update_event_times(event); | ||
3302 | raw_spin_unlock_irqrestore(&ctx->lock, flags); | 3327 | raw_spin_unlock_irqrestore(&ctx->lock, flags); |
3303 | } | 3328 | } |
3304 | } | 3329 | } |
@@ -3817,7 +3842,7 @@ u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running) | |||
3817 | 3842 | ||
3818 | mutex_lock(&event->child_mutex); | 3843 | mutex_lock(&event->child_mutex); |
3819 | 3844 | ||
3820 | perf_event_read(event); | 3845 | perf_event_read(event, false); |
3821 | total += perf_event_count(event); | 3846 | total += perf_event_count(event); |
3822 | 3847 | ||
3823 | *enabled += event->total_time_enabled + | 3848 | *enabled += event->total_time_enabled + |
@@ -3826,7 +3851,7 @@ u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running) | |||
3826 | atomic64_read(&event->child_total_time_running); | 3851 | atomic64_read(&event->child_total_time_running); |
3827 | 3852 | ||
3828 | list_for_each_entry(child, &event->child_list, child_list) { | 3853 | list_for_each_entry(child, &event->child_list, child_list) { |
3829 | perf_event_read(child); | 3854 | perf_event_read(child, false); |
3830 | total += perf_event_count(child); | 3855 | total += perf_event_count(child); |
3831 | *enabled += child->total_time_enabled; | 3856 | *enabled += child->total_time_enabled; |
3832 | *running += child->total_time_running; | 3857 | *running += child->total_time_running; |
@@ -3987,7 +4012,7 @@ static unsigned int perf_poll(struct file *file, poll_table *wait) | |||
3987 | 4012 | ||
3988 | static void _perf_event_reset(struct perf_event *event) | 4013 | static void _perf_event_reset(struct perf_event *event) |
3989 | { | 4014 | { |
3990 | perf_event_read(event); | 4015 | perf_event_read(event, false); |
3991 | local64_set(&event->count, 0); | 4016 | local64_set(&event->count, 0); |
3992 | perf_event_update_userpage(event); | 4017 | perf_event_update_userpage(event); |
3993 | } | 4018 | } |