[riot-notifications] [RIOT-OS/RIOT] sys: Added simple memory barrier API (#11438)

Marian Buschsieweke notifications at github.com
Fri Apr 26 13:58:22 CEST 2019


> Using volatile as a compiler barrier e.g., in AVR periph code, is perfectly possible.

Let me prove this wrong.

`foo.c`:
```C
#include <stdint.h>

#ifdef VOL
extern volatile uint8_t __barrier;
#define memory_barrier() __barrier = 0
#else
#define memory_barrier() __sync_synchronize()
#endif

typedef struct {
	uint8_t left : 4;
	uint8_t right : 4;
} foo_t;

extern foo_t a;

void foo(void)
{
	a.left = 0xf;
	memory_barrier();
	a.right = 0xf;
}
```

Output of `avr-gcc -O3 -S foo.c -o sync.s` with some comments added:
```
	.file	"foo.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__tmp_reg__ = 0
__zero_reg__ = 1
	.text
.global	foo
	.type	foo, @function
foo:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
	lds r24,a          /* <-- Content of a.right unknown, thus load */
	ori r24,lo8(15)    /* <-- Set a.left to 0xf, keep a.right unmodified */
	sts a,r24          /* <-- Store a */
/* memory_barrier() */
	lds r24,a          /* <-- Load a again */
	ori r24,lo8(-16)   /* <-- Set a.right to 0xf, keep a.left unmodified */
	sts a,r24          /* <-- Store a */
/* epilogue start */
	ret
	.size	foo, .-foo
	.ident	"GCC: (GNU) 8.3.0"
```

Output of `avr-gcc -DVOL -O3 -S foo.c -o vol.s` with some comments added:
```
	.file	"foo.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__tmp_reg__ = 0
__zero_reg__ = 1
	.text
.global	foo
	.type	foo, @function
foo:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
	sts __barrier,__zero_reg__  /* <-- memory_barrier() */
	ldi r24,lo8(-1)             /* <-- r24 = 0xff */
	sts a,r24                   /* <-- a = r24 (== 0xff) */
/* epilogue start */
	ret
	.size	foo, .-foo
	.ident	"GCC: (GNU) 8.3.0"
```

So when using an access to `volatile` memory as barrier, memory access can be moved across this "barrier": Here one 4bit access was moved across the barrier and combined with another 4 bit access. At the time of the barrier the data in `a` is thus corrupted.

(Note: When using avr-gcc 5.4.0 from the docker image `riot/riotbuild` I get the same output except for the different version number in `.ident  "GCC: (GNU) 8.3.0"`)

-- 
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/11438#issuecomment-487031644
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.riot-os.org/pipermail/notifications/attachments/20190426/e861b696/attachment-0001.html>


More information about the notifications mailing list