EmbeddedRelated.com
Forums
Memfault State of IoT Report

Question About Sequence Points and Interrupt/Thread Safety

Started by Jujitsu Lizard February 24, 2009
REH <spamjunk@stny.rr.com> writes:

> On Feb 24, 6:58&nbsp;pm, "Jujitsu Lizard" <jujitsu.liz...@gmail.com> wrote:
<snip>
>> Is there any reason that the compiler cannot delay writing "x" back so that >> I get effectively this: >> >> DI(); >> cpu_register = x; >> if(cpu_register) >> &nbsp; &nbsp;cpu_register--; >> EI(); >> x = cpu_register; >> > > Hopefully, the regulars will confirm or discount this, but I believe > you can force the ordering by making wrappers for your two functions > at take x as a parameter. I think this make the compiler think they > are dependent on x's value, and not reorder the code. Something like: > > DIx(x); > if (x) > x--; > EIx(x);
I would not rely on that. x can be passed (to EI) by copying the register from the OP's example and the change to x could still occur later. You might have move luck with &x because in that case the compiler would have to do extra work to avoid the obvious method of updating x "on time". -- Ben.
REH wrote:
> On Feb 24, 6:58 pm, "Jujitsu Lizard" <jujitsu.liz...@gmail.com> wrote: >> I've included a function below and the generated STM8 assembly-language. As >> it ends up (based on the assembly-language), the function is interrupt safe >> as intended. >> >> My question is, let's assume I have this: >> >> DI(); >> if (x) >> x--; >> EI(); >> >> where DI and EI just expand to the compiler's asm( ) feature to insert the >> right machine instruction to disable and enable interrupts, ... >> >> Is there any reason that the compiler cannot delay writing "x" back so that >> I get effectively this: >> >> DI(); >> cpu_register = x; >> if(cpu_register) >> cpu_register--; >> EI(); >> x = cpu_register; >> > > Hopefully, the regulars will confirm or discount this, but I believe > you can force the ordering by making wrappers for your two functions > at take x as a parameter. I think this make the compiler think they > are dependent on x's value, and not reorder the code. Something like: > > DIx(x); > if (x) > x--; > EIx(x);
Others have already pointer out that there can be inter-function and even inter-translation-unit (link time) optimisation which will allow the compiler to break the code. Using non-standard (possibly OS provided) routines is probably the best way to go in my opinion. -- Flash Gordon
Phil Carmody wrote:
> I'm feeling a bit dense currently. I'm having issues with the > following: > """ > 2. WHAT DOES VOLATILE MEAN? > ... > A compiler may not move accesses to volatile variables across > sequence points.[1] > ... > No guarantees are made about the atomicity of > any given volatile access, about the ordering of multiple volatile > accesses between two consecutive sequence points, or about the > ordering of volatile and non-volatile accesses. > """ > > That final clause seems to contradict the initial footnoted clause, > on the presumption that the non-volatile accesses begin with, end > with, or contain, a sequence point.
The former quote says that compilers can't move volatile accesses _across_ a sequence point; the latter quote says that the order of volatile accesses _between_ two sequence points is undefined. The two do not contradict each other. For instance, consider the following: volatile int a, b, c; /* other code */ foo(); a += b + c; bar(); The compiler cannot move the volatile accesses before foo() or after bar(), but it _can_ choose in what order to read a, b, and c. However, it can also choose to move other (non-volatile) code between foo() and bar(), or move code before foo() to after bar() or vice versa, if it could prove that doing so wouldn't violate the as-if rule. S -- Stephen Sprunk "Stupid people surround themselves with smart CCIE #3723 people. Smart people surround themselves with K5SSS smart people who disagree with them." --Isaac Jaffe
Stephen Sprunk wrote:

