Messages in this thread | | | Date | Thu, 22 Dec 2005 18:09:15 +1100 | From | Nick Piggin <> | Subject | Re: [PATCH] fix race with preempt_enable() |
| |
Nicolas Pitre wrote: > Currently a simple > > void foo(void) { preempt_enable(); } > > produces the following code on ARM: > > foo: > bic r3, sp, #8128 > bic r3, r3, #63 > ldr r2, [r3, #4] > ldr r1, [r3, #0] > sub r2, r2, #1 > tst r1, #4 > str r2, [r3, #4] > blne preempt_schedule > mov pc, lr > > The problem is that the TIF_NEED_RESCHED flag is loaded _before_ the > preemption count is stored back, hence any interrupt coming within that > 3 instruction window causing TIF_NEED_RESCHED to be set won't be > seen and scheduling won't happen as it should. > > Nothing currently prevents gcc from performing that reordering. There > is already a barrier() before the decrement of the preemption count, but > another one is needed between this and the TIF_NEED_RESCHED flag test > for proper code ordering. >
Nice catch, this is not ARM specific either of course.
kernel/sched.c:preempt_schedule() has an equivalent barrier after subtracting the preempt count and before checking TIF_NEED_RESCHED, so I think this is the correct fix.
Linus will you apply?
> Signed-off-by: Nicolas Pitre <nico@cam.org> > > --- > > diff --git a/include/linux/preempt.h b/include/linux/preempt.h > index d9a2f52..5769d14 100644 > --- a/include/linux/preempt.h > +++ b/include/linux/preempt.h > @@ -48,6 +48,7 @@ do { \ > #define preempt_enable() \ > do { \ > preempt_enable_no_resched(); \ > + barrier(); \ > preempt_check_resched(); \ > } while (0) >
-- SUSE Labs, Novell Inc.
Send instant messages to your online friends http://au.messenger.yahoo.com
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |