diff options
Diffstat (limited to 'kernel/perf_event.c')
| -rw-r--r-- | kernel/perf_event.c | 46 | 
1 files changed, 27 insertions, 19 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 84522c796987..126a302c481c 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c  | |||
| @@ -2201,13 +2201,6 @@ find_lively_task_by_vpid(pid_t vpid) | |||
| 2201 | if (!task) | 2201 | if (!task) | 
| 2202 | return ERR_PTR(-ESRCH); | 2202 | return ERR_PTR(-ESRCH); | 
| 2203 | 2203 | ||
| 2204 | /* | ||
| 2205 | * Can't attach events to a dying task. | ||
| 2206 | */ | ||
| 2207 | err = -ESRCH; | ||
| 2208 | if (task->flags & PF_EXITING) | ||
| 2209 | goto errout; | ||
| 2210 | |||
| 2211 | /* Reuse ptrace permission checks for now. */ | 2204 | /* Reuse ptrace permission checks for now. */ | 
| 2212 | err = -EACCES; | 2205 | err = -EACCES; | 
| 2213 | if (!ptrace_may_access(task, PTRACE_MODE_READ)) | 2206 | if (!ptrace_may_access(task, PTRACE_MODE_READ)) | 
| @@ -2268,14 +2261,27 @@ retry: | |||
| 2268 | 2261 | ||
| 2269 | get_ctx(ctx); | 2262 | get_ctx(ctx); | 
| 2270 | 2263 | ||
| 2271 | if (cmpxchg(&task->perf_event_ctxp[ctxn], NULL, ctx)) { | 2264 | err = 0; | 
| 2272 | /* | 2265 | mutex_lock(&task->perf_event_mutex); | 
| 2273 | * We raced with some other task; use | 2266 | /* | 
| 2274 | * the context they set. | 2267 | * If it has already passed perf_event_exit_task(). | 
| 2275 | */ | 2268 | * we must see PF_EXITING, it takes this mutex too. | 
| 2269 | */ | ||
| 2270 | if (task->flags & PF_EXITING) | ||
| 2271 | err = -ESRCH; | ||
| 2272 | else if (task->perf_event_ctxp[ctxn]) | ||
| 2273 | err = -EAGAIN; | ||
| 2274 | else | ||
| 2275 | rcu_assign_pointer(task->perf_event_ctxp[ctxn], ctx); | ||
| 2276 | mutex_unlock(&task->perf_event_mutex); | ||
| 2277 | |||
| 2278 | if (unlikely(err)) { | ||
| 2276 | put_task_struct(task); | 2279 | put_task_struct(task); | 
| 2277 | kfree(ctx); | 2280 | kfree(ctx); | 
| 2278 | goto retry; | 2281 | |
| 2282 | if (err == -EAGAIN) | ||
| 2283 | goto retry; | ||
| 2284 | goto errout; | ||
| 2279 | } | 2285 | } | 
| 2280 | } | 2286 | } | 
| 2281 | 2287 | ||
| @@ -5374,6 +5380,8 @@ free_dev: | |||
| 5374 | goto out; | 5380 | goto out; | 
| 5375 | } | 5381 | } | 
| 5376 | 5382 | ||
| 5383 | static struct lock_class_key cpuctx_mutex; | ||
| 5384 | |||
| 5377 | int perf_pmu_register(struct pmu *pmu, char *name, int type) | 5385 | int perf_pmu_register(struct pmu *pmu, char *name, int type) | 
| 5378 | { | 5386 | { | 
| 5379 | int cpu, ret; | 5387 | int cpu, ret; | 
| @@ -5422,6 +5430,7 @@ skip_type: | |||
| 5422 | 5430 | ||
| 5423 | cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); | 5431 | cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); | 
| 5424 | __perf_event_init_context(&cpuctx->ctx); | 5432 | __perf_event_init_context(&cpuctx->ctx); | 
| 5433 | lockdep_set_class(&cpuctx->ctx.mutex, &cpuctx_mutex); | ||
| 5425 | cpuctx->ctx.type = cpu_context; | 5434 | cpuctx->ctx.type = cpu_context; | 
| 5426 | cpuctx->ctx.pmu = pmu; | 5435 | cpuctx->ctx.pmu = pmu; | 
| 5427 | cpuctx->jiffies_interval = 1; | 5436 | cpuctx->jiffies_interval = 1; | 
| @@ -6127,7 +6136,7 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn) | |||
| 6127 | * scheduled, so we are now safe from rescheduling changing | 6136 | * scheduled, so we are now safe from rescheduling changing | 
| 6128 | * our context. | 6137 | * our context. | 
| 6129 | */ | 6138 | */ | 
| 6130 | child_ctx = child->perf_event_ctxp[ctxn]; | 6139 | child_ctx = rcu_dereference_raw(child->perf_event_ctxp[ctxn]); | 
| 6131 | task_ctx_sched_out(child_ctx, EVENT_ALL); | 6140 | task_ctx_sched_out(child_ctx, EVENT_ALL); | 
| 6132 | 6141 | ||
| 6133 | /* | 6142 | /* | 
| @@ -6440,11 +6449,6 @@ int perf_event_init_context(struct task_struct *child, int ctxn) | |||
| 6440 | unsigned long flags; | 6449 | unsigned long flags; | 
| 6441 | int ret = 0; | 6450 | int ret = 0; | 
| 6442 | 6451 | ||
| 6443 | child->perf_event_ctxp[ctxn] = NULL; | ||
| 6444 | |||
| 6445 | mutex_init(&child->perf_event_mutex); | ||
| 6446 | INIT_LIST_HEAD(&child->perf_event_list); | ||
| 6447 | |||
| 6448 | if (likely(!parent->perf_event_ctxp[ctxn])) | 6452 | if (likely(!parent->perf_event_ctxp[ctxn])) | 
| 6449 | return 0; | 6453 | return 0; | 
| 6450 | 6454 | ||
| @@ -6533,6 +6537,10 @@ int perf_event_init_task(struct task_struct *child) | |||
| 6533 | { | 6537 | { | 
| 6534 | int ctxn, ret; | 6538 | int ctxn, ret; | 
| 6535 | 6539 | ||
| 6540 | memset(child->perf_event_ctxp, 0, sizeof(child->perf_event_ctxp)); | ||
| 6541 | mutex_init(&child->perf_event_mutex); | ||
| 6542 | INIT_LIST_HEAD(&child->perf_event_list); | ||
| 6543 | |||
| 6536 | for_each_task_context_nr(ctxn) { | 6544 | for_each_task_context_nr(ctxn) { | 
| 6537 | ret = perf_event_init_context(child, ctxn); | 6545 | ret = perf_event_init_context(child, ctxn); | 
| 6538 | if (ret) | 6546 | if (ret) | 
