[riot-notifications] [RIOT-OS/RIOT] cpu/atmega_common: RTT and RTC support (#8842)

Marian Buschsieweke notifications at github.com
Thu Apr 18 21:25:02 CEST 2019


> An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects.

In other words: Hardware that is somehow mapped into the memory has to be volatile. The state structures you're declaring resides in ordinary memory: It is not changed by the hardware, nor does changing it have any side effects like changing the voltage level at a GPIO pin. This is not a use case for `volatile`.

> 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.

``` C
    TIMSK2 &= ~(1 << OCIE2A); /* <-- volatile access */

    [some rtt_state accesses] /* <-- sequence points */

    TIMSK2 |= (1 << OCIE2A); /* <-- volatile access */
```

This means specifically, that during the access to the `rtt_state`, which are sequence points, "the value last stored in the object [here `TIMSK2`] shall agree with that prescribed by the abstract machine". This means during those accesses, the volatile object `TIMSK2` must have the value "interrupts disabled".

---

But, as seeing is believing:
``` C
#include <stdint.h>
typedef union {
    uint32_t u32;
    uint8_t u8[4];
} foo_t;

extern foo_t a, b;
extern
#ifdef USE_VOLATILE
volatile
#endif
int interrupts_enabled;

void bar(void) {
    interrupts_enabled = 0;
    a.u8[0] = 0xa0;
    a.u8[1] = 0xa1;
    b.u8[0] = 0xb0;
    a.u8[2] = 0xa2;
    a.u8[3] = 0xa3;
    interrupts_enabled = 1;
    b.u8[1] = 0xb1;
    b.u8[2] = 0xb2;
    b.u8[3] = 0xb3;
}
```

(Partial) output of `gcc -O3 -o foo1.s -S foo.c`:
``` .s
bar:
.LFB0:
	.cfi_startproc
	movl	$-1549622880, a(%rip)
	movl	$1, interrupts_enabled(%rip)
	movl	$-1280134736, b(%rip)
	ret
	.cfi_endproc
```

Here the accesses get reordered and combined to a single 32-bit write. (And one access to `interrrupts_enabled` is optimized out, as it was deemed unneeded when not taking side effects into account.)

(Partial) output of `gcc -O3 -o foo2.s -S -DUSE_VOLATILE foo.c`:
``` .s
bar:
.LFB0:
	.cfi_startproc
	movl	$-19534, %eax
	movl	$0, interrupts_enabled(%rip)
	movb	$-80, b(%rip)
	movl	$-1549622880, a(%rip)
	movl	$1, interrupts_enabled(%rip)
	movb	$-79, 1+b(%rip)
	movw	%ax, 2+b(%rip)
	ret
	.cfi_endproc
```

Here the accesses to `a` get still optimized and reordered, as they all have been between the two accesses two `interrupts_enabled`. Those accesses to `b` that are supposed to happen while interrupts are disabled are indeed happening then, and those supposed to happen when interrupts are enabled again are happening there.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/RIOT-OS/RIOT/pull/8842#issuecomment-484653302
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.riot-os.org/pipermail/notifications/attachments/20190418/8c159e2e/attachment-0001.html>


More information about the notifications mailing list