mirror of
https://github.com/torvalds/linux.git
synced 2026-01-25 15:03:52 +08:00
Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: perf tools: Fix time function double declaration with glibc perf tools: Fix build by checking if extra warnings are supported perf tools: Fix build when using gcc 3.4.6 perf tools: Add missing header, fixes build perf tools: Fix 64 bit integer format strings perf test: Fix build on older glibcs perf: perf_event_exit_task_context: s/rcu_dereference/rcu_dereference_raw/ perf test: Use cpu_map->[cpu] when setting affinity perf symbols: Fix annotation of thumb code perf: Annotate cpuctx->ctx.mutex to avoid a lockdep splat powerpc, perf: Fix frequency calculation for overflowing counters (FSL version) perf: Fix perf_event_init_task()/perf_event_free_task() interaction perf: Fix find_get_context() vs perf_event_exit_task() race
This commit is contained in:
@@ -2201,13 +2201,6 @@ find_lively_task_by_vpid(pid_t vpid)
|
||||
if (!task)
|
||||
return ERR_PTR(-ESRCH);
|
||||
|
||||
/*
|
||||
* Can't attach events to a dying task.
|
||||
*/
|
||||
err = -ESRCH;
|
||||
if (task->flags & PF_EXITING)
|
||||
goto errout;
|
||||
|
||||
/* Reuse ptrace permission checks for now. */
|
||||
err = -EACCES;
|
||||
if (!ptrace_may_access(task, PTRACE_MODE_READ))
|
||||
@@ -2268,14 +2261,27 @@ retry:
|
||||
|
||||
get_ctx(ctx);
|
||||
|
||||
if (cmpxchg(&task->perf_event_ctxp[ctxn], NULL, ctx)) {
|
||||
/*
|
||||
* We raced with some other task; use
|
||||
* the context they set.
|
||||
*/
|
||||
err = 0;
|
||||
mutex_lock(&task->perf_event_mutex);
|
||||
/*
|
||||
* If it has already passed perf_event_exit_task().
|
||||
* we must see PF_EXITING, it takes this mutex too.
|
||||
*/
|
||||
if (task->flags & PF_EXITING)
|
||||
err = -ESRCH;
|
||||
else if (task->perf_event_ctxp[ctxn])
|
||||
err = -EAGAIN;
|
||||
else
|
||||
rcu_assign_pointer(task->perf_event_ctxp[ctxn], ctx);
|
||||
mutex_unlock(&task->perf_event_mutex);
|
||||
|
||||
if (unlikely(err)) {
|
||||
put_task_struct(task);
|
||||
kfree(ctx);
|
||||
goto retry;
|
||||
|
||||
if (err == -EAGAIN)
|
||||
goto retry;
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5374,6 +5380,8 @@ free_dev:
|
||||
goto out;
|
||||
}
|
||||
|
||||
static struct lock_class_key cpuctx_mutex;
|
||||
|
||||
int perf_pmu_register(struct pmu *pmu, char *name, int type)
|
||||
{
|
||||
int cpu, ret;
|
||||
@@ -5422,6 +5430,7 @@ skip_type:
|
||||
|
||||
cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
|
||||
__perf_event_init_context(&cpuctx->ctx);
|
||||
lockdep_set_class(&cpuctx->ctx.mutex, &cpuctx_mutex);
|
||||
cpuctx->ctx.type = cpu_context;
|
||||
cpuctx->ctx.pmu = pmu;
|
||||
cpuctx->jiffies_interval = 1;
|
||||
@@ -6127,7 +6136,7 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
|
||||
* scheduled, so we are now safe from rescheduling changing
|
||||
* our context.
|
||||
*/
|
||||
child_ctx = child->perf_event_ctxp[ctxn];
|
||||
child_ctx = rcu_dereference_raw(child->perf_event_ctxp[ctxn]);
|
||||
task_ctx_sched_out(child_ctx, EVENT_ALL);
|
||||
|
||||
/*
|
||||
@@ -6440,11 +6449,6 @@ int perf_event_init_context(struct task_struct *child, int ctxn)
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
child->perf_event_ctxp[ctxn] = NULL;
|
||||
|
||||
mutex_init(&child->perf_event_mutex);
|
||||
INIT_LIST_HEAD(&child->perf_event_list);
|
||||
|
||||
if (likely(!parent->perf_event_ctxp[ctxn]))
|
||||
return 0;
|
||||
|
||||
@@ -6533,6 +6537,10 @@ int perf_event_init_task(struct task_struct *child)
|
||||
{
|
||||
int ctxn, ret;
|
||||
|
||||
memset(child->perf_event_ctxp, 0, sizeof(child->perf_event_ctxp));
|
||||
mutex_init(&child->perf_event_mutex);
|
||||
INIT_LIST_HEAD(&child->perf_event_list);
|
||||
|
||||
for_each_task_context_nr(ctxn) {
|
||||
ret = perf_event_init_context(child, ctxn);
|
||||
if (ret)
|
||||
|
||||
Reference in New Issue
Block a user