Bug Finder обнаруживает гонки данных между параллельными задачами. Используя опции анализа Bug Finder, можно зафиксировать обнаружение гонки данных путем указывания, что определенные задачи имеют более высокие приоритеты над другими. Задача с более высоким приоритетом является атомарной относительно задач с более низким приоритетом и не может быть прервана теми задачами.
![]()
Можно задать до четырех различных приоритетов с этими опциями (с самым высоким приоритетом, перечисленным сначала):
(nonpreemptable) прерывания: Используйте опцию Interrupts (-interrupts).
(Выгружаемые) прерывания: Используйте опции Interrupts (-interrupts) и -preemptable-interrupts.
Циклические (nonpreemptable) задачи: Используйте опции 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 nonpreemptable прерывания, к совместно используемой переменной нельзя получить доступ одновременно.
Измените task1 к выгружаемому прерыванию при помощи опции -preemptable-interrupts.
Запустите Bug Finder снова. Вы теперь видите, что данные мчатся на совместно используемой переменной var.
![]()
Измените этот пример следующими способами и смотрите эффект модификации:
Измените приоритеты task1 и task2.
Например, можно оставить task1 как nonpreemptable прерывание, но изменение 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)