рекурсивные мьютексы
Помимо обычных мьютексов, рассмотрен-
ных выше, FreeRTOS поддерживает также
рекурсивные мьютексы (Recursive Mutexes)
[6]. Их основное отличие от обычных мью-
тексов заключается в том, что они коррек-
тно работают при вложенных операциях за-
хвата и освобождения мьютекса. Вложенные
операции захвата/освобождения мьютекса
допускаются только в теле задачи-владельца
мьютекса. Рассмотрим пример рекурсивного
захвата обычного мьютекса:
xSemaphoreHandle xMutex;
/* ... */
xMutex = xSemaphoreCreateMutex();
/* ... */
/* Функция, реализующая задачу. */
void vTask(void *pvParameters) {
for (;;) {
/* Захват мьютекса */
xSemaphoreTake( xMutex, portMAX_DELAY );
/* Действия с ресурсом */
/* ... */
/* Вызов функции, которая выполняет операции с этим же
ресурсом. */
vSomeFunction();
/* Действия с ресурсом */
/* ... */
/* Действия с ресурсом закончены. Освободить мьютекс. */
xSemaphoreGive( xMutex );
}
}
/* Функция, которая вызывается из тела задачи vTask*/
void vSomeFunction(void) {
/* Захватить тот же самый мьютекс.
Т. к. тайм-аут не указан, то задача «зависнет» в ожидании,
пока мьютекс не освободится.
Однако это никогда не произойдет! */
if (xSemaphoreTake( xMutex, portMAX_DELAY ) == pdTRUE )
{
/* Действия с ресурсом внутри функции */
/* ... */
/* Освободить мьютекс */
xSemaphoreGive( xMutex );
}
}
Такое использование обычного мьютекса
приведет к краху программы. При попытке
повторно захватить мьютекс внутри функ-
ции vSomeFunction() задача vTask перейдет
в блокированное состояние, пока мьютекс
не будет возвращен. Другие задачи смогут вы-
полнить возврат мьютекса только после того,
как сами его захватят. Однако мьютекс уже за-
хвачен, поэтому задача vTask заблокируется
на бесконечно долгое время («зависнет»).
Если при повторном вызове API-функции
Достарыңызбен бөлісу: |