Bird
Raised Fist0
FreeRTOSprogramming~20 mins

Recursive mutex for nested locking in FreeRTOS - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Recursive Mutex Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Output of nested recursive mutex lock calls

Consider the following FreeRTOS code snippet using a recursive mutex. What will be the output printed to the console?

FreeRTOS
#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;
}
A
Lock acquired first time
Lock released once
Lock acquired second time
Lock fully released
B
Lock acquired first time
Lock acquired second time
Lock fully released
Lock released once
C
Lock acquired first time
Lock acquired second time
Lock released once
Lock fully released
D
Lock acquired first time
Lock acquired second time
Lock released once
Lock released once
Attempts:
2 left
💡 Hint

Remember that recursive mutexes allow the same task to lock multiple times and must be released the same number of times.

🧠 Conceptual
intermediate
1:30remaining
Why use recursive mutexes in FreeRTOS?

Which of the following best explains why recursive mutexes are used in FreeRTOS?

AThey are faster than normal mutexes because they use spinlocks.
BThey allow multiple tasks to lock the mutex simultaneously for better performance.
CThey automatically release the mutex after a timeout period.
DThey allow a task to lock the same mutex multiple times without causing a deadlock.
Attempts:
2 left
💡 Hint

Think about what happens if a task tries to lock a mutex it already holds.

🔧 Debug
advanced
2:00remaining
Identify the error in recursive mutex usage

What error will occur when running the following FreeRTOS code snippet?

FreeRTOS
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;
}
AThe code will compile but cause a runtime error due to incorrect mutex release.
BThe code will cause a compile-time error because xSemaphoreGive is undefined.
CThe code will deadlock because the mutex is never released.
DThe code will run correctly without any errors.
Attempts:
2 left
💡 Hint

Check if the function used to release the mutex matches the type of mutex created.

📝 Syntax
advanced
1:30remaining
Syntax error in recursive mutex creation

Which option correctly creates a recursive mutex in FreeRTOS?

AxSemaphoreHandle xMutex = xSemaphoreCreateRecursiveMutex();
BSemaphoreHandle_t xMutex = xSemaphoreCreateRecursiveMutex();
CSemaphoreHandle_t xMutex = xSemaphoreCreateMutexRecursive();
DxSemaphoreHandle xMutex = xSemaphoreCreateMutex();
Attempts:
2 left
💡 Hint

Check the correct type and function name for recursive mutex creation in FreeRTOS.

🚀 Application
expert
2:30remaining
Count recursive mutex lock depth after nested calls

Given the following code snippet, what is the value of lockCount after all calls?

FreeRTOS
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;
}
A0
B1
C2
D-1
Attempts:
2 left
💡 Hint

Consider how the increments and decrements of lockCount correspond to the recursive mutex locks and releases.

Practice

(1/5)
1.

What is the main advantage of using a recursive mutex in FreeRTOS?

easy
A. It increases the priority of the task holding the mutex.
B. It automatically unlocks after a fixed time.
C. It allows the same task to lock the mutex multiple times without deadlock.
D. It can be shared between tasks without any locking.

Solution

  1. Step 1: Understand mutex behavior

    Normal mutexes block if the same task tries to lock again, causing deadlock.
  2. Step 2: Role of recursive mutex

    Recursive mutexes allow the same task to lock multiple times safely, avoiding deadlock.
  3. Final Answer:

    It allows the same task to lock the mutex multiple times without deadlock. -> Option C
  4. Quick Check:

    Recursive mutex = multiple locks by same task [OK]
Hint: Recursive mutex lets one task lock repeatedly safely [OK]
Common Mistakes:
  • Thinking mutex unlocks automatically
  • Confusing recursive mutex with priority inheritance
  • Assuming mutex can be shared without locking
2.

Which FreeRTOS function is used to lock a recursive mutex?

SemaphoreHandle_t xMutex = xSemaphoreCreateRecursiveMutex();
// Lock the mutex here
easy
A. xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);
B. xSemaphoreGiveRecursive(xMutex);
C. xSemaphoreTake(xMutex, portMAX_DELAY);
D. xSemaphoreCreateMutex();

