Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #61986 > unrolled thread

Sequence points and commit to memory

Started by"James Harris" <james.harris.1@gmail.com>
First post2015-05-14 11:43 +0100
Last post2015-05-24 08:11 -0700
Articles 20 on this page of 101 — 15 participants

Back to article view | Back to comp.lang.c


Contents

  Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-14 11:43 +0100
    Re: Sequence points and commit to memory Richard Heathfield <rjh@cpax.org.uk> - 2015-05-14 12:02 +0100
      Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-14 13:39 +0200
        Re: Sequence points and commit to memory Richard Heathfield <rjh@cpax.org.uk> - 2015-05-14 13:18 +0100
          Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-14 23:11 +0200
    Re: Sequence points and commit to memory Stephen Sprunk <stephen@sprunk.org> - 2015-05-14 09:06 -0500
    Re: Sequence points and commit to memory Siri Cruz <chine.bleu@yahoo.com> - 2015-05-14 08:35 -0700
      Re: Sequence points and commit to memory David Kleinecke <dkleinecke@gmail.com> - 2015-05-14 10:23 -0700
        Re: Sequence points and commit to memory Siri Cruz <chine.bleu@yahoo.com> - 2015-05-14 10:44 -0700
          Re: Sequence points and commit to memory David Kleinecke <dkleinecke@gmail.com> - 2015-05-14 11:09 -0700
            Re: Sequence points and commit to memory Keith Thompson <kst-u@mib.org> - 2015-05-14 12:58 -0700
            Re: Sequence points and commit to memory Morris Dovey <mrdovey@iedu.com> - 2015-05-14 16:31 -0500
              Re: Sequence points and commit to memory Keith Thompson <kst-u@mib.org> - 2015-05-14 17:24 -0700
                Re: Sequence points and commit to memory Morris Dovey <mrdovey@iedu.com> - 2015-05-14 20:18 -0500
                  Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-15 09:34 +0200
                    Re: Sequence points and commit to memory Morris Dovey <mrdovey@iedu.com> - 2015-05-15 10:18 -0500
                    Re: 'register' attribute (was: Sequence points and commit to memory) Morris Dovey <mrdovey@iedu.com> - 2015-05-16 01:26 -0500
                      Re: 'register' attribute David Brown <david.brown@hesbynett.no> - 2015-05-17 00:02 +0200
                        Re: 'register' attribute Morris Dovey <mrdovey@iedu.com> - 2015-05-16 19:29 -0500
              Re: Sequence points and commit to memory David Kleinecke <dkleinecke@gmail.com> - 2015-05-15 09:52 -0700
                Re: Sequence points and commit to memory James Kuyper <jameskuyper@verizon.net> - 2015-05-15 13:27 -0400
                  Re: Sequence points and commit to memory Keith Thompson <kst-u@mib.org> - 2015-05-15 10:50 -0700
                Re: Sequence points and commit to memory Morris Dovey <mrdovey@iedu.com> - 2015-05-15 12:32 -0500
        Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-14 23:23 +0200
          Re: Sequence points and commit to memory David Kleinecke <dkleinecke@gmail.com> - 2015-05-15 09:42 -0700
            Re: Sequence points and commit to memory James Kuyper <jameskuyper@verizon.net> - 2015-05-15 13:13 -0400
              Re: Sequence points and commit to memory David Kleinecke <dkleinecke@gmail.com> - 2015-05-16 08:32 -0700
            Re: Sequence points and commit to memory Keith Thompson <kst-u@mib.org> - 2015-05-15 10:35 -0700
            Re: Sequence points and commit to memory Keith Thompson <kst-u@mib.org> - 2015-05-15 11:08 -0700
              Re: Sequence points and commit to memory Robert Wessel <robertwessel2@yahoo.com> - 2015-05-15 16:40 -0500
              Re: Sequence points and commit to memory David Kleinecke <dkleinecke@gmail.com> - 2015-05-16 08:48 -0700
            Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-15 21:46 +0100
              Re: Sequence points and commit to memory David Kleinecke <dkleinecke@gmail.com> - 2015-05-16 08:56 -0700
                Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-16 19:35 +0100
                  Re: Sequence points and commit to memory David Kleinecke <dkleinecke@gmail.com> - 2015-05-18 09:49 -0700
                    Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-19 09:04 +0100
                    Re: Sequence points and commit to memory Keith Thompson <kst-u@mib.org> - 2015-05-19 08:42 -0700
      Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-14 22:00 +0100
        Re: Sequence points and commit to memory Siri Cruz <chine.bleu@yahoo.com> - 2015-05-14 14:26 -0700
          Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-14 22:33 +0100
        Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-14 23:38 +0200
          Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-14 23:04 +0100
            Re: Sequence points and commit to memory Stephen Sprunk <stephen@sprunk.org> - 2015-05-15 13:09 -0500
              Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-15 21:56 +0100
                Re: Sequence points and commit to memory James Kuyper <jameskuyper@verizon.net> - 2015-05-15 17:30 -0400
                  Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-16 07:51 +0100
                    Re: Sequence points and commit to memory James Kuyper <jameskuyper@verizon.net> - 2015-05-16 22:10 -0400
                      Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-19 00:25 +0200
                        Re: Sequence points and commit to memory James Kuyper <jameskuyper@verizon.net> - 2015-05-18 18:55 -0400
                          Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-19 09:10 +0200
                            Re: Sequence points and commit to memory James Kuyper <jameskuyper@verizon.net> - 2015-05-19 12:05 -0400
                              Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-19 18:42 +0200
                Re: Sequence points and commit to memory Stephen Sprunk <stephen@sprunk.org> - 2015-05-16 16:33 -0500
                  Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-19 00:27 +0200
                    Re: Sequence points and commit to memory James Kuyper <jameskuyper@verizon.net> - 2015-05-18 19:05 -0400
                      Re: Sequence points and commit to memory glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-05-19 00:09 +0000
                        Re: Sequence points and commit to memory Richard Heathfield <rjh@cpax.org.uk> - 2015-05-19 01:11 +0100
                          Re: Sequence points and commit to memory Tim Rentsch <txr@alumni.caltech.edu> - 2015-05-23 07:02 -0700
                        Re: Sequence points and commit to memory James Kuyper <jameskuyper@verizon.net> - 2015-05-18 23:21 -0400
                          Re: Sequence points and commit to memory glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-05-19 06:25 +0000
                            Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-19 08:58 +0200
                              Re: Sequence points and commit to memory glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-05-19 23:20 +0000
                                Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-20 12:31 +0200
                            Re: Sequence points and commit to memory James Kuyper <jameskuyper@verizon.net> - 2015-05-19 12:10 -0400
                              Re: Sequence points and commit to memory glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-05-19 23:24 +0000
                      Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-19 09:05 +0200
                        Re: Sequence points and commit to memory Keith Thompson <kst-u@mib.org> - 2015-05-19 08:37 -0700
                        Re: Sequence points and commit to memory James Kuyper <jameskuyper@verizon.net> - 2015-05-19 12:14 -0400
                          Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-19 19:02 +0200
              Re: Sequence points and commit to memory Robert Wessel <robertwessel2@yahoo.com> - 2015-05-15 16:46 -0500
            Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-17 00:20 +0200
              Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-17 18:19 +0100
                Re: Sequence points and commit to memory Philip Lantz <prl@canterey.us> - 2015-05-17 16:11 -0700
                  Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-18 08:30 +0100
                    Re: Sequence points and commit to memory David Kleinecke <dkleinecke@gmail.com> - 2015-05-18 10:31 -0700
                      Re: Sequence points and commit to memory Keith Thompson <kst-u@mib.org> - 2015-05-18 11:11 -0700
                        Re: Sequence points and commit to memory David Kleinecke <dkleinecke@gmail.com> - 2015-05-19 09:37 -0700
                      Re: Sequence points and commit to memory Ian Collins <ian-news@hotmail.com> - 2015-05-19 17:40 +1200
                        Re: Sequence points and commit to memory Morris Dovey <mrdovey@iedu.com> - 2015-05-19 01:31 -0500
                          Re: Sequence points and commit to memory Ian Collins <ian-news@hotmail.com> - 2015-05-19 20:38 +1200
                            Re: Sequence points and commit to memory Morris Dovey <mrdovey@iedu.com> - 2015-05-19 10:50 -0500
                    Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-19 00:46 +0200
                Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-19 00:35 +0200
        Re: Sequence points and commit to memory Robert Wessel <robertwessel2@yahoo.com> - 2015-05-15 16:42 -0500
          Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-16 07:58 +0100
            Re: Sequence points and commit to memory Robert Wessel <robertwessel2@yahoo.com> - 2015-05-16 02:18 -0500
              Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-16 08:36 +0100
                Re: Sequence points and commit to memory Robert Wessel <robertwessel2@yahoo.com> - 2015-05-17 04:31 -0500
                  Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-17 18:24 +0100
                    Re: Sequence points and commit to memory David Brown <david.brown@hesbynett.no> - 2015-05-19 00:55 +0200
    Re: Sequence points and commit to memory Keith Thompson <kst-u@mib.org> - 2015-05-14 11:26 -0700
      Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-14 22:07 +0100
        Re: Sequence points and commit to memory Keith Thompson <kst-u@mib.org> - 2015-05-14 14:22 -0700
          Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-14 22:36 +0100
      Re: Sequence points and commit to memory Tim Rentsch <txr@alumni.caltech.edu> - 2015-05-22 08:16 -0700
        Re: Sequence points and commit to memory Keith Thompson <kst-u@mib.org> - 2015-05-22 11:31 -0700
    Re: Sequence points and commit to memory James Kuyper <jameskuyper@verizon.net> - 2015-05-15 00:05 -0400
      Re: Sequence points and commit to memory "James Harris" <james.harris.1@gmail.com> - 2015-05-15 22:25 +0100
        Re: Sequence points and commit to memory James Kuyper <jameskuyper@verizon.net> - 2015-05-15 17:56 -0400
    Re: Sequence points and commit to memory Nobody <nobody@nowhere.invalid> - 2015-05-17 10:04 +0100
    Re: Sequence points and commit to memory Tim Rentsch <txr@alumni.caltech.edu> - 2015-05-24 08:11 -0700