> The former quote says that compilers can't move volatile accesses > _across_ a sequence point;
[...]
> bar(), or move code before foo() to after bar() or vice versa, if it > could prove that doing so wouldn't violate the as-if rule.
Ehm, no. You're overlooking that by moving code down from before foo() to after bar(), you're also moving your volatile accesses up, across the sequence point(s) in that code, which would violate the first statement above. It cuts both ways --- whenever you talking about "moving" code, what actually happens is that operations are swapped, and that means you move each across the other.
"Tim Rentsch" <txr@alumnus.caltech.edu> wrote in message 
news:kfny6vuvqyw.fsf@alumnus.caltech.edu...
> > Two: The comment to the function talks about decrementing an > array of timers, but the function body shown only ever deals with > the first element of such an array. So something is amiss there.
You are correct. Actually, I hadn't unit-tested the function, and I would have found that. Want to be my code reviewer? That is embarrassing. I don't do that often.
> Eight: There is a corresponding question going the other > direction, i.e., from the ISR back to the interrupted process.
I don't see that corresponding question, at least not on my hardware. By the time the ISR returns, the data will have been written to memory. The STM8 is one step above toaster/dishwasher grade ... If you're seeing a problem going the other way, please explain it ... The Lizard
Hans-Bernhard Br&ouml;ker wrote:
> Stephen Sprunk wrote: >> The former quote says that compilers can't move volatile accesses >> _across_ a sequence point; > [...] >> bar(), or move code before foo() to after bar() or vice versa, if it >> could prove that doing so wouldn't violate the as-if rule. > > Ehm, no. You're overlooking that by moving code down from before foo() > to after bar(), you're also moving your volatile accesses up, across the > sequence point(s) in that code, which would violate the first statement > above. > > It cuts both ways --- whenever you talking about "moving" code, what > actually happens is that operations are swapped, and that means you move > each across the other.
Hmm. I think that you're right in theory, but is it possible that a conforming program could tell the difference? Doesn't the as-if rule still apply to the non-volatile parts of the code? Or does a single volatile access break the as-if rule even for non-volatile operations? I've seen compilers do what I described (from studying the asm output), and nobody seems to complain about it. Mixing volatile and non-volatile operations is pretty unpredictable in practice, so I have always avoided that entirely rather than try to figure out exactly what the Standard guarantees (which doesn't appear to be much when it comes to volatile variables). S -- Stephen Sprunk "Stupid people surround themselves with smart CCIE #3723 people. Smart people surround themselves with K5SSS smart people who disagree with them." --Isaac Jaffe
Stephen Sprunk <stephen@sprunk.org> writes:
> Phil Carmody wrote: >> I'm feeling a bit dense currently. I'm having issues with the >> following: >> """ >> 2. WHAT DOES VOLATILE MEAN? >> ... >> A compiler may not move accesses to volatile variables across >> sequence points.[1] ... >> No guarantees are made about the atomicity of any given volatile >> access, about the ordering of multiple volatile >> accesses between two consecutive sequence points, or about the >> ordering of volatile and non-volatile accesses. """ >> >> That final clause seems to contradict the initial footnoted clause, >> on the presumption that the non-volatile accesses begin with, end >> with, or contain, a sequence point. > > The former quote says that compilers can't move volatile accesses > _across_ a sequence point; the latter quote says that the order of > volatile accesses _between_ two sequence points is undefined. The two > do not contradict each other. > > For instance, consider the following: > > volatile int a, b, c; > /* other code */ > foo(); > a += b + c; > bar(); > > The compiler cannot move the volatile accesses before foo() or after > bar(),
I'm happy with that. A nice clear absolute. No wondering about 'as if's.
> but it _can_ choose in what order to read a, b, and c.
Perfectly happy with that too, wouldn't want it any other way.
> However, it can also choose to move other (non-volatile) code between > foo() and bar(), or move code before foo() to after bar() or vice versa
What's so special about function calls? Why wouldn't a for loop, or even simple assignments, contain sequence points that the volatile accesses couldn't be moved past? What property do foo() and bar() have that those other things with sequence points don't have? Phil -- I tried the Vista speech recognition by running the tutorial. I was amazed, it was awesome, recognised every word I said. Then I said the wrong word ... and it typed the right one. It was actually just detecting a sound and printing the expected word! -- pbhj on /.
Phil Carmody wrote:

