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

Marian Buschsieweke notifications at github.com
Sun Apr 28 20:26:36 CEST 2019

maribu commented on this pull request.

> + * @brief       Memory Barriers
+ *
+ * # FAQ
+ * ## What are Memory Barriers
+ * Memory barriers suppress specific kinds optimization performed by the
+ * compiler or (in case of out-of-order CPUs) CPUs, depending on the barrier.
+ * This will most likely result in slower program execution and, thus, is in
+ * general unwanted. However, under specific circumstances, optimization can
+ * prevent correct execution.
+ *
+ * ## Why can't I use `volatile` instead
+ * Memory accesses to `volatile` can be viewed as an alternative to
+ * @ref compiler_barrier, but only in regard to other accesses to `volatile`
+ * variables. (Some compilers do not reorder memory accesses to non-`volatile`s
+ * across accesses to `volatile`s as well, but not all compilers do so.)
+ * Resorting to mark all variables as `volatile` to enforce the correct order

I totally forgot the obvious argument here:

> A memory barrier forces the compiler to forget everything it knows about all variables in the current scope.

This is an incorrect generalization. The compiler will assume that global memory is expected to be accessed during the barrier. In general local variables are still fully optimized. (When the address of the stack variables has been passed to an external function, the compiler has to treat those as potentially accessed as well.)  So the compiler will only reload globals after the barrier (and only if they are used on both sides of the barrier). Thus, the odds for the barrier to be cheaper than `volatile` are very good. (And e.g. for the Linux community this was also true in practice.)

Let me prove that GCC is able to optimize access to stack variables (unless their address is passed to external code) across barriers:

#include <stdint.h>

#define memory_barrier() __sync_synchronize()

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

foo_t foo(foo_t a)
	a.left = 0xf;
	a.right = 0xf;
	return a;

Output of `avr-gcc -O3 -S`:
	.file	"foo_local.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__tmp_reg__ = 0
__zero_reg__ = 1
.global	foo
	.type	foo, @function
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
	ldi r24,lo8(-1)
/* epilogue start */
	.size	foo, .-foo
	.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:
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.riot-os.org/pipermail/notifications/attachments/20190428/6cc64717/attachment.html>

More information about the notifications mailing list