xSemaphoreTake() было указано конечное
время тайм-аута, «зависания» задачи не про-
изойдет. Вместо этого действия с ресурсом,
выполняемые внутри функции, никогда
не будут произведены, что также являет-
ся недопустимой ситуацией.
Когда программа проектируется так, что
операции захват/освобождение мьютекса яв-
ляются вложенными, следует использовать
рекурсивные мьютексы:
xSemaphoreHandle xRecursiveMutex;
/* ... */
xRecursiveMutex = xSemaphoreCreateRecursiveMutex();
/* ... */
/* Функция, реализующая задачу. */
void vTask(void *pvParameters) {
for (;;) {
/* Захват мьютекса */
xSemaphoreTakeRecursive( xRecursiveMutex, portMAX_DELAY );
/* Действия с ресурсом */
/* ... */
/* Вызов функции, которая выполняет операции с этим же
ресурсом. */
vSomeFunction();
/* Действия с ресурсом */
/* ... */
/* Действия с ресурсом закончены. Освободить мьютекс. */
xSemaphoreGiveRecursive( xRecursiveMutex );
}
}
/* Функция, которая вызывается из тела задачи vTask*/
void vSomeFunction(void) {
/* Захватить тот же самый мьютекс.
При этом состояние мьютекса никоим образом не изменится.
Задача не заблокируется, действия с ресурсом внутри этой
функции будут выполнены. */
if (xSemaphoreTakeRecursive( xRecursiveMutex, portMAX_DELAY
) == pdTRUE ) {
/* Действия с ресурсом внутри функции */
/* ... */
/* Освободить мьютекс */
xSemaphoreGiveRecursive( xRecursiveMutex );
}
}
В этом случае программа будет работать
корректно. При повторном захвате мьютекса
API-функцией xSemaphoreTakeRecursive() за-
дача не перейдет в блокированное состояние,
и эта же задача останется владельцем мью-
текса. Вместо этого увеличится на единицу
внутренний счетчик, который определяет,
сколько операций «захват» было применено
к мьютексу, действия с ресурсом внутри функ-
ции vSomeFunction() будут выполнены, так
как задача vTask остается владельцем мьютек-
са. При освобождении мьютекса (при вызове
API-функции xSemaphoreGiveRecursive())
из тела одной и той же задачи внутренний
счетчик уменьшается на единицу. Когда этот
счетчик станет равен нулю, это будет озна-
чать, что текущая задача больше не являет-
ся владельцем мьютекса и теперь он может
быть захвачен другой задачей.
Таким образом, каждому вызову API-
ф ун к ц ии xSemaphoreTakeRecursive()
внутри тела одной и той же задачи дол-
жен соответствовать вызов API-функции
Достарыңызбен бөлісу: |