Page 5 of 6 — ← Prev page 1 2 3 4 [5] 6  Next page →


#62293

FromMorris Dovey <mrdovey@iedu.com>
Date2015-05-19 10:50 -0500
Message-ID<mjfm3l$v2n$1@speranza.aioe.org>
In reply to#62278
On 5/19/15 3:38 AM, Ian Collins wrote:
> Morris Dovey wrote:
>> On 5/19/15 12:40 AM, Ian Collins wrote:
>>
>>> The question is
>>> whether the C langauge can be made to fit comfortably into an event-
>>> diven world. It can be forced in but the fits I have seen are far from
>>> comfortable.
>
> No I didn't!
>
> Please take more care with your quotes.

Please accept my apology. I managed to quote a quote (something I try to 
avoid doing) that was originally from David Kleinecke.

I’m not sure how I managed that. :-P

-- 
Morris Dovey
http://www.iedu.com/Solar

[toc] | [prev] | [next] | [standalone]


#62259

FromDavid Brown <david.brown@hesbynett.no>
Date2015-05-19 00:46 +0200
Message-ID<mjdq1n$kcp$1@dont-email.me>
In reply to#62213
On 18/05/15 09:30, James Harris wrote:
> "Philip Lantz" <prl@canterey.us> wrote in message
> news:MPG.2fc2c01210c570f926@news.eternal-september.org...
>> James Harris wrote:
>>>
>>> "David Brown" <david.brown@hesbynett.no> wrote in message
>>> news:mj8fps$7ru$1@dont-email.me...
>>>> On 15/05/15 00:04, James Harris wrote:
>>>>> "David Brown" <david.brown@hesbynett.no> wrote in message
>>>>> news:mj34ho$jll$1@dont-email.me...
>>>
>>> ...
>>>
>>>>>>    The compiler could move the assignments to before the interrupt
>>>>>> disable, or after the restore, or in pretty much any other order
>>>>>> it
>>>>>> wants.
>>>>>
>>>>> That is a big surprise - and a big problem. Are you sure that a
>>>>> compiler
>>>>> could do that? If it did it would change the semantics of the
>>>>> program.
>>>>>
>>>>
>>>> Yes, I have no doubts.  And I have no doubts that it happens in
>>>> practice (though it is unlikely to happen here - the compiler won't
>>>> move things around unless there are clear advantages in doing so.
>>>> It
>>>> is seldom awkward just to annoy people!).
>>>>
>>>> I have seen people write code like this:
>>>>
>>>> int x = long_calculation();
>>>> disableInterrupts();
>>>> volatile_variable = x;
>>>> enableInterrupts();
>>>>
>>>> and been surprised when the compiler moves the long_calculation()
>>>> into
>>>> the interrupt-disabled area.
>>>
>>> AFAICS the only way the compiler should do that is if it could prove
>>> that interrupts would be disabled prior to the disableInterrupts call
>>> that you show so that the call will always be a no-op. If the
>>> compiler
>>> cannot prove that for all possible execution paths it should not,
>>> AFAICS, reorder the code as it did.
>>
>> The compiler doesn't know anything about interrupts.
>
> No, but the way that interrupts are disabled may be seen by the
> compiler. Imagine that on a certain machine the disableInterrupts call
> sets a value in a memory-mapped register and that register value has
> already been set (and the memory-mapped register address has not been
> declared as volatile).

Only the volatile accesses need to be ordered as written in the program 
- anything else can be re-arranged.  So the volatile store to 
volatile_variable must come between the two volatile stores to 
interrupt_enable_flag - but the non-volatile calculations can be done at 
any time (including at compile-time or prior to starting main()).

>
>> Sequence points affect the behavior of the abstract machine; in the
>> real
>> machine, the compiler only needs to worry about the ordering of
>> volatile
>> accesses (as long as every thing else gives the same results as the
>> abstract machine).
>>
>> If long_calculation doesn't involve any volatile accesses (which I
>> presume it doesn't), the compiler can put it any where it wants, even
>> before the call to main, as long as the result is the same.
>> (Obviously,
>> if it depends on input, it can't be done before that input is
>> available.)
>
> I can see this in two ways and I don't know which model the compiler is
> supposed to follow. The two are
>
> 1. The compiler can prove that the disableInterrupts call will not be
> able to modify any of this function's *internal* state, possibly because
> this function operates only on automatic variables and there are no
> pointers into this function's memory. It therefore feels free to reorder
> statements around the disableInterrupts call.

Yes.  Presumably the declaration or definition of disableInterrupts() 
makes it clear that is a volatile access.

If the compiler knows that long_calculation() does not perform volatile 
accesses or otherwise interact with the interrupt enable and disable 
functions, it can do the re-ordering.

(Note that if the compiler does not know the details of a function, it 
must assume that it makes volatile access.  But it also assumes that the 
function obeys the rules of C, and cannot access local variables in 
another function unless they are passed by pointers.)

>
> 2. The compiler does not know what disableInterrupts does so it realises
> that it cannot reorder it with respect to other statements.
>

That could also be correct, and may hinder some compiler re-ordering.

> I suppose the one which is correct comes down to what the C compiler
> considers to comprise the state of the abstract machine.

No, the abstract machine is quite clear about such things.  But 
different compilers (or the same compiler with different flags) may 
track more or less details about functions (for example, with link-time 
optimisation it will usually have more details), and they may also take 
more or less advantage of the flexibility allowed.

>
>>>> I have also seen code like this:
>>>>
>>>> testPinOn(); // Using volatile write to a PORT
>>>> longCalculation();
>>>> testPinOff();
>>>>
>>>> and try to use an oscilloscope to measure the time taken by
>>>> longCalculation() - only to discover that it has been moved before
>>>> or
>>>> after the testPin functions, so the pin goes on and off within a
>>>> few
>>>> instruction cycles.
>>>
>>> Possibly some slow hardware response to turning the pin on, or the
>>> longCalculation taking less time than expected? Rather than look at
>>> the
>>> timing do you remember whether you checked the generated code to see
>>> whether the compiler had really moved the longCalculation as you
>>> suggest? If it had then that has to be a compiler bug, doesn't it in
>>> that it has changed the effect of the program?
>>
>> No, not a compiler bug. Again, if longCalculation() doesn't involve
>> any
>> volatile accesses, the compiler can move it. Timing is not considered
>> an
>> "effect of the program."
>
> No, but order of operations seems to be the key thing. I would have
> hoped that the compiler would only reorder operations if it could prove
> that such reordering did not have an impact on the effect of the
> program.
>

Certainly the compiler will only re-order code if it can prove that the 
re-ordering does not have a /visible/ effect on the program - using C's 
definition of visible effects (which basically means the order of 
volatile accesses, the order and values of external code calls, and the 
start and exit of the program).

The key mistake people make is assuming that volatile accesses have an 
effect on the ordering of other parts of the code with respect to these 
accesses - C gives no such guarantees.

[toc] | [prev] | [next] | [standalone]


#62257

FromDavid Brown <david.brown@hesbynett.no>
Date2015-05-19 00:35 +0200
Message-ID<mjdpe9$hus$1@dont-email.me>
In reply to#62186
On 17/05/15 19:19, James Harris wrote:
> "David Brown" <david.brown@hesbynett.no> wrote in message
> news:mj8fps$7ru$1@dont-email.me...
>> On 15/05/15 00:04, James Harris wrote:
>>> "David Brown" <david.brown@hesbynett.no> wrote in message
>>> news:mj34ho$jll$1@dont-email.me...
>
> ...
>
>>>>    The compiler could move the assignments to before the interrupt
>>>> disable, or after the restore, or in pretty much any other order it
>>>> wants.
>>>
>>> That is a big surprise - and a big problem. Are you sure that a
>>> compiler
>>> could do that? If it did it would change the semantics of the
>>> program.
>>>
>>
>> Yes, I have no doubts.  And I have no doubts that it happens in
>> practice (though it is unlikely to happen here - the compiler won't
>> move things around unless there are clear advantages in doing so.  It
>> is seldom awkward just to annoy people!).
>>
>> I have seen people write code like this:
>>
>> int x = long_calculation();
>> disableInterrupts();
>> volatile_variable = x;
>> enableInterrupts();
>>
>> and been surprised when the compiler moves the long_calculation() into
>> the interrupt-disabled area.
>
> AFAICS the only way the compiler should do that is if it could prove
> that interrupts would be disabled prior to the disableInterrupts call
> that you show so that the call will always be a no-op. If the compiler
> cannot prove that for all possible execution paths it should not,
> AFAICS, reorder the code as it did.
>

No, the compiler generated valid code - the programmer was making the 
same incorrect assumptions that you are.  The compiler knew the effect 
of the long_calculation() call (or sequence of statements), and knew 
there were no volatile accesses or any accesses whose order was related 
to the order of accesses in the disableInterrupts() call.  It could not 
move the storage to volatile_variable outside the disableInterrupts() / 
enableInterrupts() pair, since these calls were volatile accesses.  But 
it could move the calculation of the value to store in volatile_variable 
to whereever it liked before the store.

>> I have also seen code like this:
>>
>> testPinOn(); // Using volatile write to a PORT
>> longCalculation();
>> testPinOff();
>>
>> and try to use an oscilloscope to measure the time taken by
>> longCalculation() - only to discover that it has been moved before or
>> after the testPin functions, so the pin goes on and off within a few
>> instruction cycles.
>
> Possibly some slow hardware response to turning the pin on, or the
> longCalculation taking less time than expected? Rather than look at the
> timing do you remember whether you checked the generated code to see
> whether the compiler had really moved the longCalculation as you
> suggest? If it had then that has to be a compiler bug, doesn't it in
> that it has changed the effect of the program?
>

Of course I checked the generated code (even though this was not my 
program - I know about issues like this), and again the compiler was 
correct.  As long as the compiler knows that longCalculation is 
independent of the test pin writes, and no other volatile accesses are 
made, the compiler may do this reordering.

I am not posting this stuff because I don't know the speed of my 
hardware - I am giving you examples of real-life cases where 
misunderstandings about compiler optimisations have caused people 
trouble, to teach /you/ how to avoid the same problems yourself.

[toc] | [prev] | [next] | [standalone]


#62077

FromRobert Wessel <robertwessel2@yahoo.com>
Date2015-05-15 16:42 -0500
Message-ID<ovpcla11flbendmoa1vimlk2ht0ll76e5t@4ax.com>
In reply to#62020
On Thu, 14 May 2015 22:00:00 +0100, "James Harris"
<james.harris.1@gmail.com> wrote:

>"Siri Cruz" <chine.bleu@yahoo.com> wrote in message 
>news:chine.bleu-804F61.08350514052015@news.eternal-september.org...

>> volatile int u means that no assignment nor load can be redundant. The 
>> compiler
>> must assume some unknown process can alter u asynchronously anywhere 
>> even in the
>> execution of any instruction except an atomic load or store.
>
>In reality volatile is too strong a restriction. I don't need the values 
>to be read from memory each time they are referenced. I only need to 
>ensure that updates to them are written to memory.


Without forcing a read, isn't a forced write useless?

[toc] | [prev] | [next] | [standalone]


#62100

From"James Harris" <james.harris.1@gmail.com>
Date2015-05-16 07:58 +0100
Message-ID<mj6ppc$669$1@dont-email.me>
In reply to#62077
"Robert Wessel" <robertwessel2@yahoo.com> wrote in message 
news:ovpcla11flbendmoa1vimlk2ht0ll76e5t@4ax.com...
> On Thu, 14 May 2015 22:00:00 +0100, "James Harris"
> <james.harris.1@gmail.com> wrote:
>
>>"Siri Cruz" <chine.bleu@yahoo.com> wrote in message
>>news:chine.bleu-804F61.08350514052015@news.eternal-september.org...
>
>>> volatile int u means that no assignment nor load can be redundant. 
>>> The
>>> compiler
>>> must assume some unknown process can alter u asynchronously anywhere
>>> even in the
>>> execution of any instruction except an atomic load or store.
>>
>>In reality volatile is too strong a restriction. I don't need the 
>>values
>>to be read from memory each time they are referenced. I only need to
>>ensure that updates to them are written to memory.
>
>
> Without forcing a read, isn't a forced write useless?

If I understand your question, no. If only one module changes a value in 
memory and one or more others read it then the one which changes it does 
not need to keep rereading it.

Forcing a read is only necessary if something else could have changed 
the value behind our back.

James

[toc] | [prev] | [next] | [standalone]


#62103

FromRobert Wessel <robertwessel2@yahoo.com>
Date2015-05-16 02:18 -0500
Message-ID<2ordlatkut0h026ruk5i7fp685b6v3gj2q@4ax.com>
In reply to#62100
On Sat, 16 May 2015 07:58:54 +0100, "James Harris"
<james.harris.1@gmail.com> wrote:

>"Robert Wessel" <robertwessel2@yahoo.com> wrote in message 
>news:ovpcla11flbendmoa1vimlk2ht0ll76e5t@4ax.com...
>> On Thu, 14 May 2015 22:00:00 +0100, "James Harris"
>> <james.harris.1@gmail.com> wrote:
>>
>>>"Siri Cruz" <chine.bleu@yahoo.com> wrote in message
>>>news:chine.bleu-804F61.08350514052015@news.eternal-september.org...
>>
>>>> volatile int u means that no assignment nor load can be redundant. 
>>>> The
>>>> compiler
>>>> must assume some unknown process can alter u asynchronously anywhere
>>>> even in the
>>>> execution of any instruction except an atomic load or store.
>>>
>>>In reality volatile is too strong a restriction. I don't need the 
>>>values
>>>to be read from memory each time they are referenced. I only need to
>>>ensure that updates to them are written to memory.
>>
>>
>> Without forcing a read, isn't a forced write useless?
>
>If I understand your question, no. If only one module changes a value in 
>memory and one or more others read it then the one which changes it does 
>not need to keep rereading it.
>
>Forcing a read is only necessary if something else could have changed 
>the value behind our back.


Yes, but you need to force the read in those other modules who *will*
have that value "changed behind their backs".

[toc] | [prev] | [next] | [standalone]


#62104

From"James Harris" <james.harris.1@gmail.com>
Date2015-05-16 08:36 +0100
Message-ID<mj6s01$cbi$1@dont-email.me>
In reply to#62103
"Robert Wessel" <robertwessel2@yahoo.com> wrote in message 
news:2ordlatkut0h026ruk5i7fp685b6v3gj2q@4ax.com...
> On Sat, 16 May 2015 07:58:54 +0100, "James Harris"
> <james.harris.1@gmail.com> wrote:
>
>>"Robert Wessel" <robertwessel2@yahoo.com> wrote in message
>>news:ovpcla11flbendmoa1vimlk2ht0ll76e5t@4ax.com...
>>> On Thu, 14 May 2015 22:00:00 +0100, "James Harris"
>>> <james.harris.1@gmail.com> wrote:
>>>
>>>>"Siri Cruz" <chine.bleu@yahoo.com> wrote in message
>>>>news:chine.bleu-804F61.08350514052015@news.eternal-september.org...
>>>
>>>>> volatile int u means that no assignment nor load can be redundant.
>>>>> The
>>>>> compiler
>>>>> must assume some unknown process can alter u asynchronously 
>>>>> anywhere
>>>>> even in the
>>>>> execution of any instruction except an atomic load or store.
>>>>
>>>>In reality volatile is too strong a restriction. I don't need the
>>>>values
>>>>to be read from memory each time they are referenced. I only need to
>>>>ensure that updates to them are written to memory.
>>>
>>>
>>> Without forcing a read, isn't a forced write useless?
>>
>>If I understand your question, no. If only one module changes a value 
>>in
>>memory and one or more others read it then the one which changes it 
>>does
>>not need to keep rereading it.
>>
>>Forcing a read is only necessary if something else could have changed
>>the value behind our back.
>
>
> Yes, but you need to force the read in those other modules who *will*
> have that value "changed behind their backs".

Not in this case. That would be true only if their activations persist, 
I would have thought, i.e. if the two were running concurrently. For a 
function which starts, executes and stops and only reads the value once 
(or reads it multiple times knowing that it cannot be changed while this 
function is executing) I don't see that there would be a problem and 
that is the case here. The interrupt handler would read some of these 
values knowing that from the start of the interrupt handler's execution 
until it returns the main program will not be able to modify the value 
because it will not be executing concurrently with the interrupt 
handler.

That said, if I went down the volatile route I would probably declare it 
as volatile in both. That would achieve the same effect and be safer 
against future changes.

James

[toc] | [prev] | [next] | [standalone]


#62141

FromRobert Wessel <robertwessel2@yahoo.com>
Date2015-05-17 04:31 -0500
Message-ID<4ingla5ndd1krtpomnc6q6cp1g2rlt6ffp@4ax.com>
In reply to#62104
On Sat, 16 May 2015 08:36:36 +0100, "James Harris"
<james.harris.1@gmail.com> wrote:

>"Robert Wessel" <robertwessel2@yahoo.com> wrote in message 
>news:2ordlatkut0h026ruk5i7fp685b6v3gj2q@4ax.com...
>> On Sat, 16 May 2015 07:58:54 +0100, "James Harris"
>> <james.harris.1@gmail.com> wrote:
>>
>>>"Robert Wessel" <robertwessel2@yahoo.com> wrote in message
>>>news:ovpcla11flbendmoa1vimlk2ht0ll76e5t@4ax.com...
>>>> On Thu, 14 May 2015 22:00:00 +0100, "James Harris"
>>>> <james.harris.1@gmail.com> wrote:
>>>>
>>>>>"Siri Cruz" <chine.bleu@yahoo.com> wrote in message
>>>>>news:chine.bleu-804F61.08350514052015@news.eternal-september.org...
>>>>
>>>>>> volatile int u means that no assignment nor load can be redundant.
>>>>>> The
>>>>>> compiler
>>>>>> must assume some unknown process can alter u asynchronously 
>>>>>> anywhere
>>>>>> even in the
>>>>>> execution of any instruction except an atomic load or store.
>>>>>
>>>>>In reality volatile is too strong a restriction. I don't need the
>>>>>values
>>>>>to be read from memory each time they are referenced. I only need to
>>>>>ensure that updates to them are written to memory.
>>>>
>>>>
>>>> Without forcing a read, isn't a forced write useless?
>>>
>>>If I understand your question, no. If only one module changes a value 
>>>in
>>>memory and one or more others read it then the one which changes it 
>>>does
>>>not need to keep rereading it.
>>>
>>>Forcing a read is only necessary if something else could have changed
>>>the value behind our back.
>>
>>
>> Yes, but you need to force the read in those other modules who *will*
>> have that value "changed behind their backs".
>
>Not in this case. That would be true only if their activations persist, 
>I would have thought, i.e. if the two were running concurrently. For a 
>function which starts, executes and stops and only reads the value once 
>(or reads it multiple times knowing that it cannot be changed while this 
>function is executing) I don't see that there would be a problem and 
>that is the case here. The interrupt handler would read some of these 
>values knowing that from the start of the interrupt handler's execution 
>until it returns the main program will not be able to modify the value 
>because it will not be executing concurrently with the interrupt 
>handler.


This may be due to my having lost track of exactly which case we're
trying to discuss here, but...

Assuming the interrupt handler is the one to update the field, it
would be the interrupted routine that would need to re-read the value.


>That said, if I went down the volatile route I would probably declare it 
>as volatile in both. That would achieve the same effect and be safer 
>against future changes.


Is it actually legal to *not* declare them as both with the same
volatility?

[toc] | [prev] | [next] | [standalone]


#62187

From"James Harris" <james.harris.1@gmail.com>
Date2015-05-17 18:24 +0100
Message-ID<mjaipk$d77$1@dont-email.me>
In reply to#62141
"Robert Wessel" <robertwessel2@yahoo.com> wrote in message 
news:4ingla5ndd1krtpomnc6q6cp1g2rlt6ffp@4ax.com...
> On Sat, 16 May 2015 08:36:36 +0100, "James Harris"
> <james.harris.1@gmail.com> wrote:
>
>>"Robert Wessel" <robertwessel2@yahoo.com> wrote in message
>>news:2ordlatkut0h026ruk5i7fp685b6v3gj2q@4ax.com...
>>> On Sat, 16 May 2015 07:58:54 +0100, "James Harris"
>>> <james.harris.1@gmail.com> wrote:
>>>

...

>>>>Forcing a read is only necessary if something else could have 
>>>>changed
>>>>the value behind our back.
>>>
>>>
>>> Yes, but you need to force the read in those other modules who 
>>> *will*
>>> have that value "changed behind their backs".
>>
>>Not in this case. That would be true only if their activations 
>>persist,
>>I would have thought, i.e. if the two were running concurrently. For a
>>function which starts, executes and stops and only reads the value 
>>once
>>(or reads it multiple times knowing that it cannot be changed while 
>>this
>>function is executing) I don't see that there would be a problem and
>>that is the case here. The interrupt handler would read some of these
>>values knowing that from the start of the interrupt handler's 
>>execution
>>until it returns the main program will not be able to modify the value
>>because it will not be executing concurrently with the interrupt
>>handler.
>
>
> This may be due to my having lost track of exactly which case we're
> trying to discuss here, but...

I know how you feel!

> Assuming the interrupt handler is the one to update the field, it
> would be the interrupted routine that would need to re-read the value.

The case I was thinking of was the converse: the main routine making the 
updates and the interrupt handler just reading. Nothing would change the 
value while the interrupt handler was running.

>>That said, if I went down the volatile route I would probably declare 
>>it
>>as volatile in both. That would achieve the same effect and be safer
>>against future changes.
>
>
> Is it actually legal to *not* declare them as both with the same
> volatility?

I don't know. There seem to be lots of gotchas.

James

[toc] | [prev] | [next] | [standalone]


#62261

FromDavid Brown <david.brown@hesbynett.no>
Date2015-05-19 00:55 +0200
Message-ID<mjdqjm$m1e$1@dont-email.me>
In reply to#62187
On 17/05/15 19:24, James Harris wrote:
> "Robert Wessel" <robertwessel2@yahoo.com> wrote in message
> news:4ingla5ndd1krtpomnc6q6cp1g2rlt6ffp@4ax.com...
>> On Sat, 16 May 2015 08:36:36 +0100, "James Harris"
>> <james.harris.1@gmail.com> wrote:
>>
>>> "Robert Wessel" <robertwessel2@yahoo.com> wrote in message
>>> news:2ordlatkut0h026ruk5i7fp685b6v3gj2q@4ax.com...
>>>> On Sat, 16 May 2015 07:58:54 +0100, "James Harris"
>>>> <james.harris.1@gmail.com> wrote:
>>>>
>
> ...
>
>>>>> Forcing a read is only necessary if something else could have
>>>>> changed
>>>>> the value behind our back.
>>>>
>>>>
>>>> Yes, but you need to force the read in those other modules who
>>>> *will*
>>>> have that value "changed behind their backs".
>>>
>>> Not in this case. That would be true only if their activations
>>> persist,
>>> I would have thought, i.e. if the two were running concurrently. For a
>>> function which starts, executes and stops and only reads the value
>>> once
>>> (or reads it multiple times knowing that it cannot be changed while
>>> this
>>> function is executing) I don't see that there would be a problem and
>>> that is the case here. The interrupt handler would read some of these
>>> values knowing that from the start of the interrupt handler's
>>> execution
>>> until it returns the main program will not be able to modify the value
>>> because it will not be executing concurrently with the interrupt
>>> handler.
>>
>>
>> This may be due to my having lost track of exactly which case we're
>> trying to discuss here, but...
>
> I know how you feel!
>
>> Assuming the interrupt handler is the one to update the field, it
>> would be the interrupted routine that would need to re-read the value.
>
> The case I was thinking of was the converse: the main routine making the
> updates and the interrupt handler just reading. Nothing would change the
> value while the interrupt handler was running.

In either case, "volatile" is your best bet here.  I don't know why you 
think "volatile" is "too strong a restriction" - a volatile write is not 
more costly than a non-volatile write if the write actually hits memory, 
nor is a volatile read more costly than a non-volatile read.  (Multiple 
unnecessary reads or writes can be costly - but a local "cache" variable 
solves that problem.)

>
>>> That said, if I went down the volatile route I would probably declare
>>> it
>>> as volatile in both. That would achieve the same effect and be safer
>>> against future changes.
>>
>>
>> Is it actually legal to *not* declare them as both with the same
>> volatility?
>
> I don't know. There seem to be lots of gotchas.
>

It is not legal to declare the same variable as "volatile" in one place 
and not volatile somewhere else.  But you can use casts to add a 
volatile qualifier to an object in order to force a volatile access. 
Remember, it is /accesses/ that are volatile, not the variable itself - 
declaring the variable "volatile" just means that all accesses to it 
will be volatile.

Personally, I sometimes make use of this macro:

#define volatileAccess(v) *((volatile typeof((v)) *) &(v))

I can then force a read or write of a non-volatile variable using:

	volatileAccess(x) = y;
or
	x = volatileAccess(y);

[toc] | [prev] | [next] | [standalone]


#62014

FromKeith Thompson <kst-u@mib.org>
Date2015-05-14 11:26 -0700
Message-ID<87mw17c8wz.fsf@kst-u.example.com>
In reply to#61986
"James Harris" <james.harris.1@gmail.com> writes:
> I understand that there is a so-called "sequence point" after an 
> assignment (taking an assignment as "the expression in an expression 
> statement"). As far as what that means, I read: "all side effects of 
> previous evaluations shall be complete and no side effects of subsequent 
> evaluations shall have taken place."

It's clearer to say that there's a sequence point at the end of any
statement.  A statement that happens to be an expression statement,
where the expression happens to be an assignment, is just a special
case.

> But does that mean that the value of u will have been updated in memory? 
> I guess not because a compiler will normally carry values around in 
> registers and only spill them to memory when it has to.

The program must behave *as if* any side effects have *not* taken place
before the previous sequence point, and *have* taken place after the
following sequence point.

> I was looking for guarantees about updates reaching memory so that they 
> would be visible to an interrupt handling function. When I speak about 
> writes to memory they would not have had to have reached RAM. Storage in 
> cache would be OK.

You probably want to use "volatile".

> How about:
>
>   u = 0;
>   f();
>
> Is u guaranteed to have been written to memory before function f is 
> called? Does f need to be in a different translation unit to force prior 
> commits to memory (so that pointers to their values are valid)?

If u is visible to the body of f(), then any reads of u within f() must
see the updated value.  Likewise if an object containing the address of
u is visible to the body of f().  (If the compiler can prove that f
doesn't actually access u, then it can postpone the update of u, since
doing so has no visible effect on the program's behavior.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#62022

From"James Harris" <james.harris.1@gmail.com>
Date2015-05-14 22:07 +0100
Message-ID<mj32ni$crf$1@dont-email.me>
In reply to#62014
"Keith Thompson" <kst-u@mib.org> wrote in message 
news:87mw17c8wz.fsf@kst-u.example.com...
> "James Harris" <james.harris.1@gmail.com> writes:
>> I understand that there is a so-called "sequence point" after an
>> assignment (taking an assignment as "the expression in an expression
>> statement"). As far as what that means, I read: "all side effects of
>> previous evaluations shall be complete and no side effects of 
>> subsequent
>> evaluations shall have taken place."
>
> It's clearer to say that there's a sequence point at the end of any
> statement.  A statement that happens to be an expression statement,
> where the expression happens to be an assignment, is just a special
> case.

According to the C89 draft I have been using:

"A.2 SEQUENCE POINTS
The following are the sequence points described in 2.1.2.3

* The call to a function, after the arguments have been evaluated 
(3.3.2.2).

* The end of the first operand of the following operators: logical AND 
&& (3.3.13); logical OR || (3.3.14); conditional ? (3.3.15); comma , 
(3.3.17).

* The end of a full expression: an initializer (3.5.7); the expression 
in an expression statement (3.6.3); the controlling expression of a 
selection statement ( if or switch ) (3.6.4); the controlling expression 
of a while or do statement (3.6.5); the three expressions of a for 
statement (3.6.5.3); the expression in a return statement (3.6.6.4). "

I presume that includes embedded assignment as in the assignment to X in

  if ((X = f()) != 0) ...

James

[toc] | [prev] | [next] | [standalone]


#62024

FromKeith Thompson <kst-u@mib.org>
Date2015-05-14 14:22 -0700
Message-ID<878ucqdfbq.fsf@kst-u.example.com>
In reply to#62022
"James Harris" <james.harris.1@gmail.com> writes:
> "Keith Thompson" <kst-u@mib.org> wrote in message 
> news:87mw17c8wz.fsf@kst-u.example.com...
>> "James Harris" <james.harris.1@gmail.com> writes:
>>> I understand that there is a so-called "sequence point" after an
>>> assignment (taking an assignment as "the expression in an expression
>>> statement"). As far as what that means, I read: "all side effects of
>>> previous evaluations shall be complete and no side effects of 
>>> subsequent
>>> evaluations shall have taken place."
>>
>> It's clearer to say that there's a sequence point at the end of any
>> statement.  A statement that happens to be an expression statement,
>> where the expression happens to be an assignment, is just a special
>> case.
>
> According to the C89 draft I have been using:

Are you using a C89/C90 compiler?  If not, I suggest referring instead
to a draft of a more recent edition of the standard.  N1256 consists of
the C99 standard with the three Technical Corrigenda merged into it
(it's more current than the official C99 standard).  N1570 is the last
public draft of the C11 standard; the differences between it and the
published standard are very minor.

    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

> "A.2 SEQUENCE POINTS
> The following are the sequence points described in 2.1.2.3
>
> * The call to a function, after the arguments have been evaluated 
> (3.3.2.2).
>
> * The end of the first operand of the following operators: logical AND 
> && (3.3.13); logical OR || (3.3.14); conditional ? (3.3.15); comma , 
> (3.3.17).
>
> * The end of a full expression: an initializer (3.5.7); the expression 
> in an expression statement (3.6.3); the controlling expression of a 
> selection statement ( if or switch ) (3.6.4); the controlling expression 
> of a while or do statement (3.6.5); the three expressions of a for 
> statement (3.6.5.3); the expression in a return statement (3.6.6.4). "
>
> I presume that includes embedded assignment as in the assignment to X in
>
>   if ((X = f()) != 0) ...

In that case, the controlling expression (which is a "full expression")
is not `X = f()`, but `(X = f()) != 0` -- the comparison, not the
assignment.  It doesn't matter in this case, but in general an
assignment by itself does not imply a sequence point.  The side effect
of updating X does not necessarily happen before the next sequence
point; in particular, X might be updated before or after the right hand
side of the "!=" operator is evaluated.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#62029

From"James Harris" <james.harris.1@gmail.com>
Date2015-05-14 22:36 +0100
Message-ID<mj34ff$jdq$1@dont-email.me>
In reply to#62024
"Keith Thompson" <kst-u@mib.org> wrote in message 
news:878ucqdfbq.fsf@kst-u.example.com...
> "James Harris" <james.harris.1@gmail.com> writes:
>> "Keith Thompson" <kst-u@mib.org> wrote in message
>> news:87mw17c8wz.fsf@kst-u.example.com...
>>> "James Harris" <james.harris.1@gmail.com> writes:
>>>> I understand that there is a so-called "sequence point" after an
>>>> assignment (taking an assignment as "the expression in an 
>>>> expression
>>>> statement"). As far as what that means, I read: "all side effects 
>>>> of
>>>> previous evaluations shall be complete and no side effects of
>>>> subsequent
>>>> evaluations shall have taken place."
>>>
>>> It's clearer to say that there's a sequence point at the end of any
>>> statement.  A statement that happens to be an expression statement,
>>> where the expression happens to be an assignment, is just a special
>>> case.
>>
>> According to the C89 draft I have been using:
>
> Are you using a C89/C90 compiler?

No. I am using more than one compiler (on the same source) and one of 
them is much older than C89.  :-(

> If not, I suggest referring instead
> to a draft of a more recent edition of the standard.  N1256 consists 
> of
> the C99 standard with the three Technical Corrigenda merged into it
> (it's more current than the official C99 standard).  N1570 is the last
> public draft of the C11 standard; the differences between it and the
> published standard are very minor.
>
>    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
>    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
>
>> "A.2 SEQUENCE POINTS
>> The following are the sequence points described in 2.1.2.3
>>
>> * The call to a function, after the arguments have been evaluated
>> (3.3.2.2).
>>
>> * The end of the first operand of the following operators: logical 
>> AND
>> && (3.3.13); logical OR || (3.3.14); conditional ? (3.3.15); comma ,
>> (3.3.17).
>>
>> * The end of a full expression: an initializer (3.5.7); the 
>> expression
>> in an expression statement (3.6.3); the controlling expression of a
>> selection statement ( if or switch ) (3.6.4); the controlling 
>> expression
>> of a while or do statement (3.6.5); the three expressions of a for
>> statement (3.6.5.3); the expression in a return statement (3.6.6.4). 
>> "
>>
>> I presume that includes embedded assignment as in the assignment to X 
>> in
>>
>>   if ((X = f()) != 0) ...
>
> In that case, the controlling expression (which is a "full 
> expression")
> is not `X = f()`, but `(X = f()) != 0` -- the comparison, not the
> assignment.  It doesn't matter in this case, but in general an
> assignment by itself does not imply a sequence point.  The side effect
> of updating X does not necessarily happen before the next sequence
> point; in particular, X might be updated before or after the right 
> hand
> side of the "!=" operator is evaluated.

Thanks for explaining that.

James

[toc] | [prev] | [next] | [standalone]


#62447

FromTim Rentsch <txr@alumni.caltech.edu>
Date2015-05-22 08:16 -0700
Message-ID<kfnvbfk8wy5.fsf@x-alumni2.alumni.caltech.edu>
In reply to#62014
Keith Thompson <kst-u@mib.org> writes:

> "James Harris" <james.harris.1@gmail.com> writes:
>> I understand that there is a so-called "sequence point" after
>> an assignment (taking an assignment as "the expression in an
>> expression statement").  As far as what that means, I read:
>> "all side effects of previous evaluations shall be complete and
>> no side effects of subsequent evaluations shall have taken
>> place."
>
> It's clearer to say that there's a sequence point at the end of
> any statement.  A statement that happens to be an expression
> statement, where the expression happens to be an assignment, is
> just a special case.  [snip]

Where do you get this?  AFAICS the Standard doesn't say anything
about sequence points at the end of statements.  There is a
sequence point between the evaluation of a full expression and
that of the next full expression, and some other cases, but
nothing about ends of statements.  Am I missing something?

[toc] | [prev] | [next] | [standalone]


#62460

FromKeith Thompson <kst-u@mib.org>
Date2015-05-22 11:31 -0700
Message-ID<87h9r4sbtv.fsf@kst-u.example.com>
In reply to#62447
Tim Rentsch <txr@alumni.caltech.edu> writes:
> Keith Thompson <kst-u@mib.org> writes:
>> "James Harris" <james.harris.1@gmail.com> writes:
>>> I understand that there is a so-called "sequence point" after
>>> an assignment (taking an assignment as "the expression in an
>>> expression statement").  As far as what that means, I read:
>>> "all side effects of previous evaluations shall be complete and
>>> no side effects of subsequent evaluations shall have taken
>>> place."
>>
>> It's clearer to say that there's a sequence point at the end of
>> any statement.  A statement that happens to be an expression
>> statement, where the expression happens to be an assignment, is
>> just a special case.  [snip]
>
> Where do you get this?  AFAICS the Standard doesn't say anything
> about sequence points at the end of statements.  There is a
> sequence point between the evaluation of a full expression and
> that of the next full expression, and some other cases, but
> nothing about ends of statements.  Am I missing something?

You're right, my mistake.

In my defense, I said it was clearer; I didn't say it was correct.
8-)})

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#62035

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-05-15 00:05 -0400
Message-ID<mj3r8i$kva$1@dont-email.me>
In reply to#61986
On 05/14/2015 06:43 AM, James Harris wrote:
> I understand that there is a so-called "sequence point" after an 
> assignment (taking an assignment as "the expression in an expression 
> statement"). ...

There is a sequence point at the end of an expression statement. There
is no sequence point associated with an assignment expression. If you
have an expression statement where the expression is an assignment
expression, there is a sequence point, but you're far better off
associating it with the statement, than with the expression, because
that's how the standard describes it. Associating it with the expression
would give you an incorrect understanding of expression statements that
contain assignment expressions as sub-expressions of the main expression.

> ... As far as what that means, I read: "all side effects of 
> previous evaluations shall be complete and no side effects of subsequent 
> evaluations shall have taken place."
> 
> But does that mean that the value of u will have been updated in memory? 
> I guess not because a compiler will normally carry values around in 
> registers and only spill them to memory when it has to.

"Accessing a volatile object, modifying an object, modifying a file, or
calling a function that does any of those operations are all side
effects, ..." (5.1.2.3p2)

The term "side effect" appears in italics in that clause, which is an
ISO convention indicating that the clause in which it appears is the
official definition of the italicized term.

Since an object is defined as a "region of data storage", "modifying an
object" is closely related to your concerns about spilling a register to
memory.

However, both registers and RAM are merely implementation details - the
standard deliberately avoids specifying such details - it would be
entirely feasible to implement C on hardware that has neither. All that
matters is the actual behavior of the program. If it matters, for the
behavior of a strictly conforming program, whether or not a value has
been spilled from a register to memory - then the program must behave as
if it was in fact spilled (it need not actually spill the register - so
long as it can find some other way to produce the same behavior as if it
had spilled the register).

In C2011, support for multi-threading was added to the standard. As a
result, the standard needed to be much more specific about what it does
and does not require with regards to sequencing of events. An event can
be sequenced before another event, or sequenced after or indeterminately
sequenced. A sequence point requires that the side-effects of one
expression be sequenced after the ones associated with a different
expression. However, other expressions (for instance, those occurring in
a different thread) might be indeterminately sequenced with respect to a
given assignment expression, and if so, you shouldn't have any
expectations about whether or not the values from the registers have
been spilled to memory as far as the evaluation of those expressions is
concerned.

> I was looking for guarantees about updates reaching memory so that they 
> would be visible to an interrupt handling function. When I speak about 
> writes to memory they would not have had to have reached RAM. Storage in 
> cache would be OK.

The standard deliberately leaves such things unspecified. It's
discussion of concurrency is limited to signal handlers and
multi-threaded programs. An interrupt handler is neither. You'll have to
look to your operating system for relevant guarantees (or the lack
thereof).

> How about:
> 
>   u = 0;
>   f();
> 
> Is u guaranteed to have been written to memory before function f is 
> called? ...

Unambiguously. That's what sequence points are for.

> ... Does f need to be in a different translation unit to force prior 
> commits to memory (so that pointers to their values are valid)?

No, it can be in the same translation unit.

-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#62073

From"James Harris" <james.harris.1@gmail.com>
Date2015-05-15 22:25 +0100
Message-ID<mj5o6u$dpn$1@dont-email.me>
In reply to#62035
"James Kuyper" <jameskuyper@verizon.net> wrote in message 
news:mj3r8i$kva$1@dont-email.me...
> On 05/14/2015 06:43 AM, James Harris wrote:

...

>>   u = 0;
>>   f();
>>
>> Is u guaranteed to have been written to memory before function f is
>> called? ...
>
> Unambiguously. That's what sequence points are for.

AIUI sequence points guarantee the apparent order of evaluation but that 
they do not make any guarantees about values being written to memory.

>> ... Does f need to be in a different translation unit to force prior
>> commits to memory (so that pointers to their values are valid)?
>
> No, it can be in the same translation unit.

I was concerned about inter-function optimisation if the compiler could 
see both caller and callee code and that would permit it not to write u 
to memory before making the call. If the called function is in a 
separate translation unit, however, then unless the compiler can prove 
that no called function can access u ISTM that it has to write it to 
memory before calling f (and reload it afterwards, if necessary).

James

[toc] | [prev] | [next] | [standalone]


#62080

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-05-15 17:56 -0400
Message-ID<55566B83.7010900@verizon.net>
In reply to#62073
On 05/15/2015 05:25 PM, James Harris wrote:
> "James Kuyper" <jameskuyper@verizon.net> wrote in message 
> news:mj3r8i$kva$1@dont-email.me...
>> On 05/14/2015 06:43 AM, James Harris wrote:
> 
> ...
> 
>>>   u = 0;
>>>   f();
>>>
>>> Is u guaranteed to have been written to memory before function f is
>>> called? ...
>>
>> Unambiguously. That's what sequence points are for.
> 
> AIUI sequence points guarantee the apparent order of evaluation but that 
> they do not make any guarantees about values being written to memory.

The standard does not care where the value of an object is actually
stored; it only requires that code involving that object have the
defined behavior, without worrying about the details of how that defined
behavior is achieved.
However, if the current value of an object is stored only in a register
rather than in RAM, any code that attempts to read the value stored in
that object must be translated into loads from that register, rather
than from RAM - failing to do so would render the compiler non-conforming.
Strictly conforming code should not be able to tell the difference.
Can you give an example of strictly conforming code that demonstrates
the issue you're worried about?

Note: certain ways of using debuggers, linking in assembler code, and
triggering interrupt handlers are all ways to make a C program no longer
strictly conforming. You should NOT expect C code to continue having the
expected behavior when fiddling with it in those ways.

>>> ... Does f need to be in a different translation unit to force prior
>>> commits to memory (so that pointers to their values are valid)?
>>
>> No, it can be in the same translation unit.
> 
> I was concerned about inter-function optimisation if the compiler could 
> see both caller and callee code and that would permit it not to write u 
> to memory before making the call. If the called function is in a 
> separate translation unit, however, then unless the compiler can prove 
> that no called function can access u ISTM that it has to write it to 
> memory before calling f (and reload it afterwards, if necessary).

A compiler couldn't do that, but a modern smart linker might. However,
the key thing that allows such optimizations is the as-if rule. This
means that code which has defined behavior must actually produce
behavior that matches the definition, even if those optimizations occur.

[toc] | [prev] | [next] | [standalone]


#62140

FromNobody <nobody@nowhere.invalid>
Date2015-05-17 10:04 +0100
Message-ID<pan.2015.05.17.09.04.03.959000@nowhere.invalid>
In reply to#61986
On Thu, 14 May 2015 11:43:46 +0100, James Harris wrote:

> I understand that there is a so-called "sequence point" after an 
> assignment (taking an assignment as "the expression in an expression 
> statement"). As far as what that means, I read: "all side effects of 
> previous evaluations shall be complete and no side effects of subsequent 
> evaluations shall have taken place."
> 
> But does that mean that the value of u will have been updated in memory? 

No. It means that the value of u where it occurs after the sequence point
will incorporate any side effects which must occur before the sequence
point.

This is all within the "abstract machine" execution model used by the
standard.

> I guess not because a compiler will normally carry values around in 
> registers and only spill them to memory when it has to.
> 
> I was looking for guarantees about updates reaching memory so that they 
> would be visible to an interrupt handling function.

You won't find them in the C standard. Even "volatile" isn't sufficient.
You need to look into memory barriers, which (assuming that they exist)
are implementation-specific.

Roughly, "volatile" tells the compiler not to re-order or elide load/store
operations based upon whether the result is observable according to the
rules of the language (because it might be observable by means outside the
scope of the language, and you happen to care about that case).

Memory barriers tell the CPU not to re-order the execution of load/store
instructions.

For multi-threaded code (which includes interrupt handlers), you need
to use both in order to ensure that neither then compiler nor the CPU
alters the order in which load/store operations are actually performed.

[toc] | [prev] | [next] | [standalone]


Page 5 of 6 — ← Prev page 1 2 3 4 [5] 6  Next page →

Back to top | Article view | comp.lang.c


csiph-web