Comment 0 for bug 1764595

Revision history for this message
fenugrec (fenugrec) wrote :

Hi,
this is mostly a rehash of https://answers.launchpad.net/gcc-arm-embedded/+question/265649 .

Here's the essential:

Compiling the following code with "arm-none-eabi-gcc -save-temps -mcpu=cortex-m0 -mthumb -fverbose-asm at.c"
**** at.c ****
#include <stdatomic.h>

atomic_flag aflag = ATOMIC_FLAG_INIT;

int main(void) {
 while (1) {
  while (atomic_flag_test_and_set( &aflag));
  atomic_flag_clear( &aflag);
 }
 return 0;
}
*********

 gives the following intermediate assembly :

********* at.s (excerpt) ****
main:
 push {r7, lr} @
 add r7, sp, #0 @,,
.L3:
@ t1.c:16: while (atomic_flag_test_and_set( &aflag));
 nop
.L2:
@ t1.c:16: while (atomic_flag_test_and_set( &aflag));
 ldr r3, .L4 @ tmp114,
 ldrb r2, [r3] @ tmp115,
 movs r1, #1 @ tmp116,
 strb r1, [r3] @ tmp117,
 uxtb r3, r2 @ _1, tmp115
@ t1.c:16: while (atomic_flag_test_and_set( &aflag));
 cmp r3, #0 @ _1,
 bne .L2 @,
 ........
**********

The problem is the "ldrb ...strb" sequence which is not atomic. M0 cores do not have strex/ldrex , they require an interrupt disable around the protected operation (mrs + cpsid + msr).

I believe gcc shouldn't silently generate a non-atomic sequence like this !