[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <E9F17630-A879-4EEC-8ACB-5E339DB0C79F@mac.com>
Date: Sat, 2 Dec 2006 05:39:03 -0500
From: Kyle Moffett <mrmacman_g4@....com>
To: davids@...master.com
Cc: "Linux-Kernel@...r. Kernel. Org" <linux-kernel@...r.kernel.org>,
schwab@...e.de
Subject: Re: [patch 2.6.19-rc6] Stop gcc 4.1.0 optimizing wait_hpet_tick away
On Dec 01, 2006, at 09:03:26, David Schwartz wrote:
>> "David Schwartz" <davids@...master.com> writes:
>>> The problem is that '*(volatile unsigned int *)' results in a
>>> 'volatile unsigned int'.
>>
>> No, it doesn't. Values don't have qualifiers, only objects have.
>> Qualifiers on rvalues are meaningless.
>
> Yeah. That's the problem here. The 'volatile' has no object to
> qualify. You are essentially lying to the compiler (telling it the
> pointer points to a volatile object when it doesn't) and hoping it
> does the right thing.
No, the volatile has a perfectly valid object to qualify; the object
pointed to by the provided pointer. Casting in C is explicitly
defined so that you can change the properties of something. When I
cast a "char *" pointer to "int *", I'm not telling the compiler to
go through and magically convert a bunch of data, I'm telling it to
treat the preexisting memory addresses, whatever they happened to be,
as integer data. The _only_ place where that is not true is casting
an "int" to a "float" or vice versa, and even then it doesn't apply
to any levels of indirection (casting "int *" to "float *" is
virtually guaranteed to cause headaches for first-year CS students).
Likewise when I cast a pointer to "(volatile int *)", I am telling it
that whatever happened before I want it to treat accesses through
that new pointer as accesses to a volatile object, with all the
implied confusion. Now if my code isn't careful about aliasing and I
modified the data through a different pointer a few moments before
(and I have strict-aliasing turned on) then I may get inconsistent
results because the value has not been written to memory yet just
stored in a register.
> Nothing in the standard requires any special behavior for accesses
> through volatile-qualified pointers. It only requires special
> behavior for access to objects that are in fact volatile.
This is completely and utterly wrong. See this quote from the C99
standard pulled from the bugzilla page:
>> 6.7.3: any expression referring to an object of volatile-
>> qualified type must be evaluated strictly by the rules of the
>> abstract machine, although precisely what constitutes an "access"
>> to the object is implementation-defined. (Note, implementation-
>> defined" behavior is required to be well-defined and
>> documented*.) So if the reference in question is an "access", it
>> must occur where the abstract machine says it should.
Now GCC's documentation in multiple places refer to an empty
statement containing an lvalue or rvalue as being "read" access.
Example: The statement "int i = 0; i;" would cause "i" to be "read"
in the second statement. Since "i" is not volatile then it may be
optimized out, however if I stated "volatile int i = 0; i;", then the
compiler would allocate "i" on the stack, assign 0 to it, then read
it into a register. GCC could not optimize any part of that out
without breaking the rules of the abstract machine.
> I think the technically right solution is some mechanism to define
> an object (which can be volatile-qualified) that exists at a
> particular address. Accessing this object would be accessing a
> volatile object and you'd get all the things the standard promises.
Umm, that's exactly what "volatile" on a pointer means; treat this
memory address as containing a volatile-qualified object.
> An adequate solution would probably be to make 'readl' return a
> volatile-qualified unsigned integer.
No, you cannot return a volatile-qualified value because you a return
value is an "rvalue" and rvalues cannot be "volatile". They can't be
"const" or "restrict" either, it just doesn't make any sense.
What would these mean?
const int foo(float x);
restrict int foo(float x);
How can a return-value be const or restrict? It doesn't have an
address I can take so I can't modify it where it is. If you have an
expression for which you cannot get the address of with the "&"
operator (in other words, an rvalue) then "volatile", "const", or
"restrict" make no sense on the type of your expression.
> It comes down to just what those guarantees GCC provides actually are.
This is the first correct statement in your email. In any case the
documented GCC guarantees have always been much stronger than you
have been trying to persuade us they should be. I would argue that
the C standard somewhat indirectly specifies those guarantees but I
really don't have the heart for any more language-lawyering so I'm
going to leave it at that.
Cheers,
Kyle Moffett
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists