diff options
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r-- | kernel/perf_event.c | 36 |
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 | ||
405 | static inline int | ||
406 | event_filter_match(struct perf_event *event) | ||
407 | { | ||
408 | return event->cpu == -1 || event->cpu == smp_processor_id(); | ||
409 | } | ||
410 | |||
405 | static void | 411 | static void |
406 | event_sched_out(struct perf_event *event, | 412 | event_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, | |||
2184 | static int perf_event_period(struct perf_event *event, u64 __user *arg) | 2202 | static 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 | ||