* [PATCH] fix race with preempt_enable()
@ 2005-12-21 17:26 Nicolas Pitre
2005-12-22 7:09 ` Nick Piggin
0 siblings, 1 reply; 2+ messages in thread
From: Nicolas Pitre @ 2005-12-21 17:26 UTC (permalink / raw)
To: Linus Torvalds, Russell King; +Cc: lkml
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.
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)
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH] fix race with preempt_enable()
2005-12-21 17:26 [PATCH] fix race with preempt_enable() Nicolas Pitre
@ 2005-12-22 7:09 ` Nick Piggin
0 siblings, 0 replies; 2+ messages in thread
From: Nick Piggin @ 2005-12-22 7:09 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: Linus Torvalds, Russell King, lkml
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
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2005-12-22 7:09 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-12-21 17:26 [PATCH] fix race with preempt_enable() Nicolas Pitre
2005-12-22 7:09 ` Nick Piggin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox