Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > return x = 0; // under C99 for volatile x

Reply
Thread Tools

return x = 0; // under C99 for volatile x

 
 
Tim Rentsch
Guest
Posts: n/a
 
      01-15-2010
Kaz Kylheku <(E-Mail Removed)> writes:

> On 2010-01-14, http://www.velocityreviews.com/forums/(E-Mail Removed) <(E-Mail Removed)> wrote:
>> Keith Thompson <(E-Mail Removed)> wrote:
>>> (E-Mail Removed) writes:
>>> >
>>> > That's a common misconception, it was not the committee's intent. The
>>> > committee intended that "after" could be taken as "immediately after",
>>> > in which case the compiler can infer the value without having to refetch
>>> > it (although it's certainly allowed to refetch if it wants).
>>>
>>> What if the value of the RHS expression of the assignment is never
>>> actually stored in the object, or at least can never be retrieved
>>> from the object?

>>
>> The abstract machine doesn't admit to such possibilities. A volatile
>> object is still an object with normal object semantics (e.g., it retains

>
> No it is not. This is completely a wrong path to take regarding
> the meaning of an assignment expression; it does not rest on the
> semantics of volatile, but on the semantics of ``assignment expression''.


I think what Larry meant was it's still a normal object as far
as the abstract machine is concerned. In the abstract machine
all accesses get performed and none are ever optimized away
whether the reference in question is volatile-qualified or not.


>> its last stored value), it's just that its value can be stored in ways

>
> The volatile qualifier expresses precisely the opposite idea: that the object
> does not have normal object semantics: that it cannot be relied upon to retain
> its last stored value. [snip elaboration]


The two sets of comments here use the word "stored" in two different
ways. The '>>' comments used "stored" to mean "stored by any machine
or hardware action whatsoever"; the '>' comments use "stored" to mean
"stored by the C program under consideration". That inconsistency
needs to be cleared up before the response is meaningful.


>> The only reason for the peculiar wording was to handle the cases where
>> the value is changed by the assignment in ways that aren't obvious from
>> the overt type of the left hand side (e.g., the value is truncated when
>> assigned to a small bit-field).

>
> There are other ways to express such an intent
> without actually saying that the value of the expression /is/ that of
> the left operand.
>
> Now let's think about this. Suppose that the lvalue foo.three is
> an unsigned bit-field, three bits wide, and suppose that it's
> a normal object which retains its last stored value.
>
> If we perform this expression:
>
> return foo.three = 42;
>
> the value 42 is reduced modulo 8 into the range 0-7, and that resulting value
> is also returned.
>
> Why does assignment return this reduced value?
>
> Argument: it's could be because the value is understood as going into the
> object, and then emerging again to form the result.


An explanation more consistent with what the standard says
is that the RHS value is converted to the type of the LHS
prior to assignment.

> If the value does not go into the object, there is no reason to reduce
> it to three bits; the assignment expression might as well yield 42.


The rules for type conversion explain why the value is reduced
modulo 8, because it has been converted -- notice, prior to
storing it -- to a three-bit unsigned type. For whatever
reason the Standard is rather vague in talking about the
types of bitfields (perhaps because those types can't be
typedef'ed?), but they behave just as though they are
integer types of limited precision (that is, they don't
have to match the precision of any integer types that
can be used for non-bitfield variables).

> I.e. the right hand side is shunted into the object, where it must be reduced,
> /and/ it is also returned.
>
> For that matter, the resulting value can have the original type, too.


Yes, certainly in some other language it could, but in C
it doesn't (assuming the LHS type is different from the
RHS type); in C the RHS value is always converted to
the type of the LHS value, and the type of an assignment
expression is (the unqualified version of) the LHS type.

> Someone designing a language in which the assignment /forks/ the value into two
> destinations might not design it this way. The resulting value would be the
> original value of the right hand side, of the original type. That's a much
> more sensible design: why introduce a potentially dangerous conversion where
> one isn't needed?
>
> For instance, we could have a C dialect in which the following initializes
> the two real values to 3.14:
>
> double1 = double2 = integer = 3.14;
>
> The 3.14 is truncated when it is shunted into the integer, but the
> result of (integer = 3.14) is of type double, so the original 3.14 (or best
> approximation of that constant in the double type) propagates to real2 and
> real1. Basically, the initialization is fully paralellizeable.


Arguably that would be a better design choice. However, it's
a different design choice than the choice that was made for C.


> If you want an alternate rationale for the strange wording which
> supports your case, how about this: it is necessary because without it,
> expressions like the following would be undefined behavior:
>
> node = node->next = NULL;
>
> The NULL could race ahead and get stored into node, turning node->next
> into a null dereference. The wording ``value of the left operand after the
> assignment'' introduces a data flow constraint which allows expressions like
> the above to be harmless and even useful.


I find Larry's explanation more plausible. Because the Standard
is vague about the types of bit-fields, it was necessary to
put in wording like that in 6.5.16p3 in order to require the
semantics that the standards committee intended the assignment
operator to have, namely, the value that comes out is the
same as the value that is actually stored.
 
Reply With Quote
 
 
 
 
Tim Rentsch
Guest
Posts: n/a
 
      01-15-2010
Kaz Kylheku <(E-Mail Removed)> writes:

> On 2010-01-14, Tim Rentsch <(E-Mail Removed)> wrote:
>> Having said that, the Standard does contain a clear out that
>> allows either interpretation (reading after assigning, or not
>> reading after assigning) to be chosen by an implementation,
>> namely, the proviso that what constitutes a volatile-qualified
>> access is implementation-defined.

>
> The implementation-defined constitution of a volatile access in no way permits
> an actual access to be omitted when an abstract access is called for to a
> volatile object.


Other people feel differently.

> The ultimate conclusion if this interpretation is that any and all volatile
> access can be optimized in exactly the same way as regular accesses,


Yes, in fact, some people who have a lot of experience dealing
with standard C and the C standards committee apparently believe
just that, and that the committee agrees with them.

> which is preposterous.


I wasn't meaning to pass judgment one way or the other,
only to relay my best understanding of the community's
consensus.

> An implementation cannot simply say that ``Sometimes,
> just to thumb our noses at the programmer, a volatile access is constituted of
> nothing: our compiler infers the value without consulting the object.''


My understanding (and admittedly I am not omniscient) is that
the committee means that implementations may do just that.
And I know of at least one implementation group that
reached the same conclusion. (I can't say which one for
reasons of confidentiality obligations.)

> If this were the case, then the standard-blessed volatile sig_atomic_t trick in
> a singal handler wouldn't work, and volatile would not ensure the proper
> behavior of modified local variables between a setjmp and longjmp.


I think your reasoning here is a little bit off. The clauses
regarding volatile for setjmp/longjmp and sig_atomic_t don't
depend on what constitutes a volatile access, only that certain
variables be declared volatile in order for those things not
to misbehave. The implementation-definedness of volatile
access doesn't affect those one way or the other.

> Cleary, a failure to access the object at all cannot possibly constitute any
> kind of access to that object! That is just nonsense and anyone who implements
> along those lines will not produce a viable tool, even if it may be regarded as
> conforming.


Yes, I sympathize, but it's important to realize that these two
concerns are separate, namely, is this a compiler someone might
want to use, and is this compiler conforming? The question that
was asked is about conforming compilers, not necessarily limited
just to reasonable compilers, and that question is the one I was
meaning to address.

> (The /bin/true program on Unix can be regarded as a conforming
> impelmentation of C90, too, due to poor wording in the standard).


Cool. Do you happen to know what non-trivial program
it compiles and executes (since it has to be able to for
at least one)?

> The authors of the paper _Volatiles Are Miscompiled, and What to Do about It_
> looked hard, and up the most plausible reason for the implementation-defined
> constitution of a volatile access.


Yes, I've read that paper. I think some of the details they
get wrong in a few cases, but it definitely seems like a good
paper. I hope there is more work published in this area.

> They provide the following reference to a
> Usenet posting by Doug Gwyn, who was on the standardization committee for C90:
>
> Douglas Gwyn. NEVERMIND! (was: Re: A question on volatile
> accesses). USENET post to comp.std.c, November 1990.
> http://groups.google.com/group/comp....09e4162620f2cd.
>
> Chasing that reference:
>
> ``However, although it was proposed that conforming implementations be
> required to implement the minimum possible access "width" for
> volatile-qualified data, and that is the intent of requiring an
> implementation definition for it, it was not practical to insist on it
> in every implementation; thus, some latitude was allowed implementors
> in that regard.''


I read the full message. As far as I can tell it's consistent
with my understanding and with the comments I've made here.


> See there is the question of width. If accessing an object has side effects,
> there is the issue that a C lvalue doesn't necessarily correspond to the
> addressable range that is tied to the same effect. Accessing an unsigned char
> x[0] may produce the a side effect related also to adjacent x[1].
> So in fact, the access to x[0] constitutes not only an access to x[0]
> but an access to x[1], and possibly elsewhere.


Yes, certainly that is one factor. But notice that Doug says
that they didn't go so far as to codify that, because doing
so "was not practical to insist on it for every implementation".
So what they ended up doing was punting on the problem, making
it implementation-defined without imposing any specific limits
as to what the definition could or could not say about what
a volatile-qualified access is.
 
Reply With Quote
 
 
 
 
lawrence.jones@siemens.com
Guest
Posts: n/a
 
      01-15-2010
Kaz Kylheku <(E-Mail Removed)> wrote:
>
> The implementation-defined constitution of a volatile access in no way permits
> an actual access to be omitted when an abstract access is called for to a
> volatile object.
>
> The ultimate conclusion if this interpretation is that any and all volatile
> access can be optimized in exactly the same way as regular accesses,
> which is preposterous.


On the contrary, it's quite reasonable for an implementation that has no
desire to support any kind of concurrency to do exactly that. Of
course, it would be foolish for someone who wants concurrency to use
such an implementation, which is why it's required to be documented.
Don't forget that volatile comes from the very early days of the ANSI C
Standard, long before threading was as common as it is today. Volatile
was a hook for those implementations that wanted it, it was never
intended to force implementations to support concurrency whether they
wanted to or not.
--
Larry Jones

Well of course the zipper's going to get stuck if everyone
stands around WATCHING me! -- Calvin
 
Reply With Quote
 
Phil Carmody
Guest
Posts: n/a
 
      01-16-2010
(E-Mail Removed) writes:
> Kaz Kylheku <(E-Mail Removed)> wrote:
>>
>> The implementation-defined constitution of a volatile access in no way permits
>> an actual access to be omitted when an abstract access is called for to a
>> volatile object.
>>
>> The ultimate conclusion if this interpretation is that any and all volatile
>> access can be optimized in exactly the same way as regular accesses,
>> which is preposterous.

>
> On the contrary, it's quite reasonable for an implementation that has no
> desire to support any kind of concurrency to do exactly that. Of
> course, it would be foolish for someone who wants concurrency to use
> such an implementation, which is why it's required to be documented.
> Don't forget that volatile comes from the very early days of the ANSI C
> Standard, long before threading was as common as it is today. Volatile
> was a hook for those implementations that wanted it, it was never
> intended to force implementations to support concurrency whether they
> wanted to or not.


Kaz doesn't mention concurrency at all, why do you focus on it so?

Phil
--
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
 
Reply With Quote
 
lawrence.jones@siemens.com
Guest
Posts: n/a
 
      01-16-2010
Phil Carmody <(E-Mail Removed)> wrote:
>
> Kaz doesn't mention concurrency at all, why do you focus on it so?


Because without some kind of concurrency (whether real or virtual),
there's no way to tell whether volatile does anything or not.
--
Larry Jones

I told her to expect you to deny everything. -- Calvin
 
Reply With Quote
 
Antoninus Twink
Guest
Posts: n/a
 
      01-17-2010
On 16 Jan 2010 at 22:35, (E-Mail Removed) wrote:
> Because without some kind of concurrency (whether real or virtual),
> there's no way to tell whether volatile does anything or not.


Looking at the assembly code produced by the compiler usually gives you
a pretty good idea.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
volatile in C99 George C Programming 3 12-01-2008 11:20 PM
I don't find the keyword "volatile" in C99.............. lostlander C Programming 3 09-19-2007 11:35 AM
Difference between "library parts" of C99 and "language parts" of C99 albert.neu@gmail.com C Programming 3 03-31-2007 08:14 PM
C99 struct initialization (C99/gcc) jilerner@yahoo.com C Programming 3 02-20-2006 04:41 AM
Use of the Volatile keyword for a pointer to a volatile memory block ben C Programming 5 01-11-2005 05:38 PM



Advertisments