Data race including atomic operations

Несколько задач выполняют незащищенные операции на совместно используемой переменной

Описание

Этот дефект происходит когда:

  1. Несколько задач выполняют незащищенные операции на совместно используемой переменной.

  2. По крайней мере одна задача выполняет операцию записи.

Если вы проверяете на этот дефект, вы видите гонки данных и на атомарных и на неатомарных операциях. Чтобы видеть гонки данных на одних только неатомарных операциях, выберите Data race. Bug Finder рассматривает операцию как атомарную, если он может быть выполнен в одной машинной команде. Например, операция:

int var = 0;
может быть выполнен в одной машинной команде на целях где размер int меньше размера слова на цели (или размера указателя). Смотрите Задают Атомарные Операции в Многозадачном Коде. Если вы не хотите использовать это определение атомарных операций, включите это средство проверки.

Чтобы найти этот дефект, необходимо задать многозадачные опции перед анализом. Смотрите Многозадачность. Если ваш код не использует критические разделы вообще, чтобы не отмечать слишком много операций, это средство проверки отключено. Чтобы отметить гонки данных, включающие только атомарные операции, используйте опцию -force-data-races.

Риск

Гонка данных может привести к непредсказуемым значениям совместно используемой переменной, потому что вы не управляете порядком операций в различных задачах.

Фиксация

Чтобы зафиксировать этот дефект, защитите операции на совместно используемой переменной с помощью критических разделов, временного исключения, или другой означает. Смотрите Меры защиты для Совместно используемых переменных в Многозадачном Коде.

Чтобы идентифицировать существующие меры защиты, которые можно снова использовать, см. таблицу и графики, сопоставленные результатом. Таблица показывает каждую пару конфликтных вызовов. Столбец Access Protections показывает существующие меры защиты на вызовах. Чтобы видеть, что последовательность вызова функции ведет к конфликтам, кликните по значку. Для примера смотрите ниже.

Примеры

развернуть все

#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();
}

В этом примере, чтобы эмулировать многозадачное поведение, задают следующие опции:

ОпцияСпецификация
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

На командной строке можно использовать следующее:

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

В этом примере, операция записи var=1; в задаче task1 выполняет одновременно с операцией чтения local_var=var; в задаче task2.

task3 использует критический раздел, который может быть снова использован для других задач.

Коррекция — операции места в критическом разделе

Одна возможная коррекция должна поместить эти операции в тот же критический раздел:

  • var=1; в task1

  • local_var=var; в task2

Когда task1 вводит ее критический раздел, другие задачи не могут ввести свои критические разделы до task1 оставляет его критический раздел. Поэтому эти две операции не могут выполниться одновременно.

Чтобы реализовать критический раздел, снова используйте уже существующий критический раздел в task3. Поместите эти две операции между вызовами begin_critical_section и 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();
}
Коррекция — делает задачи временно исключительными

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

На панели Configuration задайте следующие дополнительные опции:

ОпцияЗначение
Temporally exclusive tasks (-temporal-exclusions-file)task1 task2

На командной строке используйте следующее:

 polyspace-bug-finder
     -temporal-exclusions-file "C:\exclusions_file.txt"
где файл C:\exclusions_file.txt имеет следующую линию:
task1 task2

Информация о результате

Группа: параллелизм
Язык: C | C++
Значение по умолчанию: Off
Синтаксис командной строки: DATA_RACE_ALL
Удар: Средняя
ID CWE: 366, 413
Введенный в R2014b