Contenu principal

Atomic load and store sequence not atomic (ATOMIC_VAR_SEQUENCE_NOT_ATOMIC)

R2026b

Variable accessible between load and store operations

Description

This defect occurs when you use these functions to load, and then store an atomic variable.

  • C functions:

    • atomic_load()

    • atomic_load_explicit()

    • atomic_store()

    • atomic_store_explicit()

  • C++ functions:

    • std::atomic_load()

    • std::atomic_load_explicit()

    • std::atomic_store()

    • std::atomic_store_explicit()

    • std::atomic::load()

    • std::atomic::store()

A thread cannot interrupt an atomic load or an atomic store operation on a variable, but a thread can interrupt a store, and then load sequence.

Risk

A thread can modify a variable between the load and store operations, resulting in a data race condition.

Fix

To read, modify, and store a variable atomically, use a compound assignment operator such as +=, atomic_compare_exchange() or atomic_fetch_*-family functions.

Examples

expand all

        
        
        
#include <stdatomic.h>
#include <stdbool.h>

static atomic_bool flag = ATOMIC_VAR_INIT(false);

void init_flag(void)
{
    atomic_init(&flag, false);
}

void toggle_flag(void)
{
    bool temp_flag = atomic_load(&flag);
    temp_flag = !temp_flag;
    atomic_store(&flag, temp_flag);
}

bool get_flag(void)
{
    return atomic_load(&flag);
}

In this example, variable flag of type atomic_bool is referenced twice inside the toggle_flag() function. The function loads the variable, negates its value, then stores the new value back to the variable. If two threads call toggle_flag(), the second thread can access flag between the load and store operations of the first thread. flag can end up in an incorrect state.

Correction — Use Compound Assignment to Modify Variable

One possible correction is to use a compound assignment operator to toggle the value of flag. The C standard defines the operation by using ^= as atomic.

          
          
          
#include <stdatomic.h>
#include <stdbool.h>

static atomic_bool flag = ATOMIC_VAR_INIT(false);

void toggle_flag(void)
{
    flag ^= 1;
}

bool get_flag(void)
{
    return flag;
}

Result Information

Group: Concurrency
Language: C | C++
Default: On for handwritten code, off for generated code
Command-Line Syntax: ATOMIC_VAR_SEQUENCE_NOT_ATOMIC
Impact: Medium
PQL Name: std.defects.ATOMIC_VAR_SEQUENCE_NOT_ATOMIC

Version History

Introduced in R2018b