aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2015-09-03 23:07:48 -0400
committerIngo Molnar <mingo@kernel.org>2015-09-13 05:27:27 -0400
commit0492d4c5b8c4dc3a7591bf6fa0e35d117812cc85 (patch)
treeccd5edfcd8b444dc4eea0c0ee9e94695f0e48934 /kernel/events
parentb15f495b4e9295cf21065d8569835a2f18cfe41b (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.c39
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
3187struct 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 */
3190static void __perf_event_read(void *info) 3195static 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
3231unlock:
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
3278static void perf_event_read(struct perf_event *event) 3296static 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
3988static void _perf_event_reset(struct perf_event *event) 4013static 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}