Re: question on memory barrier

From: Andy Isaacson
Date: Wed Aug 24 2005 - 14:49:32 EST


On Wed, Aug 24, 2005 at 07:31:31PM +0200, moreau francis wrote:
> --- "linux-os (Dick Johnson)" <linux-os@xxxxxxxxxxxx> a écrit :
> > On Wed, 24 Aug 2005, moreau francis wrote:
> > > I'm currently trying to write a USB driver for Linux. The device must be
> > > configured by writing some values into the same register but I want to be
> > > sure that the writing order is respected by either the compiler and the
> > > cpu.
[snip]
> > > static inline void dev_out(u32 *reg, u32 value)
> > > {
> > > writel(value, regs);
> > > }
> > >
> > > void config_dev(void)
> > > {
> > > dev_out(reg_a, 0x0); /* first io */
> > > dev_out(reg_a, 0xA); /* second io */
> > > }
> > >
> >
> > This should be fine. The effect of the first bit of code
> > plus all side-effects (if any) should be complete at the
> > first effective sequence-point (;) but you need to

While sequence points are relevant for purposes of reasoning about the
effects of C code on the abstract state machine as defined by the C
standard, they are irrelevant when talking about IO.

> sorry but I'm not sure to understand you...Do you mean that the first write
> into reg_a pointer will be completed before the second write because they're
> separated by a (;) ?
> Or because writes are encapsulated inside an inline function,
> therefore compiler must execute every single writes before returning
> from the inline function ?

The first register write will be completed before the second register
write because you use writel, which is defined to have the semantics you
want. (It uses a platform-specific method to guarantee this, possibly
"volatile" or "asm("eieio")" or whatever method your platform requires.)

The sequence points, by themselves, do not make any requirements on the
externally visible behavior of the program. Nor does the fact that
there's an inline function involved. It's just the writel() that
contains the magic to force in-order execution.

You might benefit by running your source code through gcc -E and seeing
what the writel() expands to. (I do something like "rm drivers/mydev.o;
make V=1" and then copy-n-paste the gcc line, replacing the "-c -o mydev.o"
options with -E.)

The sequence point argument is obviously wrong, BTW - if it were the
case that a mere sequence point required the compiler to have completed
all externally-visible side effects, then almost every optimization that
gcc does with -O2 would be impossible. CSE, loop splitting, etc.

-andy
-
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/