[PATCH] fix race with preempt_enable()
authorNicolas Pitre <nico@cam.org>
Wed, 21 Dec 2005 17:26:25 +0000 (12:26 -0500)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 22 Dec 2005 17:17:39 +0000 (09:17 -0800)
commitd6f029130fb83b36fb709a187275b0494035d689
tree27a5f8fb9fe1fc0df911231b5d9913b246427039
parentd5ea4e26602fa7f5141872f2c17a862f1974a73f
[PATCH] fix race with preempt_enable()

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>
Acked-by: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
include/linux/preempt.h