📜 ⬆️ ⬇️

FreeRTOS: mutexes and critical sections


Hello. This is the final article about the multithreaded environment of FreeRTOS in which I will talk about mutexes and critical sections.
Links to previous parts:


Mutexes


Consider a situation in which it is necessary to have shared access to a resource (port, memory area, some variable) and even so that in a unit of time only one task can access this resource, while other tasks that want to access resource must wait for their turn.
A special type of semaphore comes to the rescue - mutex. This abstraction is a kind of token, having which a task can have access to a resource, and which must be returned at the end of work with the resource, and only the task that took it can return the “token”.
The following images illustrate this logic:

Figure 1 . The initial situation is 3 tasks that want to access the resource.

Figure 2 . Task B - took a "token" (mutex).

Figure 3 . Task B got access to the resource and performs the necessary actions.

Figure 4 . After the work is completed, task B returns the token and as a result other tasks can get access to the resource.
To create a mutex, a special API function is used:
xSemaphoreHandle xSemaphoreCreateMutex( void ); 

Which returns the created mutex, or NULL if there is not enough memory.
The following code shows the mechanism for working with mutex:
  if( xSemaphoreTake( xMutex, portMAX_DELAY ) == pdTRUE ) { //      . //  "". xSemaphoreGive( xMutex ); } 

Critical sections.


What if, in the course of the operation of the logic of your code, a short section of code is needed, the execution of which should not be interrupted by switching to another task (an example of such a section is the recording of a value to a port). For this, FreeRTOS uses special macros:
 taskENTER_CRITICAL(); { //    ,      . } taskEXIT_CRITICAL(); 

During the execution of this part of the code, the context cannot be switched (ie, switching to another task), but interruptions on versions of FreeRTOS with support for nested interrupts may come, but not all, but only those with priority above the constant configMAX_SYSCALL_INTERRUPT_PRIORITY .

Another approach to building critical sections is to suspend the work of the scheduler. The only difference is that the critical section, built on macros, protects the executable code section from sharing other tasks and interrupts, and the critical section, built on suspending the scheduler, only from other tasks.
To do this, use 2 API functions:
 void vTaskSuspendAll(); { //   . } portBASE_TYPE xTaskResumeAll(); 

In this case, the value returned by the function xTaskResumeAll (); indicates the need to perform a forced context switch using taskYIELD ();

Inversion of priorities and dead ends.


In the last article, I casually mentioned the gatekeeper task as a solution to the problem of inversion of priorities and getting tasks into a dead end. Here I would like to describe in more detail what it is.
')
Priority inversion is a situation in which Task A has a higher priority than Task B expects its completion because he was the first to capture a token (mutex).

Deadlock is a situation in which 2 tasks are waiting for each other because Everyone must give the "token" necessary to another. For example:
  1. Task A runs and captures an X token.
  2. The execution of Task A is interrupted by Task B.
  3. Task B captures the “token” Y, before it tries to capture the “token” X, which is currently used by Task A. As a result, Task B falls into the wait of Task A.
  4. Task A continues to run, and wants to capture the Y token, which is used by Task B and as a result also waits.

In order to avoid "dead ends" it is necessary that all tasks get a "token" in a certain order, for example, first task A, then B, etc.

Perhaps this is all, it would be interesting to hear the amendments throughout the cycle, in order to correct the article, and further refer to them.
For further study, I would first of all advise you to read the original manual “Using the FreeRTOS real time kernel”, the information from which was used when writing articles, as well as the documentation on the official website.

Source: https://habr.com/ru/post/129445/


All Articles