diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/perf_event.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index eac7e336433..7b870174c56 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
| @@ -3824,6 +3824,8 @@ static void perf_event_task_event(struct perf_task_event *task_event) | |||
| 3824 | rcu_read_lock(); | 3824 | rcu_read_lock(); |
| 3825 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 3825 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
| 3826 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); | 3826 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); |
| 3827 | if (cpuctx->active_pmu != pmu) | ||
| 3828 | goto next; | ||
| 3827 | perf_event_task_ctx(&cpuctx->ctx, task_event); | 3829 | perf_event_task_ctx(&cpuctx->ctx, task_event); |
| 3828 | 3830 | ||
| 3829 | ctx = task_event->task_ctx; | 3831 | ctx = task_event->task_ctx; |
| @@ -3959,6 +3961,8 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) | |||
| 3959 | rcu_read_lock(); | 3961 | rcu_read_lock(); |
| 3960 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 3962 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
| 3961 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); | 3963 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); |
| 3964 | if (cpuctx->active_pmu != pmu) | ||
| 3965 | goto next; | ||
| 3962 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); | 3966 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); |
| 3963 | 3967 | ||
| 3964 | ctxn = pmu->task_ctx_nr; | 3968 | ctxn = pmu->task_ctx_nr; |
| @@ -4144,6 +4148,8 @@ got_name: | |||
| 4144 | rcu_read_lock(); | 4148 | rcu_read_lock(); |
| 4145 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 4149 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
| 4146 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); | 4150 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); |
| 4151 | if (cpuctx->active_pmu != pmu) | ||
| 4152 | goto next; | ||
| 4147 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, | 4153 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, |
| 4148 | vma->vm_flags & VM_EXEC); | 4154 | vma->vm_flags & VM_EXEC); |
| 4149 | 4155 | ||
| @@ -5145,20 +5151,36 @@ static void *find_pmu_context(int ctxn) | |||
| 5145 | return NULL; | 5151 | return NULL; |
| 5146 | } | 5152 | } |
| 5147 | 5153 | ||
| 5148 | static void free_pmu_context(void * __percpu cpu_context) | 5154 | static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu) |
| 5149 | { | 5155 | { |
| 5150 | struct pmu *pmu; | 5156 | int cpu; |
| 5157 | |||
| 5158 | for_each_possible_cpu(cpu) { | ||
| 5159 | struct perf_cpu_context *cpuctx; | ||
| 5160 | |||
| 5161 | cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); | ||
| 5162 | |||
| 5163 | if (cpuctx->active_pmu == old_pmu) | ||
| 5164 | cpuctx->active_pmu = pmu; | ||
| 5165 | } | ||
| 5166 | } | ||
| 5167 | |||
| 5168 | static void free_pmu_context(struct pmu *pmu) | ||
| 5169 | { | ||
| 5170 | struct pmu *i; | ||
| 5151 | 5171 | ||
| 5152 | mutex_lock(&pmus_lock); | 5172 | mutex_lock(&pmus_lock); |
| 5153 | /* | 5173 | /* |
| 5154 | * Like a real lame refcount. | 5174 | * Like a real lame refcount. |
| 5155 | */ | 5175 | */ |
| 5156 | list_for_each_entry(pmu, &pmus, entry) { | 5176 | list_for_each_entry(i, &pmus, entry) { |
| 5157 | if (pmu->pmu_cpu_context == cpu_context) | 5177 | if (i->pmu_cpu_context == pmu->pmu_cpu_context) { |
| 5178 | update_pmu_context(i, pmu); | ||
| 5158 | goto out; | 5179 | goto out; |
| 5180 | } | ||
| 5159 | } | 5181 | } |
| 5160 | 5182 | ||
| 5161 | free_percpu(cpu_context); | 5183 | free_percpu(pmu->pmu_cpu_context); |
| 5162 | out: | 5184 | out: |
| 5163 | mutex_unlock(&pmus_lock); | 5185 | mutex_unlock(&pmus_lock); |
| 5164 | } | 5186 | } |
| @@ -5190,6 +5212,7 @@ int perf_pmu_register(struct pmu *pmu) | |||
| 5190 | cpuctx->ctx.pmu = pmu; | 5212 | cpuctx->ctx.pmu = pmu; |
| 5191 | cpuctx->jiffies_interval = 1; | 5213 | cpuctx->jiffies_interval = 1; |
| 5192 | INIT_LIST_HEAD(&cpuctx->rotation_list); | 5214 | INIT_LIST_HEAD(&cpuctx->rotation_list); |
| 5215 | cpuctx->active_pmu = pmu; | ||
| 5193 | } | 5216 | } |
| 5194 | 5217 | ||
| 5195 | got_cpu_context: | 5218 | got_cpu_context: |
| @@ -5241,7 +5264,7 @@ void perf_pmu_unregister(struct pmu *pmu) | |||
| 5241 | synchronize_rcu(); | 5264 | synchronize_rcu(); |
| 5242 | 5265 | ||
| 5243 | free_percpu(pmu->pmu_disable_count); | 5266 | free_percpu(pmu->pmu_disable_count); |
| 5244 | free_pmu_context(pmu->pmu_cpu_context); | 5267 | free_pmu_context(pmu); |
| 5245 | } | 5268 | } |
| 5246 | 5269 | ||
| 5247 | struct pmu *perf_init_event(struct perf_event *event) | 5270 | struct pmu *perf_init_event(struct perf_event *event) |
