Deadlock prevention patterns in FreeRTOS - Step-by-Step Execution
void Task1() {
if (xSemaphoreTake(mutex1, 0) == pdTRUE) {
if (xSemaphoreTake(mutex2, 0) == pdTRUE) {
// Critical section
xSemaphoreGive(mutex2);
}
xSemaphoreGive(mutex1);
}
}| Step | Action | Resource Requested | Result | Reason |
|---|---|---|---|---|
| 1 | Task1 tries to take mutex1 | mutex1 | Success | mutex1 is free |
| 2 | Task1 tries to take mutex2 | mutex2 | Success | mutex2 is free |
| 3 | Task1 enters critical section | - | - | Both mutexes acquired |
| 4 | Task1 releases mutex2 | mutex2 | Released | End of critical section |
| 5 | Task1 releases mutex1 | mutex1 | Released | End of critical section |
| 6 | Task1 ends or requests next resource | - | - | Resources freed |
| 7 | If mutex2 was busy at step 2 | mutex2 | Fail | No wait to prevent deadlock, task retries later |
| Variable | Start | After Step 1 | After Step 2 | After Step 4 | After Step 5 | Final |
|---|---|---|---|---|---|---|
| mutex1 | Free | Taken by Task1 | Taken by Task1 | Taken by Task1 | Free | Free |
| mutex2 | Free | Free | Taken by Task1 | Free | Free | Free |
Deadlock prevention in FreeRTOS: - Tasks try to take mutexes with zero wait time. - If resource unavailable, release held mutexes immediately. - Acquire resources in fixed order. - Always release mutexes after use. - Avoid waiting to prevent circular waits.
Practice
What is a common method to prevent deadlocks in FreeRTOS when multiple tasks need several mutexes?
Choose the best practice.
Solution
Step 1: Understand deadlock cause in FreeRTOS
Deadlocks happen when tasks wait forever for mutexes held by each other in a cycle.Step 2: Apply fixed order mutex acquisition
Taking mutexes always in the same order prevents circular wait, stopping deadlocks.Final Answer:
Always take mutexes in a fixed global order -> Option DQuick Check:
Fixed mutex order = deadlock prevention [OK]
- Taking mutexes in random order
- Ignoring priority inheritance
- Using recursive mutexes incorrectly
Which of the following is the correct way to create a mutex in FreeRTOS to help prevent deadlocks?
?Solution
Step 1: Identify FreeRTOS mutex creation functions
FreeRTOS uses xSemaphoreCreateMutex() to create a standard mutex.Step 2: Differentiate from other semaphore types
Counting semaphores and recursive mutexes serve different purposes; standard mutex is best for deadlock prevention.Final Answer:
xSemaphoreCreateMutex(); -> Option AQuick Check:
Standard mutex creation = xSemaphoreCreateMutex() [OK]
- Confusing counting semaphore with mutex
- Using recursive mutex without need
- Trying to create mutex with queue functions
Consider this FreeRTOS code snippet where two tasks try to take two mutexes in different orders:
Task1:
xSemaphoreTake(mutexA, portMAX_DELAY);
xSemaphoreTake(mutexB, portMAX_DELAY);
Task2:
xSemaphoreTake(mutexB, portMAX_DELAY);
xSemaphoreTake(mutexA, portMAX_DELAY);What is the likely outcome?
Solution
Step 1: Analyze mutex acquisition order
Task1 takes mutexA then mutexB; Task2 takes mutexB then mutexA, creating circular wait.Step 2: Identify deadlock condition
Each task waits for the other's mutex, causing deadlock with portMAX_DELAY blocking indefinitely.Final Answer:
Deadlock occurs because tasks wait on each other's mutex -> Option CQuick Check:
Opposite mutex order + infinite wait = deadlock [OK]
- Assuming tasks run without blocking
- Ignoring portMAX_DELAY effect
- Thinking one task fails immediately
Given this FreeRTOS code snippet, identify the problem that can cause deadlock:
void Task1(void *pvParameters) {
xSemaphoreTake(mutex1, portMAX_DELAY);
vTaskDelay(10);
xSemaphoreTake(mutex2, portMAX_DELAY);
// ...
xSemaphoreGive(mutex2);
xSemaphoreGive(mutex1);
}
void Task2(void *pvParameters) {
xSemaphoreTake(mutex2, portMAX_DELAY);
vTaskDelay(10);
xSemaphoreTake(mutex1, portMAX_DELAY);
// ...
xSemaphoreGive(mutex1);
xSemaphoreGive(mutex2);
}What is the best fix to prevent deadlock?
Solution
Step 1: Identify cause of deadlock
Task1 takes mutex1 then mutex2; Task2 takes mutex2 then mutex1, causing circular wait and deadlock.Step 2: Apply fixed mutex order to both tasks
Changing Task2 to take mutex1 then mutex2 avoids circular wait and prevents deadlock.Final Answer:
Make both tasks take mutexes in the same order -> Option BQuick Check:
Same mutex order = no deadlock [OK]
- Removing delays does not fix deadlock
- Using recursive mutexes won't solve order problem
- Increasing delay time only delays deadlock
You have three tasks that need to access three shared resources protected by mutexes: mutexX, mutexY, and mutexZ. To prevent deadlocks, which strategy is best?
- Task A needs
mutexXandmutexY - Task B needs
mutexYandmutexZ - Task C needs
mutexXandmutexZ
Choose the best deadlock prevention pattern.
Solution
Step 1: Analyze mutex requirements and potential deadlocks
Tasks share mutexes in overlapping pairs, risking circular wait if order differs.Step 2: Apply fixed global order for mutex acquisition
Taking mutexes always in alphabetical order (mutexX, mutexY, mutexZ) prevents circular wait and deadlocks.Final Answer:
Each task takes mutexes in alphabetical order: mutexX, mutexY, mutexZ -> Option AQuick Check:
Global fixed mutex order = deadlock prevention [OK]
- Taking mutexes randomly causes deadlocks
- Recursive mutexes don't fix order issues
- Waiting for all mutexes simultaneously is complex
Ready to prove it?
Pass the test and this pattern moves unknown
