Hacker News new | ask | show | jobs
by cperciva 4145 days ago
The silly thing here is that this macro is not guaranteed to accomplish anything. The C standard limits how compilers can optimize accesses to volatile objects, but says nothing about accesses to non-volatile objects which are accessed via volatile-qualified pointers.
2 comments

That's certainly true if you mix accesses to the same object via volatile and non-volatile pointers. It's even explicitly undefined in the standard. (C99 §6.7.3/5). [while in practice it will work most of the time]

But if you always access a certain object through casts to ((volatile )&x), I don't see how this should be different than accesses to a globally declared "volatile x" variable, as pointers are guaranteed to not change if casted hence-and-forth (§6.3.2.3/7).

The key text is in C99 §6.7.4: "An object that has volatile-qualified type...". Note that this does not say "An object accessed via a pointer to a volatile-qualified type": What matters is the type of the underlying object, i.e., how it is originally defined.
Ok, that's quite some language-lawyering going on here ;-), and while I enjoy it, I'm completely aware of the fact that in practice the behavior of actual implementation (in software, compilers, operating systems) always trumps theoretic considerations.

That being said...

§6.5.3.1/4 The unary * operator denotes indirection. (...) the result is an lvalue designating the object.

So, I believe that there will be no difference in access to something declared as

    volatile X v;
    v = ...;
and

    X v;
    *((volatile X*)&v) = ...;
if the access to v will always be performed through such a cast, as ((volatile..)) will always denote the same "volatile" X object stored in v, independent of the fact that storage to the volatile X object is allocated in a "nonvolatile" X object.
In practice most compilers respect the volatile keyword on a pointer target type. But if you want to conform to the standard you need to look at what the standard says, not merely how it's commonly implemented.

    §6.5.3.1/4 The unary * operator denotes indirection.
    (...) the result is an lvalue designating the object.
Yes, but calling the sky green doesn't make it so. Dereferencing a pointer to an object yields that object, and the object is volatile or not depending on whether it was declared as volatile; whether you say that it's volatile before you dereference the pointer is irrelevant. (That is, irrelevant to the requirements of the standard; it's very relevant to most compilers, because it's usually impossible to prove whether the object ultimately being accessed is volatile or not.)
It is not in the C standard but the way GCC implements it is that it is hands-off with optimizations to any volatile variables and pointers. And since Linux is only compiled with GCC, it works.
Linux is also compiled with llvm as well as icc
People porting to llvm and icc have to do whatever it takes so that all the gadgets defined by the kernel work in those compilers as expected.

ISO C standard conformance isn't entirely irrelevant, but thereabouts.

There is no such thing as building systems from the ground up without controlling compilers beyond what is specified in the applicable language standards.