Introduction to RTOS Part 6 - Mutex | Digi-Key Electronics

preview_player
Показать описание
A mutex, short for MUTual EXclusion, is a locking mechanism that is used to prevent other threads from interrupting or overwriting a section of shared data (such as a global variable or common buffer).

FreeRTOS implements mutexes and semaphores with queues, and operations to read, increment, and decrement these kernel objects are all atomic (meaning other threads cannot interrupt or modify the variables during those operations).

We use a mutex as a locking mechanism to protect a shared resource or critical section of code. When a thread or task takes a mutex, the value of the mutex is decremented from 1 to 0, and other tasks may not take the mutex while it is 0.

When the task is done working in the critical section, it gives the mutex back, which increments it from 0 to 1. This action of taking and giving a mutex allows only one thread to operate in a critical section of code at a time (it is mutually exclusive: no other threads may execute that section or take the mutex during that time).

In the video, we give an example of a race condition and how a mutex can be used to prevent it from happening. We provide a demonstration of using a mutex in FreeRTOS and then issue a challenge to use a mutex to allow parameters to be passed to tasks (note: this is a hack!).

Product Links:

Related Videos:

Related Project Links:

Related Articles:

Learn more:

Рекомендации по теме
Комментарии
Автор

I just have to chime in and give another thanks to Shawn for these awesome videos that are so clear and concise!
Big thanks to Digi-Key for sponsoring these!

yogimarkmac
Автор

Your tutorials are amazing, thanks a lot. I've been using mutexes in Linux desktop applications for a while now, but never really understood how they work.

ksawery
Автор

Shawn, thank you so much. You make one of the most concise and informative vids.

gopsLiverpool
Автор

I wish you could suggest more challenges so that the audience could practice and understand the knowledge much better. Anw, thank you so much for your effort to create such good videos like this one.

ducdoanxuan
Автор

Thank you for the series. In this one, I think you have a great opportunity to demonstrate starvation. If you extend your 'else' to do some work (aka is delayed), then you could get to the point that task A is the only one incrementing the shared resource -- hence task B is starving.

mahamasamataman
Автор

I am watching this 3 years later and it's bomb

todorator
Автор

Hi Shawn. Thank you for the nice work.
I wanted to make sure "Serial.println(shared_var)" was "actually" being executed by different tasks, so I added to print the task name along the shared_var.
It works beautifully for the "race-condition", showing which task is actually printing the 'right' and 'wrong' values. But ...
When I did the same for the "demo-mutex", to my surprise only "Increment Task 1" executes, never "Increment Task 2".
Maybe the compiler is optimizing something ... even with two functions with the random delay.
At the end what worked was to add a small delay "vTaskDelay(1 / portTICK_PERIOD_MS);" right after "xSemaphoreGive(mutex);"
Only then you see one task printing after another in sucession.
Any thoughts?

crs
Автор

Nice example, but you print the shared_var after you give the Mutex. The shared variable is updated correct but there is a risk of printing the wrong value. You should print the local_var to safe

jamesytterstene
Автор

Hi Shawn, great tutorial, thanks.
I have an App that runs on a ESP32CAM. Task1, when triggered, takes a picture and stores it to SPIFFS.
Task2 keeps checking SPIFFS to see if it finds new pictures, send them to FTP and deletes them.
The conflict would be if Task2 finds a picture partially written to SPIFFS by Task1 and tries to send it to FTP while it is still incomplete.
So I am using a Global variable fileName that is populated when Task1 takes the picture and saves it to SPIFFS and as soon as the save is done fileName is set to "". So Task2, before grabbing a picture for transfer to FTP it checks if the name of the picture on SPIFFS is equal to the global variable fileName.
If it maches it means Task1 is still writing the file and FTP file transfer is postponed.
Only Task1 writes to fileName, Task2 only reads although it has a big chance of concurrency as each task runs in its own core.
Do I need to implement the strategy shown in this tutorial to my App?
Thanks

fingerprint
Автор

sir my name is Akash iam a msc electronics student from kerala india i am a big fan of you

akashr
Автор

I attempted your challenge problem but it wasn't working but the code seemed fine.. It looked like the blinkLed task was taking too long to start and just wasn't able to take the mutex in time so I has to use a little bit of delay in setup so that the task can start and take the mutex, copy the variable and return it to signal the setup function to finish.. I was only able to solve the problem this way, is there another way to do this without using delays?

phizaics
Автор

Is it possible to put the user program to run on the same core as the WiFi on the ESP32?
What happens if a core has nothing to do? Lower power consumption?

piconano
Автор

Love it!! Thanks for your effort, it helps me a lot.

ppan
Автор

Thanks very much for your wonderful tutorials. Regarding the solution of this challenge, I think it's not essential to set the Mutex Blocking Time to maximum in line 83.

shsh
Автор

What happens if a Task exits or is deleted whilst holding a mutex? Does FreeRTOS have any way of auto-releasing a mutex when a Task dies?

GrahamStw
Автор

I may have missed this, but how does task created? I am confused about the hack offered in the solution. it seems to me that the xTaskCreatePinnedToCore() function will enter the blinkLED() so it can yield the mutex. is it how it works? thank you.

急眼的海老
Автор

Hi Shawn, In the solution, I'm completely confused.
So in the setup() we took the Mutex a second time with xSemaphoreTake(mutex, portMAX_DELAY). Just for the purpose of waiting the maximum amount of time (so that it is blocked), that's the only reason right? If this is the only reason why not just use a a simple delay function vTaskDelay(1000 / portMAX_DELAY)?

Also, after we have run the second xSemaphoreTake(mutex, portMAX_DELAY).. since the mutex was released earlier, then the Mutex will be taken again returning pdTRUE, but I don't see a function afterwards to release it?

Any help is appreciated

tadm
Автор

There is one thing I dont understand. Why can't I just use a global variable instead of the Mutex and set it 0 once the shared ressource is being used?

marcg.
Автор

Great video. But why not simply disable interrupts, check the global value, write to it and re-enable interrupts? Could this be what a mutex actually does behind the scenes?

ytubeleo
Автор

is it necessary that both the task has to run on the same core for the mutex method?

pruthvijagadeesh