Missing unlock

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

Описание

Этот дефект возникает, когда:

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

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

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

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

Риск

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

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

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

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

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

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

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

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

Примеры

расширить все



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)Starting routineEnding routine
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)Starting routineEnding routine
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 цикл, критическое сечение не заканчивается. Поэтому возникает Missing unlock дефект.

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

Потому что 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++
По умолчанию: On
Синтаксис командной строки: BAD_LOCK
Влияние: Высокий
ИДЕНТИФИКАТОР CWE: 667
Введенный в R2014b