Гонка данных включая атомарные операции

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

Описание

Гонка данных включая атомарные операции происходит когда:

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

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

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

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

Чтобы найти этот дефект, необходимо задать многозадачные опции перед анализом. Чтобы задать эти опции, на панели Configuration, выбирают Multitasking.

Риск

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

Фиксация

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

Чтобы идентифицировать существующие меры защиты, которые можно снова использовать, см. таблицу и графики, сопоставленные с результатом. Таблица показывает каждую пару конфликтных вызовов. Столбец 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