diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-11-28 15:25:02 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-11-28 15:25:02 -0500 |
| commit | a9e40a2493d805224f900d839b06188639b7ccd6 (patch) | |
| tree | b33c9477a0728f6299a00a3e817aa26872019576 /kernel | |
| parent | 75f5d2c9bd36047364d1fb35c0720ab37df3be02 (diff) | |
| parent | ee6dcfa40a50fe12a3ae0fb4d2653c66c3ed6556 (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.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 671f6c8c8a3..eac7e336433 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) { |
