exponenta event banner

Отсутствует разблокировка

Функция блокировки без функции разблокировки

Описание

Этот дефект возникает в следующих случаях:

  • Задача вызывает функцию блокировки.

  • Задача завершается без вызова функции разблокировки.

В многозадачном коде функция блокировки начинает критический раздел кода и функция разблокировки заканчивает его. Когда задача, my_task, вызывает функцию блокировки, my_lock, другие задачи, вызывающие my_lock должен подождать до my_task вызывает соответствующую функцию разблокировки. Polyspace ® требует, чтобы функции блокировки и разблокировки имели формуvoid func(void).

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

Риск

Функция разблокировки заканчивает критический раздел, чтобы другие ожидающие задачи могли войти в критический раздел. Отсутствие функции разблокировки может привести к блокировке задач на ненужный период времени.

Зафиксировать

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

Могут быть и другие причины и соответствующие исправления дефекта. Возможно, вы назвали неправильную функцию разблокировки. Проверьте пару функций блокировки-разблокировки в конфигурации анализа Polyspace и устраните несоответствие.

См. примеры исправлений ниже. Чтобы избежать проблемы, можно следовать практике вызова функций блокировки и разблокировки в одном модуле на одном уровне абстракции. Например, в этом примере func вызывает функцию блокировки и разблокировки на одном уровне, но func2 не делает.

void func() {
  my_lock();
  {
    ...
  }
  my_unlock();
}

void func2() {
  {
   my_lock();
   ...
  }
  my_unlock();
}

Если вы не хотите устранять проблему, добавьте комментарии к результату или коду, чтобы избежать другой проверки. См. раздел Результаты анализа пространства адресов с помощью исправлений ошибок или обоснований.

Примеры

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



void begin_critical_section(void);
void end_critical_section(void);

int global_var;

void reset() 
{
    begin_critical_section();
    global_var = 0;
    end_critical_section();
}

void my_task(void)
{
    begin_critical_section(); 
    global_var += 1;
}

В этом примере для эмуляции многозадачности задайте следующие параметры.

ВыборСтоимость
Configure multitasking manually
Tasks (-entry-points)

my_task, reset

Critical section details (-critical-section-begin -critical-section-end)Запуск подпрограммыЗавершение процедуры
begin_critical_sectionend_critical_section

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

polyspace-bug-finder
   -entry-points my_task,reset
   -critical-section-begin begin_critical_section:cs1
   -critical-section-end end_critical_section:cs1

Пример имеет две точки входа, my_task и reset. my_task входит в критический раздел через вызов begin_critical_section();. my_task заканчивается без вызова end_critical_section.

Исправление - Предоставление разблокировки

Одной из возможных корректировок является вызов функции разблокировки. end_critical_section после инструкций в критическом разделе.



void begin_critical_section(void);
void end_critical_section(void);

int global_var;

void reset(void)
{
    begin_critical_section(); 
    global_var = 0;
    end_critical_section();
}

void my_task(void)
{
    begin_critical_section(); 
    global_var += 1;
    end_critical_section();
}


void begin_critical_section(void);
void end_critical_section(void);

int global_var;

void reset() {
    begin_critical_section();
    global_var=0;
    end_critical_section();
}

void my_task(void) {
    int index=0;
    volatile int numCycles;

    while(numCycles) {
      begin_critical_section();
      global_var ++;
      if(index%10==0) {
        global_var = 0;
        end_critical_section();
      }
      index++;
    }
}

В этом примере для эмуляции многозадачности задайте следующие параметры.

ВыборСпецификация
Configure multitasking manually
Tasks (-entry-points)

my_task, reset

Critical section details (-critical-section-begin -critical-section-end)Запуск подпрограммыЗавершение процедуры
begin_critical_sectionend_critical_section

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

polyspace-bug-finder
   -entry-points my_task,reset
   -critical-section-begin begin_critical_section:cs1
   -critical-section-end end_critical_section:cs1

Пример имеет две точки входа, my_task и reset.

В while петля, my_task входит в критический раздел через вызов begin_critical_section();. В итерации while цикл:

  • Если my_task входит в if состояние ветвь, критический раздел заканчивается через вызов end_critical_section.

  • Если my_task не вводит if состояние ветвь и покидает while цикл, критическое сечение не заканчивается. Поэтому возникает дефект «Отсутствует разблокировка».

  • Если my_task не вводит if ветвь условия и переходит к следующей итерации while шлейф, функция блокировки begin_critical_section вызывается снова. Возникает дефект двойной блокировки.

Поскольку numCycles является volatile переменная, она может принимать любое значение. Возможен любой из вышеуказанных случаев. Поэтому при вызове появляются дефект «Missing unlock» и дефект «Double lock» begin_critical_section.

Исправление - Разблокировать внешнее условие

Одной из возможных корректировок является вызов функции разблокировки. end_critical_section за пределами if состояние.



void begin_critical_section(void);
void end_critical_section(void);

int global_var;

void reset() {
    begin_critical_section();
    global_var=0;
    end_critical_section();
}

void my_task(void) {
    int index=0;
    volatile int numCycles;

    while(numCycles) {
      begin_critical_section();
      global_var ++;
      if(index%10==0) {
        global_var=0;
      }
      end_critical_section();
      index++;
    }
}
Коррекция - разблокирование в каждой условной ветви

Другой возможной поправкой является вызов функции разблокировки. end_critical_section во всех ветвях if состояние.



void begin_critical_section(void);
void end_critical_section(void);

int global_var;

void reset() {
    begin_critical_section();
    global_var=0;
    end_critical_section();
}

void my_task(void) {
    int index=0;
    volatile int numCycles;

    while(numCycles) {
      begin_critical_section();
      global_var ++;
      if(index%10==0) {
        global_var=0;
        end_critical_section();
      }
      else
        end_critical_section();
      index++;
    }
}

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

Группа: Параллелизм
Язык: C | C++
По умолчанию: Вкл.
Синтаксис командной строки: BAD_LOCK
Воздействие: Высокое
ИДЕНТИФИКАТОР CWE: 667
Представлен в R2014b