On Fri, Nov 26, 2010 at 9:00 PM, tip-bot for Thomas Gleixner <tglx@xxxxxxxxxxxxx> wrote: > Commit-ID: dddd3379a619a4cb8247bfd3c94ca9ae3797aa2e > Gitweb: http://git.kernel.org/tip/dddd3379a619a4cb8247bfd3c94ca9ae3797aa2e > Author: Thomas Gleixner <tglx@xxxxxxxxxxxxx> > AuthorDate: Wed, 24 Nov 2010 10:05:55 +0100 > Committer: Ingo Molnar <mingo@xxxxxxx> > CommitDate: Fri, 26 Nov 2010 15:00:56 +0100 > > perf: Fix inherit vs. context rotation bug > > It was found that sometimes children of tasks with inherited events had > one extra event. Eventually it turned out to be due to the list rotation > no being exclusive with the list iteration in the inheritance code. > > Cure this by temporarily disabling the rotation while we inherit the events. > > Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> > Signed-off-by: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx> > LKML-Reference: <new-submission> > Cc: <stable@xxxxxxxxxx> > Signed-off-by: Ingo Molnar <mingo@xxxxxxx> > --- > include/linux/perf_event.h | 1 + > kernel/perf_event.c | 22 ++++++++++++++++++++-- > 2 files changed, 21 insertions(+), 2 deletions(-) > > diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h > index 40150f3..142e3d6 100644 > --- a/include/linux/perf_event.h > +++ b/include/linux/perf_event.h > @@ -850,6 +850,7 @@ struct perf_event_context { > int nr_active; > int is_active; > int nr_stat; > + int rotate_disable; Isn't it convincing to use atomic_t instead of int as rotate_disable type. Since, we just have to increment or decrement it inside raw_spin_lock_irqsave(), we could've easily do it using atomic_inc/atomic_dec and atomic_read while calling list_rotate_left(). It will allow us to remove raw_spin_lock_irqsave() at increment/decrement. Am I missing anyting? thanks, rakib > atomic_t refcount; > struct task_struct *task; > > diff --git a/kernel/perf_event.c b/kernel/perf_event.c > index 671f6c8..f365dd8 100644 > --- a/kernel/perf_event.c > +++ b/kernel/perf_event.c > @@ -1622,8 +1622,12 @@ static void rotate_ctx(struct perf_event_context *ctx) > { > raw_spin_lock(&ctx->lock); > > - /* Rotate the first entry last of non-pinned groups */ > - list_rotate_left(&ctx->flexible_groups); > + /* > + * Rotate the first entry last of non-pinned groups. Rotation might be > + * disabled by the inheritance code. > + */ > + if (!ctx->rotate_disable) > + list_rotate_left(&ctx->flexible_groups); > > raw_spin_unlock(&ctx->lock); > } > @@ -6162,6 +6166,7 @@ int perf_event_init_context(struct task_struct *child, int ctxn) > struct perf_event *event; > struct task_struct *parent = current; > int inherited_all = 1; > + unsigned long flags; > int ret = 0; > > child->perf_event_ctxp[ctxn] = NULL; > @@ -6202,6 +6207,15 @@ int perf_event_init_context(struct task_struct *child, int ctxn) > break; > } > > + /* > + * We can't hold ctx->lock when iterating the ->flexible_group list due > + * to allocations, but we need to prevent rotation because > + * rotate_ctx() will change the list from interrupt context. > + */ > + raw_spin_lock_irqsave(&parent_ctx->lock, flags); > + parent_ctx->rotate_disable = 1; > + raw_spin_unlock_irqrestore(&parent_ctx->lock, flags); > + > list_for_each_entry(event, &parent_ctx->flexible_groups, group_entry) { > ret = inherit_task_group(event, parent, parent_ctx, > child, ctxn, &inherited_all); > @@ -6209,6 +6223,10 @@ int perf_event_init_context(struct task_struct *child, int ctxn) > break; > } > > + raw_spin_lock_irqsave(&parent_ctx->lock, flags); > + parent_ctx->rotate_disable = 0; > + raw_spin_unlock_irqrestore(&parent_ctx->lock, flags); > + > child_ctx = child->perf_event_ctxp[ctxn]; > > if (child_ctx && inherited_all) { > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ > -- To unsubscribe from this list: send the line "unsubscribe linux-tip-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html
![]() |