Consider two tasks trying to acquire two mutexes in different orders. What output will the following code produce?
#include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include <stdio.h> SemaphoreHandle_t mutexA; SemaphoreHandle_t mutexB; void Task1(void *pvParameters) { if (xSemaphoreTake(mutexA, portMAX_DELAY) == pdTRUE) { vTaskDelay(10 / portTICK_PERIOD_MS); if (xSemaphoreTake(mutexB, portMAX_DELAY) == pdTRUE) { printf("Task1 acquired both mutexes\n"); xSemaphoreGive(mutexB); } xSemaphoreGive(mutexA); } vTaskDelete(NULL); } void Task2(void *pvParameters) { if (xSemaphoreTake(mutexB, portMAX_DELAY) == pdTRUE) { vTaskDelay(10 / portTICK_PERIOD_MS); if (xSemaphoreTake(mutexA, portMAX_DELAY) == pdTRUE) { printf("Task2 acquired both mutexes\n"); xSemaphoreGive(mutexA); } xSemaphoreGive(mutexB); } vTaskDelete(NULL); } int main(void) { mutexA = xSemaphoreCreateMutex(); mutexB = xSemaphoreCreateMutex(); xTaskCreate(Task1, "Task1", 1000, NULL, 1, NULL); xTaskCreate(Task2, "Task2", 1000, NULL, 1, NULL); vTaskStartScheduler(); return 0; }
Think about what happens when two tasks wait for each other's mutex indefinitely.
Task1 locks mutexA and waits for mutexB. Task2 locks mutexB and waits for mutexA. Both wait forever, causing a deadlock and no output.
In FreeRTOS, to avoid deadlocks when multiple mutexes are needed, which pattern is best described by acquiring all mutexes in a consistent order?
Think about how ordering resources can prevent cycles in resource allocation.
Resource Ordering prevents deadlocks by enforcing a strict order in which mutexes are acquired, avoiding circular wait conditions.
Examine the following code snippet. What causes the deadlock?
SemaphoreHandle_t mutex1 = xSemaphoreCreateMutex();
SemaphoreHandle_t mutex2 = xSemaphoreCreateMutex();
void TaskA(void *pvParameters) {
xSemaphoreTake(mutex1, portMAX_DELAY);
vTaskDelay(5 / portTICK_PERIOD_MS);
xSemaphoreTake(mutex2, portMAX_DELAY);
// Critical section
xSemaphoreGive(mutex2);
xSemaphoreGive(mutex1);
vTaskDelete(NULL);
}
void TaskB(void *pvParameters) {
xSemaphoreTake(mutex2, portMAX_DELAY);
vTaskDelay(5 / portTICK_PERIOD_MS);
xSemaphoreTake(mutex1, portMAX_DELAY);
// Critical section
xSemaphoreGive(mutex1);
xSemaphoreGive(mutex2);
vTaskDelete(NULL);
}Look at the order in which each task takes the mutexes.
TaskA locks mutex1 then waits for mutex2. TaskB locks mutex2 then waits for mutex1. This circular wait causes deadlock.
To prevent deadlock, a task tries to take a mutex but gives up if not immediately available. Which code snippet correctly implements this try-lock?
SemaphoreHandle_t mutex = xSemaphoreCreateMutex();
void Task(void *pvParameters) {
// Try to take mutex
if (/* condition here */) {
// Critical section
xSemaphoreGive(mutex);
} else {
// Could not get mutex
}
vTaskDelete(NULL);
}Try-lock means attempt to take mutex without waiting.
Using xSemaphoreTake with a block time of 0 attempts to take the mutex immediately and returns pdTRUE if successful.
Given a FreeRTOS system where tasks use a queue to signal resource availability and avoid deadlock, how many items remain in the queue after both tasks run?
#include "FreeRTOS.h" #include "task.h" #include "queue.h" #include <stdio.h> QueueHandle_t resourceQueue; void Task1(void *pvParameters) { int resource = 1; xQueueSend(resourceQueue, &resource, portMAX_DELAY); vTaskDelay(10 / portTICK_PERIOD_MS); xQueueReceive(resourceQueue, &resource, portMAX_DELAY); printf("Task1 done\n"); vTaskDelete(NULL); } void Task2(void *pvParameters) { int resource = 0; xQueueReceive(resourceQueue, &resource, portMAX_DELAY); xQueueSend(resourceQueue, &resource, portMAX_DELAY); printf("Task2 done\n"); vTaskDelete(NULL); } int main(void) { resourceQueue = xQueueCreate(1, sizeof(int)); xTaskCreate(Task1, "Task1", 1000, NULL, 1, NULL); xTaskCreate(Task2, "Task2", 1000, NULL, 1, NULL); vTaskStartScheduler(); return 0; }
Consider how the queue is used to pass resource tokens between tasks.
The queue starts empty. Task1 sends one item, Task2 receives it and sends it back. Task1 receives it after the delay. After both finish, the queue has 0 items.
