Bird
Raised Fist0
FreeRTOSprogramming~10 mins

Mutex vs binary semaphore difference in FreeRTOS - Visual Side-by-Side Comparison

Choose your learning style10 modes available
Concept Flow - Mutex vs binary semaphore difference
Start
↓
Task wants resource
↓
Take resource
↓
Use resource
↓
Release resource
↓
Next task can take resource
↓
End
Tasks try to take a resource; if free, they take it and use it; if not, they wait. Mutex adds ownership and priority rules; binary semaphore is simpler signaling.
Execution Sample
FreeRTOS
/* Mutex example */
xSemaphoreTake(mutex, portMAX_DELAY);
// critical section
xSemaphoreGive(mutex);

/* Binary semaphore example */
xSemaphoreTake(binSem, portMAX_DELAY);
// critical section
xSemaphoreGive(binSem);
Shows how tasks take and give mutex or binary semaphore to control access to shared resources.
Execution Table
StepActionResource StateTask StateNotes
1Task A tries to take mutexFreeRunningMutex is free, Task A takes it
2Task A enters critical sectionTaken by Task ARunningTask A owns mutex, can access resource
3Task B tries to take mutexTaken by Task ABlockedTask B waits because mutex is owned
4Task A releases mutexFreeRunningMutex released, Task B can take it next
5Task B takes mutexTaken by Task BRunningTask B now owns mutex
6Task B releases mutexFreeRunningMutex free again
7Task C gives binary semaphoreSignaledWaiting tasks notifiedBinary semaphore signals availability
8Task D takes binary semaphoreNot signaledRunningTask D proceeds after signal
9Task D releases binary semaphoreSignaledRunningSemaphore available again
10Task E tries to take binary semaphoreSignaledRunningSemaphore is signaled, Task E takes it
11Task E releases binary semaphoreSignaledRunningSemaphore signaled again
12End--Execution ends
💡 All tasks have taken and released resources; no more waiting tasks.
Variable Tracker
VariableStartAfter Step 1After Step 3After Step 4After Step 5After Step 7After Step 8Final
Mutex StateFreeTaken by Task ATaken by Task AFreeTaken by Task BFreeFreeFree
Binary Semaphore StateFreeFreeFreeFreeFreeSignaledNot signaledSignaled
Task A StateReadyRunningRunningRunningReadyReadyReadyReady
Task B StateReadyReadyBlockedReadyRunningReadyReadyReady
Task D StateReadyReadyReadyReadyReadyWaitingRunningReady
Key Moments - 3 Insights
Why does Task B block when trying to take the mutex but not necessarily with a binary semaphore?
Because mutex enforces ownership and blocks tasks if already taken (see Step 3 in execution_table), while binary semaphore acts as a simple signal and does not enforce ownership.
Can a task release a mutex it did not take?
No, mutex requires the same task to release it to avoid resource conflicts, unlike binary semaphore which can be given by any task (refer to mutex ownership in Steps 1-6).
What happens when a binary semaphore is given while no task is waiting?
The semaphore becomes signaled and the next task that takes it proceeds immediately (see Step 7 and 8).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, at which step does Task B start running after waiting?
AStep 5
BStep 3
CStep 7
DStep 8
💡 Hint
Check the Task B State column in execution_table rows for Step 5.
According to variable_tracker, what is the state of the mutex after Step 4?
ATaken by Task A
BFree
CTaken by Task B
DSignaled
💡 Hint
Look at Mutex State after Step 4 in variable_tracker.
If Task C did not give the binary semaphore at Step 7, what would happen to Task D at Step 8?
ATask D would release the semaphore
BTask D would run immediately
CTask D would be blocked waiting
DTask D would take the mutex instead
💡 Hint
Refer to binary semaphore signaling in execution_table Steps 7 and 8.
Concept Snapshot
Mutex vs Binary Semaphore in FreeRTOS:
- Mutex: resource ownership, priority inheritance, blocks tasks if taken
- Binary Semaphore: simple signal, no ownership, used for event notification
- Mutex must be released by owner task
- Binary semaphore can be given by any task
- Use mutex for resource protection, semaphore for signaling
Full Transcript
This visual execution compares mutex and binary semaphore in FreeRTOS. Tasks try to take a resource; if free, they take it and run critical code; if not, they wait. Mutex enforces ownership and blocks other tasks until released by owner, shown by Task A and Task B states. Binary semaphore acts as a simple signal to notify tasks, shown by Task C giving and Task D taking the semaphore. Variable tracker shows resource states changing step-by-step. Key moments clarify ownership and blocking differences. Quiz questions check understanding of task states and resource availability during execution.

Practice

(1/5)
1. Which of the following best describes the main difference between a mutex and a binary semaphore in FreeRTOS?
easy
A. Binary semaphores have ownership; mutexes do not.
B. Mutexes have ownership and priority inheritance; binary semaphores do not.
C. Mutexes are used only for signaling; binary semaphores are for exclusive access.
D. There is no difference; both behave exactly the same.

