kernel-ark/include
Nicolas Pitre 02828845dd [ARM] 4016/1: prefetch macro is wrong wrt gcc's "delete-null-pointer-checks"
optimization

The gcc manual says:

|`-fdelete-null-pointer-checks'
|     Use global dataflow analysis to identify and eliminate useless
|     checks for null pointers.  The compiler assumes that dereferencing
|     a null pointer would have halted the program.  If a pointer is
|     checked after it has already been dereferenced, it cannot be null.
|     Enabled at levels `-O2', `-O3', `-Os'.

Now the problem can be seen with this test case:

#include <linux/prefetch.h>
extern void bar(char *x);
void foo(char *x)
{
	prefetch(x);
	if (x)
		bar(x);
}

Because the constraint to the inline asm used in the prefetch() macro is
a memory operand, gcc assumes that the asm code does dereference the
pointer and the delete-null-pointer-checks optimization kicks in.
Inspection of generated assembly for the above example shows that bar()
is indeed called unconditionally without any test on the value of x.

Of course in the prefetch case there is no real dereference and it
cannot be assumed that a null pointer would have been caught at that
point. This causes kernel oopses with constructs like
hlist_for_each_entry() where the list's 'next' content is prefetched
before the pointer is tested against NULL, and only when gcc feels like
applying this optimization which doesn't happen all the time with more
complex code.

It appears that the way to prevent delete-null-pointer-checks
optimization to occur in this case is to make prefetch() into a static
inline function instead of a macro. At least this is what is done on
x86_64 where a similar inline asm memory operand is used (I presume they
would have seen the same problem if it didn't work) and resulting code
for the above example confirms that.

An alternative would consist of replacing the memory operand by a
register operand containing the pointer, and use the addressing mode
explicitly in the asm template. But that would be less optimal than an
offsettable memory reference.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2006-12-13 18:30:20 +00:00
..
acpi [PATCH] slab: remove kmem_cache_t 2006-12-07 08:39:25 -08:00
asm-alpha [PATCH] Pass struct dev pointer to dma_cache_sync() 2006-12-07 08:39:41 -08:00
asm-arm [ARM] 4016/1: prefetch macro is wrong wrt gcc's "delete-null-pointer-checks" 2006-12-13 18:30:20 +00:00
asm-arm26 [PATCH] cleanup asm/setup.h userspace visibility 2006-12-07 08:39:46 -08:00
asm-avr32 Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm 2006-12-07 15:40:39 -08:00
asm-cris [PATCH] include/asm-cris/: "extern inline" -> "static inline" 2006-12-07 08:39:45 -08:00
asm-frv [PATCH] cleanup asm/setup.h userspace visibility 2006-12-07 08:39:46 -08:00
asm-generic Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6 2006-12-07 08:59:11 -08:00
asm-h8300 [PATCH] include/asm-h8300/: "extern inline" -> "static inline" 2006-12-07 08:39:45 -08:00
asm-i386 Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6 2006-12-07 08:59:11 -08:00
asm-ia64 Merge branch 'release' of master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6 2006-12-07 15:39:22 -08:00
asm-m32r [PATCH] cleanup asm/setup.h userspace visibility 2006-12-07 08:39:46 -08:00
asm-m68k [PATCH] cleanup asm/setup.h userspace visibility 2006-12-07 08:39:46 -08:00
asm-m68knommu [PATCH] cleanup asm/setup.h userspace visibility 2006-12-07 08:39:46 -08:00
asm-mips [PATCH] cleanup asm/setup.h userspace visibility 2006-12-07 08:39:46 -08:00
asm-parisc [PATCH] Pass struct dev pointer to dma_cache_sync() 2006-12-07 08:39:41 -08:00
asm-powerpc [PATCH] cleanup asm/setup.h userspace visibility 2006-12-07 08:39:46 -08:00
asm-ppc [PATCH] mm: pagefault_{disable,enable}() 2006-12-07 08:39:21 -08:00
asm-s390 [PATCH] cleanup asm/setup.h userspace visibility 2006-12-07 08:39:46 -08:00
asm-sh [PATCH] cleanup asm/setup.h userspace visibility 2006-12-07 08:39:46 -08:00
asm-sh64 [PATCH] cleanup asm/setup.h userspace visibility 2006-12-07 08:39:46 -08:00
asm-sparc [PATCH] remove kernel syscalls 2006-12-07 08:39:37 -08:00
asm-sparc64 [PATCH] Pass struct dev pointer to dma_cache_sync() 2006-12-07 08:39:41 -08:00
asm-um [PATCH] Pass struct dev pointer to dma_cache_sync() 2006-12-07 08:39:41 -08:00
asm-v850 [PATCH] remove kernel syscalls 2006-12-07 08:39:37 -08:00
asm-x86_64 Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6 2006-12-07 08:59:11 -08:00
asm-xtensa [PATCH] Pass struct dev pointer to dma_cache_sync() 2006-12-07 08:39:41 -08:00
crypto [CRYPTO] lib: table driven multiplications in GF(2^128) 2006-12-06 18:38:55 -08:00
keys
linux Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm 2006-12-07 15:40:39 -08:00
math-emu
media
mtd
net Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 2006-12-07 09:05:15 -08:00
pcmcia [PATCH] pcmcia: multifunction card handling fixes 2006-12-04 20:09:15 -05:00
rdma IB/cm: Fix automatic path migration support 2006-11-29 15:33:10 -08:00
rxrpc
scsi [PATCH] slab: remove kmem_cache_t 2006-12-07 08:39:25 -08:00
sound Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 2006-12-05 17:01:28 +00:00
video
Kbuild