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

Данное диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.

Это правило актуально только для языка C.

При использовании функций для работы с атомарными операциями аргумент, отвечающий за тип модели памяти, должен всегда иметь значение `memory_order::memory_order_seq_cst` (последовательная согласованность).

При использовании в многопоточном коде атомарных операций может сложиться ситуация, когда один поток обратится к значению переменной раньше, чем другой поток это значение изменит. Для синхронизации операций чтения/записи в языке C существуют модели памяти, определённые в перечислении `memory_order`.

Выбранная модель памяти влияет на то, как компилятор и процессор оптимизируют код. Поведением по умолчанию является sequentially consistent ordering (последовательная согласованность). Эта модель поведения наиболее интуитивно понятна для человека. А также это самая строгая модель для компилятора и процессора. При её использовании операции чтения/записи будут выполняться чётко в том порядке, в котором они написаны в коде.

Данное диагностическое правило призвано уменьшить вероятность ошибки и исключить зависимость выполнения параллельного кода от оптимизаций процессора и компилятора.

Ниже перечислены функции из Concurrency support library, которые должны вызываться со значением `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`.

Помимо явной передачи аргумента можно использовать не `*_explicit` альтернативы вышеописанных функций. В таком случае будет неявно передан аргумент `memory_order::memory_order_seq_cst`.

Пример некорректного кода:

    _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);
      }
    }

В приведённом выше синтетическом примере порядок выполнения операций `load` и `store` не может быть заранее предсказан, поскольку нестрогая модель памяти позволит компилятору и процессору менять очередность операций.

Корректный код:

    _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);
      }
    }

Данная диагностика классифицируется как:

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