Consider the following FreeRTOS code snippet using a recursive mutex. What will be the output printed to the console?
#include "FreeRTOS.h" #include "semphr.h" #include "task.h" #include <stdio.h> SemaphoreHandle_t xRecursiveMutex; void vTaskFunction(void *pvParameters) { if(xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) == pdTRUE) { printf("Lock acquired first time\n"); if(xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) == pdTRUE) { printf("Lock acquired second time\n"); xSemaphoreGiveRecursive(xRecursiveMutex); printf("Lock released once\n"); } xSemaphoreGiveRecursive(xRecursiveMutex); printf("Lock fully released\n"); } vTaskDelete(NULL); } int main() { xRecursiveMutex = xSemaphoreCreateRecursiveMutex(); if(xRecursiveMutex == NULL) { printf("Failed to create mutex\n"); return 1; } xTaskCreate(vTaskFunction, "Task", 1000, NULL, 1, NULL); vTaskStartScheduler(); return 0; }
Remember that recursive mutexes allow the same task to lock multiple times and must be released the same number of times.
The recursive mutex allows nested locking by the same task. The first xSemaphoreTakeRecursive succeeds and prints "Lock acquired first time". The second nested call also succeeds and prints "Lock acquired second time". Then the first xSemaphoreGiveRecursive releases one level of the lock, printing "Lock released once". The final xSemaphoreGiveRecursive releases the mutex fully, printing "Lock fully released".
Which of the following best explains why recursive mutexes are used in FreeRTOS?
Think about what happens if a task tries to lock a mutex it already holds.
Recursive mutexes allow the same task to lock the mutex multiple times without blocking itself, preventing deadlocks in nested locking scenarios. Normal mutexes would cause a deadlock if the same task tries to lock twice.
What error will occur when running the following FreeRTOS code snippet?
SemaphoreHandle_t xMutex;
void vTask(void *pvParameters) {
if(xSemaphoreTakeRecursive(xMutex, portMAX_DELAY) == pdTRUE) {
// Do some work
xSemaphoreGive(xMutex); // Note: Using xSemaphoreGive instead of xSemaphoreGiveRecursive
}
vTaskDelete(NULL);
}
int main() {
xMutex = xSemaphoreCreateRecursiveMutex();
if(xMutex == NULL) {
return 1;
}
xTaskCreate(vTask, "Task", 1000, NULL, 1, NULL);
vTaskStartScheduler();
return 0;
}Check if the function used to release the mutex matches the type of mutex created.
Using xSemaphoreGive to release a recursive mutex that was taken with xSemaphoreTakeRecursive is incorrect. This mismatch can cause undefined behavior or runtime errors because the recursive lock count is not properly decremented.
Which option correctly creates a recursive mutex in FreeRTOS?
Check the correct type and function name for recursive mutex creation in FreeRTOS.
The correct type for mutex handles in FreeRTOS is SemaphoreHandle_t. The function to create a recursive mutex is xSemaphoreCreateRecursiveMutex(). Option B uses both correctly.
Given the following code snippet, what is the value of lockCount after all calls?
SemaphoreHandle_t xRecursiveMutex; int lockCount = 0; void vTask(void *pvParameters) { if(xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) == pdTRUE) { lockCount++; if(xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) == pdTRUE) { lockCount++; xSemaphoreGiveRecursive(xRecursiveMutex); lockCount--; } xSemaphoreGiveRecursive(xRecursiveMutex); lockCount--; } vTaskDelete(NULL); } int main() { xRecursiveMutex = xSemaphoreCreateRecursiveMutex(); if(xRecursiveMutex == NULL) { return 1; } xTaskCreate(vTask, "Task", 1000, NULL, 1, NULL); vTaskStartScheduler(); return 0; }
Consider how the increments and decrements of lockCount correspond to the recursive mutex locks and releases.
The variable lockCount is incremented each time the mutex is taken and decremented each time it is given back. After the nested calls, all locks are released, so lockCount returns to 0.
