Topic: question about volatile
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/20 Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <8q8436$7jk$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
> writes
>>It's easy enough to construct an implementation (with no input ports)
>>where the first of these sentences is false.
> In that case, the compiler should, IMHO, issue a warning (this is a QoI
> issue).
Under any implementation, consider a program that involves no input,
longjmps, signal handling, or aliasing. How is the compiler going
to not know the factors that can set a volatile variable?
>>(Does such an
>>implementation fail to conform simply because it "knows" what's going
>>on?) The second sentence simply says that expressions involving
>>volatile lvalues must behave correctly. That admonition adds nothing
>>new -- either we get the prescribed behavior or we don't.
> Actually, I think it says more. It says how values are to be obtained.
> No caching, no retention of values in registers etc.
Those are implemenation matters, and the standards are very strict about
not prescribing implementation.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/20 Raw View
In article <8qaop6$1dqd$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>> Actually, I think it says more. It says how values are to be obtained.
>> No caching, no retention of values in registers etc.
>
>Those are implemenation matters, and the standards are very strict about
>not prescribing implementation.
We are not moving forward. One of the purposes, or so I have been led to
believe, of the volatile keyword is to require strict adherence to the
abstract machine. That abstraction has simple concepts of reading and
writing storage which must be complete at sequence points, no carry
over, no guessing about what is stored. However, in the absence of
volatile qualification the implementation is permitted to treat stored
data as if it cannot change. That allows many optimisations.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/20 Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <8qaop6$1dqd$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
> writes
>>> Actually, I think it says more. It says how values are to be obtained.
>>> No caching, no retention of values in registers etc.
>>
>>Those are implemenation matters, and the standards are very strict about
>>not prescribing implementation.
> We are not moving forward. One of the purposes, or so I have been led to
> believe, of the volatile keyword is to require strict adherence to the
> abstract machine.
The purpose of "volatile" is to ADVISE the implemenation that if it
doesn't strictly adhere, it is likely to generate incorrect behavior
(usually because the object is likely to be accessed by asynchronous
streams of activity, perhaps even streams external to the program).
But there is no requirement on how a conforming implemenation
generates the correct behavior. If every read/write of a
volatile-typed object is observable behavior, then it is very
difficult to play any helpful tricks (optimizations), but one can
still get correct behavior without strict adherence to the abstract
machine -- the behavior of a program to print out the first hundred
digits of pi could be prestored in arrays and played like a piano
roll, even if all of its variables are declared volatile.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/20 Raw View
James Kuyper <kuyper@wizard.net> wrote:
> thp@roam-thp2.cs.ucr.edu wrote:
>>
>> James Kuyper <kuyper@wizard.net> wrote:
>> > Fergus Henderson wrote:
>>
>> > The C++ standard says nothing that allows an object, whether of
>> > volatile-qualified type, or not, whether residing in volatile memory or
>> > not, to undergo such arbitrary changes. The only thing it does say
>> > that's relevant is that 'volatile' is meant to have the same semantics
>> > as in C. The C standard does explicitly say that objects of
>> > volatile-qualified are subject to such arbitrary changes.
>>
>> Unfortunately, it isn't explicit as to whether that applies to all
>> or to some objects of volatile-qualified type.
> I'd say 'any', rather than 'all' OR 'some'.
Unfortunately, the term "any" has ambiguous quantification that varies with
context. In the context "Any object of volatile qualified type.", however,
it means all.
> I claim that volatile qualification permits arbitrary changes;
The standard requires the implementation to document what constitutes
an access to a volatile and notes in a footnote that in the case of
volatiles, "the last store may not be explicit in the program." That
would seem to require that the implementation document ahead of time
which volatile objects are subject to such non-explicit stores and how
such stores might come about.
> it neither mandates nor prohibits them, but does make some
> requirements that the value after the change must be the one read by
> the next access.
>> > However, that any program that uses volatile memory necessarily
>> > allows undefined behavior,
>>
>> Why?
> Keep in mind that this is NOT my argument; I'm restating Fergus'
> argument, so he can verify whether I've understood it correctly. He
> claims that every method that can be legally be provided to access
> volatile memory (as opposed volatile-qualified objects) requires use of
> implementation-specific features with behavior that is undefined
> according by the standard, but which may be defined by the
> implementation.
AFIK, implementation-defined behavior and undefined behavior are two
very distinct concepts.
> He specifically rejects my suggestion that a conforming
> implementation (though an inconvenient one!) could automatically
> allocate volatile memory as needed to hold user-defined
> volatile-qualified objects.
I have to go with Fergus' interpretation, not because of textual
analysis of the standard, but because your interpretation would render
non-portable any program that has a signal handler that communicates
with the rest of the program. I don't believe that the authors of
the standard had that in mind.
>> > and that is the only thing that actually allows the volatile
>> > behavior of that memory.
>>
>> I thought the thing that allows such volatile behavior is the
>> implementation's perogative to define what constitutes an access to an
>> object of volatile-qualified types. I'm not exactly sure what that
>> means, however.
> No - you need a statement somewhere that allows the value read from an
> object to be different from the value last written to it. The C++
> standard contains no such wording, just a non-normative cross-reference
> to the C semantics. I claim that the C standard has such wording, but
> Fergus disagrees with my interpretation of the relevant clause.
I think you may have been led to your view by the following nonsense
from the C standard:
An object that has volatile-qualified type may be modified in ways
unknown to the implementation or have unknown side effects.
For a one-file program, a compiler that knows where the input ports
are knows all of the ways that any variable can be modified. (We can
of course talk about the difficulties in statically determining
aliases but that problem is the same for volatiles and non-volatiles.)
> ...
>> >> The whole clause does apply to objects of volatile-qualified type.
>> >> But stating that they can "be modified in ways unknown to the
>> >> implementation or have other unknown side effects" does not mean that
>> >> the implementation is allowed to modify them arbitrarily.
>>
>> The conformance of an implemenation cannot hang on what it "knows."
> Why not, if the standard says so?
Because it is an implemenation's duty to attatch the prescribed behavior
to conforming programs, not to be ignorant of certain possibilities.
> The C standard does say that the value of an object of
> volatile-qualified type can "be modified in ways unknown to the
> implementation".
That obligation to ignorance that the standard places on conforming
implemenation is nonsense. In many cases there is no way that the
implemenation can not know how variables get modified.
> It does not otherwise exempt an implementation from
> providing, on read, the same value last written to the object
> (except by way of undefined behavior). ]
> I think it is that clause of the C standard which allows volatile
> memory to be used by a C implementation. What, if anything, allows
> it in a C++ implementation is unclear.
Okay:
Furthermore, at every sequence point the value last stored in the
object shall agree with that prescribed by the abstract machine,
except as modified by the unknown factors mentioned previously.
[C89 6.5.3]
But the implementation knows all factors (explicit or otherwise) that
have store access to volatiles, because it has to be accompanied by
a document that specifies them:
What constitutes an access to an object that has volatile-qualified
type is implemenation defined. [C89 6.5.3]
An implemenation shall be accompanied by a document that defines
all implemenation defined characteristics and all extensions.
[C89 4 Compliance]
>> Before it gets the program, the implementation must specify what
>> constitutes accesses to objects of volatile-qualified types.
>> Presumably, the types, semantics and identities (names or addresses)
>> of all objects that are subject to external observation and/or
>> modification must be disclosed, and all other objects of
>> volatile-qualified types must be allocated to ordinary memory.
> That's what's in dispute. Can you cite supporting text that allows that
> distinction?
There's no dispute about the fact that the need for implementation
specification of what constitutes an access to a volatile object.
>> It would be unfortunate if a conforming implementation could specify,
>> for instance, that each occurrence of a sequence point is a write
>> access that sets ALL objects of volatile-qualified type to zero. In
>> such an implemenation there would be no way for a signal handler to
>> communicate with a conforming program.
> Just because it's useless doesn't mean it's not conforming.
It would indicate a defect in the standard if a conforming
implementation could specify that every volatile variable is an input
port.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/20 Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <8q8dqm$dcu$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
> writes
>>To get an lvalue to work correctly when it designates an object that is
>>accessible by asynchrounous streams of activity (either inside our
>>outside the program), it is almost always necessary to generate the same
>>kind of code that one would generate if the object were an io port.
>>That's the whole point to volatile-qualified types.
> So how does a compiler know that it must generate such code? Because we
> tell it so with the keyword volatile. It is my belief that 'volatile'
> qualification removes the liberty that the compiler has otherwise to
> optimise the abstract machine. It is not for the compiler to hypothesise
> why I place such a restriction on it, it is my servant, not my master.
The obligation of the implementation (servant) is to generate correct
behavior. How it achieves that behavior is not the business of the
program (master). The standard does not give the master the
permission or ability to micromanage -- one has to link to assembly
language routines for that.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/20 Raw View
David J. Littleboy <davidjl@gol.com> wrote:
> <thp@roam-thp2.cs.ucr.edu> wrote:
>> Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> <snip>
>> > The implementation cannot wilfully select a memory mapped io port to
>> > store a volatile variable simply because we said the variable was
>> > volatile.
>>
>> Agreed, wholeheartedly. But all other memory must remember, i.e.,
>> values cannot be modified except by the program. Getting back to
>> the example
>>
>> int main() {
>> volatile int i = 0;
>> cout << i;
>> }
>>
>> how might the value of i get set to 2 under a conforming
>> implementation/environment? (Please don't say via a debugger or a
>> high-energy particle from another galaxy, because no implementation
>> conforms in those environments.)
> Now I see why there's disagreement here: FG and I are perfectly happy to
> assume that there are other agents (e.g. threads, "streams of activity")
> smashing our volatile variables, and you are not willing to entertain that
> possibility.
Quite the contrary. But in the program above, what you see is what
you get. There is no multithreading, no signal handling, no longjmps,
no input statements, etc. Francis and I agree that the implementation
is not free to allocate i to an input port, so what's going to change
the value of i?
> I guess since the standard doesn't mention multi-threading, one
> might see that as reasonable, but
>> > However, a program maybe invoked from elsewhere (or be part of a
>> > multi-threaded program) and we may know that this other thread or
>> > process can access the storage. The compiler cannot know this, so
>> > how do we get it to compile code that will be robust against such
>> > change?
>>
>> To get an lvalue to work correctly when it designates an object that
>> is accessible by asynchrounous streams of activity (either inside our
>> outside the program), it is almost always necessary to generate the
>> same kind of code that one would generate if the object were an io
>> port. That's the whole point to volatile-qualified types.
> But now you are assuming that there are other agents: ones that are only
> allowed to _read_ volatile qualified types. I'd be perfectly happy to have
> the standard interpreted or patched to allow either both read and write or
> neither, but just one seems a bit arbitrary.
You misunderstand me. The implemenation is free to specify that
certain objects of volatile-qualified type are io ports (i.e., subject
to modification and observation by factors outside the program). But
a document saying which objects those are must accompany the
implementation.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 2000/09/21 Raw View
thp@roam-thp2.cs.ucr.edu wrote:
>
> James Kuyper <kuyper@wizard.net> wrote:
> > thp@roam-thp2.cs.ucr.edu wrote:
...
> >> Unfortunately, it isn't explicit as to whether that applies to all
> >> or to some objects of volatile-qualified type.
>
> > I'd say 'any', rather than 'all' OR 'some'.
>
> Unfortunately, the term "any" has ambiguous quantification that varies with
> context. In the context "Any object of volatile qualified type.", however,
> it means all.
What the C standard says is that "An object that has volatile-qualified
type may be modified in ways unknown to the implementation or have other
unknown side effects."
Given the fact that unknown modification is permitted, rather than
required, I don't see that it would make any difference whether the
opening phrase is written the way it actually is, or using any of the
following three alternatives:
"All objects that have ..."
"Any object that has ..."
"Some objects that have ..."
Regardless of which one you chose, they all mean that a
volatile-qualified object who's value doesn't change arbitrarily is
permitted by the standard, and a volatile-qualified object whose value
does change arbitrarily is also permitted, and they both can reside in
the same program.
> > I claim that volatile qualification permits arbitrary changes;
>
> The standard requires the implementation to document what constitutes
> an access to a volatile and notes in a footnote that in the case of
> volatiles, "the last store may not be explicit in the program." That
> would seem to require that the implementation document ahead of time
> which volatile objects are subject to such non-explicit stores and how
> such stores might come about.
>
The standard does say that what constitutes access to a volatile is
implementation-defined. I couldn't find any words that says that the
actual events that cause volatile behavior must be
implementation-defined; only the types of events that can cause such
behavior need be defined.
...
> AFIK, implementation-defined behavior and undefined behavior are two
> very distinct concepts.
That's why I was very careful to avoid using those terms
implementation-defined behavior is defined by the standard as applying
only for "well-formed program constructs and correct data". Thus,
implementation-defined behavior is not the same as behavior defined by
an implementation. An implementation is free to define what the behavior
of ill-formed program construct will be; that definition of behavior by
the implementation does not, however, qualify as implementation-defined
behavior as the term is that defined in the standard. Another one of the
paradoxes of technical jargon. It's no worse than the concept in higher
mathematics of a "countable" infinity.
Similarly, "undefined behavior" does NOT mean behavior that isn't
defined; it only means behavior that the standard doesn't define, and
which an implementation is not required to define. An implementation is
still free to define it, if it wants to. A significant portion of every
well-documented compiler's documentation consists of definitions for
what the standard calls "undefined" behavior.
...
> I have to go with Fergus' interpretation, not because of textual
> analysis of the standard, but because your interpretation would render
> non-portable any program that has a signal handler that communicates
> with the rest of the program. I don't believe that the authors of
> the standard had that in mind.
I'm arguing words, not intent. Did their intent actually get correctly
expressed by the words?
> I think you may have been led to your view by the following nonsense
> from the C standard:
>
> An object that has volatile-qualified type may be modified in ways
> unknown to the implementation or have unknown side effects.
Well caught! That's a plausible assumption, given that I've explicitly
quoted that section several times by now. Bravo!
> For a one-file program, a compiler that knows where the input ports
> are knows all of the ways that any variable can be modified. (We can
> of course talk about the difficulties in statically determining
> aliases but that problem is the same for volatiles and non-volatiles.)
Yes, but there's no reason why a compiler needs to know where the input
ports are. It can be completely shielded from that information by the
operating system. Consider a compiler running in a DOS emulation under
Linux - how much does the compiler really "know" (or have to know) about
the environement it's executing in?
...
> >> The conformance of an implemenation cannot hang on what it "knows."
>
> > Why not, if the standard says so?
>
> Because it is an implemenation's duty to attatch the prescribed behavior
> to conforming programs, not to be ignorant of certain possibilities.
Not if the standard explicitly allows their ignorance.
...
> But the implementation knows all factors (explicit or otherwise) that
> have store access to volatiles, because it has to be accompanied by
> a document that specifies them:
>
> What constitutes an access to an object that has volatile-qualified
> type is implemenation defined. [C89 6.5.3]
Just because the implementation defines what constitutes access doesn't
mean it knows anything about which of several possible access methods
has actually occured, nor when it has occurred. Thus, the way in which
the object was actally modified may be unknown to the implementation,
even though the possibility that it could be modified in that way was
known by it. A definition which says "accesses may occur whenever
electricity flows across any relevant circuit element" will meet that
requirement. It might even be the best possible description of certain
kinds of volatile memory :-)
...
> >> Before it gets the program, the implementation must specify what
> >> constitutes accesses to objects of volatile-qualified types.
> >> Presumably, the types, semantics and identities (names or addresses)
> >> of all objects that are subject to external observation and/or
> >> modification must be disclosed, and all other objects of
^^^^^
> >> volatile-qualified types must be allocated to ordinary memory.
>
> > That's what's in dispute. Can you cite supporting text that allows that
> > distinction?
>
> There's no dispute about the fact that the need for implementation
> specification of what constitutes an access to a volatile object.
My apologies; I misread your statement, and made an irrelevant response.
What I should have said is:
Agreed. A conforming implementation such as I've described would require
just such a specification, one which states that all volatile-qualified
objects, regardless of name, no matter where defined, are subject to
volatile behavior; optionally it could define the precise circumstances
under which that behavior could be expected, but that's more explanation
than the standard requries. In other words, the "other" category could
be empty.
...
> > Just because it's useless doesn't mean it's not conforming.
>
> It would indicate a defect in the standard if a conforming
> implementation could specify that every volatile variable is an input
> port.
Not really a defect, just an excessively lenient standard. There are
many other ways whereby the standard allows useless implementation; this
would be nothing new.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/21 Raw View
In article <8qbci5$ed1$3@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>You misunderstand me. The implemenation is free to specify that certain
>objects of volatile-qualified type are io ports (i.e., subject to
>modification and observation by factors outside the program). But a
>document saying which objects those are must accompany the
>implementation.
I am not convinced. I had, perhaps erroneously, always read the part of
the standard about 'what constitutes access' as referring to the program
side and not the external environment. Indeed, I think it very close to
impossible for an implementor to document external access. What he can
say is how the following is to be handled:
int volatile a;
a = a + a;
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 2000/09/18 Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> writes:
>thp@roam-thp2.cs.ucr.edu writes
>>Are you suggesting that under a conforming implementation the following
>>program could print out the number 2 ?
>
>Well, I would. If I did not want to allow such behaviour I would not use
>a volatile qualifier.
I take it you never use a volatile qualifier?
Some of us here do use volatile qualifiers in programs which
are intended to be portable, and which are intended to be
strictly conforming except only for the fact that they make
use of additional libraries such as Posix threads (and in some cases,
e.g. programs using setjmp() or signal(), not even that).
For these programs, it is important that the use of `volatile' should
not allow the implementation to arbitrarily modify the values of
variables.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 2000/09/18 Raw View
James Kuyper <kuyper@wizard.net> writes:
>Fergus Henderson wrote:
>>
>> James Kuyper <kuyper@wizard.net> writes:
>>
>> >Fergus Henderson wrote:
>...
>> >> Since the abstract machine does not include any volatile memory
>> >> (real time clocks, memory-mapped I/O, concurrent processes, etc.),
>> >
>> >Why not? [...]
>>
>> Well, this is implied by the definition of "storage".
>
>I don't understand - can you explain the relevance of that definition to
>this question?
Well, storage is stuff that stores things. Real time clocks,
memory-mapped I/O and other devices for which reads yield arbitrary
results are not "storage". But the C++ standard says that objects
are composed of storage (see 1.8 paragraph 1).
>The C++ standard says nothing that allows an object, whether of
>volatile-qualified type, or not, whether residing in volatile memory or
>not, to undergo such arbitrary changes. The only thing it does say
>that's relevant is that 'volatile' is meant to have the same semantics
>as in C.
>
>The C standard does explicitly say that objects of
>volatile-qualified are subject to such arbitrary changes. You can either
>say that volatile memory is disallowed, or invoke the cross-reference to
>C to allow it.
That cross-reference is only in an informative note, not in a
normative part of the standard. So if you're talking about what the
normative standard says rather than the intent, then I think you have
to take the former option.
>You're saying that 'volatile' tells an implementation to compile the
>code in a way that is basically what's needed to make proper use of
>volatile memory. However, that any program that uses volatile memory
>necessarily allows undefined behavior, and that is the only thing that
>actually allows the volatile behavior of that memory.
>
>That's a reasonable way for the standard to be written; I just don't
>think that's what it actually says.
I think that _is_ what the normative part of the C++ standard says.
The only wording that you've been able to quote in defense of your
claim here is in a non-normative note.
What the C standard says is a separate question, as is the question of
what the C++ authors intended.
----------
Now, let's discuss what the C standard says.
>If you do allow invokation of that cross-reference then
>such arbitrary actions are in fact explicitly mentioned; you can't
>invoke silence as a reason to disallow them. And that invocation is
>specific to objects of volatile-qualified type; no mention is made in
>that section of whether or not they reside in volatile memory.
That mention only allows such effects if they are "unknown to the
implementation". So the implementation can't produce such effects.
>> If you mean 6.7.3 in the C standard (see below),
>> that is clearly a statement about implementation conformance,
>> not part of the definition of the abstract machine.
>> Since it twice refers to semantics of the abstract machine,
>> you can't interpret it as being part of the definition of the
>> abstract machine without rendering that definition circular.
>
>Yes you can. I interpret that statement about the semantics as referring
>to order of reads and writes of the value, and to the value written by
>those writes, but not to the connection between the value written and
>the value read: the first part of that section explicitly revokes all
>guarantees about the stored value.
Here I disagree. As I interpret it, that section is giving permission
to the user, not to the implementation. So the guarantees remain,
unless the user does something to violate them.
>> The C++ abstract machine doesn't provide any way to create volatile
>> memory (see above), or to place variables in it. So in order to place
>> a variable in volatile memory, the user must have requested that via
>> some facility not specified in the C++ standard. This means that all
>> bets are off. The C++ standard does not and cannot give any guarantees
>> about the behaviour if you make use of facilities that are not defined
>> by the standard.
>
>Then it would seem that there's no need to state that objects of
>volatile-qualified type can be modified arbitrarily; by that same
>argument, all behavior of any program that uses those facilities is
>undefined, whether or not it involves objects of volatile-qualified
>type.
There's no *need*; however, some ways of stating things are better
than others.
The difference is that stating things in this way means that
implementation documentation for implementation-specific features like
threads can be much shorter: it need only say that the other
guarantees of the C standard still hold if this feature is used (often
this can reasonably be left implicit, e.g. if the facility in question
is just an additional library), rather than talking about the
behaviour of volatile. This leads to a proper separation of concerns,
where the C standard talks about the behaviour of C keywords, and
where the implementation's documentation of implementation-specific
facilities talks only about those facilities, not about the behaviour
of `volatile'.
For this reason, the wording in the C standard is much better than
the wording in the C++ standard.
>...
>> >So why do you believe that the 'except' clause apply only to objects in
>> >volatile memory, and not to user-defined objects of volatile-qualified
>> >type?
>>
>> The except clause *does* apply to all user-defined objects of
>> volatile-qualified type, but unless those objects are
>> mapped to volatile memory, there won't be any unknown
>> factors, and so the sense in which it applies is vacuous.
>
>Not if the implementation makes such a mapping occur automatically (and
>statically) for any user-defined object of volatile-qualified type. I'd
>agree that this would be an inconvenient implementation, and probably
>not what was intended, but I don't think it's non-conforming.
Well, I don't agree here. I think this comes down to a disagreement
about the meaning of the wording in 6.7.3 in the C standard.
It looks like a good case for a defect report.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/19 Raw View
In article <8q1u8t$76j$1@mulga.cs.mu.OZ.AU>, Fergus Henderson
<fjh@cs.mu.OZ.AU> writes
>For these programs, it is important that the use of `volatile' should
>not allow the implementation to arbitrarily modify the values of
>variables.
Exactly where did I say that it could? What I did say was that unless I
knew exactly what was going on elsewhere, the result might not be what a
straight reading of the code suggests.
There is a great difference between arbitrary change, and change outside
the view of the program. In general, without a crystal ball a compiler
cannot know how and where code will be executed, that is one of the
costs of separate compilation coupled with execution separated from
compilation.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/19 Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <8ptpn1$auf$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
> writes
>>When a programmer uses the volatile qualifier in declaring such an
>>variable, does he/she really want to give the implementation license to
>>put arbitrary garbage into that variable whenever it pleases? I think
>>not. Of course, some (implementation-specified) volatile objects are
>>subject to non-explicit modifications. But it doesn't make sense for
>>all objects of volatile-qualified types to have indeterminate value.
>>That makes them useless.
> Where do you come up with these ideas?
It's all Fergus' fault. ;-)
> It has absolutely nothing to do with what the implementation can
> do. It is not allowed to do anything other than what the program
> specifies. However that is quite different from warning the
> implementation that something else may change the contents of
> storage and so it must not rely on cached values but must go and
> read what is there.
Agreed.
> Volatile is NOT a licence to the implementation, indeed it is exactly
> the opposite, it is a constraint on the implementation disallowing
> assumptions that it can make otherwise.
Agreed, but note that the implementation gets to define "what
constitutes an access to an object that has volatile-qualified type."
> Please try to understand this, because your posts seem to imply that
> you think volatile behaves like const (which allows the value to be
> stored in read only memory) and allows the implementation to store
> values where they may change arbitrarily. Sometimes a programmer
> may choose the location of the storage (e.g. memory mapped io ports)
> but otherwise the compiler must choose storage that does not
> arbitrarily change.
That's exactly the point I was trying to make (for variables of
volatile-qualified types) in the paragraph you quoted above.
> That is NOT the same as saying that the storage may not be accessed
> and changed by some other mechanism outside the knowledge and
> control of the program.
Huh? In the previous sentence, I understood you to say above that if
the programmer doesn't explicitly choose a storage location, such as
an input port, that is subject to modification by other factors, the
implementation MUST allocate the object to normal storage, which AFIK
is modifiable only by explicit operations of the program, i.e.,
"storage that does not arbitrarily change." But, when I remove the
double negation in the sentence above, you seem to be saying that the
implementation-chosen storage may "be accessed and changed by some
other mechanisms outside the knowledge and control of the program."
How can it be both ways?
Tom Payne
> Francis Glassborow Association of C & C++ Users
> 64 Southfield Rd
> Oxford OX4 1PA +44(0)1865 246490
> All opinions are mine and do not represent those of any organisation
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
======================================= MODERATOR'S COMMENT:
Please don't quote moderation banners when posting replies. Thankyou.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/19 Raw View
kanze@gabi-soft.de wrote:
> <thp@roam-thp2.cs.ucr.edu> writes:
> |> The alternative is to take the view that the debugger is not part of
> |> the conforming implementation's intended "execution environment," in
> |> which case there would be no requirements on the consequences of
> |> debugger modifications to any variable, whether volatile or not.
> That's really the point I've been trying to make. The implementation
> gets to decide what the intended "execution environment" is. If it does
> so that in fact volatile objects are not actually observable, I think
> that it could probably just ignore the volatile attribute.
It still has to generate conservative code for statics of type
"volatile sigatomic_t" so that writes by signal handlers work
correctly. Similarly, for volatile automatics that are local to a
function that invokes setjmp. Also, for any volatiles that the the
implementation exposes to manipulation by external "unknown factors."
> At any rate, you could never tell if it did.
AFIK, output functions in the standard library are not required to do
their outputting through volatiles, and they could leave a trail of
nonconforming behavior.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 2000/09/19 Raw View
Fergus Henderson wrote:
>
> James Kuyper <kuyper@wizard.net> writes:
...
> Well, storage is stuff that stores things. Real time clocks,
> memory-mapped I/O and other devices for which reads yield arbitrary
> results are not "storage". But the C++ standard says that objects
> are composed of storage (see 1.8 paragraph 1).
The storage might be shared with things "unknown to the implementation",
which pull out the value that your code stored, and replace it with a
different one that gets stored for your retrieval. That's still storage,
just not reliable storage. It's no worse than what happened when I
stored most of my belongings in my parent's house for a few years. :-}
...
> I think that _is_ what the normative part of the C++ standard says.
> The only wording that you've been able to quote in defense of your
> claim here is in a non-normative note.
I've repeatedly pointed out the non-normative nature of that link. I
don't like it. It leaves a significant part of the C++ language neither
defined within the C++ standard, nor normatively cross-referenced from
the C standard. I tried to formulate my arguments so that they would
have (different) coherent meanings, whether or not you considered that
cross-reference relevant.
> >If you do allow invokation of that cross-reference then
> >such arbitrary actions are in fact explicitly mentioned; you can't
> >invoke silence as a reason to disallow them. And that invocation is
> >specific to objects of volatile-qualified type; no mention is made in
> >that section of whether or not they reside in volatile memory.
>
> That mention only allows such effects if they are "unknown to the
> implementation". So the implementation can't produce such effects.
That's fine, I wasn't suggesting that it could produce them, only that
it could allow them.
...
> >Yes you can. I interpret that statement about the semantics as referring
> >to order of reads and writes of the value, and to the value written by
> >those writes, but not to the connection between the value written and
> >the value read: the first part of that section explicitly revokes all
> >guarantees about the stored value.
>
> Here I disagree. As I interpret it, that section is giving permission
> to the user, not to the implementation. So the guarantees remain,
> unless the user does something to violate them.
How can the user do anything to affect the volatile memory? The C
language provide no defined mechanism for a user to cause volatile
changes to stored values; by your own arguments, the only way to cause
them involves undefined behavior. They can't be triggered by a call to
an implementation-defined function, because they must be "unknown to the
implementation".
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/19 Raw View
James Kuyper <kuyper@wizard.net> wrote:
> Fergus Henderson wrote:
> The C++ standard says nothing that allows an object, whether of
> volatile-qualified type, or not, whether residing in volatile memory or
> not, to undergo such arbitrary changes. The only thing it does say
> that's relevant is that 'volatile' is meant to have the same semantics
> as in C. The C standard does explicitly say that objects of
> volatile-qualified are subject to such arbitrary changes.
Unfortunately, it isn't explicit as to whether that applies to all
or to some objects of volatile-qualified type.
> You're saying that 'volatile' tells an implementation to compile the
> code in a way that is basically what's needed to make proper use of
> volatile memory.
That's reasonable.
> However, that any program that uses volatile memory necessarily
> allows undefined behavior,
Why?
> and that is the only thing that actually allows the volatile
> behavior of that memory.
I thought the thing that allows such volatile behavior is the
implementation's perogative to define what constitutes an access to an
object of volatile-qualified types. I'm not exactly sure what that
means, however.
[...]
>> >That distinction doesn't seem to be supported by this clause. To
>> >be more precise, the whole clause seems specific to objects of
>> >volatile-qualified type, regardless of whether or not they're stored in
>> >volatile memory.
>>
>> The whole clause does apply to objects of volatile-qualified type.
>> But stating that they can "be modified in ways unknown to the
>> implementation or have other unknown side effects" does not mean that
>> the implementation is allowed to modify them arbitrarily.
The conformance of an implemenation cannot hang on what it "knows."
> No - but the implementation can place them in locations where things
> outside the implementation can modify them.
Before it gets the program, the implementation must specify what
constitutes accesses to objects of volatile-qualified types.
Presumably, the types, semantics and identities (names or addresses)
of all objects that are subject to external observation and/or
modification must be disclosed, and all other objects of
volatile-qualified types must be allocated to ordinary memory.
It would be unfortunate if a conforming implementation could specify,
for instance, that each occurrence of a sequence point is a write
access that sets ALL objects of volatile-qualified type to zero. In
such an implemenation there would be no way for a signal handler to
communicate with a conforming program.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "David J. Littleboy" <davidjl@gol.com>
Date: 2000/09/19 Raw View
"Fergus Henderson" <fjh@cs.mu.OZ.AU> wrote:
> Francis Glassborow <francis.glassborow@ntlworld.com> writes:
>
> >thp@roam-thp2.cs.ucr.edu writes
> >>Are you suggesting that under a conforming implementation the following
> >>program could print out the number 2 ?
> >
> >Well, I would. If I did not want to allow such behaviour I would not use
> >a volatile qualifier.
<snip>
> For these programs, it is important that the use of `volatile' should
> not allow the implementation to arbitrarily modify the values of
> variables.
Huh? Who ever said anything about _the implementation_ modifying the value?
In the standard scenario, a volatile value gets changed by something
_outside_ the implementation, and the implementation then, correctly,
returns that changed value. If you declare something "volatile" then you are
asking the implementation to return whatever the outside agent stuffed into
that volatile something while you weren't looking. In the (long since
snipped) example, I'd hope that the volatile declaration would cause the
implementation to allow the return of any bit pattern, including 2, that
might get stuffed into that location between the initialization and the
return.
Now, whether it's meaningful or reasonable to declare volatile a location
(such as a local variable) that the implementation gets to determine where
said location actually is (stack, heap, stack allocated on the heap) may be
an interesting question, but the idea that volatile could be used to allow
debuggers or other threads to access data in a running program seems
reasonable...
David J. Littleboy
Tokyo, Japan
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/19 Raw View
In article <8q5q6g$26sp$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>Huh? In the previous sentence, I understood you to say above that if
>the programmer doesn't explicitly choose a storage location, such as an
>input port, that is subject to modification by other factors, the
>implementation MUST allocate the object to normal storage, which AFIK is
>modifiable only by explicit operations of the program, i.e., "storage
>that does not arbitrarily change." But, when I remove the double
>negation in the sentence above, you seem to be saying that the
>implementation-chosen storage may "be accessed and changed by some other
>mechanisms outside the knowledge and control of the program." How can it
>be both ways?
The implementation cannot wilfully select a memory mapped io port to
store a volatile variable simply because we said the variable was
volatile. However, a program maybe invoked from elsewhere (or be part of
a multi-threaded program) and we may know that this other thread or
process can access the storage. The compiler cannot know this, so how do
we get it to compile code that will be robust against such change?
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/19 Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <8q1u8t$76j$1@mulga.cs.mu.OZ.AU>, Fergus Henderson
> <fjh@cs.mu.OZ.AU> writes
>>For these programs, it is important that the use of `volatile' should
>>not allow the implementation to arbitrarily modify the values of
>>variables.
[...]
> There is a great difference between arbitrary change, and change
> outside the view of the program.
I'm not sure that I see the difference that you have in mind.
> In general, without a crystal ball a compiler cannot know how and
> where code will be executed, that is one of the costs of separate
> compilation coupled with execution separated from compilation.
A compiler can and should announce its intended execution
environment(s).
IMHO much confusion arises from the following two normative sentences
from C89 6.5.3:
An object that has volatile-qualified type may be modified in
ways unknown to the implementation or have other unknown side
effects. Therefore any expression referring to such an object
shall be evaluated strictly according to the rules of the
abstract machine, as described in 5.1.2.3.
It's easy enough to construct an implementation (with no input ports)
where the first of these sentences is false. (Does such an
implementation fail to conform simply because it "knows" what's going
on?) The second sentence simply says that expressions involving
volatile lvalues must behave correctly. That admonition adds nothing
new -- either we get the prescribed behavior or we don't.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/19 Raw View
David J. Littleboy <davidjl@gol.com> wrote:
> "Fergus Henderson" <fjh@cs.mu.OZ.AU> wrote:
>> Francis Glassborow <francis.glassborow@ntlworld.com> writes:
>>
>> >thp@roam-thp2.cs.ucr.edu writes
>> >>Are you suggesting that under a conforming implementation the following
>> >>program could print out the number 2 ?
>> >
>> >Well, I would. If I did not want to allow such behaviour I would not use
>> >a volatile qualifier.
> <snip>
>> For these programs, it is important that the use of `volatile' should
>> not allow the implementation to arbitrarily modify the values of
>> variables.
> Huh? Who ever said anything about _the implementation_ modifying the value?
> In the standard scenario, a volatile value gets changed by something
> _outside_ the implementation, and the implementation then, correctly,
> returns that changed value.
IIRC the standardese for that something is "the execution
environment." I believe that Fergus is indulging in a fairly common
abuse of language wherein the term "implementation" refers to both the
implementation and the execution environment. (From the perspective of
the program, it makes little difference that the implementation
subcontracts the implemenation for certain services.)
> If you declare something "volatile" then you are asking the
> implementation to return whatever the outside agent stuffed into
> that volatile something while you weren't looking. In the (long
> since snipped) example, I'd hope that the volatile declaration would
> cause the implementation to allow the return of any bit pattern,
> including 2, that might get stuffed into that location between the
> initialization and the return.
But not every volatile variable is intended to be an input port. For
example, if I want my signal handler to communicate with the rest of
my program, I must use a static of type volatile sigatomic_t, and I
don't want the implementation or anything else except the signal
handler writing to that object.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/19 Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <8q5q6g$26sp$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
> writes
>>Huh? In the previous sentence, I understood you to say above that if
>>the programmer doesn't explicitly choose a storage location, such as an
>>input port, that is subject to modification by other factors, the
>>implementation MUST allocate the object to normal storage, which AFIK is
>>modifiable only by explicit operations of the program, i.e., "storage
>>that does not arbitrarily change." But, when I remove the double
>>negation in the sentence above, you seem to be saying that the
>>implementation-chosen storage may "be accessed and changed by some other
>>mechanisms outside the knowledge and control of the program." How can it
>>be both ways?
> The implementation cannot wilfully select a memory mapped io port to
> store a volatile variable simply because we said the variable was
> volatile.
Agreed, wholeheartedly. But all other memory must remember, i.e.,
values cannot be modified except by the program. Getting back to
the example
int main() {
volatile int i = 0;
cout << i;
}
how might the value of i get set to 2 under a conforming
implementation/environment? (Please don't say via a debugger or a
high-energy particle from another galaxy, because no implementation
conforms in those environments.)
> However, a program maybe invoked from elsewhere (or be part of a
> multi-threaded program) and we may know that this other thread or
> process can access the storage. The compiler cannot know this, so
> how do we get it to compile code that will be robust against such
> change?
To get an lvalue to work correctly when it designates an object that
is accessible by asynchrounous streams of activity (either inside our
outside the program), it is almost always necessary to generate the
same kind of code that one would generate if the object were an io
port. That's the whole point to volatile-qualified types.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 2000/09/20 Raw View
thp@roam-thp2.cs.ucr.edu wrote:
>
> James Kuyper <kuyper@wizard.net> wrote:
> > Fergus Henderson wrote:
>
> > The C++ standard says nothing that allows an object, whether of
> > volatile-qualified type, or not, whether residing in volatile memory or
> > not, to undergo such arbitrary changes. The only thing it does say
> > that's relevant is that 'volatile' is meant to have the same semantics
> > as in C. The C standard does explicitly say that objects of
> > volatile-qualified are subject to such arbitrary changes.
>
> Unfortunately, it isn't explicit as to whether that applies to all
> or to some objects of volatile-qualified type.
I'd say 'any', rather than 'all' OR 'some'. I claim that volatile
qualification permits arbitrary changes; it neither mandates nor
prohibits them, but does make some requirements that the value after the
change must be the one read by the next access.
> > However, that any program that uses volatile memory necessarily
> > allows undefined behavior,
>
> Why?
Keep in mind that this is NOT my argument; I'm restating Fergus'
argument, so he can verify whether I've understood it correctly. He
claims that every method that can be legally be provided to access
volatile memory (as opposed volatile-qualified objects) requires use of
implementation-specific features with behavior that is undefined
according by the standard, but which may be defined by the
implementation. He specifically rejects my suggestion that a conforming
implementation (though an inconvenient one!) could automatically
allocate volatile memory as needed to hold user-defined
volatile-qualified objects.
> > and that is the only thing that actually allows the volatile
> > behavior of that memory.
>
> I thought the thing that allows such volatile behavior is the
> implementation's perogative to define what constitutes an access to an
> object of volatile-qualified types. I'm not exactly sure what that
> means, however.
No - you need a statement somewhere that allows the value read from an
object to be different from the value last written to it. The C++
standard contains no such wording, just a non-normative cross-reference
to the C semantics. I claim that the C standard has such wording, but
Fergus disagrees with my interpretation of the relevant clause.
...
> >> The whole clause does apply to objects of volatile-qualified type.
> >> But stating that they can "be modified in ways unknown to the
> >> implementation or have other unknown side effects" does not mean that
> >> the implementation is allowed to modify them arbitrarily.
>
> The conformance of an implemenation cannot hang on what it "knows."
Why not, if the standard says so? The C standard does say that the value
of an object of volatile-qualified type can "be modified in ways
unknown to the implementation". It does not otherwise exempt an
implementation from providing, on read, the same value last written to
the object (except by way of undefined behavior). I think it is that
clause of the C standard which allows volatile memory to be used by a C
implementation. What, if anything, allows it in a C++ implementation is
unclear.
> Before it gets the program, the implementation must specify what
> constitutes accesses to objects of volatile-qualified types.
> Presumably, the types, semantics and identities (names or addresses)
> of all objects that are subject to external observation and/or
> modification must be disclosed, and all other objects of
> volatile-qualified types must be allocated to ordinary memory.
That's what's in dispute. Can you cite supporting text that allows that
distinction?
> It would be unfortunate if a conforming implementation could specify,
> for instance, that each occurrence of a sequence point is a write
> access that sets ALL objects of volatile-qualified type to zero. In
> such an implemenation there would be no way for a signal handler to
> communicate with a conforming program.
Just because it's useless doesn't mean it's not conforming. QoI rules
out lots of possible conforming implementations. The key question is
what was the intent, and was that intent successfully embodied in the
actual text of the standard? It was clearly the intent that 'volatile'
be allowed to be useful; it's less clear to me that the actual text is
sufficient to guarantee that it is. I believe that in practice it is
useful in typical implementations, but I think that the text allows (but
does not require) that it not be.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "David J. Littleboy" <davidjl@gol.com>
Date: 2000/09/20 Raw View
<thp@roam-thp2.cs.ucr.edu> wrote:
> Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
<snip>
> > The implementation cannot wilfully select a memory mapped io port to
> > store a volatile variable simply because we said the variable was
> > volatile.
>
> Agreed, wholeheartedly. But all other memory must remember, i.e.,
> values cannot be modified except by the program. Getting back to
> the example
>
> int main() {
> volatile int i = 0;
> cout << i;
> }
>
> how might the value of i get set to 2 under a conforming
> implementation/environment? (Please don't say via a debugger or a
> high-energy particle from another galaxy, because no implementation
> conforms in those environments.)
Now I see why there's disagreement here: FG and I are perfectly happy to
assume that there are other agents (e.g. threads, "streams of activity")
smashing our volatile variables, and you are not willing to entertain that
possibility. I guess since the standard doesn't mention multi-threading, one
might see that as reasonable, but
> > However, a program maybe invoked from elsewhere (or be part of a
> > multi-threaded program) and we may know that this other thread or
> > process can access the storage. The compiler cannot know this, so
> > how do we get it to compile code that will be robust against such
> > change?
>
> To get an lvalue to work correctly when it designates an object that
> is accessible by asynchrounous streams of activity (either inside our
> outside the program), it is almost always necessary to generate the
> same kind of code that one would generate if the object were an io
> port. That's the whole point to volatile-qualified types.
But now you are assuming that there are other agents: ones that are only
allowed to _read_ volatile qualified types. I'd be perfectly happy to have
the standard interpreted or patched to allow either both read and write or
neither, but just one seems a bit arbitrary.
David J. Littleboy
Tokyo, Japan
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/20 Raw View
In article <8q8dqm$dcu$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>To get an lvalue to work correctly when it designates an object that is
>accessible by asynchrounous streams of activity (either inside our
>outside the program), it is almost always necessary to generate the same
>kind of code that one would generate if the object were an io port.
>That's the whole point to volatile-qualified types.
So how does a compiler know that it must generate such code? Because we
tell it so with the keyword volatile. It is my belief that 'volatile'
qualification removes the liberty that the compiler has otherwise to
optimise the abstract machine. It is not for the compiler to hypothesise
why I place such a restriction on it, it is my servant, not my master.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/20 Raw View
In article <8q8436$7jk$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>It's easy enough to construct an implementation (with no input ports)
>where the first of these sentences is false.
In that case, the compiler should, IMHO, issue a warning (this is a QoI
issue).
>(Does such an
>implementation fail to conform simply because it "knows" what's going
>on?) The second sentence simply says that expressions involving
>volatile lvalues must behave correctly. That admonition adds nothing
>new -- either we get the prescribed behavior or we don't.
Actually, I think it says more. It says how values are to be obtained.
No caching, no retention of values in registers etc.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/16 Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <8plh5k$hkd$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
> writes
>>Are you suggesting that under a conforming implementation the following
>>program could print out the number 2 ?
> Well, I would. If I did not want to allow such behaviour I would not use
> a volatile qualifier.
Any static object that gets set by a signal handler must be of type
volatile sigatomic_t
When a programmer uses the volatile qualifier in declaring such an
variable, does he/she really want to give the implementation license
to put arbitrary garbage into that variable whenever it pleases? I
think not. Of course, some (implementation-specified) volatile
objects are subject to non-explicit modifications. But it doesn't
make sense for all objects of volatile-qualified types to have
indeterminate value. That makes them useless.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: 2000/09/16 Raw View
<thp@roam-thp2.cs.ucr.edu> writes:
|> The alternative is to take the view that the debugger is not part of
|> the conforming implementation's intended "execution environment," in
|> which case there would be no requirements on the consequences of
|> debugger modifications to any variable, whether volatile or not.
That's really the point I've been trying to make. The implementation
gets to decide what the intended "execution environment" is. If it does
so that in fact volatile objects are not actually observable, I think
that it could probably just ignore the volatile attribute. At any rate,
you could never tell if it did.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/17 Raw View
In article <8ptpn1$auf$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>When a programmer uses the volatile qualifier in declaring such an
>variable, does he/she really want to give the implementation license to
>put arbitrary garbage into that variable whenever it pleases? I think
>not. Of course, some (implementation-specified) volatile objects are
>subject to non-explicit modifications. But it doesn't make sense for
>all objects of volatile-qualified types to have indeterminate value.
>That makes them useless.
Where do you come up with these ideas? It has absolutely nothing to do
with what the implementation can do. It is not allowed to do anything
other than what the program specifies. However that is quite different
from warning the implementation that something else may change the
contents of storage and so it must not rely on cached values but must go
and read what is there.
Volatile is NOT a licence to the implementation, indeed it is exactly
the opposite, it is a constraint on the implementation disallowing
assumptions that it can make otherwise. Please try to understand this,
because your posts seem to imply that you think volatile behaves like
const (which allows the value to be stored in read only memory) and
allows the implementation to store values where they may change
arbitrarily. Sometimes a programmer may choose the location of the
storage (e.g. memory mapped io ports) but otherwise the compiler must
choose storage that does not arbitrarily change. That is NOT the same as
saying that the storage may not be accessed and changed by some other
mechanism outside the knowledge and control of the program.
'const' is permissive, volatile is restrictive and those are fundamental
characteristics of the two keywords.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 2000/09/15 Raw View
Fergus Henderson wrote:
>
> James Kuyper <kuyper@wizard.net> writes:
>
> >Fergus Henderson wrote:
...
> >> Since the abstract machine does not include any volatile memory
> >> (real time clocks, memory-mapped I/O, concurrent processes, etc.),
> >
> >Why not? [...]
>
> Well, this is implied by the definition of "storage".
I don't understand - can you explain the relevance of that definition to
this question?
...
> And in general, you can't read the standard as allowing the
> implementation to perform arbitrary actions not mentioned by the
> standard. If the standard says that executing one piece of code
> causes the value 42 to be stored in a variable, and then the
> next piece of code reads the value of that variable, you have
> to assume that the value is still 42 unless otherwise stated.
> The standard defines the semantics of an abstract machine,
> and in such definitions the reader must always assume that
> the machine performs only the actions specified by the definition.
> If we assume arbitrary actions can be performed at any time,
> it would be impossible to make sense of any such definition.
The C++ standard says nothing that allows an object, whether of
volatile-qualified type, or not, whether residing in volatile memory or
not, to undergo such arbitrary changes. The only thing it does say
that's relevant is that 'volatile' is meant to have the same semantics
as in C. The C standard does explicitly say that objects of
volatile-qualified are subject to such arbitrary changes. You can either
say that volatile memory is disallowed, or invoke the cross-reference to
C to allow it. If you do allow invokation of that cross-reference then
such arbitrary actions are in fact explicitly mentioned; you can't
invoke silence as a reason to disallow them. And that invocation is
specific to objects of volatile-qualified type; no mention is made in
that section of whether or not they reside in volatile memory.
> >I'd say off hand that, given the rules on 'volatile', the presence (and,
> >if present, the nature) of any volatile memory qualifies as one of the
> >unspecified aspects of the abstract machine.
>
> Given which rules on `volatile'?
The cross-referenced section of the C standard I've already cited
earlier on this thread.
> As far as I can see, none of the rules on volatile allow the
> implementation to poke arbitrary values in volatile variables at
> arbitrary times, any more than the rules allow the implementation to
> poke arbitrary values in non-volatile variables at arbitrary times.
Except the cited cross-reference. I will grant you that it is not in the
C++ standard, but without the C cross-reference 'volatile' is nearly
meaningless. The real-life equivalent of the 'as-if' rule applies: if
you can't prove the implementation is non-conforming, then it doesn't
matter whether or not it is. It takes volatile memory to make the
properties guaranteed for volatile-qualified objects detectably
different from those that aren't so qualified (use of a debugger makes
all memory effectively volatile: it can be modified by the debugger, and
has side effects, in terms of the displayed value of the variable). The
one exception is the behavior guaranteed for volatile sig_atomic_t, but
a conforming implementation could provide that same behavior for
unqualified sig_atomic_t.
> If your argument is just that this is allowed simply because there is
> no rule that excludes it, then my counter-argument is that (a) the
No - I cited a specific rule that allows it.
...
> If you mean 6.7.3 in the C standard (see below),
> that is clearly a statement about implementation conformance,
> not part of the definition of the abstract machine.
> Since it twice refers to semantics of the abstract machine,
> you can't interpret it as being part of the definition of the
> abstract machine without rendering that definition circular.
Yes you can. I interpret that statement about the semantics as referring
to order of reads and writes of the value, and to the value written by
those writes, but not to the connection between the value written and
the value read: the first part of that section explicitly revokes all
guarantees about the stored value. The order of those reads and writes
is part of the observable behavior of the program, and must therefore
match one of the orders legal for the abstract machine. When there is
volatile memory mapped to volatile-qualified objects, that becomes a
detectable characteristic of the program.
...
> The C++ abstract machine doesn't provide any way to create volatile
> memory (see above), or to place variables in it. So in order to place
> a variable in volatile memory, the user must have requested that via
> some facility not specified in the C++ standard. This means that all
> bets are off. The C++ standard does not and cannot give any guarantees
> about the behaviour if you make use of facilities that are not defined
> by the standard.
Then it would seem that there's no need to state that objects of
volatile-qualified type can be modified arbitrarily; by that same
argument, all behavior of any program that uses those facilities is
undefined, whether or not it involves objects of volatile-qualified
type.
You're saying that 'volatile' tells an implementation to compile the
code in a way that is basically what's needed to make proper use of
volatile memory. However, that any program that uses volatile memory
necessarily allows undefined behavior, and that is the only thing that
actually allows the volatile behavior of that memory.
That's a reasonable way for the standard to be written; I just don't
think that's what it actually says.
...
> >So why do you believe that the 'except' clause apply only to objects in
> >volatile memory,
>
> What I mean by "volatile memory" is memory that is modified in ways
> other than by the abstract machine. So the reason that the
> "except" clause here applies only to objects in volatile memory
> is simply by definition: if the "except" clause is needed, then I
> define the memory to be volatile.
>
> >and not to user-defined objects of volatile-qualified
> >type?
>
> The except clause *does* apply to all user-defined objects of
> volatile-qualified type, but unless those objects are
> mapped to volatile memory, there won't be any unknown
> factors, and so the sense in which it applies is vacuous.
Not if the implementation makes such a mapping occur automatically (and
statically) for any user-defined object of volatile-qualified type. I'd
agree that this would be an inconvenient implementation, and probably
not what was intended, but I don't think it's non-conforming.
> >That distinction doesn't seem to be supported by this clause. To
> >be more precise, the whole clause seems specific to objects of
> >volatile-qualified type, regardless of whether or not they're stored in
> >volatile memory.
>
> The whole clause does apply to objects of volatile-qualified type.
> But stating that they can "be modified in ways unknown to the
> implementation or have other unknown side effects" does not mean that
> the implementation is allowed to modify them arbitrarily.
No - but the implementation can place them in locations where things
outside the implementation can modify them.
> If you were to interpret that paragraph as allowing the implementation
> to modify volatile-qualified objects arbitrarily, then the part
>
> | Therefore any expression referring to
> | such an object shall be evaluated strictly according to the
> | rules of the abstract machine, as described in 5.1.2.3.
>
> would not make any sense (particularly the word "therefore").
> So such an interpretation is internally inconsistent.
It's not inconsistent if, as I claim, the volatile behavior of that
memory is an explicitly allowed feature of the abstract machine. It
means that the modified value must be picked up by any read; that the
abstract machine is not allowed to hold the original value in a register
across sequence points. I know that you disagree with me about volatile
memory in the abstract machine, but you've failed to convince me of
that. Until you have, this last argument doesn't help. Once you have,
this last argument is unnecessary.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 2000/09/15 Raw View
thp@roam-thp2.cs.ucr.edu wrote:
>
> James Kuyper <kuyper@wizard.net> wrote:
> > Fergus Henderson wrote:
> >> The wording in the C 99 standard (6.7.3/6) is much clearer about this
> >> point:
> >>
> >> | 6.7.3 Type qualifiers
> >> | [#6] An object that has volatile-qualified type may be
> > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >> | modified in ways unknown to the implementation or have other
> >> | unknown side effects. Therefore any expression referring to
> >> | such an object shall be evaluated strictly according to the
> >> | rules of the abstract machine, as described in 5.1.2.3.
> >> | Furthermore, at every sequence point the value last stored
> >> | in the object shall agree with that prescribed by the
> >> | abstract machine, except as modified by the unknown factors
> >> | mentioned previously. [...]
>
> > So why do you believe that the 'except' clause apply only to objects in
> > volatile memory, and not to user-defined objects of volatile-qualified
> > type? That distinction doesn't seem to be supported by this clause. To
> > be more precise, the whole clause seems specific to objects of
> > volatile-qualified type, regardless of whether or not they're stored in
> > volatile memory.
>
> Are you suggesting that under a conforming implementation the following
> program could print out the number 2 ?
>
> int main() {
> volatile int x = 0;
> cout << x;
> }
Yes.
> AFIK, the normative text of C89 requires all variables to retain their
> values. Footnotes suggest that this might not always happen for
> volatile variables, but I view that as making provision for
> implementation-specific exceptions to normal memory semantics.
I don't have access to C89, so I can't be sure what the standard used to
say. However, I do have the current standard, and in C99 the relevant
text is normative - section 6.7.3p6, cited above. That may not have been
the intent, but I do think that's what it actually says.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/15 Raw View
In article <8plh5k$hkd$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>Are you suggesting that under a conforming implementation the following
>program could print out the number 2 ?
Well, I would. If I did not want to allow such behaviour I would not use
a volatile qualifier.
>
> int main() {
> volatile int x = 0;
> cout << x;
> }
>
>AFIK, the normative text of C89 requires all variables to retain their
>values. Footnotes suggest that this might not always happen for
>volatile variables, but I view that as making provision for
>implementation-specific exceptions to normal memory semantics.
I think your view is too restricted.
>
>Tom Payne
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jthill@telus.net (Jim Hill)
Date: 2000/09/15 Raw View
<kanze@gabi-soft.de> wrote:
> Dennis Yelle <dennis51@jps.net> writes:
>
> |> Going back to this example:
> |> int main() {
> |> volatile int x = 0;
> |> return x;
> |> }
>
> |> My opinion is that the compiler may use the "as if" rule to ignore
> |> "volatile" when it is applied to an auto variable who's address is
> |> never taken.
>
> The implementation *is* required to access x in the return statement.
> The access is "observable behavior." The compiler is required to
> document what it considers an access.
Agreed. I have always regarded `volatile` values as debugger-accessible:
you're guaranteed to be able to set a breakpoint on any line that
accesses a volatile, and you're guaranteed that any changes you make
will propagate "correctly" (i.e. as if the corresponding expression were
in the source), no matter what's been done to the rest of the code.
For instance, I'd say an implementation that could prove a non-volatile
two-valued-enum variable was stored only via its defined constants could
implement that variable as a single bit regardless of the declared
numeric values. But if it were `volatile`, even as a local variable in
a leaf function, I'd question the compiler's conformance if it took such
liberties.
Unless of course the implementation docs specify somehow (as e.g. by not
mentioning them) that such accesses aren't considered volatile.
Jim
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Mark Williams <markw65@my-deja.com>
Date: 2000/09/15 Raw View
In article <8plh5k$hkd$1@mortar.ucr.edu>,
thp@cs.ucr.edu wrote:
> James Kuyper <kuyper@wizard.net> wrote:
> > Fergus Henderson wrote:
> >> The wording in the C 99 standard (6.7.3/6) is much clearer about
this
> >> point:
> >>
> >> | 6.7.3 Type qualifiers
> >> | [#6] An object that has volatile-qualified type may be
> > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >> | modified in ways unknown to the implementation or have other
> >> | unknown side effects. Therefore any expression referring to
> >> | such an object shall be evaluated strictly according to the
> >> | rules of the abstract machine, as described in 5.1.2.3.
> >> | Furthermore, at every sequence point the value last stored
> >> | in the object shall agree with that prescribed by the
> >> | abstract machine, except as modified by the unknown factors
> >> | mentioned previously. [...]
>
> > So why do you believe that the 'except' clause apply only to objects
in
> > volatile memory, and not to user-defined objects of
volatile-qualified
> > type? That distinction doesn't seem to be supported by this clause.
To
> > be more precise, the whole clause seems specific to objects of
> > volatile-qualified type, regardless of whether or not they're stored
in
> > volatile memory.
>
> Are you suggesting that under a conforming implementation the
following
> program could print out the number 2 ?
>
> int main() {
> volatile int x = 0;
> cout << x;
> }
>
> AFIK, the normative text of C89 requires all variables to retain their
> values. Footnotes suggest that this might not always happen for
> volatile variables, but I view that as making provision for
> implementation-specific exceptions to normal memory semantics.
More to the point, the normative text of the C++ standard requires all
automatic variables to retain their last stored value (1.9 paragraph
10); it makes no exemption for volatile variables.
-------------
Mark Williams
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Tue, 12 Sep 2000 20:31:19 GMT Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
|> In practice, implementations treat "volatile" as an indication that
|> they should avoid any optimization, including placing variables in
|> registers, and so implementations do not allocate volatile objects in
|> registers. IMHO the C and C++ standards should recognize and codify
|> this existing practice.
|> I don't think such a requirement can
|> reasonably be formalized
That is, of course, exactly why the exact meaning of volatile is
implementation defined.
|> (how would you define "register" in an
|> implementation-independant way?), but nevertheless it should be
|> included in the standards as "recommended practice", stated using
|> "should" rather than "shall".
The intent is clear. In the C standard, there is a footnote which even
gives memory mapped IO ports as an example.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Tue, 12 Sep 2000 20:36:53 GMT Raw View
Dennis Yelle <dennis51@jps.net> writes:
|> Going back to this example:
|> int main() {
|> volatile int x =3D 0;
|> return x;
|> }
|> Is there anything to prohibit the compiler from keeping x in a regist=
er?
|> If not, is there anything that prevents the compiler from compiling
|> the program above to the same executable as the program below?
|> int main() {
|> return 0;
|> }
|> My opinion is that the compiler may use the "as if" rule to ignore
|> "volatile" when it is applied to an auto variable who's address is
|> never taken.
The implementation *is* required to access x in the return statement.
The access is "observable behavior." The compiler is required to
document what it considers an access.
If what it documents as an access is in no way really observable, then I
suppose that it can ignore volatile, because there is no way for you to
possibly detect that it has done so. I know of no compiler which
defines access in this manner.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Tue, 12 Sep 2000 20:37:57 GMT Raw View
kanze@gabi-soft.de wrote:
> Francis Glassborow <francis.glassborow@ntlworld.com> writes:
> |> In article <86r96t7bpe.fsf@gabi-soft.de>, kanze@gabi-soft.de writes
> |> >This is no simple condition. Suppose I have a debugger, which allows
> |> >stopping the program and examining and modifying the variables.
> |> Exactly, and a program that uses volatile qualified variables must
> |> behave 'correctly' in such an environment and how is the compiler to
> |> know?
> Must it? I'm not sure. I certainly can find nothing in the standard
> that guarantees this. (There is language, at least in the C standard,
> which would imply that this is the intention.)
> There is too much that it "implementation defined". In the end, if
> volatile is present, the compiler must ensure that the volatile accesses
> occur in the correct order. But the implementation gets to define what
> constitutes an access, and unless it documents that an access results in
> something that can be read by a debugger, and that it takes into account
> modifications by the debugger, I don't see where it is required to
> support this.
Absolutely. Per C89 6.5.3:
If an attempt is made to refer to an object defined with a
volatile-qualified type through use of a lvalue with non-volatile
qualified type, the behavior is undefined. [Footnote: "This applies
to those objects that behave as if they were defined with qualified
type ... ]
If every location that can be modified by a debugger is behaves as if
it were volatile memory, then every variable would have to be of a
volatile-qualified type. Right?
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Wed, 13 Sep 2000 02:39:52 GMT Raw View
kanze@gabi-soft.de wrote:
> <thp@roam-thp2.cs.ucr.edu> writes:
> |> An object is (really) volatile if and only if
> |> * its value ever changes without the execution of an instruction
> |> that modifies it or
> |> * accesses to it are (specified by the implementation to be)
> |> "observable behavior".
> |> Non-volatile objects are persistent and accesses to them are
> |> stealthy (i.e., not visible outside the program), so redundant
> |> and/or useless accesses to them can be as-if'd away.
> I think that the important point is that whether an object is volatile
> or not is a fact in some way exterior to the program. We declare an
> object volatile to inform the compiler of something that it cannot
> otherwise know. (And lying to the compiler doesn't pay.) Practically
> speaking, anytime there is something that concerns the variable that we
> cannot tell the compiler otherwise, we use volatile.
Agreed.
> In a course, I think I'd start with the example of memory mapped
> real-time clock, which reads seconds from midnight, and to which writes
> are simply no-ops. From a practical point of view, I think volatile is
> easier to understand from concrete examples of what it is meant to do.
> But of course, I would -- I never really studied computer science as
> such, and started in a the field in real-time, were memory mapped
> registers were my daily bread.
Many people think that it is best to proceed from the abstract to the
particular. My taste and experience go in the opposite.
> |> If a program fails to declare really volatile objects as volatile,
> |> it is apt to invoke undefined behavior. The same holds for objects
> |> that are "pseudo-volatile" in the sense that they are asynchronously
> |> accessed by signal handlers and/or multiple threads of execution.
> Right. The key is that the volatility is in some way an "external
> requirement". It is not something that I decide according to how I want
> to use the value (as is the case with const).
Pseudo-volatility is internal to the program but somewhat external to
the thread of control that in which the volatile lvalue occurs.
> |> If an implementation fails to treat appropriately objects that have
> |> been declared volatile, that implementation fails to conform.
> With the caveat that in this case, "appropriately" means "as described
> in the documentation of the implementation".
Plus, the (implicit) prohititions on using stale values and delaying
updates past sequence points.
> With the exception of setjmp/longjmp and signal, I think an
> implementation could define volatile as meaningless, and still be
> conform.
Agreed.
> |> The
> |> same holds if the implementation allocates variables that have not
> |> been declared volatile to objects that are volatile or pseudo-volatile
> |> in reality.
> That's a bit delicate. In practice, an implementation will allocate all
> variables somewhere in memory, unless specifically told otherwise. If
> an implementation maps a global variable to a memory mapped register, it
> is normally only because the programmer told it to.
I agree with Fergus on this one: in the absence of permission from the
program, a conforming implementation may not map user-declared variable
to io registers.
> If the programmer also forgot to declare the variable volatile, is
> that the fault of the implementation, or of the programmer?
Right.
> And of course, once multiple threads come into play, how is the
> implementation to even know?
As you have pointed out, technically it is not obliged to know. But the
intent is that lvalue-to-rvalue conversions of volatile lvalues fetch
the current value and assignments to volatile lvalues occur before any
subsequent sequence points.
> |> The standards imply (and should specify) that read operations on any
> |> object must obtain a value that is no less recent than that
> |> operation's preceding sequence point.
> It neither implies nor can specify that. Sequence points concern the
> syntax of the source program, and *not* the sequence of execution. They
> do not exist during execution, only in the source.
> What the standard can, and does specify, is that the partial ordering
> implied by sequence points will be respected with regards to observable
> behavior -- that is: if X and Y are two operations that have observable
> behavior, and if there is a sequence point in the source code which
> orders X and Y, then the observable behavior associated with X will
> precede that associated with Y.
> All that is guaranteed is a (partial) ordering of observable behavior.
> The difference is subtle, but without it, the presence of volatile
> variables would invalidate the as if rule.
Note that (modulo the as-if rule) the behavior of program is required
to respect the syntax-induced partial ordering of operations including
those pseudo-operations that we call "sequence points." In particular,
an operation is not allowed to use a stale value of a variable. That's
not much of a problem with non-volatile variables, but since a volatile
variable might be continuously changing, there is a real problem. One
cannot require that the "current" value be used because a fetched value
can become stale almost instantly. Therefore, we need to specify how
stale is too stale. What I'm saying is that the program must behave
as if it fetches a fresh value right after each sequence point (before
any subsequent use of that variable).
> |> For non-volatile objects, the as-if rule allows a lot of shortcuts,
> |> e.g., using a value that was left in registers prior to that
> |> sequence point. However, because the value of a volatile object
> |> might spontaneously change at any time and because reading a
> |> volatile object might be observable behavior, reads of the volatile
> |> objects are difficult or impossible to as-if away.
> |> The standards also specify that any object modified by an operation
> |> must have its new value before any sequence point following that
> |> operation occurs. But storing to a volatile object might be
> |> observable, so there is less lattitude for as-if'ing such modifying
> |> operations away (or to a later time).
> The store can be deffered as long as no other observable behavior
> occurs.
Agreed.
Tom Payne
P.S.: Thanks very much for the comments. I'm going to try to incorporate
your suggestions and recast this stuff as a FAQ.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Wed, 13 Sep 2000 02:40:13 GMT Raw View
James Kuyper <kuyper@wizard.net> wrote:
> Fergus Henderson wrote:
>> The wording in the C 99 standard (6.7.3/6) is much clearer about this
>> point:
>>
>> | 6.7.3 Type qualifiers
>> | [#6] An object that has volatile-qualified type may be
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> | modified in ways unknown to the implementation or have other
>> | unknown side effects. Therefore any expression referring to
>> | such an object shall be evaluated strictly according to the
>> | rules of the abstract machine, as described in 5.1.2.3.
>> | Furthermore, at every sequence point the value last stored
>> | in the object shall agree with that prescribed by the
>> | abstract machine, except as modified by the unknown factors
>> | mentioned previously. [...]
> So why do you believe that the 'except' clause apply only to objects in
> volatile memory, and not to user-defined objects of volatile-qualified
> type? That distinction doesn't seem to be supported by this clause. To
> be more precise, the whole clause seems specific to objects of
> volatile-qualified type, regardless of whether or not they're stored in
> volatile memory.
Are you suggesting that under a conforming implementation the following
program could print out the number 2 ?
int main() {
volatile int x = 0;
cout << x;
}
AFIK, the normative text of C89 requires all variables to retain their
values. Footnotes suggest that this might not always happen for
volatile variables, but I view that as making provision for
implementation-specific exceptions to normal memory semantics.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: christian.bau@isltd.insignia.com (Christian Bau)
Date: 2000/09/13 Raw View
In article <8pm3p2$10gq$1@mortar.ucr.edu>, thp@cs.ucr.edu wrote:
> If every location that can be modified by a debugger is behaves as if
> it were volatile memory, then every variable would have to be of a
> volatile-qualified type. Right?
Not really. It only means that if you modify a variable that is declared
as volatile, your program will still work correctly and use the modified
value. If you modify a variable that is not declared as volatile, then
anything can happen.
For example:
volatile int i = 3;
int j = 4;
int k = 3*i;
int l = 3*j;
You change i to 5: k will be set to 15.
You change j to 5: l could be anything. The compiler could have replaced
"3*j" by "12", "(j << 1) + j", "j+8" etc.
In other words, you CAN change every variable using the debugger, but you
MUST NOT do it except if the variable is volatile.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/13 Raw View
In article <8pm3p2$10gq$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>If every location that can be modified by a debugger is behaves as if it
>were volatile memory, then every variable would have to be of a
>volatile-qualified type. Right?
No. But if you elect to use a debugger to change a variable that is not
so qualified the standard places no requirements on the consequences.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/13 Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <8pm3p2$10gq$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
> writes
>>If every location that can be modified by a debugger is behaves as if it
>>were volatile memory, then every variable would have to be of a
>>volatile-qualified type. Right?
> No. But if you elect to use a debugger to change a variable that is not
> so qualified the standard places no requirements on the consequences.
Exactly. And, unless every variable is of a volatile-qualified type,
I can so elect, thereby, causing such undefined behavior and taking
the program out of conformance.
The alternative is to take the view that the debugger is not part of
the conforming implementation's intended "execution environment," in
which case there would be no requirements on the consequences of
debugger modifications to any variable, whether volatile or not.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: Thu, 7 Sep 2000 14:30:05 CST Raw View
Fergus Henderson <fjh@cs.mu.OZ.AU> writes
>> int main() {
>> volatile int x = 0;
>> return x;
>> }
>>
>> This is portable code, and the standard guarantees that it will
>> return zero. Just the same as it does if `volatile' were replaced
>> with `const'.
Francis Glassborow wrote:
> I have to say that this claim surprises me. Of course in a program
> this simple you are probably right, but only because there is nothing
> in this program that would lead me to suppose that the storage for x
> could be accessed from outside the program. However, suppose that we
> are in some odd multitasking system with shared memory...
Yes, for example:
int foo(volatile int *ip)
{
*ip = 0;
// contents of *ip might be modified here
return *ip;
}
This is also portable code, and the standard gurantees that the
assignment to *ip and the read from *ip will result in two separate
accesses of the object at *ip. So while the behavior of reads and
writes to *ip is guaranteed, the result returned from foo() is not.
When discussing the effects and guarantees of 'volatile', you must
be careful about the context in which it is used. Fergus's example
shows when 'volatile' has little, if any, effect on the behavior
of the program. My example shows when it does have a noticeable
effect.
--
David R. Tribble, mailto:david@tribble.com, http://david.tribble.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Thu, 7 Sep 2000 23:39:43 CST Raw View
In article <8p8i18$2ipk$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>But the as-if rule remains in effect. So, for example, it the
>implementation knows that write access to a particular volatile variable
>is not implementation-specified to be "observable", then it is possible
>in some cases to defer modifications of that variable past the next
>sequence point, or even to eliminate them altogether at points where the
>variable is dead. (But you knew that already.)
But the point is that an implementation cannot know this because
volatile says: 'This can change outside your knowledge'
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: Fri, 8 Sep 2000 07:50:19 CST Raw View
thp@roam-thp2.cs.ucr.edu wrote:
>
> James Kuyper <kuyper@wizard.net> wrote:
> [...]
> > The sequence point rules about 'volatile' essentially require that every
> > time the value of a volatile object is read, it is retrieved straight
> > from the source, rather than using a previously retrieved value
> > currently stored somewhere else.
>
> I agree, but I'm frustrated in my attempts to find words that say so,
> even indirectly. Since the value of a volatile can be constantly
> changing, it is impossible to require that the absolutely current
> value gets used in any compuation. The best that can be required is
> that the value that is used is more recent than the preceding sequence
> point.
Yes, as I indicated at the start of that paragraph, I was just giving a
rough description of the sequence point rules. That's pretty much as
close as you can get within the C/C++ context to defining it.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Fri, 8 Sep 2000 07:52:52 CST Raw View
James Kuyper <kuyper@wizard.net> writes:
>Fergus Henderson wrote:
>>
>> James Kuyper <kuyper@wizard.net> writes:
>> >Getting back to 'volatile', 7.1.5.1p8 contains a Note which says that
>> >"... the value of the [volatile] object might be changed by means
>> >undetectable by an implementation ...
>>
>> This text is giving the user permission to modify the object in ways
>> that the implementation can't detect. IMHO it is definitely NOT
>> giving the implementation permission to arbitrarily modify the object.
>
>The standard doesn't specify what those means are. The example is given
>of memory-mapped hardware. The model I've always used for thinking about
>volatile memory is a memory-mapped device that can, at arbitrary times,
>change the value stored in a piece of volatile memory, and the behavior
>of which is controlled by writes to volatile memory.
That's a fine model for volatile _memory_. But objects declared volatile
need not be stored in volatile memory. Indeed, as I interpret the standard,
simply declaring a variable to be volatile does NOT give the implementation
permission to store that variable in volatile memory. The implementation
must treat volatile objects as if they were stored in volatile memory,
but it must not actually put them in volatile memory.
>> >However, I can't find normative text specifying those semantics. The C
>> >standard says in 6.7.3p6 that "An object that has volatile-qualified
>> >type may be modified in ways unknown to the implementation or have other
>> >unknown side effects."
>>
>> Again, I read that as giving permission to the user, not to the
>> implementation.
>
>I'm unclear as to how a "user" could changed the value by means
>undetectable by the implementation. The user of a C++ implementation
>interacts with a C++ program entirely through the implementation; that's
>what makes him or her the 'user'.
"Unknown" means only "not detected", not "undetectable".
The implementation is not required to detect every such modification.
The typical way that kind of thing happens is that the user
writes code which either forks off different threads which
access the memory concurrently, or writes code which allocates
volatile-qualified.
The point is that these "unknown side effects" happen only
if the user writes code (or performs some other action,
such as running the program under a debugger) which causes
them to happen.
>> The converse interpretation of that paragraph is clearly wrong-headed.
>> Firstly, it makes `volatile' much less useful. But more importantly,
>
>What makes it useful is that it allows memory-mapped hardware and memory
>shared between processes, among other things. It is precisely because it
>can be modified by an external source that you want a piece of memory to
>be volatile - you read it because you want to know what value it was
>modified to. It is precisely because storing a value in volatile memory
>can have side effects that you want a piece of memory to be volatile -
>you write to it because you want to cause the side effect.
Sure, I agree with all that. But interpreting the text from the
standard quoted above as allowing the C compiler to arbitrarily modify
volatile objects would mean that there was no guarantee that such
programs would work.
> This is
>extremely useful in the right context, though it's necessarily extremely
>non-portable.
I don't agree. Programs using e.g. POSIX threads and communicating
via volatile shared variables are quite portable these days.
Not quite as portable as strictly conforming C programs, since
support for POSIX threads is not as widespread as support for ISO C,
but nevertheless still far from "extremely non-portable".
>My career has involved almost entirely high-level programs that need to
>be as portable as possible, and hence make no use whatsoever of
>'volatile'. Therefore, the following paragraphs represent merely my own
>guesses about how it might be used. I think that typical uses will
>involve volatile-qualified pointers (and references?) more than
>volatile-qualified objects. I suspect that implementations will either
>document specific addresses that point to mapped memory, or provide
>functions for returning pointers to such memory. Since your example
>makes no use of such mechanisms, it's obviously safe from problems from
>that source.
>
>However, one feasible way of creating such a mapping is for all
>statically and automatically allocated volatile objects to be allocated
>out of a block of mappable memory. It would then be the user's
>responsibility to communicate the addresses of volatile objects to the
>other processes/devices that will uses those blocks to communicate with
>the program. If the implementor documents the order in which that memory
>is allocated, and where it's located, another program could predict in
>advance, where 'x' was going to be allocated, and write to that location
>between the time that 'x' was initialized by your code, and the time
>that it returns from 'main'. The timing is so tight that such
>interference is unlikely, but the possibility need not be 0, and would
>increase as more lines of code are inserted between them.
That's certainly a possible approach. Indeed systems such as Linux
provide all the necessary features to eable you to write code like
that if you want to (process memory can be accessed via files in /proc,
and dlsym() can be used to obtain the addresses of global variables).
But my point is that the C implementation cannot arbitrarily start
processes which go around poking at volatile variables in the user's C
programs. Only if the user somehow requests it, e.g. by writing and
executing such a process, would the value of variables in the original
program declared volatile actually be modified other than by
statements in the original program.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Fri, 8 Sep 2000 16:44:59 GMT Raw View
Fergus Henderson <fjh@cs.mu.oz.au> wrote:
> James Kuyper <kuyper@wizard.net> writes:
>>Fergus Henderson wrote:
>>>
>>> James Kuyper <kuyper@wizard.net> writes:
>>> >Getting back to 'volatile', 7.1.5.1p8 contains a Note which says that
>>> >"... the value of the [volatile] object might be changed by means
>>> >undetectable by an implementation ...
>>>
>>> This text is giving the user permission to modify the object in ways
>>> that the implementation can't detect. IMHO it is definitely NOT
>>> giving the implementation permission to arbitrarily modify the object.
>>
>>The standard doesn't specify what those means are. The example is given
>>of memory-mapped hardware. The model I've always used for thinking about
>>volatile memory is a memory-mapped device that can, at arbitrary times,
>>change the value stored in a piece of volatile memory, and the behavior
>>of which is controlled by writes to volatile memory.
> That's a fine model for volatile _memory_. But objects declared volatile
> need not be stored in volatile memory. Indeed, as I interpret the standard,
> simply declaring a variable to be volatile does NOT give the implementation
> permission to store that variable in volatile memory. The implementation
> must treat volatile objects as if they were stored in volatile memory,
> but it must not actually put them in volatile memory.
Agreed. But, AFIK, through implemetation-specific extensions of the
Standard, a conforming implementation can allow programs to force
obects to be allocated at volatile locations, e.g., via placement-new.
(In the absence of such permission/force from the program, of course,
any conforming implementation must allocate objects, even those
declared volatile, at non-volatile locations.)
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Fri, 8 Sep 2000 16:53:37 GMT Raw View
<thp@roam-thp2.cs.ucr.edu> writes:
>Fergus Henderson <fjh@cs.mu.oz.au> wrote:
>> James Kuyper <kuyper@wizard.net> writes:
>[...]
>>>Getting back to 'volatile', 7.1.5.1p8 contains a Note which says that
>>>"... the value of the [volatile] object might be changed by means
>>>undetectable by an implementation ...
>
>> This text is giving the user permission to modify the object in ways
>> that the implementation can't detect. IMHO it is definitely NOT
>> giving the implementation permission to arbitrarily modify the object.
>
>>>However, I can't find normative text specifying those semantics. The C
>>>standard says in 6.7.3p6 that "An object that has volatile-qualified
>>>type may be modified in ways unknown to the implementation or have other
>>>unknown side effects."
>
>> Again, I read that as giving permission to the user, not to the
>> implementation.
>
>> The converse interpretation of that paragraph is clearly wrong-headed.
>> Firstly, it makes `volatile' much less useful. But more importantly,
>> it leads to an interpretation of the standard that is internally
>> inconsistent, since it would make `volatile' impossible to use in
>> strictly conforming programs, and yet would require the use of
>> `volatile' in certain situations involving setjmp() and sig_atomic_t.
>
>Wow! I couldn't agree less.
>
>According to C89 6.5.3:
>According to C89 6.1.2.4:
What's your point in quoting those?
I don't see how they relate to your argument.
In fact I don't understand what your argument is.
>According to C89 3.9:
>
> implementation: a particular set of software, running in a particular
> translation environment under particular control options, that performs
> translation of programs for, and supports execution of function in, a
> particular execution environment.
>
>Under any definition of "user" that I can think of, modifications of
>the content of memory-mapped input ports are usually actions of the
>"execution environment" rather than the "user."
Sure. But as I interpret it, only the user has permission to map
volatile objects onto memory-mapped input ports. The C implementation
must not allocate volatile objects onto memory-mapped input ports,
unless the user requests it. (Such a request must of course use some
implementation-specific facility not defined by the C standard).
>> If the authors of the C standard had intended to make the semantics of
>> `volatile' objects completely undefined, why would they bother
>> specifying all those details about the use of `volatile' in conjunction
>> with setjmp() and sig_atomic_t?
>
>IMHO, the authors intended "volatile" to remove certain guarantees
>that pertain to nonvolatile variables, namely the guarantees of:
>
> * persistence (the property that a nonvolatile variable retains its
> value unless it is explicitly modified by the program),
>
> * stealth (the property that accesses to a nonvolatile variable are
> not "observable").
>
>Those two properties together with the as-if rule permit a lot of
>optimizations that are not guaranteed to be "as if" in the case of
>volatile variables.
Guarantees that permit the implementation to perform optimizations
are restrictions on users. Removing such guarantees is giving
permissions to users. So it sounds like you are agreeing with me
here -- the authors intended to remove guarantees that the user
normally makes to the implementation, not to remove guarantees
that the implementation makes to the user.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Fri, 8 Sep 2000 16:57:33 GMT Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <8p8i18$2ipk$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
> writes
>>But the as-if rule remains in effect. So, for example, it the
>>implementation knows that write access to a particular volatile variable
>>is not implementation-specified to be "observable", then it is possible
>>in some cases to defer modifications of that variable past the next
>>sequence point, or even to eliminate them altogether at points where the
>>variable is dead. (But you knew that already.)
> But the point is that an implementation cannot know this because
> volatile says: 'This can change outside your knowledge'
Consider the program
int main(){
volatile int i;
for( i = 1; i < 10; ++i ) cout << i;
}
The compiler knows perfectly well that i is NOT going to spontaneously
change in value, because the compiler knows that it is allocating i to
nonvolatile memory and that the program isn't multithreaded and that i
isn't accessed by a signal handler or involved in a longjmp, etc.
I believe that the "volatile" qualifier on the declaration of i tells
the compiler: "I have reason to doubt the persistence of i and/or
the unobservability of accesses to i that you might otherwise count
on in generating code, so, unless you know otherwise, generate very
conservative code."
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Fri, 8 Sep 2000 20:35:38 GMT Raw View
Fergus Henderson <fjh@cs.mu.oz.au> wrote:
> <thp@roam-thp2.cs.ucr.edu> writes:
>>Fergus Henderson <fjh@cs.mu.oz.au> wrote:
>>> James Kuyper <kuyper@wizard.net> writes:
>>[...]
>>>>Getting back to 'volatile', 7.1.5.1p8 contains a Note which says that
>>>>"... the value of the [volatile] object might be changed by means
>>>>undetectable by an implementation ...
>>
>>> This text is giving the user permission to modify the object in ways
>>> that the implementation can't detect. IMHO it is definitely NOT
>>> giving the implementation permission to arbitrarily modify the object.
>>
>>>>However, I can't find normative text specifying those semantics. The C
>>>>standard says in 6.7.3p6 that "An object that has volatile-qualified
>>>>type may be modified in ways unknown to the implementation or have other
>>>>unknown side effects."
>>
>>> Again, I read that as giving permission to the user, not to the
>>> implementation.
>>
>>> The converse interpretation of that paragraph is clearly wrong-headed.
>>> Firstly, it makes `volatile' much less useful. But more importantly,
>>> it leads to an interpretation of the standard that is internally
>>> inconsistent, since it would make `volatile' impossible to use in
>>> strictly conforming programs, and yet would require the use of
>>> `volatile' in certain situations involving setjmp() and sig_atomic_t.
>>
>>Wow! I couldn't agree less.
>>
>>According to C89 6.5.3:
>>According to C89 6.1.2.4:
> What's your point in quoting those?
> I don't see how they relate to your argument.
> In fact I don't understand what your argument is.
The problem is that I misunderstood your point. I was trying to show
that the authors intended the volatile qualifier to accomodate objects
that get allocated to volatile locations, which of course can be
modified by agents other than "the user."
>>Under any definition of "user" that I can think of, modifications of
>>the content of memory-mapped input ports are usually actions of the
>>"execution environment" rather than the "user."
> Sure. But as I interpret it, only the user has permission to map
> volatile objects onto memory-mapped input ports. The C
> implementation must not allocate volatile objects onto memory-mapped
> input ports, unless the user requests it. (Such a request must of
> course use some implementation-specific facility not defined by the
> C standard).
[...]
> Guarantees that permit the implementation to perform optimizations
> are restrictions on users. Removing such guarantees is giving
> permissions to users. So it sounds like you are agreeing with me
> here -- the authors intended to remove guarantees that the user
> normally makes to the implementation, not to remove guarantees
> that the implementation makes to the user.
I couldn't agree more.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: Fri, 8 Sep 2000 22:21:03 GMT Raw View
Fergus Henderson wrote:
>
> James Kuyper <kuyper@wizard.net> writes:
...
> >The standard doesn't specify what those means are. The example is given
> >of memory-mapped hardware. The model I've always used for thinking about
> >volatile memory is a memory-mapped device that can, at arbitrary times,
> >change the value stored in a piece of volatile memory, and the behavior
> >of which is controlled by writes to volatile memory.
>
> That's a fine model for volatile _memory_. But objects declared volatile
> need not be stored in volatile memory. Indeed, as I interpret the standard,
> simply declaring a variable to be volatile does NOT give the implementation
> permission to store that variable in volatile memory. The implementation
> must treat volatile objects as if they were stored in volatile memory,
> but it must not actually put them in volatile memory.
That sounds reasonable. Where in the standard does it make such a
distinction? The C++ standard allows unpredictable reads, and writes
with side effects, only by way of cross-referencing the C standard - I
couldn't find comparable words in the C++ standard itself. The relevant
quote from the C standard referred only to an "object that has
volatile-qualified type"; as I read it, that wording means that it's the
qualification that provides those special features, not the object's
physical location.
...
> >What makes it useful is that it allows memory-mapped hardware and memory
> >shared between processes, among other things. It is precisely because it
> >can be modified by an external source that you want a piece of memory to
> >be volatile - you read it because you want to know what value it was
> >modified to. It is precisely because storing a value in volatile memory
> >can have side effects that you want a piece of memory to be volatile -
> >you write to it because you want to cause the side effect.
>
> Sure, I agree with all that. But interpreting the text from the
> standard quoted above as allowing the C compiler to arbitrarily modify
> volatile objects would mean that there was no guarantee that such
> programs would work.
More precisely, it would mean that the relevant guarantee must come from
the implementor, rather than from the C standard.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Fri, 8 Sep 2000 22:46:32 GMT Raw View
In article <8pb25e$gpl$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>Consider the program
>
> int main(){
> volatile int i;
> for( i = 1; i < 10; ++i ) cout << i;
> }
>
>The compiler knows perfectly well that i is NOT going to spontaneously
>change in value, because the compiler knows that it is allocating i to
>nonvolatile memory and that the program isn't multithreaded and that i
>isn't accessed by a signal handler or involved in a longjmp, etc.
>
>I believe that the "volatile" qualifier on the declaration of i tells
>the compiler: "I have reason to doubt the persistence of i and/or the
>unobservability of accesses to i that you might otherwise count on in
>generating code, so, unless you know otherwise, generate very
>conservative code."
Of course you are entitled to believe this, I just think you are
mistaken and that a compiler that ignored my use of volatile would be
non-conforming.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Sat, 9 Sep 2000 00:06:22 GMT Raw View
James Kuyper <kuyper@wizard.net> wrote:
> Fergus Henderson wrote:
>>
>> James Kuyper <kuyper@wizard.net> writes:
> ...
>> >The standard doesn't specify what those means are. The example is given
>> >of memory-mapped hardware. The model I've always used for thinking about
>> >volatile memory is a memory-mapped device that can, at arbitrary times,
>> >change the value stored in a piece of volatile memory, and the behavior
>> >of which is controlled by writes to volatile memory.
>>
>> That's a fine model for volatile _memory_. But objects declared volatile
>> need not be stored in volatile memory. Indeed, as I interpret the standard,
>> simply declaring a variable to be volatile does NOT give the implementation
>> permission to store that variable in volatile memory. The implementation
>> must treat volatile objects as if they were stored in volatile memory,
>> but it must not actually put them in volatile memory.
> That sounds reasonable. Where in the standard does it make such a
> distinction? The C++ standard allows unpredictable reads, and writes
> with side effects, only by way of cross-referencing the C standard - I
> couldn't find comparable words in the C++ standard itself. The relevant
> quote from the C standard referred only to an "object that has
> volatile-qualified type"; as I read it, that wording means that it's the
> qualification that provides those special features, not the object's
> physical location.
The footnotes certainly seem to confuse the notion of non-persistent
memory (e.g., memory-mapped io ports) with volatile-qualified type,
for instance the following from C89 6.5.3:
This applies to those objects that behave as if they were defined
with qualified types, even if they are never actually defined as
objects in the program (such as an object at a memory mapped io
address.
> ...
>> >What makes it useful is that it allows memory-mapped hardware and memory
>> >shared between processes, among other things. It is precisely because it
>> >can be modified by an external source that you want a piece of memory to
>> >be volatile - you read it because you want to know what value it was
>> >modified to. It is precisely because storing a value in volatile memory
>> >can have side effects that you want a piece of memory to be volatile -
>> >you write to it because you want to cause the side effect.
>>
>> Sure, I agree with all that. But interpreting the text from the
>> standard quoted above as allowing the C compiler to arbitrarily modify
>> volatile objects would mean that there was no guarantee that such
>> programs would work.
> More precisely, it would mean that the relevant guarantee must come from
> the implementor, rather than from the C standard.
Simply adding the qualifier "volatile" to a declaration in a portable
program should not (allow conforming implementations to) change the
program's behavior. A program can introduce non-persistent objects
only via implementation-specific extensions to the Standard(s), and
the Standard(s) requires that such objects be accessed only via
volatile lvalues.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Sat, 9 Sep 2000 13:42:22 GMT Raw View
In article <8pb46t$m3m$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>Agreed. But, AFIK, through implemetation-specific extensions of the
>Standard, a conforming implementation can allow programs to force obects
>to be allocated at volatile locations, e.g., via placement-new. (In the
>absence of such permission/force from the program, of course, any
>conforming implementation must allocate objects, even those declared
>volatile, at non-volatile locations.)
What exactly is a non-volatile location? Of course as long as the
compiler's code real does behave 'as if' then all is fine but the day
that it optimises away a read of a volatile qualified object an I change
it behind the programs back (e.g. in a debugger) the compiler is wrong.
I contend that the compiler is required to believe the programmer.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Sat, 9 Sep 2000 13:43:22 GMT Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <8pb25e$gpl$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
> writes
>>Consider the program
>>
>> int main(){
>> volatile int i;
>> for( i = 1; i < 10; ++i ) cout << i;
>> }
>>
>>The compiler knows perfectly well that i is NOT going to spontaneously
>>change in value, because the compiler knows that it is allocating i to
>>nonvolatile memory and that the program isn't multithreaded and that i
>>isn't accessed by a signal handler or involved in a longjmp, etc.
>>
>>I believe that the "volatile" qualifier on the declaration of i tells
>>the compiler: "I have reason to doubt the persistence of i and/or the
>>unobservability of accesses to i that you might otherwise count on in
>>generating code, so, unless you know otherwise, generate very
>>conservative code."
> Of course you are entitled to believe this, I just think you are
> mistaken and that a compiler that ignored my use of volatile would be
> non-conforming.
Your use of "volatile" does not suspend the as-if rule, so the
compiler IS indeed allowed to ignore your use of "volatile" as long as
the resulting program behaved as if the more conservative code had
been generated. In the example above, my use of "volatile" does not
allow or require the program to behave in any way different from how
it would behave otherwise (i.e., if "volatile" weren't there).
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: Sat, 9 Sep 2000 13:44:08 GMT Raw View
thp@roam-thp2.cs.ucr.edu wrote:
...
> Simply adding the qualifier "volatile" to a declaration in a portable
> program should not (allow conforming implementations to) change the
> program's behavior. A program can introduce non-persistent objects
> only via implementation-specific extensions to the Standard(s), and
As I said to Francis; that sounds reasonable - where does it say that in
the standard?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Sat, 9 Sep 2000 13:46:39 GMT Raw View
In article <8pbsp2$157b$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>Simply adding the qualifier "volatile" to a declaration in a portable
>program should not (allow conforming implementations to) change the
>program's behavior. A program can introduce non-persistent objects only
>via implementation-specific extensions to the Standard(s), and the
>Standard(s) requires that such objects be accessed only via volatile
>lvalues.
That is not true. You can overload on volatile. That may be an awful
design decision but it is the case.
#include <iostream>
void report(int) { cout << "I am persistent.";}
void report(int volatile){cout << "I am volatile.";}
int main(){
int i=0;
report(i);
}
Now change that declaration to:
int volatile i = 0;
I think the above program is about as portable as you can get, and the
results are about as predictable as is possible.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Sun, 10 Sep 2000 00:27:07 GMT Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
|> Francis Glassborow <francis.glassborow@ntlworld.com> writes:
|> >Fergus Henderson <fjh@cs.mu.OZ.AU> writes
|> >> int main() {
|> >> volatile int x =3D 0;
|> >> return x;
|> >> }
|> >>This is portable code, and the standard guarantees that it will
|> >>return zero. Just the same as it does if `volatile' were replaced
|> >>with `const'.
|> >I have to say that this claim surprises me. Of course in a program
|> >this simple you are probably right, but only because there is
|> >nothing in this program that would lead me to suppose that the
|> >storage for x could be accessed from outside the program. However,
|> >suppose that we are in some odd multitasking system with shared
|> >memory...
|> The C standard does not define any facilities for multitasking or
|> shared memory, so the behaviour of any such facilities that an
|> implementation happens to provide must certainly be undefined from
|> the point of view of the C standard. But the blame must go to the
|> use of those implementation-specific facilities, not to `volatile'.
It may not define facilities for multitasking, but it certainly does
allow the implementation to provide them as an extension. Just as it
allows the implementation to provide memory mapped IO. Suppose that the
implementation, by some means that I cannot imagine, has a way of
mapping particular stack addresses (that have been declared volatile) to
a hardware register which counts accesses. The initialization
effectively sets the value to 0, and starts counting. The return
statement accesses, incrementing the register and causing it to return
1.
|> Of course if you do use implementation-specific facilities, the
|> implementation (or some other standard) is free to define the
|> behaviour in that case. For example, the POSIX standard defines
|> functions for multithreading. If you use `volatile' appropriately
|> in a program that makes use of POSIX threads, then the behaviour
|> will be defined by the appropriate POSIX standards.
And since the standard makes volatile the opening for implementation
defined behavior, by stating that 1) the value may change in ways
invisible to the compiler (thus presumably outside of the language), and
2) that what constitutes an access (which is observable behavior) is
implementation defined.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Sun, 10 Sep 2000 00:27:12 GMT Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
|> >Getting back to 'volatile', 7.1.5.1p8 contains a Note which says
|> >that "... the value of the [volatile] object might be changed by
|> >means undetectable by an implementation ...
|> This text is giving the user permission to modify the object in ways
|> that the implementation can't detect. IMHO it is definitely NOT
|> giving the implementation permission to arbitrarily modify the
|> object.
In the C standard, it was the definite intention that a volatile
variable could be mapped to a real time clock -- the compiler was
supposed to read it each access, because it could have changed since the
last access.
If the variable is mapped to a real time clock, is the arbitrary change
the user who is changing it, or the implementation (given, of course,
that the user requested the mapping).
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Dennis Yelle <dennis51@jps.net>
Date: Mon, 11 Sep 2000 18:26:17 GMT Raw View
Francis Glassborow wrote:
>
> In article <86r96t7bpe.fsf@gabi-soft.de>, kanze@gabi-soft.de writes
> >This is no simple condition. Suppose I have a debugger, which allows
> >stopping the program and examining and modifying the variables.
>
> Exactly, and a program that uses volatile qualified variables must
> behave 'correctly' in such an environment and how is the compiler to
> know?
Going back to this example:
int main() {
volatile int x = 0;
return x;
}
Is there anything to prohibit the compiler from keeping x in a register?
If not, is there anything that prevents the compiler from compiling
the program above to the same executable as the program below?
int main() {
return 0;
}
My opinion is that the compiler may use the "as if" rule to
ignore "volatile" when it
is applied to an auto variable who's address is never taken.
Dennis Yelle
--
I am a computer programmer and I am looking for a job.
There is a link to my resume here:
http://table.jps.net/~vert/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Mon, 11 Sep 2000 21:41:43 GMT Raw View
Fergus Henderson <fjh@cs.mu.oz.au> wrote:
> <thp@roam-thp2.cs.ucr.edu> writes:
>>Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
>>> I just think you are
>>> mistaken and that a compiler that ignored my use of volatile would be
>>> non-conforming.
>>
>>Your use of "volatile" does not suspend the as-if rule, so the
>>compiler IS indeed allowed to ignore your use of "volatile" as long as
>>the resulting program behaved as if the more conservative code had
>>been generated.
> The "as-if" rule is stated in the standard in a way which explicitly
> excludes optimization of reads and writes to volatile objects.
> In particular:
> | 1.9 - Program execution [intro.execution]
> |
> | -1- The semantic descriptions in this International Standard define a
> | parameterized nondeterministic abstract machine. This International
> | Standard places no requirement on the structure of conforming
> | implementations. In particular, they need not copy or emulate the
> | structure of the abstract machine. Rather, conforming implementations
> | are required to emulate (only) the observable behavior of the abstract
> | machine as explained below.*
> |
> | [Footnote: This provision is sometimes called the ``as-if'' rule,
> ...
> | -6- The observable behavior of the abstract machine is its sequence of
> | reads and writes to volatile data and calls to library I/O functions.
>>In the example above, my use of "volatile" does not
>>allow or require the program to behave in any way different from how
>>it would behave otherwise (i.e., if "volatile" weren't there).
> No, it does behave differently, because reads and writes to volatile
> data are part of the program's observable behaviour.
C89 6.5.3 contains the following:
What constitutes an access to an object that has volatile-qualified
type is implemetation defined. [C89 6.5.3]
I interpret that to mean that the implementation gets to say which
reads and write of volatile objects are externally observable. If so,
it would be reasonable for an implementation to treat as unobservable
all volatile variables that are not allocated to volatile memory and
not accessed by other threads of execution (including signal handlers
and segments between a longjmp and its corresponding setjmp). In full
conformity, such an implementation could generate the same optimized
code for the cited example regardless of whether i is volatile.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Mon, 11 Sep 2000 22:06:30 GMT Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <8pb46t$m3m$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
> writes
>>Agreed. But, AFIK, through implemetation-specific extensions of the
>>Standard, a conforming implementation can allow programs to force obects
>>to be allocated at volatile locations, e.g., via placement-new. (In the
>>absence of such permission/force from the program, of course, any
>>conforming implementation must allocate objects, even those declared
>>volatile, at non-volatile locations.)
> What exactly is a non-volatile location?
One that has persistence and stealth, i.e., one that remembers its
values and whose accesses are not externally observable.
> Of course as long as the compiler's code real does behave 'as if'
> then all is fine
[...]
Exactly.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 12 Sep 2000 13:37:46 GMT Raw View
Dennis Yelle <dennis51@jps.net> writes:
>Going back to this example:
> int main() {
> volatile int x = 0;
> return x;
> }
>
>Is there anything to prohibit the compiler from keeping x in a register?
In the current C and C++ standards, as I interpret them, no.
The closest thing to such a prohibition that I can see is the
following argument: in the standard's abstract machine, objects
(other than bitfields) occupy regions of storage composed of at least
one byte, and bytes have addresses. Since evaluation of expressions
involving volatile objects must procede exactly according to the
rules of the abstract machine, an implementation is not allowed
to allocate volatile objects in storage which is not addressable.
(The relevant sections of the C++ standard which justify this
argument are 1.7[intro.memory]p1, 1.8[intro.object]p5,
and 1.9[intro.execution]p1&6, and of the 1999 C standard
3.6p1, 3.6p2, and 6.7.3p6.)
However, that argument fails, because an implementation can
quite reasonably argue that registers have addresses.
There's no reason why the C standard's notion of "address"
needs to correspond exactly with the hardware's notion of
"address".
>If not, is there anything that prevents the compiler from compiling
>the program above to the same executable as the program below?
>
> int main() {
> return 0;
> }
I don't think so.
In practice, implementations treat "volatile" as an indication that
they should avoid any optimization, including placing variables in
registers, and so implementations do not allocate volatile objects in
registers. IMHO the C and C++ standards should recognize and codify
this existing practice. I don't think such a requirement can
reasonably be formalized (how would you define "register" in an
implementation-independant way?), but nevertheless it should be
included in the standards as "recommended practice", stated using
"should" rather than "shall".
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: Tue, 12 Sep 2000 13:38:23 GMT Raw View
Fergus Henderson wrote:
...
> Well, the standard does not describe it in that way.
> But the semantics that it specifies amount to the same thing,
> or at least are *intended* to amount to the same thing --
> I agree that the wording could and should be improved.
>
> In particular, here's where the C++ standard mandates
> the two parts of my claim:
>
> (1) "simply declaring a variable to be volatile does NOT give the
> implementation permission to store that variable in volatile memory."
>
> This is mandated by section 1.9 [intro.execution] of the C++
> standard.
>
> | 1.9 - Program execution [intro.execution]
> ...
> | -1- [...] conforming implementations are required to emulate [...]
> | the observable behavior of the abstract machine
>
> Since the abstract machine does not include any volatile memory
> (real time clocks, memory-mapped I/O, concurrent processes, etc.),
Why not? Section 1.9: "... Certain aspects of the abstract machine are
described in this International Standard as implementation-defined. ...
Certain other aspects and operations of the abstract machine are
described in this International Standard as unspecified. ..."
I'd say off hand that, given the rules on 'volatile', the presence (and,
if present, the nature) of any volatile memory qualifies as one of the
unspecified aspects of the abstract machine.
> this requirement means that the implementation is not allowed to
> arbitrarily modify the value of variables, even if those variables
> were declared volatile.
Why does this argument apply to user-defined objects of volatile
qualified type, but not to objects in volatile memory? I don't se
anything in that section which makes that distinction.
...
> The wording in the C 99 standard (6.7.3/6) is much clearer about this
> point:
>
> | 6.7.3 Type qualifiers
> | [#6] An object that has volatile-qualified type may be
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> | modified in ways unknown to the implementation or have other
> | unknown side effects. Therefore any expression referring to
> | such an object shall be evaluated strictly according to the
> | rules of the abstract machine, as described in 5.1.2.3.
> | Furthermore, at every sequence point the value last stored
> | in the object shall agree with that prescribed by the
> | abstract machine, except as modified by the unknown factors
> | mentioned previously. [...]
So why do you believe that the 'except' clause apply only to objects in
volatile memory, and not to user-defined objects of volatile-qualified
type? That distinction doesn't seem to be supported by this clause. To
be more precise, the whole clause seems specific to objects of
volatile-qualified type, regardless of whether or not they're stored in
volatile memory.
> >The C++ standard allows unpredictable reads, and writes
> >with side effects, only by way of cross-referencing the C standard - I
> >couldn't find comparable words in the C++ standard itself. The relevant
> >quote from the C standard referred only to an "object that has
> >volatile-qualified type"; as I read it, that wording means that it's the
> >qualification that provides those special features, not the object's
> >physical location.
>
> The special feature being discussed there is that the implementation
> is not allowed to optimize accesses to such variables. And that
> feature is certainly provided by the qualifier, not the physical
> location. Nevertheless, for the C standard, just as for the C++
> standard, the distinction between volatile memory and volatile objects
> is a useful one, and one which is necessitated by the requirements of
> the standard. The distinction between volatile memory and volatile
> objects is not made explicitly in the C standard, but again the
> requirements of the standard amount to the same thing.
I don't see how.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Michiel Salters <salters@lucent.com>
Date: Tue, 12 Sep 2000 15:32:21 GMT Raw View
thp@roam-thp2.cs.ucr.edu wrote:
>
> Fergus Henderson <fjh@cs.mu.oz.au> wrote:
> > No, it does behave differently, because reads and writes to volatile
> > data are part of the program's observable behaviour.
> C89 6.5.3 contains the following:
> What constitutes an access to an object that has volatile-qualified
> type is implemetation defined. [C89 6.5.3]
> I interpret that to mean that the implementation gets to say which
> reads and write of volatile objects are externally observable. If so,
> it would be reasonable for an implementation to treat as unobservable
> all volatile variables that are not allocated to volatile memory and
> not accessed by other threads of execution (including signal handlers
> and segments between a longjmp and its corresponding setjmp). In full
> conformity, such an implementation could generate the same optimized
> code for the cited example regardless of whether i is volatile.
> Tom Payne
I don't think you get away that easy. The implementation must define -
on paper, before seeing the rest of my program - what parts of the
following function constitutes an access to an object:
void f(volatile int& i) {
i;
i=1;
std::cout << i;
i++;
}
It can't let it's documentation depend on whether it's called from
void g() {
volatile int not_really;
f(not_really);
}
or
void h() {
volatile int* really_ptr = OS::GetIOPort(7);
f(*really_ptr);
}
I think the same documentation that covers f must also cover the
example you're referring to.
Michiel Salters
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 12 Sep 2000 16:18:44 GMT Raw View
James Kuyper <kuyper@wizard.net> writes:
>Fergus Henderson wrote:
>...
>> (1) "simply declaring a variable to be volatile does NOT give the
>> implementation permission to store that variable in volatile memory."
>>
>> This is mandated by section 1.9 [intro.execution] of the C++
>> standard.
>>
>> | 1.9 - Program execution [intro.execution]
>> ...
>> | -1- [...] conforming implementations are required to emulate [...]
>> | the observable behavior of the abstract machine
>>
>> Since the abstract machine does not include any volatile memory
>> (real time clocks, memory-mapped I/O, concurrent processes, etc.),
>
>Why not? [...]
Well, this is implied by the definition of "storage".
Also for auto variables, because of 1.9p10:
| 1.9 - Program execution [intro.execution]
[...]
| -10- An instance of each object with automatic storage duration
| (basic.stc.auto) is associated with each entry into its block. Such an
| object exists and retains its last-stored value during the execution
| of the block and while the block is suspended (by a call of a function
| or receipt of a signal).
And in general, you can't read the standard as allowing the
implementation to perform arbitrary actions not mentioned by the
standard. If the standard says that executing one piece of code
causes the value 42 to be stored in a variable, and then the
next piece of code reads the value of that variable, you have
to assume that the value is still 42 unless otherwise stated.
The standard defines the semantics of an abstract machine,
and in such definitions the reader must always assume that
the machine performs only the actions specified by the definition.
If we assume arbitrary actions can be performed at any time,
it would be impossible to make sense of any such definition.
>I'd say off hand that, given the rules on 'volatile', the presence (and,
>if present, the nature) of any volatile memory qualifies as one of the
>unspecified aspects of the abstract machine.
Given which rules on `volatile'?
As far as I can see, none of the rules on volatile allow the
implementation to poke arbitrary values in volatile variables at
arbitrary times, any more than the rules allow the implementation to
poke arbitrary values in non-volatile variables at arbitrary times.
If your argument is just that this is allowed simply because there is
no rule that excludes it, then my counter-argument is that (a) the
same applies to non-volatile variables and (b) this interpretation is
nonsensical since it leads to internal contradictions and makes the
whole standard useless.
If you mean 6.7.3 in the C standard (see below),
that is clearly a statement about implementation conformance,
not part of the definition of the abstract machine.
Since it twice refers to semantics of the abstract machine,
you can't interpret it as being part of the definition of the
abstract machine without rendering that definition circular.
>> this requirement means that the implementation is not allowed to
>> arbitrarily modify the value of variables, even if those variables
>> were declared volatile.
>
>Why does this argument apply to user-defined objects of volatile
>qualified type, but not to objects in volatile memory? I don't se
>anything in that section which makes that distinction.
The C++ abstract machine doesn't provide any way to create volatile
memory (see above), or to place variables in it. So in order to place
a variable in volatile memory, the user must have requested that via
some facility not specified in the C++ standard. This means that all
bets are off. The C++ standard does not and cannot give any guarantees
about the behaviour if you make use of facilities that are not defined
by the standard.
(However, if the implementation claims to conform to the C++ standard,
and the documentation of the implementation-specific facility does
not make it clear that the use of that facility invalidates guarantees
provided by the C++ standard, then it is reasonable to assume that it
does not, and to file a bug report if it does.)
>...
>> The wording in the C 99 standard (6.7.3/6) is much clearer about this
>> point:
>>
>> | 6.7.3 Type qualifiers
>> | [#6] An object that has volatile-qualified type may be
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> | modified in ways unknown to the implementation or have other
>> | unknown side effects. Therefore any expression referring to
>> | such an object shall be evaluated strictly according to the
>> | rules of the abstract machine, as described in 5.1.2.3.
>> | Furthermore, at every sequence point the value last stored
>> | in the object shall agree with that prescribed by the
>> | abstract machine, except as modified by the unknown factors
>> | mentioned previously. [...]
>
>So why do you believe that the 'except' clause apply only to objects in
>volatile memory,
What I mean by "volatile memory" is memory that is modified in ways
other than by the abstract machine. So the reason that the
"except" clause here applies only to objects in volatile memory
is simply by definition: if the "except" clause is needed, then I
define the memory to be volatile.
>and not to user-defined objects of volatile-qualified
>type?
The except clause *does* apply to all user-defined objects of
volatile-qualified type, but unless those objects are
mapped to volatile memory, there won't be any unknown
factors, and so the sense in which it applies is vacuous.
>That distinction doesn't seem to be supported by this clause. To
>be more precise, the whole clause seems specific to objects of
>volatile-qualified type, regardless of whether or not they're stored in
>volatile memory.
The whole clause does apply to objects of volatile-qualified type.
But stating that they can "be modified in ways unknown to the
implementation or have other unknown side effects" does not mean that
the implementation is allowed to modify them arbitrarily.
If you were to interpret that paragraph as allowing the implementation
to modify volatile-qualified objects arbitrarily, then the part
| Therefore any expression referring to
| such an object shall be evaluated strictly according to the
| rules of the abstract machine, as described in 5.1.2.3.
would not make any sense (particularly the word "therefore").
So such an interpretation is internally inconsistent.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Tue, 12 Sep 2000 16:50:29 GMT Raw View
Michiel Salters <salters@lucent.com> wrote:
> thp@roam-thp2.cs.ucr.edu wrote:
>>
>> Fergus Henderson <fjh@cs.mu.oz.au> wrote:
>> > No, it does behave differently, because reads and writes to volatile
>> > data are part of the program's observable behaviour.
>
>> C89 6.5.3 contains the following:
>
>> What constitutes an access to an object that has volatile-qualified
>> type is implemetation defined. [C89 6.5.3]
>
>> I interpret that to mean that the implementation gets to say which
>> reads and write of volatile objects are externally observable. If so,
>> it would be reasonable for an implementation to treat as unobservable
>> all volatile variables that are not allocated to volatile memory and
>> not accessed by other threads of execution (including signal handlers
>> and segments between a longjmp and its corresponding setjmp). In full
>> conformity, such an implementation could generate the same optimized
>> code for the cited example regardless of whether i is volatile.
> I don't think you get away that easy. The implementation must define -
> on paper, before seeing the rest of my program - what parts of the
> following function constitutes an access to an object:
> void f(volatile int& i) {
> i;
> i=1;
> std::cout << i;
> i++;
> }
> It can't let it's documentation depend on whether it's called from
> void g() {
> volatile int not_really;
> f(not_really);
> }
> or
> void h() {
> volatile int* really_ptr = OS::GetIOPort(7);
> f(*really_ptr);
> }
Agreed.
> I think the same documentation that covers f must also cover the
> example you're referring to.
Agreed. But that documentation gets to (or perhaps has to) say
whether reads and/or writes to a particular IO port are "observable."
For example, it would be reasonable to specify that writes to output
ports are observable while writes to input ports are not. Both,
however, are volatile. That documentation can also specify that reads
and writes to volatiles allocated in ordinary (non-volatile) memory
are NOT observable. I would consider that the "normal" case.
Fergus has argued (and I agree) that in the absence of implementation-
specific extensions, volatile variables are allocated in ordinary
memory. In implementations that follow the normal pattern, where
ordinary memory is not observable, I claim that a conforming
implemenation could generate fully optimized code for the example
we're discussing, e.g., it could read i into a register and never
update i's home location.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Tue, 12 Sep 2000 16:57:12 GMT Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <8pbsp2$157b$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
> writes
>>Simply adding the qualifier "volatile" to a declaration in a portable
>>program should not (allow conforming implementations to) change the
>>program's behavior. A program can introduce non-persistent objects only
>>via implementation-specific extensions to the Standard(s), and the
>>Standard(s) requires that such objects be accessed only via volatile
>>lvalues.
> That is not true. You can overload on volatile. That may be an awful
> design decision but it is the case.
You are absolutely correct. When thinking about volatility, I tend to
focus on C progams, since the C++ standard explicitly attempts to
incorporate the C semantics for "volatile".
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Tue, 12 Sep 2000 20:09:50 GMT Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> writes:
|> In article <86r96t7bpe.fsf@gabi-soft.de>, kanze@gabi-soft.de writes
|> >This is no simple condition. Suppose I have a debugger, which allow=
s=20
|> >stopping the program and examining and modifying the variables.
|> Exactly, and a program that uses volatile qualified variables must
|> behave 'correctly' in such an environment and how is the compiler to
|> know?
Must it? I'm not sure. I certainly can find nothing in the standard
that guarantees this. (There is language, at least in the C standard,
which would imply that this is the intention.) =20
There is too much that it "implementation defined". In the end, if
volatile is present, the compiler must ensure that the volatile accesses
occur in the correct order. But the implementation gets to define what
constitutes an access, and unless it documents that an access results in
something that can be read by a debugger, and that it takes into account
modifications by the debugger, I don't see where it is required to
support this.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Sun, 10 Sep 2000 00:27:32 GMT Raw View
In article <8pbq85$13s6$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
writes
>Your use of "volatile" does not suspend the as-if rule, so the compiler
>IS indeed allowed to ignore your use of "volatile" as long as the
>resulting program behaved as if the more conservative code had been
>generated. In the example above, my use of "volatile" does not allow or
>require the program to behave in any way different from how it would
>behave otherwise (i.e., if "volatile" weren't there).
The compiler is required to compile code that will 'work' even if the
values stored is changed externally. There is no way that it can know
that this will not happen (the program might be a child process with the
owner making the change). Just as compilers are supposed to trust me
when I use a cast, they are supposed to believe me when I warn them that
the value stored maybe changed externally. Anything else results in
madness, because how else am I supposed to tell the compiler that it
must generate code that exactly models the abstract machine, where
storage is always read when values are required.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Sun, 10 Sep 2000 00:27:25 GMT Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> writes:
|> In article <8pb25e$gpl$1@mortar.ucr.edu>, thp@roam-thp2.cs.ucr.edu
|> writes
|> >Consider the program
|> > int main(){
|> > volatile int i;
|> > for( i =3D 1; i < 10; ++i ) cout << i;
|> > }
|> >The compiler knows perfectly well that i is NOT going to
|> >spontaneously change in value, because the compiler knows that it
|> >is allocating i to nonvolatile memory and that the program isn't
|> >multithreaded and that i isn't accessed by a signal handler or
|> >involved in a longjmp, etc.
|> >I believe that the "volatile" qualifier on the declaration of i
|> >tells the compiler: "I have reason to doubt the persistence of i
|> >and/or the unobservability of accesses to i that you might
|> >otherwise count on in generating code, so, unless you know
|> >otherwise, generate very conservative code."
|> Of course you are entitled to believe this, I just think you are
|> mistaken and that a compiler that ignored my use of volatile would
|> be non-conforming.
But how can you show that it isn't conforming.
The idea occurs to me that the key difference is linked with what is
necessary to show non-conformance. For a non-volatile, it is necessary
that the non-conformance be observable from a conforming program. For a
volatile object, the standard supposes that the object itself is
observable and modifiable, independantly of the program.
Given this, I will agree with thp: *if* the compiler can prove that the
volatile is in fact vacuous, and that the variable cannot be modified
other than as specified by the program, it can ignore the volatile. On
the simple grounds that there is no way you can possibly tell that it
has ignored it.
This is no simple condition. Suppose I have a debugger, which allows
stopping the program and examining and modifying the variables.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Sun, 10 Sep 2000 16:10:13 GMT Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
|> kanze@gabi-soft.de writes:
|> >David R Tribble <david@tribble.com> writes:
|> >|> Andreas Unterkircher wrote:
|> >|> > So one can never be sure how a specific compiler interprets
|> >|> > volatile and thus one must not write programs depending on
|> >|> > volatile. Is this true ?
|> >|> No. You can write portable code that relies on the guaranteed
|> >|> behavior of 'volatile' objects. The behavior should be no worse
|> >|> than generated code that is not optimized at all.
|> >The "behavior" of a volatile object is not defined in the standard
|> >at all, other than to say that it is observable.
|> Sure it is. The behaviour of a volatile int object is defined in
|> all of the places that define the semantics of int, the semantics of
|> objects, and also in those few places which define the semantics of
|> volatile (e.g. in connection with sig_atomic_t/signal() and
|> setjmp()/longjmp()). This is just the same as the way that the
|> behaviour of a const int object is defined in the various places
|> that define the semantics of ints, the semantics of objects, and the
|> semantics of const.
OK. So I know that I can use + on a volatile int, just as I can on an
int. I should have been more precise: the behavior of *volatile* is,
for the most part, implementation defined. What sets the behavior of a
volatile int apart from that of a normal int is basically, that reading
and writing to it (accessing it) are "observable behavior". However,
what accessing an object actually means is implementation defined.
|> >How can you write portable code in which the behavior is not defined=
?
|> int main() {
|> volatile int x =3D 0;
|> return x;
|> }
|> This is portable code, and the standard guarantees that it will
|> return zero. Just the same as it does if `volatile' were replaced
|> with `const'. The mere fact that something is declared volatile
|> does not suddenly revoke all the other provisions of the standard.
Yes and no. Part of the expressed intent of volatile is that the
variable may change value behind the compilers back. I can't see how
this can happen for a non static local variable, but in theory... If
the value of x changes between the initialization and the return
statement, the *intent* of the standard is that the return value reflect
the changed value.
Of course, how the variable might change is implementation defined; for
a given hardware, for example, and in the absense of threads or anything
similar, could the compiler generate code here that does no more than a
"return 0"? It all depends on how the implementation defines "access",
I suppose.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Sun, 10 Sep 2000 16:12:15 GMT Raw View
<thp@roam-thp2.cs.ucr.edu> writes:
|> An object is (really) volatile if and only if
|> * its value ever changes without the execution of an instruction
|> that modifies it or
|> * accesses to it are (specified by the implementation to be)
|> "observable behavior".
|> Non-volatile objects are persistent and accesses to them are
|> stealthy (i.e., not visible outside the program), so redundant
|> and/or useless accesses to them can be as-if'd away.
I think that the important point is that whether an object is volatile
or not is a fact in some way exterior to the program. We declare an
object volatile to inform the compiler of something that it cannot
otherwise know. (And lying to the compiler doesn't pay.) Practically
speaking, anytime there is something that concerns the variable that we
cannot tell the compiler otherwise, we use volatile.
In a course, I think I'd start with the example of memory mapped
real-time clock, which reads seconds from midnight, and to which writes
are simply no-ops. From a practical point of view, I think volatile is
easier to understand from concrete examples of what it is meant to do.
But of course, I would -- I never really studied computer science as
such, and started in a the field in real-time, were memory mapped
registers were my daily bread.
|> If a program fails to declare really volatile objects as volatile,
|> it is apt to invoke undefined behavior. The same holds for objects
|> that are "pseudo-volatile" in the sense that they are asynchronously
|> accessed by signal handlers and/or multiple threads of execution.
Right. The key is that the volatility is in some way an "external
requirement". It is not something that I decide according to how I want
to use the value (as is the case with const).
|> If an implementation fails to treat appropriately objects that have
|> been declared volatile, that implementation fails to conform.
With the caveat that in this case, "appropriately" means "as described
in the documentation of the implementation". With the exception of
setjmp/longjmp and signal, I think an implementation could define
volatile as meaningless, and still be conform.
|> The
|> same holds if the implementation allocates variables that have not
|> been declared volatile to objects that are volatile or pseudo-volatil=
e
|> in reality.
That's a bit delicate. In practice, an implementation will allocate all
variables somewhere in memory, unless specifically told otherwise. If
an implementation maps a global variable to a memory mapped register, it
is normally only because the programmer told it to. If the programmer
also forgot to declare the variable volatile, is that the fault of the
implementation, or of the programmer?
And of course, once multiple threads come into play, how is the
implementation to even know?
|> The standards imply (and should specify) that read operations on any
|> object must obtain a value that is no less recent than that
|> operation's preceding sequence point.
It neither implies nor can specify that. Sequence points concern the
syntax of the source program, and *not* the sequence of execution. They
do not exist during execution, only in the source.
What the standard can, and does specify, is that the partial ordering
implied by sequence points will be respected with regards to observable
behavior -- that is: if X and Y are two operations that have observable
behavior, and if there is a sequence point in the source code which
orders X and Y, then the observable behavior associated with X will
precede that associated with Y.
All that is guaranteed is a (partial) ordering of observable behavior.
The difference is subtle, but without it, the presence of volatile
variables would invalidate the as if rule.
|> For non-volatile objects, the as-if rule allows a lot of shortcuts,
|> e.g., using a value that was left in registers prior to that
|> sequence point. However, because the value of a volatile object
|> might spontaneously change at any time and because reading a
|> volatile object might be observable behavior, reads of the volatile
|> objects are difficult or impossible to as-if away.
|> The standards also specify that any object modified by an operation
|> must have its new value before any sequence point following that
|> operation occurs. But storing to a volatile object might be
|> observable, so there is less lattitude for as-if'ing such modifying
|> operations away (or to a later time).
The store can be deffered as long as no other observable behavior
occurs.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Sun, 10 Sep 2000 19:39:29 GMT Raw View
In article <86r96t7bpe.fsf@gabi-soft.de>, kanze@gabi-soft.de writes
>This is no simple condition. Suppose I have a debugger, which allows
>stopping the program and examining and modifying the variables.
Exactly, and a program that uses volatile qualified variables must
behave 'correctly' in such an environment and how is the compiler to
know?
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Mon, 11 Sep 2000 12:59:11 GMT Raw View
James Kuyper <kuyper@wizard.net> writes:
>Fergus Henderson wrote:
>>
>> James Kuyper <kuyper@wizard.net> writes:
>...
>> >The model I've always used for thinking about
>> >volatile memory is a memory-mapped device that can, at arbitrary times,
>> >change the value stored in a piece of volatile memory, and the behavior
>> >of which is controlled by writes to volatile memory.
>>
>> That's a fine model for volatile _memory_. But objects declared volatile
>> need not be stored in volatile memory. Indeed, as I interpret the standard,
>> simply declaring a variable to be volatile does NOT give the implementation
>> permission to store that variable in volatile memory. The implementation
>> must treat volatile objects as if they were stored in volatile memory,
>> but it must not actually put them in volatile memory.
>
>That sounds reasonable. Where in the standard does it make such a
>distinction?
Well, the standard does not describe it in that way.
But the semantics that it specifies amount to the same thing,
or at least are *intended* to amount to the same thing --
I agree that the wording could and should be improved.
In particular, here's where the C++ standard mandates
the two parts of my claim:
(1) "simply declaring a variable to be volatile does NOT give the
implementation permission to store that variable in volatile memory."
This is mandated by section 1.9 [intro.execution] of the C++
standard.
| 1.9 - Program execution [intro.execution]
...
| -1- [...] conforming implementations are required to emulate [...]
| the observable behavior of the abstract machine
Since the abstract machine does not include any volatile memory
(real time clocks, memory-mapped I/O, concurrent processes, etc.),
this requirement means that the implementation is not allowed to
arbitrarily modify the value of variables, even if those variables
were declared volatile.
(2) Users are permitted to modify the value of volatile objects
in ways that are not detectable by the implementation, e.g. by
storing them in volatile memory.
The C++ standard says the following:
...
| -6- The observable behavior of the abstract machine is its sequence of
| reads and writes to volatile data and calls to library I/O functions.
...
| -11- The least requirements on a conforming implementation are:
| * At sequence points, volatile objects are stable in the sense that
| previous evaluations are complete and subsequent evaluations have
| not yet occurred.
| [...]
The fact that reads and writes to volatile objects are included in the
observable behaviour, and are required to have been performed at the
relevant sequence points, is, I believe, intended to prevent
implementations from performing any optimizations which would fail if
the volatile objects were stored in volatile memory, and conversely to
permit users to modify the values of such variables in ways that are
undetectable by the implementation. This is clear from the note in
7.1.5.1/8:
| 7.1.5.1 - The cv-qualifiers [dcl.type.cv]
...
| -8- [Note: volatile is a hint to the implementation to avoid
| aggressive optimization involving the object because the value of the
| object might be changed by means undetectable by an implementation.
| See intro.execution for detailed semantics. In general, the semantics
| of volatile are intended to be the same in C++ as they are in C. ]
However, I'm not sure if the wording in intro.execution is really
sufficient to provide the semantics intended. In particular, although
implementations must produce the same sequence of reads and writes
to volatile objects as in the abstract machine, I'm not sure whether the
wording forbids the implementation from assuming that those reads will
always read the value previously written. The wording here could
certainly be improved.
The wording in the C 99 standard (6.7.3/6) is much clearer about this
point:
| 6.7.3 Type qualifiers
| [#6] An object that has volatile-qualified type may be
| modified in ways unknown to the implementation or have other
| unknown side effects. Therefore any expression referring to
| such an object shall be evaluated strictly according to the
| rules of the abstract machine, as described in 5.1.2.3.
| Furthermore, at every sequence point the value last stored
| in the object shall agree with that prescribed by the
| abstract machine, except as modified by the unknown factors
| mentioned previously. [...]
>The C++ standard allows unpredictable reads, and writes
>with side effects, only by way of cross-referencing the C standard - I
>couldn't find comparable words in the C++ standard itself. The relevant
>quote from the C standard referred only to an "object that has
>volatile-qualified type"; as I read it, that wording means that it's the
>qualification that provides those special features, not the object's
>physical location.
The special feature being discussed there is that the implementation
is not allowed to optimize accesses to such variables. And that
feature is certainly provided by the qualifier, not the physical
location. Nevertheless, for the C standard, just as for the C++
standard, the distinction between volatile memory and volatile objects
is a useful one, and one which is necessitated by the requirements of
the standard. The distinction between volatile memory and volatile
objects is not made explicitly in the C standard, but again the
requirements of the standard amount to the same thing.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Mon, 11 Sep 2000 12:59:14 GMT Raw View
kanze@gabi-soft.de writes:
>fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
>
>|> >Getting back to 'volatile', 7.1.5.1p8 contains a Note which says
>|> >that "... the value of the [volatile] object might be changed by
>|> >means undetectable by an implementation ...
>
>|> This text is giving the user permission to modify the object in ways
>|> that the implementation can't detect. IMHO it is definitely NOT
>|> giving the implementation permission to arbitrarily modify the
>|> object.
>
>In the C standard, it was the definite intention that a volatile
>variable could be mapped to a real time clock -- the compiler was
>supposed to read it each access, because it could have changed since the
>last access.
Right. But that mapping can only be done if the user requests it.
>If the variable is mapped to a real time clock, is the arbitrary change
>the user who is changing it, or the implementation (given, of course,
>that the user requested the mapping).
So long as such things are only done if the user requests them,
I don't think it matters.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Mon, 11 Sep 2000 18:05:58 GMT Raw View
<thp@roam-thp2.cs.ucr.edu> writes:
>Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
>> I just think you are
>> mistaken and that a compiler that ignored my use of volatile would be
>> non-conforming.
>
>Your use of "volatile" does not suspend the as-if rule, so the
>compiler IS indeed allowed to ignore your use of "volatile" as long as
>the resulting program behaved as if the more conservative code had
>been generated.
The "as-if" rule is stated in the standard in a way which explicitly
excludes optimization of reads and writes to volatile objects.
In particular:
| 1.9 - Program execution [intro.execution]
|
| -1- The semantic descriptions in this International Standard define a
| parameterized nondeterministic abstract machine. This International
| Standard places no requirement on the structure of conforming
| implementations. In particular, they need not copy or emulate the
| structure of the abstract machine. Rather, conforming implementations
| are required to emulate (only) the observable behavior of the abstract
| machine as explained below.*
|
| [Footnote: This provision is sometimes called the ``as-if'' rule,
...
| -6- The observable behavior of the abstract machine is its sequence of
| reads and writes to volatile data and calls to library I/O functions.
>In the example above, my use of "volatile" does not
>allow or require the program to behave in any way different from how
>it would behave otherwise (i.e., if "volatile" weren't there).
No, it does behave differently, because reads and writes to volatile
data are part of the program's observable behaviour.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 5 Sep 2000 17:41:50 GMT Raw View
kanze@gabi-soft.de writes:
>David R Tribble <david@tribble.com> writes:
>
>|> Andreas Unterkircher wrote:
>|> > So one can never be sure how a specific compiler interprets
>|> > volatile and thus one must not write programs depending on
>|> > volatile. Is this true ?
>
>|> No. You can write portable code that relies on the guaranteed
>|> behavior of 'volatile' objects. The behavior should be no worse
>|> than generated code that is not optimized at all.
>
>The "behavior" of a volatile object is not defined in the standard at
>all, other than to say that it is observable.
Sure it is. The behaviour of a volatile int object is defined in all
of the places that define the semantics of int, the semantics of
objects, and also in those few places which define the semantics of
volatile (e.g. in connection with sig_atomic_t/signal() and
setjmp()/longjmp()). This is just the same as the way that the
behaviour of a const int object is defined in the various places that
define the semantics of ints, the semantics of objects, and the
semantics of const.
>How can you write portable code in which the behavior is not defined?
int main() {
volatile int x = 0;
return x;
}
This is portable code, and the standard guarantees that it will return zero.
Just the same as it does if `volatile' were replaced with `const'.
The mere fact that something is declared volatile does not suddenly
revoke all the other provisions of the standard.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Tue, 5 Sep 2000 17:42:11 GMT Raw View
James Kuyper <kuyper@wizard.net> writes:
|> Still, by comparison with "register" (or even "inline"), "volatile"
|> is a lot more than just a hint.
Agreed, but not enough more that one can count on it in portable code
(except with regards to signals and setjmp/longjmp).
Practically, this isn't a problem, because the set of problems volatile
was designed to solve require non-portable extensions (threads, memory
mapped IO) anyway. But I've always considered that the difference
between this group and comp.lang.c++.moderated is that here was the
place for pedantism:-).
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Tue, 5 Sep 2000 18:12:32 GMT Raw View
In article <8p0qnt$gjk$1@mulga.cs.mu.OZ.AU>, Fergus Henderson
<fjh@cs.mu.OZ.AU> writes
> int main() {
> volatile int x = 0;
> return x;
> }
>
>This is portable code, and the standard guarantees that it will return
>zero. Just the same as it does if `volatile' were replaced with `const'.
I have to say that this claim surprises me. Of course in a program this
simple you are probably right, but only because there is nothing in this
program that would lead me to suppose that the storage for x could be
accessed from outside the program. However, suppose that we are in some
odd multitasking system with shared memory...
>The mere fact that something is declared volatile does not suddenly
>revoke all the other provisions of the standard.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: Wed, 6 Sep 2000 01:43:31 GMT Raw View
Fergus Henderson wrote:
>
> kanze@gabi-soft.de writes:
> >How can you write portable code in which the behavior is not defined?
>
> int main() {
> volatile int x = 0;
> return x;
> }
>
> This is portable code, and the standard guarantees that it will return zero.
Even if 'x' weren't volatile, all that would be guaranteed for such code
is that the program returns "... an implementation-defined form of the
status _successful termination_ ...". (18.3p8) That doesn't have to be
0; it doesn't even have to be a number - there are real systems where it
can't be a number. It could be indicated by setting the carry flag, or
some other similarly arcane method.
Getting back to 'volatile', 7.1.5.1p8 contains a Note which says that
"... the value of the [volatile] object might be changed by means
undetectable by an implementation ... In general, the semantics of
volatile are intended to be the same in C++ as they are in C".
However, I can't find normative text specifying those semantics. The C
standard says in 6.7.3p6 that "An object that has volatile-qualified
type may be modified in ways unknown to the implementation or have other
unknown side effects." I can't find comparable words in the C++
standard, but that Note at least indicates that something similar was
intended to apply in C++.
Therefore, setting x to '0' might have "unknown side effects", a phrase
vague enough to cover just about anything. Secondly, by the time main()
returns, 'x' might have been modified to any valid 'int' value by causes
outside the scope of the program itself. There are only three values
that have standard-defined results when returned by main(): 0,
EXIT_SUCCESS, and EXIT_FAILURE (EXIT_SUCCESS might be the same as 0,
though that's not guaranteed). If 'x' happens to be any other value,
"... the status returned is implementation-defined ..." (18.3p8, again).
Even if does happen to be one of those three, there's no guarantee about
which one.
> Just the same as it does if `volatile' were replaced with `const'.
> The mere fact that something is declared volatile does not suddenly
> revoke all the other provisions of the standard.
The fact that "volatile" objects can be modified at any time, and have
arbitrary side effects when set by the program, changes the meaning of a
very large fraction of the standard.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Wed, 6 Sep 2000 15:43:41 GMT Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> writes:
>Fergus Henderson <fjh@cs.mu.OZ.AU> writes
>> int main() {
>> volatile int x = 0;
>> return x;
>> }
>>
>>This is portable code, and the standard guarantees that it will return
>>zero. Just the same as it does if `volatile' were replaced with `const'.
>
>I have to say that this claim surprises me. Of course in a program this
>simple you are probably right, but only because there is nothing in this
>program that would lead me to suppose that the storage for x could be
>accessed from outside the program. However, suppose that we are in some
>odd multitasking system with shared memory...
The C standard does not define any facilities for multitasking or
shared memory, so the behaviour of any such facilities that an
implementation happens to provide must certainly be undefined from
the point of view of the C standard. But the blame must go to the
use of those implementation-specific facilities, not to `volatile'.
Of course if you do use implementation-specific facilities, the
implementation (or some other standard) is free to define the
behaviour in that case. For example, the POSIX standard defines
functions for multithreading. If you use `volatile' appropriately
in a program that makes use of POSIX threads, then the behaviour
will be defined by the appropriate POSIX standards.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Mark Williams <markw65@my-deja.com>
Date: Wed, 6 Sep 2000 17:35:48 GMT Raw View
In article <39B59FEB.922D4A41@wizard.net>,
James Kuyper <kuyper@wizard.net> wrote:
> Fergus Henderson wrote:
> >
> > kanze@gabi-soft.de writes:
> > >How can you write portable code in which the behavior is not
defined?
> >
> > int main() {
> > volatile int x = 0;
> > return x;
> > }
> >
> > This is portable code, and the standard guarantees that it will
return zero.
>
> Even if 'x' weren't volatile, all that would be guaranteed for such
code
> is that the program returns "... an implementation-defined form of the
> status _successful termination_ ...". (18.3p8) That doesn't have to be
> 0; it doesn't even have to be a number - there are real systems where
it
> can't be a number. It could be indicated by setting the carry flag, or
> some other similarly arcane method.
>
> Getting back to 'volatile', 7.1.5.1p8 contains a Note which says that
> "... the value of the [volatile] object might be changed by means
> undetectable by an implementation ... In general, the semantics of
> volatile are intended to be the same in C++ as they are in C".
>
> However, I can't find normative text specifying those semantics. The C
> standard says in 6.7.3p6 that "An object that has volatile-qualified
> type may be modified in ways unknown to the implementation or have
other
> unknown side effects." I can't find comparable words in the C++
> standard, but that Note at least indicates that something similar was
> intended to apply in C++.
But 1.9 paragraph 10 says:
"An instance of each object with automatic storage duration (3.7.2) is
associated with each entry into its block. Such an object exists and
retains its last-stored value during the execution of the block and
while the block is suspended (by a call of a function or reciept of a
signal)."
So we have a non-normative paragraph which says the value could change,
and a normative one that says it cant. (Note that paragraphs 6, 7, 9 and
11 all relate to the semantics of volatile, so it seems unlikely that
failure to exclude volatile objects in paragraph 10 was accidental).
-------------
Mark Williams
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Wed, 6 Sep 2000 21:16:31 GMT Raw View
James Kuyper <kuyper@wizard.net> writes:
>Fergus Henderson wrote:
>>
>> kanze@gabi-soft.de writes:
>> >How can you write portable code in which the behavior is not defined?
>>
>> int main() {
>> volatile int x = 0;
>> return x;
>> }
>>
>> This is portable code, and the standard guarantees that it will return zero.
>
>Even if 'x' weren't volatile, all that would be guaranteed for such code
>is that the program returns "... an implementation-defined form of the
>status _successful termination_ ...".
By "it", I meant the function main(), not the program.
Probably it would have been clearer if I had named the function `foo'
rather than `main'.
>Getting back to 'volatile', 7.1.5.1p8 contains a Note which says that
>"... the value of the [volatile] object might be changed by means
>undetectable by an implementation ...
This text is giving the user permission to modify the object in ways
that the implementation can't detect. IMHO it is definitely NOT
giving the implementation permission to arbitrarily modify the object.
>However, I can't find normative text specifying those semantics. The C
>standard says in 6.7.3p6 that "An object that has volatile-qualified
>type may be modified in ways unknown to the implementation or have other
>unknown side effects."
Again, I read that as giving permission to the user, not to the
implementation.
The converse interpretation of that paragraph is clearly wrong-headed.
Firstly, it makes `volatile' much less useful. But more importantly,
it leads to an interpretation of the standard that is internally
inconsistent, since it would make `volatile' impossible to use in
strictly conforming programs, and yet would require the use of
`volatile' in certain situations involving setjmp() and sig_atomic_t.
If the authors of the C standard had intended to make the semantics of
`volatile' objects completely undefined, why would they bother
specifying all those details about the use of `volatile' in conjunction
with setjmp() and sig_atomic_t?
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: Thu, 7 Sep 2000 01:35:39 GMT Raw View
Fergus Henderson wrote:
>
> James Kuyper <kuyper@wizard.net> writes:
>
> >Fergus Henderson wrote:
> >>
> >> kanze@gabi-soft.de writes:
> >> >How can you write portable code in which the behavior is not defined?
> >>
> >> int main() {
> >> volatile int x = 0;
> >> return x;
> >> }
> >>
> >> This is portable code, and the standard guarantees that it will return zero.
> >
> >Even if 'x' weren't volatile, all that would be guaranteed for such code
> >is that the program returns "... an implementation-defined form of the
> >status _successful termination_ ...".
>
> By "it", I meant the function main(), not the program.
In C++, unlike C, you can't call main(); therefore there's no meaningful
sense in which it returns a value. Returning with a value from main() is
defined as equivalent to calling exit() with that value as an argument.
The standard defines the result of calling exit in terms of an
implementation-defined mapping between the value and exit status, not in
terms of a value returned by main().
> Probably it would have been clearer if I had named the function `foo'
> rather than `main'.
Yes, that would have avoided this side-issue. main() is a very special
"function".
> >Getting back to 'volatile', 7.1.5.1p8 contains a Note which says that
> >"... the value of the [volatile] object might be changed by means
> >undetectable by an implementation ...
>
> This text is giving the user permission to modify the object in ways
> that the implementation can't detect. IMHO it is definitely NOT
> giving the implementation permission to arbitrarily modify the object.
The standard doesn't specify what those means are. The example is given
of memory-mapped hardware. The model I've always used for thinking about
volatile memory is a memory-mapped device that can, at arbitrary times,
change the value stored in a piece of volatile memory, and the behavior
of which is controlled by writes to volatile memory.
> >However, I can't find normative text specifying those semantics. The C
> >standard says in 6.7.3p6 that "An object that has volatile-qualified
> >type may be modified in ways unknown to the implementation or have other
> >unknown side effects."
>
> Again, I read that as giving permission to the user, not to the
> implementation.
I'm unclear as to how a "user" could changed the value by means
undetectable by the implementation. The user of a C++ implementation
interacts with a C++ program entirely through the implementation; that's
what makes him or her the 'user'.
> The converse interpretation of that paragraph is clearly wrong-headed.
> Firstly, it makes `volatile' much less useful. But more importantly,
What makes it useful is that it allows memory-mapped hardware and memory
shared between processes, among other things. It is precisely because it
can be modified by an external source that you want a piece of memory to
be volatile - you read it because you want to know what value it was
modified to. It is precisely because storing a value in volatile memory
can have side effects that you want a piece of memory to be volatile -
you write to it because you want to cause the side effect. This is
extremely useful in the right context, though it's necessarily extremely
non-portable.
My career has involved almost entirely high-level programs that need to
be as portable as possible, and hence make no use whatsoever of
'volatile'. Therefore, the following paragraphs represent merely my own
guesses about how it might be used. I think that typical uses will
involve volatile-qualified pointers (and references?) more than
volatile-qualified objects. I suspect that implementations will either
document specific addresses that point to mapped memory, or provide
functions for returning pointers to such memory. Since your example
makes no use of such mechanisms, it's obviously safe from problems from
that source.
However, one feasible way of creating such a mapping is for all
statically and automatically allocated volatile objects to be allocated
out of a block of mappable memory. It would then be the user's
responsibility to communicate the addresses of volatile objects to the
other processes/devices that will uses those blocks to communicate with
the program. If the implementor documents the order in which that memory
is allocated, and where it's located, another program could predict in
advance, where 'x' was going to be allocated, and write to that location
between the time that 'x' was initialized by your code, and the time
that it returns from 'main'. The timing is so tight that such
interference is unlikely, but the possibility need not be 0, and would
increase as more lines of code are inserted between them.
> it leads to an interpretation of the standard that is internally
> inconsistent, since it would make `volatile' impossible to use in
> strictly conforming programs, and yet would require the use of
> `volatile' in certain situations involving setjmp() and sig_atomic_t.
The sequence point rules about 'volatile' essentially require that every
time the value of a volatile object is read, it is retrieved straight
from the source, rather than using a previously retrieved value
currently stored somewhere else. Every time a value is written to the
object, it must be written immediately, not deferred until later. This
is precisely what's needed to reliably use mapped memory; it's also
precisely what's needed to work with an object used to communicate
between an asynchronous signal handler and the rest of the program.
That's why 'volatile sig_atomic_t' has it's special properties.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Thu, 7 Sep 2000 08:27:27 GMT Raw View
Andreas Unterkircher <unterkir@ifu.bepr.ethz.ch> wrote:
> I would be interested in learning more about the meaning of the
> "volatile" specifier. There have been some discussions on the threads
> newsgroup concerning threaded programs working in debug mode but not when
> compiled with any optimization. After declaring some critical variables
> volatile the optimzed program versions worked. Reading the relevant
> sections of Kernighan/Ritchie and Stroustrup I conclude that "volatile" is
> just a hint for the compiler (like "register"). So one can never be sure
> how a specific compiler interprets volatile and thus one must not write
> programs depending on volatile. Is this true ?
> Any opinions are welcome !
So, here's yet another opinion, the one that I teach my students. (Comments
are appreciated.)
An object is (really) volatile if and only if
* its value ever changes without the execution of an instruction
that modifies it or
* accesses to it are (specified by the implementation to be)
"observable behavior".
Non-volatile objects are persistent and accesses to them are stealthy
(i.e., not visible outside the program), so redundant and/or useless
accesses to them can be as-if'd away.
If a program fails to declare really volatile objects as volatile, it
is apt to invoke undefined behavior. The same holds for objects that
are "pseudo-volatile" in the sense that they are asynchronously
accessed by signal handlers and/or multiple threads of execution.
If an implementation fails to treat appropriately objects that have
been declared volatile, that implementation fails to conform. The
same holds if the implementation allocates variables that have not
been declared volatile to objects that are volatile or pseudo-volatile
in reality.
The standards imply (and should specify) that read operations on any
object must obtain a value that is no less recent than that
operation's preceding sequence point. For non-volatile objects, the
as-if rule allows a lot of shortcuts, e.g., using a value that was
left in registers prior to that sequence point. However, because the
value of a volatile object might spontaneously change at any time and
because reading a volatile object might be observable behavior, reads
of the volatile objects are difficult or impossible to as-if away.
The standards also specify that any object modified by an operation
must have its new value before any sequence point following that
operation occurs. But storing to a volatile object might be
observable, so there is less lattitude for as-if'ing such modifying
operations away (or to a later time).
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Thu, 7 Sep 2000 17:02:22 GMT Raw View
Fergus Henderson <fjh@cs.mu.oz.au> wrote:
> James Kuyper <kuyper@wizard.net> writes:
[...]
>>Getting back to 'volatile', 7.1.5.1p8 contains a Note which says that
>>"... the value of the [volatile] object might be changed by means
>>undetectable by an implementation ...
> This text is giving the user permission to modify the object in ways
> that the implementation can't detect. IMHO it is definitely NOT
> giving the implementation permission to arbitrarily modify the object.
>>However, I can't find normative text specifying those semantics. The C
>>standard says in 6.7.3p6 that "An object that has volatile-qualified
>>type may be modified in ways unknown to the implementation or have other
>>unknown side effects."
> Again, I read that as giving permission to the user, not to the
> implementation.
> The converse interpretation of that paragraph is clearly wrong-headed.
> Firstly, it makes `volatile' much less useful. But more importantly,
> it leads to an interpretation of the standard that is internally
> inconsistent, since it would make `volatile' impossible to use in
> strictly conforming programs, and yet would require the use of
> `volatile' in certain situations involving setjmp() and sig_atomic_t.
Wow! I couldn't agree less.
According to C89 6.5.3:
... If an attempt is made to refer to an object defined with a
volatile-qualified type through use of an lvalue with non-volatile
qualified type, the behavior is undefined. [Footnote: "This applies
to those objects that behave as if they were defined with qualified
types, even if they are never actually defined as objects in the
program (such as an object at a memory mapped io address)."]
An object that has volatile-qualified type may be modified in ways
unknown to the implementation or have other unknown side effects.
Therefore any expression referring to such an object shall be
evaluated strictly according to the rules of the abstract machine,
as described in 5.1.2.3. Furthermore, at every sequence point the
value last stored in the object shall agree with that prescribed by
the abstract machine, except as modified by the unknown factors
mentioned previously. [Footnote: "A volatile declaration may be used
to describe an object corresponding to a memory-mapped input/output
port or an object accessed by an asynchronously interrupting function.
Actions on objects so declared shall not be "optimized out" by an
implementation or reordered except as permitted by rules for
evaluation expressions."] What constitutes an access to an object
that has volatile-qualified type is implementation defined.
According to C89 6.1.2.4:
An object whose identifier is declared with external or internal
linkage, or with the storage-class specifier static has static
storage duration. ... The object exists and retains its last-stored
value throughout the execution of the entire program. [Footnote:
"In the case of a volatile object, the last store may not be
explicit in the program."]
According to C89 3.9:
implementation: a particular set of software, running in a particular
translation environment under particular control options, that performs
translation of programs for, and supports execution of function in, a
particular execution environment.
Under any definition of "user" that I can think of, modifications of
the content of memory-mapped input ports are usually actions of the
"execution environment" rather than the "user."
> If the authors of the C standard had intended to make the semantics of
> `volatile' objects completely undefined, why would they bother
> specifying all those details about the use of `volatile' in conjunction
> with setjmp() and sig_atomic_t?
IMHO, the authors intended "volatile" to remove certain guarantees
that pertain to nonvolatile variables, namely the guarantees of:
* persistence (the property that a nonvolatile variable retains its
value unless it is explicitly modified by the program),
* stealth (the property that accesses to a nonvolatile variable are
not "observable").
Those two properties together with the as-if rule permit a lot of
optimizations that are not guaranteed to be "as if" in the case of
volatile variables. Treating certain variables as though they lack
persistence (and possibly atomic) is sufficient to guarantee that they
will have their expected values following a longjmp or modification by
a signal handler.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: Thu, 7 Sep 2000 17:20:39 GMT Raw View
James Kuyper <kuyper@wizard.net> wrote:
[...]
> The sequence point rules about 'volatile' essentially require that every
> time the value of a volatile object is read, it is retrieved straight
> from the source, rather than using a previously retrieved value
> currently stored somewhere else.
I agree, but I'm frustrated in my attempts to find words that say so,
even indirectly. Since the value of a volatile can be constantly
changing, it is impossible to require that the absolutely current
value gets used in any compuation. The best that can be required is
that the value that is used is more recent than the preceding sequence
point.
> Every time a value is written to the object, it must be written
> immediately, not deferred until later.
But the as-if rule remains in effect. So, for example, it the
implementation knows that write access to a particular volatile
variable is not implementation-specified to be "observable", then it
is possible in some cases to defer modifications of that variable past
the next sequence point, or even to eliminate them altogether at
points where the variable is dead. (But you knew that already.)
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Andreas Unterkircher <unterkir@ifu.bepr.ethz.ch>
Date: 2000/08/28 Raw View
I would be interested in learning more about the meaning of the
"volatile" specifier. There have been some discussions on the threads
newsgroup concerning threaded programs working in debug mode but not when
compiled with any optimization. After declaring some critical variables
volatile the optimzed program versions worked. Reading the relevant
sections of Kernighan/Ritchie and Stroustrup I conclude that "volatile" is
just a hint for the compiler (like "register"). So one can never be sure
how a specific compiler interprets volatile and thus one must not write
programs depending on volatile. Is this true ?
Any opinions are welcome !
Andreas
--
mailto: unterkir@ifu.bepr.ethz.ch
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Edward Diener <eddielee@abraxis.com>
Date: 2000/08/29 Raw View
Andreas Unterkircher wrote:
> I would be interested in learning more about the meaning of the
> "volatile" specifier. There have been some discussions on the threads
> newsgroup concerning threaded programs working in debug mode but not when
> compiled with any optimization. After declaring some critical variables
> volatile the optimzed program versions worked. Reading the relevant
> sections of Kernighan/Ritchie and Stroustrup I conclude that "volatile" is
> just a hint for the compiler (like "register").
No, "volatile" is not just a hint to the compiler like "register" is. It says
that this data can changed outside of the normal code the compiler generates
so the compiler must not cache away a value and assume it can treat that
cached value as the actual value of data, it must access the value of the data
directly each time.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 2000/08/29 Raw View
Andreas Unterkircher wrote:
>
> I would be interested in learning more about the meaning of the
> "volatile" specifier. There have been some discussions on the threads
> newsgroup concerning threaded programs working in debug mode but not when
> compiled with any optimization. After declaring some critical variables
> volatile the optimzed program versions worked. Reading the relevant
> sections of Kernighan/Ritchie and Stroustrup I conclude that "volatile" is
> just a hint for the compiler (like "register"). So one can never be sure
> how a specific compiler interprets volatile and thus one must not write
> programs depending on volatile. Is this true ?
No.
7.1.5.1p8 describes volatile as "... a hint to the implementation to
avoid aggressive optimization involving the object, because the value of
the object might be changed by means undetectable by an implementation."
A typical example is memory-mapped I/O; the memory might be changed by
the I/O device without any intervention by your own code.
However, 'volatile' is significantly more than just a hint. A register
variable is semantically identical to an automatic variable. In C, you
can't take the address of an register variable, but in C++ even that
distinction disappears. The entire meaning of 'register' is the hint it
provides to the implementation that the object it qualifies is heavily
used. 'volatile' means much more than just a hint. The standard make a
few very specific guarantees about volatile objects that it does not
make about non-volatile ones:
1.9p1: "... conforming implementations are required to emulate (only)
the observable behavior of the abstract machine ..."
1.9p6: "The observable behavior of the abstract machine is its sequence
of reads and writes to volatile data and calls to library I/O
functions."
1.9p7: "Accessing an object designated by a volatile lvalue [is a side
effect] ... At ... _sequence points_, all side effects of previous
evaluations shall be complete and no side effects of subsequent
evaluations shall have taken place."
1.9p9: "When processing of the abstract machine is interrupted by
receipt of a signal, the values of objects with type other than volatile
sig_atomic_t are unspecified, and the value of any object not of
volatile sig_atomic_t that is modified by the handler becomes
undefined."
1.9p11: "...
At sequence points, volatile objects are stable in the sense that
previous evaluations are complete and subsequent evaluations have not
yet occurred."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: 2000/08/30 Raw View
Edward Diener <eddielee@abraxis.com> writes:
|> Andreas Unterkircher wrote:
|> > I would be interested in learning more about the meaning of the
|> > "volatile" specifier. There have been some discussions on the
|> > threads newsgroup concerning threaded programs working in debug
|> > mode but not when compiled with any optimization. After declaring
|> > some critical variables volatile the optimzed program versions
|> > worked. Reading the relevant sections of Kernighan/Ritchie and
|> > Stroustrup I conclude that "volatile" is just a hint for the
|> > compiler (like "register").
|> No, "volatile" is not just a hint to the compiler like "register"
|> is. It says that this data can changed outside of the normal code
|> the compiler generates so the compiler must not cache away a value
|> and assume it can treat that cached value as the actual value of
|> data, it must access the value of the data directly each time.
Never the less, the exact semantics are implementation defined. It is
generally meant to be understood as a "hint" not to optimize. Accesses
to volatile variables are considered part of the observable behavior, to
be respected when optimizing, but exactly what comprises an "access" is
also implementation defined.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: Thu, 31 Aug 2000 16:02:46 GMT Raw View
kanze@gabi-soft.de wrote:
...
> Never the less, the exact semantics are implementation defined. It is
> generally meant to be understood as a "hint" not to optimize. Accesses
> to volatile variables are considered part of the observable behavior, to
> be respected when optimizing, but exactly what comprises an "access" is
> also implementation defined.
The standard defines observable behavior as including "reads and writes
to volatile data", not accesses to them.
There's more to 'volatile' than just the fact that accessing a volatile
object counts as a side-effect (with corresponding interactions with
sequence points). There is also the sequence point stability promise,
and the promise that volatile sig_atomic_t objects have defined values
during signal handling.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: Thu, 31 Aug 2000 17:37:41 GMT Raw View
kanze@gabi-soft.de wrote:
> ...
>> Never the less, the exact semantics are implementation defined.
>> It is generally meant to be understood as a "hint" not to optimize.
>> Accesses to volatile variables are considered part of the observable
>> behavior, to be respected when optimizing, but exactly what comprises
>> an "access" is also implementation defined.
James Kuyper wrote:
> The standard defines observable behavior as including "reads and
> writes to volatile data", not accesses to them.
>
> There's more to 'volatile' than just the fact that accessing a
> volatile object counts as a side-effect (with corresponding
> interactions with sequence points). There is also the sequence point
> stability promise, and the promise that volatile sig_atomic_t objects
> have defined values during signal handling.
Yes. In particular, the requirements on 'volatile' provides specific
guarantees about code such as the following:
volatile int v;
int i;
int j;
i = v; // [1]
j = v; // [2]
The rules guarantee that if the value of v changes between the two
assignments (presumably from some influence outside this particular
thread of execution), then the resulting values of i and j will be
different. In other words, the compiler must not assume that i and
j will contain the same value, because their values are derived from
separate reads of a volatile object.
Andreas Unterkircher wrote:
> So one can never be sure how a specific compiler interprets volatile
> and thus one must not write programs depending on volatile. Is this
> true ?
No. You can write portable code that relies on the guaranteed
behavior of 'volatile' objects. The behavior should be no worse than
generated code that is not optimized at all.
--
David R. Tribble, mailto:david@tribble.com, http://david.tribble.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Thu, 31 Aug 2000 21:02:47 GMT Raw View
David R Tribble <david@tribble.com> writes:
|> kanze@gabi-soft.de wrote:
|> > ...
|> >> Never the less, the exact semantics are implementation defined.
|> >> It is generally meant to be understood as a "hint" not to optimize.
|> >> Accesses to volatile variables are considered part of the observab=
le
|> >> behavior, to be respected when optimizing, but exactly what compri=
ses
|> >> an "access" is also implementation defined.
|> James Kuyper wrote:
|> > The standard defines observable behavior as including "reads and
|> > writes to volatile data", not accesses to them.
|> > There's more to 'volatile' than just the fact that accessing a
|> > volatile object counts as a side-effect (with corresponding
|> > interactions with sequence points). There is also the sequence poin=
t
|> > stability promise, and the promise that volatile sig_atomic_t objec=
ts
|> > have defined values during signal handling.
|> Yes. In particular, the requirements on 'volatile' provides specific
|> guarantees about code such as the following:
|> volatile int v;
|> int i;
|> int j;
|> i =3D v; // [1]
|> j =3D v; // [2]
|> The rules guarantee that if the value of v changes between the two
|> assignments (presumably from some influence outside this particular
|> thread of execution), then the resulting values of i and j will be
|> different. In other words, the compiler must not assume that i and
|> j will contain the same value, because their values are derived from
|> separate reads of a volatile object.
It also guarantees that there will be two reads to v. While leaving it
up to the implementation to define exactly what a read consists in. The
intent, of course, is clear : if v is a memory mapped IO port, then each
read could have a very noticeable effect.
In the case of memory mapped IO ports, or threads, for that matter, the
implementor has two choices, both conform. He can do what everyone
expects, and what the intent of the standard was, or he can ignore it,
and simply say that memory mapped IO ports and threads are not
supported, or are supported via other mechanisms than volatile. The
standard says nothing which would forbid the latter.
|> Andreas Unterkircher wrote:
|> > So one can never be sure how a specific compiler interprets
|> > volatile and thus one must not write programs depending on
|> > volatile. Is this true ?
|> No. You can write portable code that relies on the guaranteed
|> behavior of 'volatile' objects. The behavior should be no worse
|> than generated code that is not optimized at all.
The "behavior" of a volatile object is not defined in the standard at
all, other than to say that it is observable. How can you write
portable code in which the behavior is not defined?
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Fri, 1 Sep 2000 12:33:55 GMT Raw View
James Kuyper <kuyper@wizard.net> writes:
|> kanze@gabi-soft.de wrote:
|> ...
|> > Never the less, the exact semantics are implementation defined. It=
is
|> > generally meant to be understood as a "hint" not to optimize. Acce=
sses
|> > to volatile variables are considered part of the observable behavio=
r, to
|> > be respected when optimizing, but exactly what comprises an "access=
" is
|> > also implementation defined.
|> The standard defines observable behavior as including "reads and writ=
es
|> to volatile data", not accesses to them.
|> There's more to 'volatile' than just the fact that accessing a volati=
le
|> object counts as a side-effect (with corresponding interactions with
|> sequence points). There is also the sequence point stability promise,
|> and the promise that volatile sig_atomic_t objects have defined value=
s
|> during signal handling.
The sequence point stability really only concerns ordering, since there
is no way a conforming program can determine that a sequence point has
occured. And sig_atomic_t is a special case, and very limited. There
are one or two other guarantees as well with regards to setjmp/longjmp,
but on the whole, _most_ of the semantics of volatile are implementation
defined, although the standard makes it quite clear what the intent is.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: Fri, 1 Sep 2000 17:35:02 GMT Raw View
kanze@gabi-soft.de wrote:
>
> James Kuyper <kuyper@wizard.net> writes:
...
> |> The standard defines observable behavior as including "reads and writes
> |> to volatile data", not accesses to them.
>
> |> There's more to 'volatile' than just the fact that accessing a volatile
> |> object counts as a side-effect (with corresponding interactions with
> |> sequence points). There is also the sequence point stability promise,
> |> and the promise that volatile sig_atomic_t objects have defined values
> |> during signal handling.
>
> The sequence point stability really only concerns ordering, since there
> is no way a conforming program can determine that a sequence point has
> occured. And sig_atomic_t is a special case, and very limited. There
> are one or two other guarantees as well with regards to setjmp/longjmp,
I missed that, when I was making my list of guarantees.
> but on the whole, _most_ of the semantics of volatile are implementation
> defined, although the standard makes it quite clear what the intent is.
Still, by comparison with "register" (or even "inline"), "volatile" is a
lot more than just a hint.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Sat, 2 Sep 2000 22:15:42 GMT Raw View
In article <39AFB947.B29D52A@wizard.net>, James Kuyper
<kuyper@wizard.net> writes
>Still, by comparison with "register" (or even "inline"), "volatile" is a
>lot more than just a hint.
Not least because in C++ you can overload on it:)
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]