Staging
v0.8.1
https://github.com/torvalds/linux
Revision 04e2f1741d235ba599037734878d72e57cb302b5 authored by Linus Torvalds on 24 February 2008, 02:05:03 UTC, committed by Linus Torvalds on 24 February 2008, 02:05:03 UTC
Oleg Nesterov and others have pointed out that on some architectures,
the traditional sequence of

	set_current_state(TASK_INTERRUPTIBLE);
	if (CONDITION)
		return;
	schedule();

is racy wrt another CPU doing

	CONDITION = 1;
	wake_up_process(p);

because while set_current_state() has a memory barrier separating
setting of the TASK_INTERRUPTIBLE state from reading of the CONDITION
variable, there is no such memory barrier on the wakeup side.

Now, wake_up_process() does actually take a spinlock before it reads and
sets the task state on the waking side, and on x86 (and many other
architectures) that spinlock is in fact equivalent to a memory barrier,
but that is not generally guaranteed.  The write that sets CONDITION
could move into the critical region protected by the runqueue spinlock.

However, adding a smp_wmb() to before the spinlock should now order the
writing of CONDITION wrt the lock itself, which in turn is ordered wrt
the accesses within the spinlock (which includes the reading of the old
state).

This should thus close the race (which probably has never been seen in
practice, but since smp_wmb() is a no-op on x86, it's not like this will
make anything worse either on the most common architecture where the
spinlock already gave the required protection).

Acked-by: Oleg Nesterov <oleg@tv-sign.ru>
Acked-by: Dmitry Adamushko <dmitry.adamushko@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 0a3716e
Raw File
Tip revision: 04e2f1741d235ba599037734878d72e57cb302b5 authored by Linus Torvalds on 24 February 2008, 02:05:03 UTC
Add memory barrier semantics to wake_up() & co
Tip revision: 04e2f17
Kbuild
#
# Kbuild for top-level directory of the kernel
# This file takes care of the following:
# 1) Generate asm-offsets.h
# 2) Check for missing system calls

#####
# 1) Generate asm-offsets.h
#

offsets-file := include/asm-$(SRCARCH)/asm-offsets.h

always  := $(offsets-file)
targets := $(offsets-file)
targets += arch/$(SRCARCH)/kernel/asm-offsets.s
clean-files := $(addprefix $(objtree)/,$(targets))

# Default sed regexp - multiline due to syntax constraints
define sed-y
	"/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"
endef
# Override default regexp for specific architectures
sed-$(CONFIG_MIPS) := "/^@@@/{s/^@@@//; s/ \#.*\$$//; p;}"

quiet_cmd_offsets = GEN     $@
define cmd_offsets
	(set -e; \
	 echo "#ifndef __ASM_OFFSETS_H__"; \
	 echo "#define __ASM_OFFSETS_H__"; \
	 echo "/*"; \
	 echo " * DO NOT MODIFY."; \
	 echo " *"; \
	 echo " * This file was generated by Kbuild"; \
	 echo " *"; \
	 echo " */"; \
	 echo ""; \
	 sed -ne $(sed-y) $<; \
	 echo ""; \
	 echo "#endif" ) > $@
endef

# We use internal kbuild rules to avoid the "is up to date" message from make
arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c FORCE
	$(Q)mkdir -p $(dir $@)
	$(call if_changed_dep,cc_s_c)

$(obj)/$(offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s Kbuild
	$(Q)mkdir -p $(dir $@)
	$(call cmd,offsets)

#####
# 2) Check for missing system calls
#

quiet_cmd_syscalls = CALL    $<
      cmd_syscalls = $(CONFIG_SHELL) $< $(CC) $(c_flags)

PHONY += missing-syscalls
missing-syscalls: scripts/checksyscalls.sh FORCE
	$(call cmd,syscalls)
back to top