aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-11-28 15:25:02 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-11-28 15:25:02 -0500
commita9e40a2493d805224f900d839b06188639b7ccd6 (patch)
treeb33c9477a0728f6299a00a3e817aa26872019576 /kernel
parent75f5d2c9bd36047364d1fb35c0720ab37df3be02 (diff)
parentee6dcfa40a50fe12a3ae0fb4d2653c66c3ed6556 (diff)
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: Fix the software context switch counter perf, x86: Fixup Kconfig deps x86, perf, nmi: Disable perf if counters are not accessible perf: Fix inherit vs. context rotation bug
Diffstat (limited to 'kernel')
-rw-r--r--kernel/perf_event.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 671f6c8c8a32..eac7e3364335 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -1287,8 +1287,6 @@ void __perf_event_task_sched_out(struct task_struct *task,
1287{ 1287{
1288 int ctxn; 1288 int ctxn;
1289 1289
1290 perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
1291
1292 for_each_task_context_nr(ctxn) 1290 for_each_task_context_nr(ctxn)
1293 perf_event_context_sched_out(task, ctxn, next); 1291 perf_event_context_sched_out(task, ctxn, next);
1294} 1292}
@@ -1622,8 +1620,12 @@ static void rotate_ctx(struct perf_event_context *ctx)
1622{ 1620{
1623 raw_spin_lock(&ctx->lock); 1621 raw_spin_lock(&ctx->lock);
1624 1622
1625 /* Rotate the first entry last of non-pinned groups */ 1623 /*
1626 list_rotate_left(&ctx->flexible_groups); 1624 * Rotate the first entry last of non-pinned groups. Rotation might be
1625 * disabled by the inheritance code.
1626 */
1627 if (!ctx->rotate_disable)
1628 list_rotate_left(&ctx->flexible_groups);
1627 1629
1628 raw_spin_unlock(&ctx->lock); 1630 raw_spin_unlock(&ctx->lock);
1629} 1631}
@@ -6162,6 +6164,7 @@ int perf_event_init_context(struct task_struct *child, int ctxn)
6162 struct perf_event *event; 6164 struct perf_event *event;
6163 struct task_struct *parent = current; 6165 struct task_struct *parent = current;
6164 int inherited_all = 1; 6166 int inherited_all = 1;
6167 unsigned long flags;
6165 int ret = 0; 6168 int ret = 0;
6166 6169
6167 child->perf_event_ctxp[ctxn] = NULL; 6170 child->perf_event_ctxp[ctxn] = NULL;
@@ -6202,6 +6205,15 @@ int perf_event_init_context(struct task_struct *child, int ctxn)
6202 break; 6205 break;
6203 } 6206 }
6204 6207
6208 /*
6209 * We can't hold ctx->lock when iterating the ->flexible_group list due
6210 * to allocations, but we need to prevent rotation because
6211 * rotate_ctx() will change the list from interrupt context.
6212 */
6213 raw_spin_lock_irqsave(&parent_ctx->lock, flags);
6214 parent_ctx->rotate_disable = 1;
6215 raw_spin_unlock_irqrestore(&parent_ctx->lock, flags);
6216
6205 list_for_each_entry(event, &parent_ctx->flexible_groups, group_entry) { 6217 list_for_each_entry(event, &parent_ctx->flexible_groups, group_entry) {
6206 ret = inherit_task_group(event, parent, parent_ctx, 6218 ret = inherit_task_group(event, parent, parent_ctx,
6207 child, ctxn, &inherited_all); 6219 child, ctxn, &inherited_all);
@@ -6209,6 +6221,10 @@ int perf_event_init_context(struct task_struct *child, int ctxn)
6209 break; 6221 break;
6210 } 6222 }
6211 6223
6224 raw_spin_lock_irqsave(&parent_ctx->lock, flags);
6225 parent_ctx->rotate_disable = 0;
6226 raw_spin_unlock_irqrestore(&parent_ctx->lock, flags);
6227
6212 child_ctx = child->perf_event_ctxp[ctxn]; 6228 child_ctx = child->perf_event_ctxp[ctxn];
6213 6229
6214 if (child_ctx && inherited_all) { 6230 if (child_ctx && inherited_all) {