Пропавшие без вести блокировки

Разблокируйте функцию без функции блокировки

Описание

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

В многозадачном коде функция блокировки начинает критический раздел кода, и разблокировать функция заканчивает его. Когда задача, 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(void) 
{
  begin_critical_section();
  global_var = 0;
  end_critical_section();
}

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

В этом примере, чтобы эмулировать многозадачное поведение, необходимо задать следующие опции:

ОпцияСпецификация
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 вызывает end_critical_section прежде, чем вызвать begin_critical_section.

Исправление — обеспечивает блокировку

Одно возможное исправление должно вызвать функцию блокировки begin_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) {
      if(index%10==0) {
        begin_critical_section();
        global_var ++;  
      }
      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 оставляет критический раздел через вызов end_critical_section();. В итерации цикла while:

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

  • Если my_task не вводит ответвление условия if и оставляет цикл while, критический раздел не начинается. Поэтому дефект Missing lock происходит.

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

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

Проверяйте информацию

Группа: параллелизм
Язык: C | C++
Значение по умолчанию: на
Синтаксис командной строки: BAD_UNLOCK
Влияние: носитель
ID CWE: 832

Введенный в R2014b