Main Content

Extend Data Race Checkers to Atomic Operations

A data race might occur when multiple threads perform concurrent operations on a shared variable. When the operations are executed in one machine instruction, they are atomic. For instance, reading a shared variable of type char might take a single machine instruction. Such atomic operations are can be performed concurrently without triggering a data race. By default, Polyspace® Bug Finder assumes that certain operations are atomic and excludes them from data race checks. See Define Atomic Operations in Multitasking Code.

The Polyspace assumptions about the atomic nature of operations might not apply to your environment. If you are unsure whether an operation is atomic in your environment, extend the data race checkers to include these operations.

Identify Need for Extending Checker

Operations that take more than one machine cycle to execute are nonatomic operations. For instance, consider this operation:

MYREG = (u32dma0_chbit << 8UL) | u32dma0_chbit;
This operation takes more than one cycle to be performed and is therefore non-atomic. Such operations are checked for data race conditions when you activate data race checkers. If you are checking operations that take multiple instructions, use the default data race checkers, such as:

Operations that take a single machine instruction to execute are assumed to be atomic. See Define Atomic Operations in Multitasking Code.

Because different machines have different word size, the Polyspace assumptions about the atomic nature of operations might not apply to your environment. For instance, consider the operation:

long long var = 0;
In target hardware where the size of a long long object is less than or equal to the word size, this operation is atomic. In target hardware where the size of a long long object is greater than the word size, this operation is not atomic. For instance, the preceding operation is atomic when -target is x86_64, but not atomic when -target is i386. If you are not sure whether the code executes in a x86_64 machine or in an i386 machine, extend the data race checker to include such operations.

Extend Checker

To include the assumed atomic operations when checking for data race violations, specify the option Detect Data Race in Atomic Operations (-detect-atomic-data-race). Consider this code:

#include<stdio.h>

long var;

void begin_critical_section(void);
void end_critical_section(void);

void task1(void) {
    var = 1;
}

void task2(void) {
    int local_var;
    local_var = var;
    printf("%d", local_var);
}

void task3(void) {
    begin_critical_section();
    /* Operations in task3 */
    end_critical_section();
}

In this code, the write operation var=1; in task task1 executes concurrently with the read operation local_var=var; in task task2. By default, Polyspace assumes that the target processor is i386, where these operations occur within a single machine instruction. These operations are excluded from a data race check.

Data race might still occur in these operations when the target processor is different from i386. To detect possible data races in this code, specify the option Detect Data Race in Atomic Operations (-detect-atomic-data-race). At the command line, use this command:

  • Windows:

    polyspace-bug-finder -checkers  data_race -lang cpp ^
    -entry-points task1,task2,task3 ^
    -critical-section-begin begin_critical_section:CS1 ^
    -critical-section-end end_critical_section:CS1 ^
    -detect-atomic-data-race

  • Linux:

    polyspace-bug-finder -checkers  data_race -lang cpp \
    -entry-points task1,task2,task3 \
    -critical-section-begin begin_critical_section:CS1 \
    -critical-section-end end_critical_section:CS1 \
    -detect-atomic-data-race

    After specifying the option -detect-atomic-data-race, Polyspace flags the variable var.

Checkers That Can Be Extended

The concurrency defect checkers that you can extend in this way are:

See Also

Related Topics