diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2010-09-16 13:17:24 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-09-21 07:55:44 -0400 |
commit | 41945f6ccf1e86f87fddf6b32db9cf431c05fb54 (patch) | |
tree | cf64d47bfff06ff4560efcaa23a067fa99db34dd /kernel/perf_event.c | |
parent | 8b8e2ec1eeca7f6941bc81cefc9663018d6ceb57 (diff) |
perf: Avoid RCU vs preemption assumptions
The per-pmu per-cpu context patch converted things from
get_cpu_var() to this_cpu_ptr(), but that only works if
rcu_read_lock() actually disables preemption, and since
there is no such guarantee, we need to fix that.
Use the newly introduced {get,put}_cpu_ptr().
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Tejun Heo <tj@kernel.org>
LKML-Reference: <20100917093009.308453028@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r-- | kernel/perf_event.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index baae1367e945..c16158c77dfd 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -3836,18 +3836,20 @@ static void perf_event_task_event(struct perf_task_event *task_event) | |||
3836 | 3836 | ||
3837 | rcu_read_lock(); | 3837 | rcu_read_lock(); |
3838 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 3838 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
3839 | cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); | 3839 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); |
3840 | perf_event_task_ctx(&cpuctx->ctx, task_event); | 3840 | perf_event_task_ctx(&cpuctx->ctx, task_event); |
3841 | 3841 | ||
3842 | ctx = task_event->task_ctx; | 3842 | ctx = task_event->task_ctx; |
3843 | if (!ctx) { | 3843 | if (!ctx) { |
3844 | ctxn = pmu->task_ctx_nr; | 3844 | ctxn = pmu->task_ctx_nr; |
3845 | if (ctxn < 0) | 3845 | if (ctxn < 0) |
3846 | continue; | 3846 | goto next; |
3847 | ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); | 3847 | ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); |
3848 | } | 3848 | } |
3849 | if (ctx) | 3849 | if (ctx) |
3850 | perf_event_task_ctx(ctx, task_event); | 3850 | perf_event_task_ctx(ctx, task_event); |
3851 | next: | ||
3852 | put_cpu_ptr(pmu->pmu_cpu_context); | ||
3851 | } | 3853 | } |
3852 | rcu_read_unlock(); | 3854 | rcu_read_unlock(); |
3853 | } | 3855 | } |
@@ -3969,16 +3971,18 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) | |||
3969 | 3971 | ||
3970 | rcu_read_lock(); | 3972 | rcu_read_lock(); |
3971 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 3973 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
3972 | cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); | 3974 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); |
3973 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); | 3975 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); |
3974 | 3976 | ||
3975 | ctxn = pmu->task_ctx_nr; | 3977 | ctxn = pmu->task_ctx_nr; |
3976 | if (ctxn < 0) | 3978 | if (ctxn < 0) |
3977 | continue; | 3979 | goto next; |
3978 | 3980 | ||
3979 | ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); | 3981 | ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); |
3980 | if (ctx) | 3982 | if (ctx) |
3981 | perf_event_comm_ctx(ctx, comm_event); | 3983 | perf_event_comm_ctx(ctx, comm_event); |
3984 | next: | ||
3985 | put_cpu_ptr(pmu->pmu_cpu_context); | ||
3982 | } | 3986 | } |
3983 | rcu_read_unlock(); | 3987 | rcu_read_unlock(); |
3984 | } | 3988 | } |
@@ -4152,19 +4156,21 @@ got_name: | |||
4152 | 4156 | ||
4153 | rcu_read_lock(); | 4157 | rcu_read_lock(); |
4154 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 4158 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
4155 | cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); | 4159 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); |
4156 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, | 4160 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, |
4157 | vma->vm_flags & VM_EXEC); | 4161 | vma->vm_flags & VM_EXEC); |
4158 | 4162 | ||
4159 | ctxn = pmu->task_ctx_nr; | 4163 | ctxn = pmu->task_ctx_nr; |
4160 | if (ctxn < 0) | 4164 | if (ctxn < 0) |
4161 | continue; | 4165 | goto next; |
4162 | 4166 | ||
4163 | ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); | 4167 | ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); |
4164 | if (ctx) { | 4168 | if (ctx) { |
4165 | perf_event_mmap_ctx(ctx, mmap_event, | 4169 | perf_event_mmap_ctx(ctx, mmap_event, |
4166 | vma->vm_flags & VM_EXEC); | 4170 | vma->vm_flags & VM_EXEC); |
4167 | } | 4171 | } |
4172 | next: | ||
4173 | put_cpu_ptr(pmu->pmu_cpu_context); | ||
4168 | } | 4174 | } |
4169 | rcu_read_unlock(); | 4175 | rcu_read_unlock(); |
4170 | 4176 | ||