Solution

  1. Step 1: Understand ownership concept

    Mutexes have ownership, meaning the task that locks it must unlock it. Binary semaphores do not have ownership.
  2. Step 2: Understand priority inheritance

    Mutexes support priority inheritance to avoid priority inversion; binary semaphores do not.
  3. Final Answer:

    Mutexes have ownership and priority inheritance; binary semaphores do not. -> Option B
  4. Quick Check:

    Ownership + priority inheritance = Mutex [OK]
Hint: Mutex = ownership + priority; binary semaphore = simple flag [OK]
Common Mistakes:
  • Thinking binary semaphores have ownership
  • Confusing signaling role of binary semaphores
  • Assuming mutexes do not support priority inheritance
2. Which of the following is the correct way to create a mutex in FreeRTOS?
easy
A. xSemaphoreCreateMutex()
B. xQueueCreateMutex()
C. xSemaphoreCreateBinary()
D. xMutexCreateSemaphore()

Solution

  1. Step 1: Recall FreeRTOS API for mutex creation

    The function to create a mutex is xSemaphoreCreateMutex().
  2. Step 2: Verify other options

    xSemaphoreCreateBinary() creates a binary semaphore, not a mutex. The other options are invalid API calls.
  3. Final Answer:

    xSemaphoreCreateMutex() -> Option A
  4. Quick Check:

    Mutex creation function = xSemaphoreCreateMutex() [OK]
Hint: Mutex creation always uses xSemaphoreCreateMutex() [OK]
Common Mistakes:
  • Using xSemaphoreCreateBinary() for mutex
  • Confusing queue creation functions with mutex
  • Inventing non-existent API functions
3. Consider the following FreeRTOS code snippet:
SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();
if (xSemaphoreTake(xMutex, 0) == pdTRUE) {
    // Critical section
    xSemaphoreGive(xMutex);
    printf("Mutex taken and released\n");
} else {
    printf("Failed to take mutex\n");
}
What will be the output when this code runs?
medium
A. Mutex taken and released
B. Failed to take mutex
C. Compilation error
D. No output

Solution

  1. Step 1: Analyze mutex creation and take

    The mutex is created successfully. The call to xSemaphoreTake with zero block time tries to take the mutex immediately. Since it is free, it succeeds.
  2. Step 2: Check critical section and release

    The mutex is given back with xSemaphoreGive, and the message "Mutex taken and released" is printed.
  3. Final Answer:

    Mutex taken and released -> Option A
  4. Quick Check:

    Mutex free at start, take succeeds, prints message [OK]
Hint: Mutex initially free, immediate take succeeds [OK]
Common Mistakes:
  • Assuming take fails with zero block time
  • Confusing mutex with binary semaphore behavior
  • Expecting compilation errors from correct API usage
4. Identify the error in the following FreeRTOS code using a binary semaphore:
SemaphoreHandle_t xBinarySemaphore = xSemaphoreCreateBinary();
xSemaphoreGive(xBinarySemaphore);
if (xSemaphoreTake(xBinarySemaphore, portMAX_DELAY) == pdTRUE) {
    // Critical section
    xSemaphoreGive(xBinarySemaphore);
    xSemaphoreGive(xBinarySemaphore);
}
medium
A. Semaphore handle is not initialized.
B. Taking the semaphore with portMAX_DELAY is invalid.
C. Binary semaphore must be created with xSemaphoreCreateMutex().
D. Giving the semaphore twice causes incorrect behavior.

Solution

  1. Step 1: Understand binary semaphore usage

    Binary semaphores act like flags with max count 1. Giving twice without taking in between can cause logic errors.
  2. Step 2: Analyze the code's semaphore give calls

    The code gives the semaphore twice without an intervening take, which can lead to unexpected behavior or overflow.
  3. Final Answer:

    Giving the semaphore twice causes incorrect behavior. -> Option D
  4. Quick Check:

    Binary semaphore max count = 1, double give is wrong [OK]
Hint: Binary semaphore max count 1, don't give twice without take [OK]
Common Mistakes:
  • Thinking portMAX_DELAY is invalid
  • Confusing binary semaphore with mutex creation
  • Ignoring semaphore initialization
5. You have two tasks: Task A (high priority) and Task B (low priority). Both need exclusive access to a shared resource. Which synchronization method should you use to avoid priority inversion and why? A) Use a mutex because it supports priority inheritance. B) Use a binary semaphore because it is simpler. C) Use a counting semaphore to allow multiple accesses. D) Use no synchronization to improve performance.
hard
A. Use a counting semaphore to allow multiple accesses.
B. Use a binary semaphore because it is simpler.
C. Use a mutex because it supports priority inheritance.
D. Use no synchronization to improve performance.

Solution

  1. Step 1: Identify need for exclusive access with priority handling

    Both tasks need exclusive access, so synchronization is required. Priority inversion can occur if a low priority task holds the resource.
  2. Step 2: Choose synchronization with priority inheritance

    Mutexes provide priority inheritance, temporarily boosting the low priority task's priority to avoid blocking the high priority task.
  3. Final Answer:

    Use a mutex because it supports priority inheritance. -> Option C
  4. Quick Check:

    Priority inversion avoidance = mutex [OK]
Hint: Use mutex for priority inheritance and exclusive access [OK]
Common Mistakes:
  • Choosing binary semaphore ignoring priority inversion
  • Using counting semaphore for exclusive access
  • Skipping synchronization to save time
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