[riot-notifications] [RIOT-OS/RIOT] cpu/atmega_common: RTT and RTC support (#8842)
notifications at github.com
Thu Apr 18 16:13:29 CEST 2019
@maribu I can see why people are confused about volatile. That post you linked to is highly misleading, at least when applied to C (not sure how C++ is different, if at all). Rather than look at random vague advice about purpose, intent, and domains of usefulness, we need to look at actual mechanism and specification.
The GCC documentation says specifically that volatile prevents reordering with other volatile variables:
> The minimum requirement is that at a sequence point all previous accesses to volatile objects have stabilized and no subsequent accesses have occurred. Thus an implementation is free to reorder and combine volatile accesses that occur between sequence points, but cannot do so for accesses across a sequence point.
That is from [https://gcc.gnu.org/onlinedocs/gcc/Volatiles.html](url)
My assertion is also supported by the C99 standard document, ISO/IEC 9899:1999
> An object that has volatile-qualified type may be modified in ways unknown to the
> implementation or have other unknown side effects. Therefore any expression referring
> to such an object shall be evaluated strictly according to the rules of the abstract machine,
> as described in 22.214.171.124. Furthermore, at every sequence point the value last stored in the
> object shall agree with that prescribed by the abstract machine, except as modified by the
> unknown factors mentioned previously.
That is from §6.7.3 or p109. [http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf](url)
A sequence point includes variable assignments. In other words, at every variable assignment the actual value assigned to a volatile must agree with the abstract definition of what the programmer wrote, i.e. the compiler cannot reorder variable assignments. This is exactly how I am using volatile, and it is exactly how it is intended to be used. In this case, the goal to be accomplished is to prevent accesses to the struct from being moved out from between writes to the timer interrupt mask.
/* Disable alarm interrupt */
TIMSK2 &= ~(1 << OCIE2A);
[some rtt_state accesses]
/* Enable interrupt */
TIMSK2 |= (1 << OCIE2A);
If those rtt_state accesses are not marked volatile, then the compiler is free to optimize them by effectively moving them around. There is no assurance that they will not take place before the first write to TIMSK2, or after the second write to TIMSK2. By marking rtt_state volatile, the compiler is forced to place the accesses between the TIMSK2 writes. The documentation explicitly supports this exact use of volatile.
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the notifications