diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-12-14 23:20:36 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-14 23:25:02 +0100 |
commit | 0cc0c027d4e028632933f1be2dc4cd730358183b (patch) | |
tree | d64e0a45f5db7b6369198a1265a343f49e92714b /kernel/perf_counter.c | |
parent | 029af8c753bb5a7432aa1ed38bf61fe2c2f66d17 (diff) | |
download | lwn-0cc0c027d4e028632933f1be2dc4cd730358183b.tar.gz lwn-0cc0c027d4e028632933f1be2dc4cd730358183b.zip |
perfcounters: release CPU context when exiting task counters
If counters are exiting via do_exit() not via filp close, then
the CPU context needs to be released - otherwise future percpu
counter creations might fail.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_counter.c')
-rw-r--r-- | kernel/perf_counter.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 539fa8283a06..16396e9406fa 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -1273,8 +1273,19 @@ __perf_counter_exit_task(struct task_struct *child, local_irq_disable(); perf_flags = hw_perf_save_disable(); - if (child_counter->state == PERF_COUNTER_STATE_ACTIVE) + if (child_counter->state == PERF_COUNTER_STATE_ACTIVE) { + struct perf_cpu_context *cpuctx; + + cpuctx = &__get_cpu_var(perf_cpu_context); + child_counter->hw_ops->hw_perf_counter_disable(child_counter); + child_counter->state = PERF_COUNTER_STATE_INACTIVE; + child_counter->oncpu = -1; + + cpuctx->active_oncpu--; + child_ctx->nr_active--; + } + list_del_init(&child_counter->list_entry); hw_perf_restore(perf_flags); @@ -1539,4 +1550,3 @@ static int __init perf_counter_sysfs_init(void) &perfclass_attr_group); } device_initcall(perf_counter_sysfs_init); - |