aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/perf_counter.c128
1 files changed, 74 insertions, 54 deletions
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index 79c3f26541d3..da8dfef4b472 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -123,6 +123,69 @@ static void put_ctx(struct perf_counter_context *ctx)
123} 123}
124 124
125/* 125/*
126 * Get the perf_counter_context for a task and lock it.
127 * This has to cope with with the fact that until it is locked,
128 * the context could get moved to another task.
129 */
130static struct perf_counter_context *perf_lock_task_context(
131 struct task_struct *task, unsigned long *flags)
132{
133 struct perf_counter_context *ctx;
134
135 rcu_read_lock();
136 retry:
137 ctx = rcu_dereference(task->perf_counter_ctxp);
138 if (ctx) {
139 /*
140 * If this context is a clone of another, it might
141 * get swapped for another underneath us by
142 * perf_counter_task_sched_out, though the
143 * rcu_read_lock() protects us from any context
144 * getting freed. Lock the context and check if it
145 * got swapped before we could get the lock, and retry
146 * if so. If we locked the right context, then it
147 * can't get swapped on us any more.
148 */
149 spin_lock_irqsave(&ctx->lock, *flags);
150 if (ctx != rcu_dereference(task->perf_counter_ctxp)) {
151 spin_unlock_irqrestore(&ctx->lock, *flags);
152 goto retry;
153 }
154 }
155 rcu_read_unlock();
156 return ctx;
157}
158
159/*
160 * Get the context for a task and increment its pin_count so it
161 * can't get swapped to another task. This also increments its
162 * reference count so that the context can't get freed.
163 */
164static struct perf_counter_context *perf_pin_task_context(struct task_struct *task)
165{
166 struct perf_counter_context *ctx;
167 unsigned long flags;
168
169 ctx = perf_lock_task_context(task, &flags);
170 if (ctx) {
171 ++ctx->pin_count;
172 get_ctx(ctx);
173 spin_unlock_irqrestore(&ctx->lock, flags);
174 }
175 return ctx;
176}
177
178static void perf_unpin_context(struct perf_counter_context *ctx)
179{
180 unsigned long flags;
181
182 spin_lock_irqsave(&ctx->lock, flags);
183 --ctx->pin_count;
184 spin_unlock_irqrestore(&ctx->lock, flags);
185 put_ctx(ctx);
186}
187
188/*
126 * Add a counter from the lists for its context. 189 * Add a counter from the lists for its context.
127 * Must be called with ctx->mutex and ctx->lock held. 190 * Must be called with ctx->mutex and ctx->lock held.
128 */ 191 */
@@ -916,7 +979,7 @@ static int context_equiv(struct perf_counter_context *ctx1,
916{ 979{
917 return ctx1->parent_ctx && ctx1->parent_ctx == ctx2->parent_ctx 980 return ctx1->parent_ctx && ctx1->parent_ctx == ctx2->parent_ctx
918 && ctx1->parent_gen == ctx2->parent_gen 981 && ctx1->parent_gen == ctx2->parent_gen
919 && ctx1->parent_gen != ~0ull; 982 && !ctx1->pin_count && !ctx2->pin_count;
920} 983}
921 984
922/* 985/*
@@ -1271,6 +1334,7 @@ static struct perf_counter_context *find_get_context(pid_t pid, int cpu)
1271 struct perf_counter_context *ctx; 1334 struct perf_counter_context *ctx;
1272 struct perf_counter_context *parent_ctx; 1335 struct perf_counter_context *parent_ctx;
1273 struct task_struct *task; 1336 struct task_struct *task;
1337 unsigned long flags;
1274 int err; 1338 int err;
1275 1339
1276 /* 1340 /*
@@ -1323,28 +1387,9 @@ static struct perf_counter_context *find_get_context(pid_t pid, int cpu)
1323 if (!ptrace_may_access(task, PTRACE_MODE_READ)) 1387 if (!ptrace_may_access(task, PTRACE_MODE_READ))
1324 goto errout; 1388 goto errout;
1325 1389
1326 retry_lock:
1327 rcu_read_lock();
1328 retry: 1390 retry:
1329 ctx = rcu_dereference(task->perf_counter_ctxp); 1391 ctx = perf_lock_task_context(task, &flags);
1330 if (ctx) { 1392 if (ctx) {
1331 /*
1332 * If this context is a clone of another, it might
1333 * get swapped for another underneath us by
1334 * perf_counter_task_sched_out, though the
1335 * rcu_read_lock() protects us from any context
1336 * getting freed. Lock the context and check if it
1337 * got swapped before we could get the lock, and retry
1338 * if so. If we locked the right context, then it
1339 * can't get swapped on us any more and we can
1340 * unclone it if necessary.
1341 * Once it's not a clone things will be stable.
1342 */
1343 spin_lock_irq(&ctx->lock);
1344 if (ctx != rcu_dereference(task->perf_counter_ctxp)) {
1345 spin_unlock_irq(&ctx->lock);
1346 goto retry;
1347 }
1348 parent_ctx = ctx->parent_ctx; 1393 parent_ctx = ctx->parent_ctx;
1349 if (parent_ctx) { 1394 if (parent_ctx) {
1350 put_ctx(parent_ctx); 1395 put_ctx(parent_ctx);
@@ -1355,9 +1400,8 @@ static struct perf_counter_context *find_get_context(pid_t pid, int cpu)
1355 * this context won't get freed if the task exits. 1400 * this context won't get freed if the task exits.
1356 */ 1401 */
1357 get_ctx(ctx); 1402 get_ctx(ctx);
1358 spin_unlock_irq(&ctx->lock); 1403 spin_unlock_irqrestore(&ctx->lock, flags);
1359 } 1404 }
1360 rcu_read_unlock();
1361 1405
1362 if (!ctx) { 1406 if (!ctx) {
1363 ctx = kmalloc(sizeof(struct perf_counter_context), GFP_KERNEL); 1407 ctx = kmalloc(sizeof(struct perf_counter_context), GFP_KERNEL);
@@ -1372,7 +1416,7 @@ static struct perf_counter_context *find_get_context(pid_t pid, int cpu)
1372 * the context they set. 1416 * the context they set.
1373 */ 1417 */
1374 kfree(ctx); 1418 kfree(ctx);
1375 goto retry_lock; 1419 goto retry;
1376 } 1420 }
1377 get_task_struct(task); 1421 get_task_struct(task);
1378 } 1422 }
@@ -3667,7 +3711,6 @@ int perf_counter_init_task(struct task_struct *child)
3667 struct perf_counter *counter; 3711 struct perf_counter *counter;
3668 struct task_struct *parent = current; 3712 struct task_struct *parent = current;
3669 int inherited_all = 1; 3713 int inherited_all = 1;
3670 u64 cloned_gen;
3671 int ret = 0; 3714 int ret = 0;
3672 3715
3673 child->perf_counter_ctxp = NULL; 3716 child->perf_counter_ctxp = NULL;
@@ -3693,32 +3736,17 @@ int perf_counter_init_task(struct task_struct *child)
3693 get_task_struct(child); 3736 get_task_struct(child);
3694 3737
3695 /* 3738 /*
3696 * If the parent's context is a clone, temporarily set its 3739 * If the parent's context is a clone, pin it so it won't get
3697 * parent_gen to an impossible value (all 1s) so it won't get 3740 * swapped under us.
3698 * swapped under us. The rcu_read_lock makes sure that
3699 * parent_ctx continues to exist even if it gets swapped to
3700 * another process and then freed while we are trying to get
3701 * its lock.
3702 */ 3741 */
3703 rcu_read_lock(); 3742 parent_ctx = perf_pin_task_context(parent);
3704 retry: 3743
3705 parent_ctx = rcu_dereference(parent->perf_counter_ctxp);
3706 /* 3744 /*
3707 * No need to check if parent_ctx != NULL here; since we saw 3745 * No need to check if parent_ctx != NULL here; since we saw
3708 * it non-NULL earlier, the only reason for it to become NULL 3746 * it non-NULL earlier, the only reason for it to become NULL
3709 * is if we exit, and since we're currently in the middle of 3747 * is if we exit, and since we're currently in the middle of
3710 * a fork we can't be exiting at the same time. 3748 * a fork we can't be exiting at the same time.
3711 */ 3749 */
3712 spin_lock_irq(&parent_ctx->lock);
3713 if (parent_ctx != rcu_dereference(parent->perf_counter_ctxp)) {
3714 spin_unlock_irq(&parent_ctx->lock);
3715 goto retry;
3716 }
3717 cloned_gen = parent_ctx->parent_gen;
3718 if (parent_ctx->parent_ctx)
3719 parent_ctx->parent_gen = ~0ull;
3720 spin_unlock_irq(&parent_ctx->lock);
3721 rcu_read_unlock();
3722 3750
3723 /* 3751 /*
3724 * Lock the parent list. No need to lock the child - not PID 3752 * Lock the parent list. No need to lock the child - not PID
@@ -3759,7 +3787,7 @@ int perf_counter_init_task(struct task_struct *child)
3759 cloned_ctx = rcu_dereference(parent_ctx->parent_ctx); 3787 cloned_ctx = rcu_dereference(parent_ctx->parent_ctx);
3760 if (cloned_ctx) { 3788 if (cloned_ctx) {
3761 child_ctx->parent_ctx = cloned_ctx; 3789 child_ctx->parent_ctx = cloned_ctx;
3762 child_ctx->parent_gen = cloned_gen; 3790 child_ctx->parent_gen = parent_ctx->parent_gen;
3763 } else { 3791 } else {
3764 child_ctx->parent_ctx = parent_ctx; 3792 child_ctx->parent_ctx = parent_ctx;
3765 child_ctx->parent_gen = parent_ctx->generation; 3793 child_ctx->parent_gen = parent_ctx->generation;
@@ -3769,15 +3797,7 @@ int perf_counter_init_task(struct task_struct *child)
3769 3797
3770 mutex_unlock(&parent_ctx->mutex); 3798 mutex_unlock(&parent_ctx->mutex);
3771 3799
3772 /* 3800 perf_unpin_context(parent_ctx);
3773 * Restore the clone status of the parent.
3774 */
3775 if (parent_ctx->parent_ctx) {
3776 spin_lock_irq(&parent_ctx->lock);
3777 if (parent_ctx->parent_ctx)
3778 parent_ctx->parent_gen = cloned_gen;
3779 spin_unlock_irq(&parent_ctx->lock);
3780 }
3781 3801
3782 return ret; 3802 return ret;
3783} 3803}