0

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]
artless noise
  • 21,212
  • 6
  • 68
  • 105
  • 5
    Normal C increment are not atomic, neither are volatile accesses. You should use explicitly atomic operations from `` –  Oct 24 '21 at 11:22
  • I mean, just look at the assembly code. You have a load of `dbgIdx8` into a register, increment that register, and then store it back several instructions later. That's not atomic in any way, all kinds of external stuff could happen between the load and the store. You're supposed to use exclusive loads and stores, `ldrexb/strexb`, and as noted the `` operations will emit those instructions properly. – Nate Eldredge Oct 24 '21 at 15:53
  • Relevant: [Why is volatile not considered useful in multithreaded C or C++ programming?](https://stackoverflow.com/questions/2484980/why-is-volatile-not-considered-useful-in-multithreaded-c-or-c-programming/2485177?r=SearchResults&s=1|0.0000#2485177) – Nate Eldredge Oct 24 '21 at 15:57

2 Answers2

4

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.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • For processor-specific atomics on the Cortex-M, see [this answer](https://stackoverflow.com/questions/51795537/critical-sections-in-arm/51797599#51797599) (of mine). – cooperised Oct 25 '21 at 09:45
0
  1. ARM cortex cores do not modify memory. All memory modifications are performed as RMW (read-modify-write) operations which are not atomic by default.

But Cortex M3 has special instructions to lock access to the memory location. LDREX & STREX. https://developer.arm.com/documentation/100235/0004/the-cortex-m33-instruction-set/memory-access-instructions/ldaex-and-stlex

You can use them directly in the C code without touching the assembly by using intrinsic.

  1. Do not use not 32 bits data types in any performance (you want to lock for as short as possible time) sensitive programs. Most shorter data types operations add some additional code.
0___________
  • 60,014
  • 4
  • 34
  • 74
  • 1
    Cortex M3 also have LDREX & STREX instructions. g++ emits them when using std::atomic in C++. I guess modern C compilers do the same. Unfortunately M0 cores lack these instructions and using atomics in C++ code causes a link error. – Tagli Oct 25 '21 at 06:31