# 6. Mutexes

This tutorial covers the basic use of Mutual Exclusion Semaphores (Mutexes). These are particular semaphores used to 'protect' unique resources used by several tasks. You'll see what this means next.

## 1. What's the problem?

Just try this simple application:

/*
* main.c
*
*  Created on: 24/02/2018
*      Author: Laurent
*/

#include "main.h"

// Static functions
static void SystemClock_Config	(void);

// Main program
int main()
{
// Configure System Clock
SystemClock_Config();

// Initialize LED pin
BSP_LED_Init();

// Initialize the user Push-Button
BSP_PB_Init();

// Initialize Debug Console
BSP_Console_Init();

// Start Trace Recording
vTraceEnable(TRC_START);

// Start the Scheduler

while(1)
{
// The program should never be here...
}
}

/*
*/
{
while(1)
{
my_printf("With great power comes great responsibility\r\n");
}
}

/*
*/
{
while(1)
{
my_printf("#");
}
}


Here, Task_1 and Task2 are just sending messages to the console. The problem is that the message printing process in Task_1 takes 4 to 5ms. In this delay, Task_2 is activated several times. As Task_2 has higher priority level, Task_1 is suspended while Task_2 executes.

As a result, we've got the Task_1 message cluttered with '#'... hum, that's not good.

The trace record just confirms what we already assumed:

Of course, reversing the priority of Task_1 and Task_2 would solve this problem. But let us assume here that this is not what we want to do. Say, Task_2 could perform some other, highly important things, and we want to keep it at a higher priority level.

## 2. Here comes the Mutex

The problem introduced above is quite common with RTOS. It rises from an unique resource (the print peripheral here, a.k.a. USART2), either hardware (peripheral) or software (e.g. a global variables) that may be used by more than one task at a time. There are various way to prevent such collision. An usual method is to involve a specific semaphore mechanism called Mutual Exclusion semaphore (Mutex). Let us try this.

As for binary semaphore, the first step is to declare the Mutex as global variable:
...
// Kernel Objects
xSemaphoreHandle xConsoleMutex;
...


Second, we need to create the Mutex object, within main() function:

...
// Create a Mutex for accessing the console
xConsoleMutex = xSemaphoreCreateMutex();

// Give a nice name to the Mutex in the trace recorder
vTraceSetMutexName(xConsoleMutex, "Console Mutex");
...

Finally, the Mutex can be used to 'protect' the unique ressource:

*
*/
{
while(1)
{
// Take Mutex
xSemaphoreTake(xConsoleMutex, portMAX_DELAY);

// Send message to console
my_printf("With great power comes great responsibility\r\n");

// Release Mutex
xSemaphoreGive(xConsoleMutex);

}
}

/*
*/
{
while(1)
{
// Take Mutex
xSemaphoreTake(xConsoleMutex, portMAX_DELAY);

// Send message to console
my_printf("#");

// Release Mutex
xSemaphoreGive(xConsoleMutex);

}
}

Unlike the binary semaphore, which is usually first given and then taken by two different tasks, the Mutex is first taken, and then released by the same task. It's a way for that task to say others "Hey, if you want to use that resource I'm using now, please don't interrupt me!".

Now watch the result of the above code: problem solved!

The trace below show the whole process. It is worth taking some time to understand what's happening into the details.
• At t ≈ 2.112s, both Task_1 and Task_2 are ready for doing their jobs. Because Task_2 has higher priority level, it takes the mutex, prints '#', releases the mutex and then go to wait for 1ms. During this time, Task_1 is waiting.
• Right after this, Task_1 is activated. It takes the mutex and starts printing its long message.
• At t ≈ 2.113ms, Task2 is again activated, suspending Task1. It tries to take the mutex, but it is not available, therefore it enters the blocked state.
• Right after, Task1 resumes and we observe that OS sets its priority to the same level as the one of Task_2. This mechanism, called priority inheritance is related to the use of mutexes. Because Task_2 is now blocked by Task_1, the scheduler consider that Task_1 is as important as Task_2. This mechanism prevents a well-known issue when using mutexes, that arises when a third task of intermediate priority comes into the game, blocking Task_2 execution (by blocking Task_1) despite its lower priority level.
• After t ≈ 2.116s, Task_1 is done printing the message and releases the mutex. Instantly, Task_2 resumes, and then both tasks go to waiting state.

End of story!