aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/perf_event.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r--kernel/perf_event.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 403d1804b19..b98bed3d818 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -402,11 +402,31 @@ static void perf_group_detach(struct perf_event *event)
402 } 402 }
403} 403}
404 404
405static inline int
406event_filter_match(struct perf_event *event)
407{
408 return event->cpu == -1 || event->cpu == smp_processor_id();
409}
410
405static void 411static void
406event_sched_out(struct perf_event *event, 412event_sched_out(struct perf_event *event,
407 struct perf_cpu_context *cpuctx, 413 struct perf_cpu_context *cpuctx,
408 struct perf_event_context *ctx) 414 struct perf_event_context *ctx)
409{ 415{
416 u64 delta;
417 /*
418 * An event which could not be activated because of
419 * filter mismatch still needs to have its timings
420 * maintained, otherwise bogus information is return
421 * via read() for time_enabled, time_running:
422 */
423 if (event->state == PERF_EVENT_STATE_INACTIVE
424 && !event_filter_match(event)) {
425 delta = ctx->time - event->tstamp_stopped;
426 event->tstamp_running += delta;
427 event->tstamp_stopped = ctx->time;
428 }
429
410 if (event->state != PERF_EVENT_STATE_ACTIVE) 430 if (event->state != PERF_EVENT_STATE_ACTIVE)
411 return; 431 return;
412 432
@@ -432,9 +452,7 @@ group_sched_out(struct perf_event *group_event,
432 struct perf_event_context *ctx) 452 struct perf_event_context *ctx)
433{ 453{
434 struct perf_event *event; 454 struct perf_event *event;
435 455 int state = group_event->state;
436 if (group_event->state != PERF_EVENT_STATE_ACTIVE)
437 return;
438 456
439 event_sched_out(group_event, cpuctx, ctx); 457 event_sched_out(group_event, cpuctx, ctx);
440 458
@@ -444,7 +462,7 @@ group_sched_out(struct perf_event *group_event,
444 list_for_each_entry(event, &group_event->sibling_list, group_entry) 462 list_for_each_entry(event, &group_event->sibling_list, group_entry)
445 event_sched_out(event, cpuctx, ctx); 463 event_sched_out(event, cpuctx, ctx);
446 464
447 if (group_event->attr.exclusive) 465 if (state == PERF_EVENT_STATE_ACTIVE && group_event->attr.exclusive)
448 cpuctx->exclusive = 0; 466 cpuctx->exclusive = 0;
449} 467}
450 468
@@ -2184,15 +2202,13 @@ static void perf_event_for_each(struct perf_event *event,
2184static int perf_event_period(struct perf_event *event, u64 __user *arg) 2202static int perf_event_period(struct perf_event *event, u64 __user *arg)
2185{ 2203{
2186 struct perf_event_context *ctx = event->ctx; 2204 struct perf_event_context *ctx = event->ctx;
2187 unsigned long size;
2188 int ret = 0; 2205 int ret = 0;
2189 u64 value; 2206 u64 value;
2190 2207
2191 if (!event->attr.sample_period) 2208 if (!event->attr.sample_period)
2192 return -EINVAL; 2209 return -EINVAL;
2193 2210
2194 size = copy_from_user(&value, arg, sizeof(value)); 2211 if (copy_from_user(&value, arg, sizeof(value)))
2195 if (size != sizeof(value))
2196 return -EFAULT; 2212 return -EFAULT;
2197 2213
2198 if (!value) 2214 if (!value)
@@ -5743,15 +5759,15 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
5743{ 5759{
5744 unsigned int cpu = (long)hcpu; 5760 unsigned int cpu = (long)hcpu;
5745 5761
5746 switch (action) { 5762 switch (action & ~CPU_TASKS_FROZEN) {
5747 5763
5748 case CPU_UP_PREPARE: 5764 case CPU_UP_PREPARE:
5749 case CPU_UP_PREPARE_FROZEN: 5765 case CPU_DOWN_FAILED:
5750 perf_event_init_cpu(cpu); 5766 perf_event_init_cpu(cpu);
5751 break; 5767 break;
5752 5768
5769 case CPU_UP_CANCELED:
5753 case CPU_DOWN_PREPARE: 5770 case CPU_DOWN_PREPARE:
5754 case CPU_DOWN_PREPARE_FROZEN:
5755 perf_event_exit_cpu(cpu); 5771 perf_event_exit_cpu(cpu);
5756 break; 5772 break;
5757 5773