I need a thread save idx and idx-- operation. Disabling interrupts, i.e. use critical sections, is one thing, but I want to understand why my operations are not atomic, as I expect ? Here is the C-code with inline assembler code shown, using segger ozone: (Also please notice, the address of the variables show that the 32 bit variable is 32-bit-aligned in memory, and the 8- and 16-bit variables are both 16 bit aligned)
volatile static U8 dbgIdx8 = 1000U;
volatile static U16 dbgIdx16 = 1000U;
volatile static U32 dbgIdx32 = 1000U;
dbgIdx8 ;
080058BE LDR R3, [PC, #48]
080058C0 LDRB R3, [R3]
080058C2 UXTB R3, R3
080058C4 ADDS R3, #1
080058C6 UXTB R2, R3
080058C8 LDR R3, [PC, #36]
080058CA STRB R2, [R3]
dbgIdx16 ;
080058CC LDR R3, [PC, #36]
080058CE LDRH R3, [R3]
080058D0 UXTH R3, R3
080058D2 ADDS R3, #1
080058D4 UXTH R2, R3
080058D6 LDR R3, [PC, #28]
080058D8 STRH R2, [R3]
dbgIdx32 ;
080058DA LDR R3, [PC, #28]
080058DC LDR R3, [R3]
080058DE ADDS R3, #1
080058E0 LDR R2, [PC, #20]
080058E2 STR R3, [R2]
CodePudding user response:
There is no guarantee that
and --
are atomic. If you need guaranteed atomicity, you will have to find some other way.
As @StaceyGirl points out in a comment, you might be able to use the facilities of <stdatomic.h>. For example, I see there's an atomic atomic_fetch_add
function defined, which acts like the postfix
you're striving for. There's an atomic_fetch_sub
, too.
Alternatively, you might have some compiler intrinsics available to you for performing an atomic increment in some processor-specific way.
CodePudding user response:
The postfix increment operator in dbgIdx8 ;
is not atomic because the C compiler does save the current value of dbgIdx8
then do any operations on it (in this case there is nothing) then do the incrementing.
To achieve atomic operation use the prefix increment operator like dbgIdx8;
CodePudding user response:
The variables are marked as volatile
which tells the compiler to assume that it can be used or modified in an unknown way. So the processor will load value to a register, perform the required operations, and store result back to a memory location. There is no "in-memory" arithmetic in Cortex-M3.
However, removing keyword volatile
might, or might not make an operation atomic. It depends on the operations done before and after increment. There is no guarantee.