> Stephen Sprunk <stephen@sprunk.org> writes: >> volatile int a, b, c; >> /* other code */ >> foo(); >> a += b + c; >> bar(); >> >> The compiler cannot move the volatile accesses before foo() or after >> bar(), > > I'm happy with that. A nice clear absolute. No wondering about 'as if's. > >> but it _can_ choose in what order to read a, b, and c. > > Perfectly happy with that too, wouldn't want it any other way. > >> However, it can also choose to move other (non-volatile) code between >> foo() and bar(), or move code before foo() to after bar() or vice versa > > What's so special about function calls? Why wouldn't a for loop, > or even simple assignments, contain sequence points that the > volatile accesses couldn't be moved past? What property do foo() > and bar() have that those other things with sequence points don't > have?
They're in the example, so they can be referred to. -- "We are on the brink of a new era, if only --" /The Beiderbeck Affair/ Hewlett-Packard Limited registered office: Cain Road, Bracknell, registered no: 690597 England Berks RG12 1HN
Phil Carmody wrote:
> Stephen Sprunk <stephen@sprunk.org> writes: >> Phil Carmody wrote: >>> I'm feeling a bit dense currently. I'm having issues with the >>> following: >>> """ >>> 2. WHAT DOES VOLATILE MEAN? >>> ... >>> A compiler may not move accesses to volatile variables across >>> sequence points.[1] ... >>> No guarantees are made about the atomicity of any given volatile >>> access, about the ordering of multiple volatile >>> accesses between two consecutive sequence points, or about the >>> ordering of volatile and non-volatile accesses. """ >>> >>> That final clause seems to contradict the initial footnoted clause, >>> on the presumption that the non-volatile accesses begin with, end >>> with, or contain, a sequence point. >> >> The former quote says that compilers can't move volatile accesses >> _across_ a sequence point; the latter quote says that the order of >> volatile accesses _between_ two sequence points is undefined. The two >> do not contradict each other. >> >> For instance, consider the following: >> >> volatile int a, b, c; >> /* other code */ >> foo(); >> a += b + c; >> bar(); >> >> The compiler cannot move the volatile accesses before foo() or after >> bar(), > > I'm happy with that. A nice clear absolute. No wondering about 'as if's.
I know it isn't strictly true, but my mental shortcut for all the rules about volatile variables/operations is that volatile voids the as-if rule. The problems only come when you mix volatile and non-volatile operations together.
>> but it _can_ choose in what order to read a, b, and c. > > Perfectly happy with that too, wouldn't want it any other way. > >> However, it can also choose to move other (non-volatile) code between >> foo() and bar(), or move code before foo() to after bar() or vice versa > > What's so special about function calls? Why wouldn't a for loop, > or even simple assignments, contain sequence points that the > volatile accesses couldn't be moved past? What property do foo() > and bar() have that those other things with sequence points don't > have?
Any sequence point suffices; the only magical property of function calls in my example is that they're easy to refer to by name. It's hard to refer to particular semicolons because they all look the same... S -- Stephen Sprunk "Stupid people surround themselves with smart CCIE #3723 people. Smart people surround themselves with K5SSS smart people who disagree with them." --Isaac Jaffe
Stephen Sprunk <stephen@sprunk.org> writes:
> Phil Carmody wrote: >> What's so special about function calls? Why wouldn't a for loop, >> or even simple assignments, contain sequence points that the >> volatile accesses couldn't be moved past? What property do foo() >> and bar() have that those other things with sequence points don't >> have? > > Any sequence point suffices; the only magical property of function > calls in my example is that they're easy to refer to by name. It's > hard to refer to particular semicolons because they all look the > same...
So you think the document's wrong? Phil -- I tried the Vista speech recognition by running the tutorial. I was amazed, it was awesome, recognised every word I said. Then I said the wrong word ... and it typed the right one. It was actually just detecting a sound and printing the expected word! -- pbhj on /.

Memfault State of IoT Report