Re: Simultaneous Writes on Volatile



Eric Sosman wrote:
On 8/15/2010 8:16 PM, Shao Miller wrote:
Eric Sosman wrote:
On 8/15/2010 4:15 PM, Shao Miller wrote:
Does a C Standard prevent a conforming implementation from scheduling
simultaneous writes on a 'volatile'?

I think you'll need to define "simultaneous" before this question
can be answered. Also, note that each implementation makes its own
definition of what it means to access a volatile object, hence of what
it means to write such an object.
By "simultaneous," I meant "at the same time."

(Sigh.) All right, now define "time" and "same," grounding
both definitions in terms already defined by the Standard.

I meant "simultaneous" as outside of a C Standard. Posters have offered that one potential reason why the Standard doesn't define side effect order within sequence point bounds is because there is or could be hardware where a simultaneous read and write to the same object could cause an exception. If that's a relevant reason, then so should this question about simultaneity be relevant. Perhaps it's out-of-scope for what you're interested in discussing. If so, I readily accept that. Perhaps one of the posters who offered that reason might have something to say about the matter.

We have some reads and
writes to do, but I'm pondering a system where the write for the '--'
decrement might be scheduled with the write from the '=' assignment, or
if a C Standard implies that volatile accesses should be all performed
one-at-a-time. I'm trying to figure out what a conforming implementation
is within its rights to define, and beyond that, what the sensible thing
to do is.

A conforming implementation must (among other things) define
what an "access" to a volatile-qualified object is. A conforming
implementation is not obliged to sequence things one way or another
simply because there's a `volatile' lurking somewhere about.

Aha. Ok. Where "one way" might be "simultaneously". So a conforming implementation has _two_ chances to discard 'volatile'.

volatile int a = 1;
a = a + a;

1. "I define the actual semantics to be one-to-one with the abstract semantics. 'volatile' is redundant."

2. "I define that all reads of objects within the same sequence point bounds shall occur no more than once per object. At each sequence point, I will read all values for all objects read within an expression no more than once. I will pend all modifications for immediately before the next sequence point; these will be scheduled to occur simultaneously."

Seem ok?

Assuming not, and further assuming a particular scenario where there is
no unknown factor to modify the 'volatile' array below, is the output of
the following program well-defined to be one of: { 0, 5, 9 }? Or is the
output unspecified or implementation-specific?

If you're assuming no external modification, I don't see how
`volatile' enters into the question. Accessing a volatile variable
does not introduce a sequence point, if that's what you're getting at.

No, I wasn't getting at that. I'm trying to understand the intentions of
a C Standard in regards to 'volatile'. On the one hand, it suggests that
if an implementation's semantics correspond one-to-one with the abstract
semantics, then 'volatile' would be redundant[1]. On the other hand,
implementations define both what constitutes an access for a 'volatile'
object[2] as well as the order of side effects between sequence points[3].

You're right about [1] and [2], but completely wrong about [3].
The quoted text says the ordering of side-effects is "unspecified,"
not "implementation-defined." The implementation is not obliged to
define any ordering for side-effects. Corollary: The implementation
is not required to use a consistent ordering, not even from one
evaluation of the same source expression to the next.
Uhh... If the Standard doesn't define the ordering of side effects and the implementation doesn't, then who does? Even a random side effect order is a definition.

I think what you're getting at is that it doesn't need to be documented by the implementation. If so, then I agree.

Unfortunately, the constraint of using terms exactly as they appear in the Standard makes it confusing if I type "implementation-defined". What I should have typed was "implementation-chosen". Sorry about that!


#include <stdio.h>

int main(void) {
volatile int arr[2];

arr[0] = 1;
arr[1] = 5;
arr[0] = arr[arr[0]] + --(arr[arr[0] - 1]) + arr[arr[0]];

Looks like undefined behavior to me, for the same reason
discussed (at wearying length) in the "C Test Incorrectly Uses
printf() - Please Confirm" thread.
It's clear from the reference you pointed out in that thread[5] that if
the big expression above modifies some object and tries to do so twice
within the same sequence point bounds, that it's outside of the C Standard.

True, but that's not what the referenced thread is about. The
objectionable expression attempts to modify an object and to use it
for purposes other than determining the new value, and that's that.
(Since the behavior is undefined, it's not possible to tell for sure
whether the expression attempts to modify one object twice.)
Right, in regards to the other thread. But in the big expression above, 'arr[0]' is being used to determine the new value. The '--' modification side effect might or might not be on the same object, depending on the circumstances, and might not be known one way or the other until run-time.

So I'll ask if we can really call it undefined behaviour by looking at it. I think in this case that it's implementation-chosen... A combination of factors including implementation-defined and unspecified, as you've mentioned. As in, 6.5p2 cannot apply here (above) until after those bits are known, right?


If one were to develop an implementation that catches all undefined
behaviour and reports it (I think there's a name for such a theoretical
implementation),

The name you're searching for is "nonexistent," or maybe even
"impossible." (The exhibition of a counter-example would be a boon
to the practice of programming, should you feel so inclined.)
Ha! Nice one. :) I was thinking of a particular implementation acronym that's been passed around a bit and that's a bit too dreadful for me to repeat. But yes, such an implementation could make short work of assumptions that fall outside of a C Standard... If certain tricky details could be clarified.


In other words, it seems to be a messy situation. If 'volatile' is an
implementation-specific hint, could we discard it?

There's a footnote that says as much -- and what's more, you've
read the footnote.

Well, the non-normative footnote is for "information only", whereas 'register' and 'restrict' are normative, so it's worth asking opinions on.

Additionally, 'register' has some Standard-defined consequences. Is that so for 'volatile'? I think you're stating that 'volatile' does not have Standard-defined consequences.

Thank you, as always.
.



Relevant Pages

  • Re: Volatile in C99
    ... I realize that's your opinion; ... Yes as it is your opinion not everyone's that an access to volatile ... referred to several different sections of the Standard, ... unknown side-effects may be. ...
    (comp.std.c)
  • Re: Volatile in C99
    ... written so as not to need volatile for such cases. ... but saying setjmpcan be used in a strictly conforming ... fact solely by the text of the standard, which is the reason I said ... the wording should be clarified. ...
    (comp.std.c)
  • Re: Volatile in C99
    ... written so as not to need volatile for such cases. ... but saying setjmpcan be used in a strictly conforming ... the wording should be clarified. ... it isn't clear what possibilities the Standard "provides". ...
    (comp.std.c)
  • Re: ECC logging implementation
    ... C has volatile, ... to allow a program to break the sequence point rules. ... subsequent accesses have not yet occurred. ... The C standard makes it clear that using threading is undefined ...
    (comp.arch)
  • Re: Use of volatile const
    ... There's no reasonable way for that to happen, but the standard only ... It simply says "volatile qualified". ... int main ... the last store need not be explicit in the program." ...
    (comp.std.c)