# V2643. MISRA. All memory synchronization operation should be executed in sequentially consistent order.

This diagnostic rule is based on the MISRA (Motor Industry Software Reliability Association) software development guidelines.

This diagnostic rule is relevant only for C.

Using functions to handle atomic operations implies that the argument specifying the memory model type should always be set to `memory_order::memory_order_seq_cst` (sequentially consistent ordering).

When atomic operations are used in multithreaded code, one thread can access a variable value before another thread changes it. To synchronize read/write operations, C provides memory models defined in the `memory_order` enumeration.

The selected memory model can impact how the compiler and processor optimize the code. The default behavior is sequentially consistent ordering. This behavior pattern is the most intuitive for developers and the strictest model for compilers and processors. When it's used, read/write operations are performed exactly in the order in which they are written in the code.

This diagnostic rule is intended to minimize errors and exclude dependency of parallel code execution on processor and compiler optimizations.

The following functions from the Concurrency support library should be called with `memory_order::memory_order_seq_cst`:

- `atomic_load_explicit`
- `atomic_store_explicit`
- `atomic_flag_test_and_set_explicit`
- `atomic_flag_clear_explicit`
- `atomic_exchange_explicit`
- `atomic_compare_exchange_strong_explicit`
- `atomic_compare_exchange_weak_explicit`
- `atomic_fetch_add_explicit`
- `atomic_fetch_sub_explicit`
- `atomic_fetch_or_explicit`
- `atomic_fetch_xor_explicit`
- `atomic_fetch_and_explicit`
- `atomic_thread_fence`
- `atomic_signal_fence`.

In addition to explicitly passing the argument, developers can use non-`*_explicit` alternatives of these functions. In this case, the `memory_order::memory_order_seq_cst` argument will be implicitly passed.

The example of the incorrect code:

    _Atomic int flag; // initialized elsewhere with non-zero value

    void thread1()
    {
      // do stuff
      atomic_store_explicit(&flag, 0, memory_order_release);
    }

    void thread2()
    {
      auto value = atomic_load_explicit(&flag, memory_order_acquire);
      while (value != 0)
      {
        // do stuff
        value = atomic_load_explicit(&flag, memory_order_acquire);
      }
    }

In the synthetic example above, the order of the `load` and `store` operations cannot be predicted because the non-strict memory model allows the compiler and processor to rearrange the operation order.

The fixed code:

    _Atomic int flag; // initialized elsewhere with non-zero value

    void thread1()
    {
      // do some stuff

      atomic_store_explicit(&flag, 0, memory_order_seq_cst);
      // or use atomic_store(&flag, 0);
    }

    void thread2()
    {
      auto value = atomic_load_explicit(&flag, memory_order_seq_cst);

      // or declaration via 'atomic_load'
      // auto value = atomic_load(&flag);

      while (value != 0)
      {
        // do some stuff

        value = atomic_load_explicit(&flag, memory_order_seq_cst);
        // or assignment via 'atomic_load'
        // value = atomic_load(&flag);
      }
    }

This diagnostic is classified as:

MISRA-C-2012-21.25 MISRA-C-2023-21.25