Fent servir Mutex

Quan tenim un recurs, driver, memòria compartida, secció crítica o qualsevol altre recurs que només es pot fer servir una sola tasca a cada moment, cal muntar un mecanisme d’exclusió mútua que ens asseguri que no tindrem cap problema.

Aquest mecanisme és molt similar a un semàfor binari però cal incloure algun mecanisme per prevenir la inversió de prioritats. Aquest mecanisme és el  Mutex (d’aquí els ve el nom: Mutual Exclusion).

Amb aquest mecanisme, el que es fa es provar d’agafar el Mutex abans d’entrar a la secció crítica, si es te èxit s’executa el que calgui dins la secció crítica i a continuació s’allibera el Mutex. Com ens podem imaginar, cal que el temps que estem dins una secció crítica sigui el més curt possible.

En el cas de FreeRTOS cal primer crear el Mutex i a partir de llavors ja es pot fer servir per part de les tasques. Les tasques poden agafar o donar un Mutex amb les mateixes funcions de manegar semàfors que ja coneixem.

Un exemple senzill

Al repositori del curs tenim un exemple on dues tasques fan ús d’un recurs compartit com pot ser la consola de debug (amb el printf) i es comparteix amb un Mutex.

A l’exemple tal com està ara, no està definit la macro USE_MUTEX i el codi no en fa ús. Si executem el codi tal qual està, veurem que la sortida de les dues tasques es barreja ja que no hi ha cap control de qui escriu i quan.

from Task1
Other text Some text from Task 2
from Task1
Other text Some text from Task 2
from Task1
Other text Some text from Task 2
from Task1

Si traiem el comentari i activem la macro USE_MUTEX llavors el codi de manegar el Mutex s’activa i llavors veurem que la sortida per la consola ja és la correcta.

Other text from Task 2
Some text from Task1
Other text from Task 2
Some text from Task1
Other text from Task 2
Some text from Task1
Other text from Task 2

Què passa en aquest cas? Doncs que abans de treure el text per la consola, es demana el Mutex i queda protegida la secció crítica i tot funciona com ha de ser.

A l’exemple  es fa servir la comanda taskYIELD() entre mig dels dos printf per simular que la tasca en aquell punt perd l’execució. Com segur que saps, les condicions de carrera (race conditions) són molt complicades de trobar i provocar per què són infreqüents i només passen de tant en tant; i és per això que provoquem el canvi de tasca amb la comanda taskYIELD().

En aquest exemple i per fer-ho senzill, la crida per demanar el Mutex porta com a segon paràmetre portMAX_DELAY, que fa que la tasca quedi bloquejada fins que s’alliberi el Mutex. També es pot afegir un temps d’espera (timeout) i llavors la funció retorna quan o s’ha agafat el Mutex (i retorna pdTRUE) o quan ha passat el temps d’espera (i retorna pdFALSE).

L’ús de Mútex és necessari per controlar l’accés a qualsevol secció crítica que tinguem al nostre projecte. Habitualment en tindrem per cada ús o crida a un driver que pugui portar-nos problemes d’aquesta mena. Per exemple, si dues tasques han d’accedir al bus I2C per accedir a diferents sensors caldrà protegir amb un Mutex les crides a les llibreries del sistema.

Per acabar

La prioritat de les dues tasques a l’exemple és la mateixa. Pots provar de canviar les prioritats i treure els Mutex, a veure què passa i intentar entendre el perquè.

Anuncis

Un pensament sobre “Fent servir Mutex

Deixa un comentari

Fill in your details below or click an icon to log in:

WordPress.com Logo

Esteu comentant fent servir el compte WordPress.com. Log Out /  Canvia )

Google photo

Esteu comentant fent servir el compte Google. Log Out /  Canvia )

Twitter picture

Esteu comentant fent servir el compte Twitter. Log Out /  Canvia )

Facebook photo

Esteu comentant fent servir el compte Facebook. Log Out /  Canvia )

S'està connectant a %s

Aquest lloc utilitza Akismet per reduir els comentaris brossa. Apreneu com es processen les dades dels comentaris.