Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #61986 > unrolled thread
| Started by | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| First post | 2015-05-14 11:43 +0100 |
| Last post | 2015-05-24 08:11 -0700 |
| Articles | 20 on this page of 101 — 15 participants |
Back to article view | Back to comp.lang.c
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 →
| From | Morris Dovey <mrdovey@iedu.com> |
|---|---|
| Date | 2015-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2015-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2015-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2015-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]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2015-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2015-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]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2015-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2015-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]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2015-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2015-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]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-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]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2015-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]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-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]
| From | Nobody <nobody@nowhere.invalid> |
|---|---|
| Date | 2015-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