Bug Finder обнаруживает гонки данных между параллельными задачами. Используя опции анализа Bug Finder, можно исправить обнаружение гонки данных, указав, что определенные задачи имеют более высокие приоритеты по сравнению с другими. Задача с более высоким приоритетом является атомарной относительно задач с более низким приоритетом и не может быть прервана этими задачами.
![]()
Вы можете задать до четырех различных приоритетов с этими опциями (с наивысшим приоритетом, перечисленным первым):
Прерывания (незапускаемые): Используйте опцию Interrupts (-interrupts).
Прерывания (предварительно): Используйте опции Interrupts (-interrupts) и -preemptable-interrupts.
Циклические задачи (незапускаемые): Используйте опции Cyclic tasks (-cyclic-tasks) (Polyspace Bug Finder Server) и -non-preemptable-tasks (Polyspace Bug Finder Server).
Можно также задать предпусковые нециклические задачи с помощью опции Entry points (-entry-points) и -non-preemptable-tasks (Polyspace Bug Finder Server).
Циклические задачи (предварительно): Используйте опцию Cyclic tasks (-cyclic-tasks) (Polyspace Bug Finder Server).
Можно также задать нециклические задачи с помощью опции Entry points (-entry-points).
Для образца прерывания имеют наивысший приоритет и не могут быть вытеснены другими задачами. Чтобы определить класс прерываний, которые могут быть упреждены, уменьшите их приоритет, сделав их предопущенными.
![]()
Рассмотрим этот пример с тремя задачами. Переменная var совместно используется между этими двумя задачами task1 и task2 без какой-либо защиты, такой как критический раздел. В зависимости от приоритетов task1 и task2, Bug Finder показывает гонку данных. Третья задача не релевантна для примера (и добавляется только для включения критического раздела, в противном случае обнаружение гонки данных отключено).
int var;
void begin_critical_section(void);
void end_critical_section(void);
void task1(void) {
var++;
}
void task2(void) {
var=0;
}
void task3(void){
begin_critical_section();
/* Some atomic operation */
end_critical_section();
}Скорректируйте приоритеты task1 и task2 и увидеть, обнаружена ли гонка данных. Для образца:
Сконфигурируйте следующие опции многозадачности:
Interrupts (-interrupts): Задайте task1 и task2 как прерывания.
Cyclic tasks (-cyclic-tasks) (Polyspace Bug Finder Server): Укажите task3 как циклическая задача.
Critical section details (-critical-section-begin -critical-section-end): Задайте begin_critical_section как функция, начинающаяся с критического сечения и end_critical_section как функция, заканчивающая критический раздел.
Запустите Bug Finder.
Вы не видите гонки данных. Начиная с task1 и task2 являются прерываниями без предварительной очистки, доступ к общей переменной невозможен одновременно.
Изменение task1 на предпусконаладочное прерывание при помощи опции -preemptable-interrupts.
Еще раз запустите Bug Finder. Теперь вы видите гонку данных на общей переменной var.
![]()
Измените этот пример следующими способами и увидите эффект изменения:
Изменение приоритетов task1 и task2.
Например, можно уйти task1 как непередаваемое прерывание, но изменение task2 на предпусконаладочное прерывание при помощи опции -preemptable-interrupts.
Гонка данных исчезает. Причина в следующем:
task1 имеет более высокий приоритет и не может быть прерван task2.
Операция в task2 является атомарным и не может быть прерван task1.
Включите шашку Data race including atomic operations (не включен по умолчанию). Используйте опцию Find defects (-checkers).
Вы снова видите гонку данных. Шашка рассматривает все операции как потенциально неатомные и операцию в task2 теперь можно прервать из-за операции с более высоким приоритетом в task1.
Попробуйте другие изменения опций анализа и посмотрите результат проверки.
![]()
-preemptable-interrupts | Interrupts (-interrupts) | -non-preemptable-tasks (Polyspace Bug Finder Server) | Cyclic tasks (-cyclic-tasks) (Polyspace Bug Finder Server)