Co je mutex?
-
Mutex je složen ze slov Mutual Exclusion (vzájemně se vylučující).
-
Je to semafor, který zahrnuje zděděný mechnismus priority. Mutex může mít dvě hodnoty: 0 nebo 1.
-
Mutex funguje jako "jeden klíč", který se používá k ochraně dat (zdroje). Kdo chce se zdrojem manipulovat, musí si vzít klíč (mutex), potom muže manipulovat se zdrojem. Po ukončení manipulace klíč odevzdá.
-
Zabraňuje tomu, aby dvě nebo více úloh měnily nějaká data (zdroj) současně.
Když má mutex hodnotu 1, je k dispozici, pokud má hodnotu 0, někdo mutex používá a funkce volání xSemaphoreTake(mutex,prodleva) se zablokuje.
Kdy nelze používat mutex
-
Uvnitř zpracování přeušení
-
Mutex má zděděný mechanismus priority, který má smysl jenom tehdy pokud je mutex vzat nebo odevzdán z úlohy, nikoli z přerušení.
-
V rámci obsluhy přerušení nemůžeme dopustit blokování, abychom čekali na nějaký zdoj, který je chráněn mutexem, až bude uvolněn
-
FreeRTOS API funkce pro mutexy
-
xSemaphoreCreateMutex()
-
xSemaphoreTake(mutex, prodleva)
-
xSemaphoreGive(mutex)
Příklad
Nastavíme dvě úlohy tak, aby nemohly přerušovat jedna druhou, když tisknou znaky na sériovou linku.
#define configTICK_RATE_HZ 100000
#define configUSE_MUTEXES 1
#define configUSE_TIME_SLICING 1
add_executable(${ProjectName}
main.c
)
pico_enable_stdio_usb(${ProjectName} 1)
pico_enable_stdio_uart(${ProjectName} 0)
target_include_directories(${ProjectName} PRIVATE
${CMAKE_CURRENT_LIST_DIR}
)
target_link_libraries(${ProjectName}
pico_stdlib
FreeRTOS-Kernel-Heap4
)
pico_add_extra_outputs(${ProjectName})
Kód bez mutexů
#include <FreeRTOS.h>
#include <task.h>
#include <stdio.h>
#include "pico/stdlib.h"
void task1(void *pvParameters)
{
char ch = '1';
while (true) {
for(int i = 1; i < 10; i++){
putchar(ch);
}
puts("");
}
}
void task2(void *pvParameters)
{
char ch = '2';
while (true) {
for(int i = 1; i < 10; i++){
putchar(ch);
}
puts("");
}
}
int main()
{
stdio_init_all();
xTaskCreate(task1, "Task 1", 256, NULL, 1, NULL);
xTaskCreate(task2, "Task 2", 256, NULL, 1, NULL);
vTaskStartScheduler();
while(1){};
}
Kód s mutexy
#include <FreeRTOS.h>
#include <task.h>
#include <stdio.h>
#include "pico/stdlib.h"
#include "semphr.h" // zde jsou deklarace funkcí pro mutexy
// definice mutexu jako globální statické proměnné
static SemaphoreHandle_t mutex;
// definice prvního úkolu, bude tisknout na sériovou linku samé jedničky
void task1(void *pvParameters)
{
char ch = '1';
while (true) {
if(xSemaphoreTake(mutex, 0) == pdTRUE){ // test získání mutexu, pokud ho nezískám funkce blokuje
for(int i = 1; i < 10; i++){ // získal jsem mutex, mohu tisknout
putchar(ch);
}
puts("");
xSemaphoreGive(mutex); // odevzdání mutexu
}
}
}
// definice druhého úkolu, bude tisknout na sériovou linku samé dvojky
void task2(void *pvParameters)
{
char ch = '2';
while (true) {
if(xSemaphoreTake(mutex, 0) == pdTRUE){
for(int i = 1; i < 10; i++){
putchar(ch);
}
puts("");
xSemaphoreGive(mutex);
}
}
}
int main()
{
stdio_init_all();
mutex = xSemaphoreCreateMutex();
xTaskCreate(task1, "Task 1", 256, NULL, 1, NULL); // vytvoření prvního úkolu
xTaskCreate(task2, "Task 2", 256, NULL, 1, NULL); // vytvoření druhého úkolu
vTaskStartScheduler(); // spuštění obou úloh
while(1){};
}