2018-04-17 02:11:15 |
fenugrec |
description |
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 ! |
Hi,
this is mostly a rehash of https://answers.launchpad.net/gcc-arm-embedded/+question/265649 . Freshly tested against 7-2017-q4 release, issue present since forever (at least 4.9)
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 ! |
|