Re: set_bit() is broken on i386?

From: Trond Myklebust
Date: Sat Jan 21 2006 - 14:25:03 EST


On Fri, 2006-01-20 at 18:38 -0800, Andrew Morton wrote:
> We need to somehow tell the compiler "this assembly statement altered
> memory and you can't cache memory contents across it". That's what
> "memory" (ie: barrier()) does. I don't think there's a way of telling gcc
> _what_ memory was clobbered - just "all of memory".

We _can_ (and do) tell gcc that the unsigned long at address "addr"
will be clobbered. The problem here is that we're actually applying
set_bit() to a bit array that is larger than the single long, so we are
not necessarily clobbering "addr", but rather the long at addr + X.

Most non-386 architectures don't actually have this compiler reordering
problem since they tend to convert the index into the bit array into an
offset for addr + a remainder:

unsigned long *offset = addr + (nr / 8*sizeof(unsigned long));
unsigned long bit = (nr % 8*sizeof(unsigned long));

and then tell the compiler that the long at "offset" will be clobbered.
The remaining architectures appear to already have the general memory
clobber set in their asms (as far as I can see).

IOW: the 386 and x86_64 appear to be the problem cases here, and then
only when applied to large bit arrays.

Cheers
Trond

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/