Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Clarification on the applicability of compile-time optimization to astruct variable which encompasses a mixture of fields declared as volatileand non-volatile individually

Reply
Thread Tools

Clarification on the applicability of compile-time optimization to astruct variable which encompasses a mixture of fields declared as volatileand non-volatile individually

 
 
Joshua Maurice
Guest
Posts: n/a
 
      07-07-2012
On Jul 7, 6:47 am, Jens Gustedt <jens.gust...@loria.fr> wrote:
> Am 07.07.2012 01:58, schrieb Joshua Maurice:
>
> > To be topical, here's the answer for C11: volatile is useless as a
> > portable threading construct. Do not use it. It's (maybe) useful in a
> > portable way only for 3 obscure situations: MMIO, setjmp and longjmp
> > stuff, and signal handling.

>
> No, this is misleading. volatile alone is not sufficient to warrant data
> consistency between threads, but is necessary. volatile and _Atomic are
> complementary specifications that *both* are needed if you want to make
> sure that a thread always uses the latest stored value of a variable. If
> you have
>
> static int _Atomic a = ATOMIC_VAR_INIT(23);
> if (tester)
> for (; printf("current value is %d\n", a);
>
> The compiler is allowed to change the loop into something equivalent to
>
> {
> int tmp = a; // do an atomic_load operation here
> for (; printf("current value is %d\n", tmp);
> }
>
> and thus always print the same value.
>
> static int _Atomic volatile a = ATOMIC_VAR_INIT(23);
>
> would assure that each execution of printf would see an updated value.


(Let's assume you were talking about C11.) You are simply wrong. That
is not what the standard says. This is not what people on the
standards committee are saying. That is not what compile writers are
implementing. This is not what the experts are saying. volatile is
useless for threading code by the C11 standard. Entirely useless for
inter-thread communication.

However, having said that, your example is an interesting one. The
specific rule which disallows the above compiler transformation is an
obscure one, and not one of my favorites. I've tried to discuss this
very issue on comp.std.c++, with no replies IIRC. C11 threading, being
largely just a copy of C++11 threading, has the rule in question. In
the draft I have lying around of C11, n1570, the rule is:

n1570: 7.17.3 Order and consistency / 16
Quote:
Implementations should make atomic stores visible to atomic loads
within a reasonable amount of time.
That rule disallows the above transformation. The only reasonable
reading of that rule is to prevent compiler transformations like the
one above.

There's also one other new obscure rule, again copied from C++11 to
C11, which has some relevance here.

n1570: 6.8.5 Iteration statements / 6
Quote:
An iteration statement whose controlling expression is not a constant
expression, that performs no input/output operations, does not access
volatile objects, and performs no synchronization or atomic operations
in its body, controlling expression, or (in the case of a for
statement) its expression-3, may be assumed by the implementation to
terminate.
This generated a lot of discussion on the C++ newsgroups. In short,
this says:
> for(;;

is now undefined behavior. I think I dislike the wording of this one
even more than the earlier rule. However, going with the "spirit" of
this rule, I might argue that above compiler transformation is
disallowed; if you're not allowed to make a non-terminating loop with
a constant controlling expression, then the compiler probably
shouldn't be allowed to make one either. Still, I want to emphasize
that reading is merely IMHO, whereas "7.17.3 Order and consistency /
16" much less ambiguously disallows the above compiler
transformation.

For further reading, see:
http://www.open-std.org/jtc1/sc22/wg...006/n2016.html
http://msdn.microsoft.com/en-us/library/12a04hfd.aspx
http://kernel.org/doc/Documentation/...ed-harmful.txt
http://software.intel.com/en-us/blog...d-programming/
http://www.aristeia.com/Papers/DDJ_J...04_revised.pdf
http://kerneltrap.org/Linux/Volatile_Superstition
The C++11 and C11 standards.
 
Reply With Quote
 
 
 
 
Jens Gustedt
Guest
Posts: n/a
 
      07-08-2012
Am 08.07.2012 01:19, schrieb Joshua Maurice:
> On Jul 7, 6:47 am, Jens Gustedt <jens.gust...@loria.fr> wrote:
>> Am 07.07.2012 01:58, schrieb Joshua Maurice:
>>
>>> To be topical, here's the answer for C11: volatile is useless as a
>>> portable threading construct. Do not use it. It's (maybe) useful in a
>>> portable way only for 3 obscure situations: MMIO, setjmp and longjmp
>>> stuff, and signal handling.

>>
>> No, this is misleading. volatile alone is not sufficient to warrant data
>> consistency between threads, but is necessary. volatile and _Atomic are
>> complementary specifications that *both* are needed if you want to make
>> sure that a thread always uses the latest stored value of a variable. If
>> you have
>>
>> static int _Atomic a = ATOMIC_VAR_INIT(23);
>> if (tester)
>> for (; printf("current value is %d\n", a);
>>
>> The compiler is allowed to change the loop into something equivalent to
>>
>> {
>> int tmp = a; // do an atomic_load operation here
>> for (; printf("current value is %d\n", tmp);
>> }
>>
>> and thus always print the same value.
>>
>> static int _Atomic volatile a = ATOMIC_VAR_INIT(23);
>>
>> would assure that each execution of printf would see an updated value.

>
> (Let's assume you were talking about C11.)


Sure I was, _Atomic only comes with C11

> You are simply wrong. That
> is not what the standard says. This is not what people on the
> standards committee are saying. That is not what compile writers are
> implementing. This is not what the experts are saying. volatile is
> useless for threading code by the C11 standard. Entirely useless for
> inter-thread communication.


Then read the example I gave again

> However, having said that, your example is an interesting one. The
> specific rule which disallows the above compiler transformation is an
> obscure one, and not one of my favorites. I've tried to discuss this
> very issue on comp.std.c++, with no replies IIRC. C11 threading, being
> largely just a copy of C++11 threading, has the rule in question. In
> the draft I have lying around of C11, n1570, the rule is:
>
> n1570: 7.17.3 Order and consistency / 16
>
Quote:
> Implementations should make atomic stores visible to atomic loads
> within a reasonable amount of time.
>


The "should" makes it clearly a non-normative part of the standard and
leaves it to the appreciation of the compiler implementor what
"reasonable amount of time" is.

If the implementor decides that "reasonable amount of time" is 1
milli-second, the loop could be implemented to only do an update each
milli-second.

Said otherwise, there can be no guarantee that for the non-volatile
case an implementation decides to skip a load operation somewhere that
would bring a fresh value into some other thread.

> That rule disallows the above transformation.


no, I just suggest that a compiler shouldn't do it.

> The only reasonable
> reading of that rule is to prevent compiler transformations like the
> one above.


to discourage, not to prevent

Jens
 
Reply With Quote
 
 
 
 
James Kuyper
Guest
Posts: n/a
 
      07-08-2012
On 07/08/2012 03:40 AM, Jens Gustedt wrote:
> Am 08.07.2012 01:19, schrieb Joshua Maurice:

....
>> n1570: 7.17.3 Order and consistency / 16
>>
Quote:
>> Implementations should make atomic stores visible to atomic loads
>> within a reasonable amount of time.
>>

>
> The "should" makes it clearly a non-normative part of the standard and
> leaves it to the appreciation of the compiler implementor what
> "reasonable amount of time" is.


While the "should" is a strong hint, it's the fact that it's in a
"recommended practice" section which makes it perfectly clear that this
is optional.
--
James Kuyper
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      07-09-2012
On 07/07/2012 04:04 PM, Uncle Steve wrote:
....
> I realize that c.l.c. is for discussions about the C language, without
> necessary reference to any particular implementation. Nevertheless,
> with threads supported by C11 I would imagine some discussion might be
> allowed.


No one can disallow anything in an unmoderated newsgroup like this.

However, if you insist on discussing pthreads rather than C11 threads,
c.l.c is not as a good a place to have a well-informed discussion as
comp.programming.threads. If you deliberately want to get less than the
best possible answers to your question, continue posting here; but if
that is your goal, then surely a newsgroup completely unrelated to any
kind of computer programming, such as alt.fun.with.steve, would serve
that goal even better than this newsgroup?
 
Reply With Quote
 
Philip Lantz
Guest
Posts: n/a
 
      07-14-2012
Joshua Maurice wrote:
> There's also one other new obscure rule, again copied from C++11 to
> C11, which has some relevance here.
>
> n1570: 6.8.5 Iteration statements / 6
>
Quote:
> An iteration statement whose controlling expression is not a constant
> expression, that performs no input/output operations, does not access
> volatile objects, and performs no synchronization or atomic operations
> in its body, controlling expression, or (in the case of a for
> statement) its expression-3, may be assumed by the implementation to
> terminate.
>
>
> This generated a lot of discussion on the C++ newsgroups. In short,
> this says:
> > for(;;

> is now undefined behavior.


The controlling expression of that loop is a constant expression--
footnote 156 makes this clear--so it doesn't meet the prerequisites for
paragraph 6.8.5p6 to apply.

Furthermore, even if the paragraph did apply, it doesn't make the
behavior undefined, it just allows the compiler to remove the loop if it
doesn't detect any side effects.
 
Reply With Quote
 
Philip Lantz
Guest
Posts: n/a
 
      07-15-2012
Uncle Steve wrote:
> Currently I'm developing on x86_64 and x86, and I chose to
> use "lock incl %0" and then inspect the result to detect collisions.
> It is obviously very fast, and I can control how long a thread will
> spin on the lock before sleeping. I have yet to investigate whether I
> need to use a different instruction for the 64-bit arch.


You may not want to use inc, because then you can't discover the result
without reading it again, so you lose atomicity. I recommend using xadd
to add 1, it atomically returns the previous value in a register.
 
Reply With Quote
 
 
 
Reply

Thread Tools

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

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


Similar Threads
Thread Thread Starter Forum Replies Last Post
"Try:" which only encompasses head of compound statement Jameson.Quinn@gmail.com Python 9 08-29-2007 12:58 AM
sizeof(aStruct) returns fault number nass C++ 2 09-22-2006 03:24 PM
Applicability KB 831138: app that uses WebRequest has OutOfMemoryE =?Utf-8?B?dmVjb3pvQG9ubGluZS5ub3NwYW0=?= ASP .Net 9 01-05-2006 08:50 PM
wired / wireless network mixture or not ? ReceT Wireless Networking 3 07-12-2004 02:54 AM
gaussian mixture? GBartgo C++ 2 11-02-2003 12:10 AM



Advertisments