Data race including atomic operations

Multiple tasks perform unprotected operations on shared variable

Description

This defect occurs when:

  1. Multiple tasks perform unprotected operations on a shared variable.

  2. At least one task performs a write operation.

If you check for this defect, you can see data races on both atomic and non-atomic operations. To see data races on non-atomic operations alone, select Data race. Bug Finder considers an operation as atomic if it can be performed in one machine instruction. For instance, the operation:

int var = 0;
can be performed in one machine instruction on targets where the size of int is less than the word size on the target (or pointer size). See Define Atomic Operations in Multitasking Code. If you do not want to use this definition of atomic operations, turn on this checker.

To find this defect, you must specify the multitasking options before analysis. See Multitasking. If your code does not use critical sections at all, to avoid flagging too many operations, this checker is disabled. To flag data races involving only atomic operations, use the option -force-data-races.

Risk

Data race can result in unpredictable values of the shared variable because you do not control the order of the operations in different tasks.

Fix

To fix this defect, protect the operations on the shared variable using critical sections, temporal exclusion or another means. See Protections for Shared Variables in Multitasking Code.

To identify existing protections that you can reuse, see the table and graphs associated with the result. The table shows each pair of conflicting calls. The Access Protections column shows existing protections on the calls. To see the function call sequence leading to the conflicts, click the icon. For an example, see below.

Examples

expand all

#include<stdio.h>

int 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 example, to emulate multitasking behavior, specify the following options:

OptionSpecification
Configure multitasking manually
Tasks (-entry-points)

task1

task2

task3

Critical section details (-critical-section-begin -critical-section-end)Starting routineEnding routine
begin_critical_sectionend_critical_section

On the command-line, you can use the following:

 polyspace-bug-finder
   -entry-points task1,task2,task3
   -critical-section-begin begin_critical_section:cs1
   -critical-section-end end_critical_section:cs1

In this example, the write operation var=1; in task task1 executes concurrently with the read operation local_var=var; in task task2.

task3 uses a critical section that can be reused for the other tasks.

Correction — Place Operations in Critical Section

One possible correction is to place these operations in the same critical section:

  • var=1; in task1

  • local_var=var; in task2

When task1 enters its critical section, the other tasks cannot enter their critical sections until task1 leaves its critical section. Therefore, the two operations cannot execute concurrently.

To implement the critical section, reuse the already existing critical section in task3. Place the two operations between calls to begin_critical_section and end_critical_section.



#include<stdio.h>

int var;

void begin_critical_section();
void end_critical_section();

void task1(void) {
    begin_critical_section();
    var = 1;
    end_critical_section();
}

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

void task3(void) {
    begin_critical_section();
    /* Operations in task3 */
    end_critical_section();
}
Correction — Make Tasks Temporally Exclusive

Another possible correction is to make the tasks task1 and task2 temporally exclusive. Temporally exclusive tasks cannot execute concurrently.

On the Configuration pane, specify the following additional options:

On the command-line, use the following:

 polyspace-bug-finder
     -temporal-exclusions-file "C:\exclusions_file.txt"
where the file C:\exclusions_file.txt has the following line:
task1 task2

Result Information

Group: Concurrency
Language: C | C++
Default: Off
Command-Line Syntax: DATA_RACE_ALL
Impact: Medium
CWE ID: 366, 413
Introduced in R2014b