Solution

  1. Step 1: Identify locking function for recursive mutex

    Recursive mutexes require xSemaphoreTakeRecursive() to lock safely multiple times.
  2. Step 2: Match function usage

    xSemaphoreTakeRecursive(xMutex, portMAX_DELAY) locks the recursive mutex properly.
  3. Final Answer:

    xSemaphoreTakeRecursive(xMutex, portMAX_DELAY); -> Option A
  4. Quick Check:

    Lock recursive mutex = xSemaphoreTakeRecursive() [OK]
Hint: Use xSemaphoreTakeRecursive() to lock recursive mutex [OK]
Common Mistakes:
  • Using xSemaphoreTake() instead of recursive version
  • Confusing give and take functions
  • Trying to create mutex again instead of locking
3.

What will be the output of the following FreeRTOS code snippet?

SemaphoreHandle_t xMutex = xSemaphoreCreateRecursiveMutex();

void Task(void *params) {
    xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);
    xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);
    xSemaphoreGiveRecursive(xMutex);
    xSemaphoreGiveRecursive(xMutex);
    if (xSemaphoreGiveRecursive(xMutex) == pdFALSE) {
        printf("Mutex fully released\n");
    } else {
        printf("Mutex still locked\n");
    }
}
medium
A. Mutex fully released
B. Mutex still locked
C. Compilation error
D. Deadlock occurs

Solution

  1. Step 1: Count lock and unlock calls

    The mutex is locked twice and unlocked twice, so it is fully released after two gives.
  2. Step 2: Analyze extra unlock call

    The third give returns pdFALSE because mutex is already fully released, triggering "Mutex fully released" print.
  3. Final Answer:

    Mutex fully released -> Option A
  4. Quick Check:

    Extra unlock returns false = fully released [OK]
Hint: Unlock same times as lock to fully release mutex [OK]
Common Mistakes:
  • Assuming extra unlock succeeds
  • Ignoring return value of xSemaphoreGiveRecursive()
  • Thinking deadlock occurs on unlock
4.

Identify the error in this FreeRTOS recursive mutex usage:

SemaphoreHandle_t xMutex = xSemaphoreCreateRecursiveMutex();

void Task(void *params) {
    xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);
    // Some code
    xSemaphoreGive(xMutex);
}
medium
A. Not locking the mutex before unlocking.
B. Using xSemaphoreGive() instead of xSemaphoreGiveRecursive() to unlock.
C. Creating mutex inside the task instead of globally.
D. Using portMAX_DELAY as timeout.

Solution

  1. Step 1: Check unlock function for recursive mutex

    Recursive mutexes must be unlocked with xSemaphoreGiveRecursive(), not xSemaphoreGive().
  2. Step 2: Identify mismatch in lock/unlock

    Using xSemaphoreGive() causes undefined behavior or errors because it is for normal mutexes.
  3. Final Answer:

    Using xSemaphoreGive() instead of xSemaphoreGiveRecursive() to unlock. -> Option B
  4. Quick Check:

    Unlock recursive mutex = xSemaphoreGiveRecursive() [OK]
Hint: Unlock recursive mutex with xSemaphoreGiveRecursive() only [OK]
Common Mistakes:
  • Mixing normal and recursive mutex functions
  • Ignoring correct unlock function
  • Assuming portMAX_DELAY causes error here
5.

You have a recursive mutex locked three times by the same task. What must you do to avoid deadlock when unlocking?

// Pseudocode
xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);
xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);
xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);
// ... critical section ...
// Unlock here
hard
A. Call xSemaphoreTakeRecursive() again to balance locks.
B. Call xSemaphoreGiveRecursive() once to release the mutex fully.
C. Call xSemaphoreGive() three times to release the mutex.
D. Call xSemaphoreGiveRecursive() exactly three times before releasing the mutex.

Solution

  1. Step 1: Understand recursive mutex lock count

    Each lock increments a count; unlocking must decrement the same number of times.
  2. Step 2: Proper unlock calls

    To fully release, call xSemaphoreGiveRecursive() three times matching the three locks.
  3. Final Answer:

    Call xSemaphoreGiveRecursive() exactly three times before releasing the mutex. -> Option D
  4. Quick Check:

    Unlock count = lock count to avoid deadlock [OK]
Hint: Unlock recursive mutex as many times as locked [OK]
Common Mistakes:
  • Unlocking fewer times causing deadlock
  • Using xSemaphoreGive() instead of recursive version
  • Trying to unlock more times than locked
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard