diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2010-09-13 05:06:55 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-09-13 11:08:42 -0400 |
commit | cde8e88498c8de69271fcb6d4dd974979368fa67 (patch) | |
tree | 34eb745cc6f3e5a5dbe0918f4920424be70bcfff /kernel/perf_event.c | |
parent | b0b2072df3b544f56b90173c2cde7a374c51546b (diff) |
perf: Sanitize the RCU logic
Simplify things and simply synchronize against two RCU variants for
PMU unregister -- we don't care about performance, its module unload
if anything.
Reported-by: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r-- | kernel/perf_event.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index f29b52576ec1..bc46bff69620 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -3810,7 +3810,7 @@ static void perf_event_task_event(struct perf_task_event *task_event) | |||
3810 | struct pmu *pmu; | 3810 | struct pmu *pmu; |
3811 | int ctxn; | 3811 | int ctxn; |
3812 | 3812 | ||
3813 | rcu_read_lock_sched(); | 3813 | rcu_read_lock(); |
3814 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 3814 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
3815 | cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); | 3815 | cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); |
3816 | perf_event_task_ctx(&cpuctx->ctx, task_event); | 3816 | perf_event_task_ctx(&cpuctx->ctx, task_event); |
@@ -3825,7 +3825,7 @@ static void perf_event_task_event(struct perf_task_event *task_event) | |||
3825 | if (ctx) | 3825 | if (ctx) |
3826 | perf_event_task_ctx(ctx, task_event); | 3826 | perf_event_task_ctx(ctx, task_event); |
3827 | } | 3827 | } |
3828 | rcu_read_unlock_sched(); | 3828 | rcu_read_unlock(); |
3829 | } | 3829 | } |
3830 | 3830 | ||
3831 | static void perf_event_task(struct task_struct *task, | 3831 | static void perf_event_task(struct task_struct *task, |
@@ -3943,7 +3943,7 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) | |||
3943 | 3943 | ||
3944 | comm_event->event_id.header.size = sizeof(comm_event->event_id) + size; | 3944 | comm_event->event_id.header.size = sizeof(comm_event->event_id) + size; |
3945 | 3945 | ||
3946 | rcu_read_lock_sched(); | 3946 | rcu_read_lock(); |
3947 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 3947 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
3948 | cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); | 3948 | cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); |
3949 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); | 3949 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); |
@@ -3956,7 +3956,7 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) | |||
3956 | if (ctx) | 3956 | if (ctx) |
3957 | perf_event_comm_ctx(ctx, comm_event); | 3957 | perf_event_comm_ctx(ctx, comm_event); |
3958 | } | 3958 | } |
3959 | rcu_read_unlock_sched(); | 3959 | rcu_read_unlock(); |
3960 | } | 3960 | } |
3961 | 3961 | ||
3962 | void perf_event_comm(struct task_struct *task) | 3962 | void perf_event_comm(struct task_struct *task) |
@@ -4126,7 +4126,7 @@ got_name: | |||
4126 | 4126 | ||
4127 | mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size; | 4127 | mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size; |
4128 | 4128 | ||
4129 | rcu_read_lock_sched(); | 4129 | rcu_read_lock(); |
4130 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 4130 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
4131 | cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); | 4131 | cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); |
4132 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, | 4132 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, |
@@ -4142,7 +4142,7 @@ got_name: | |||
4142 | vma->vm_flags & VM_EXEC); | 4142 | vma->vm_flags & VM_EXEC); |
4143 | } | 4143 | } |
4144 | } | 4144 | } |
4145 | rcu_read_unlock_sched(); | 4145 | rcu_read_unlock(); |
4146 | 4146 | ||
4147 | kfree(buf); | 4147 | kfree(buf); |
4148 | } | 4148 | } |
@@ -5218,10 +5218,11 @@ void perf_pmu_unregister(struct pmu *pmu) | |||
5218 | mutex_unlock(&pmus_lock); | 5218 | mutex_unlock(&pmus_lock); |
5219 | 5219 | ||
5220 | /* | 5220 | /* |
5221 | * We use the pmu list either under SRCU or preempt_disable, | 5221 | * We dereference the pmu list under both SRCU and regular RCU, so |
5222 | * synchronize_srcu() implies synchronize_sched() so we're good. | 5222 | * synchronize against both of those. |
5223 | */ | 5223 | */ |
5224 | synchronize_srcu(&pmus_srcu); | 5224 | synchronize_srcu(&pmus_srcu); |
5225 | synchronize_rcu(); | ||
5225 | 5226 | ||
5226 | free_percpu(pmu->pmu_disable_count); | 5227 | free_percpu(pmu->pmu_disable_count); |
5227 | free_pmu_context(pmu->pmu_cpu_context); | 5228 | free_pmu_context(pmu->pmu_cpu_context); |