Learn about the use of mutexes and semaphores in embedded C programming from Barr Group Principal Engineer, Salomon Singer.
Related Courses
How to Prioritize RTOS Tasks (And Why It Matters)
Transcript
Andrew Girson: Hi. I'm here today with Salomon Singer, Barr Group principal engineer. And we're here today to talk about RTOS synchronization primitives.
So Salomon, that sounds like a mouthful, let's start off by talking about what is a RTOS synchronization primitive and why are they used?
Salomon Singer: Right. So, two main reasons that we're going to use a synchronization primitive.
The first one is to pass information along from one task to another or from an ISR to a task.
The second reason to use one of these synchronization primitives is to avoid a race condition--a race condition being a situation where two or more tasks one to manipulate a shared resource at about the same time.
Andrew: Okay. So shared resource being like a hardware register or a piece of hardware or something like that where there's only one of them but there might be multiple tasks in a system that might actually need to interface with that.
Salomon: Correct. So a shared resource would be either a piece of hardware or even a global variable that might be used in several threads.
Andrew: Okay. All right. And mutexes are a well-known type of RTOS synchronization primitive. What exactly is a mutex?
Salomon: Okay. So first of all, mutex stands for mutual exclusion.
Andrew: Okay.
Salomon: And in this particular case, it's a primitive used to prevent two or more tasks from accessing the same shared resource at about the same time.
From 25,000 feet, we can say--and this is an oversimplification of course--we can say that it's a threat safe binary flag in use or non-use. Okay?
Andrew: Okay.
Salomon: Okay.
Andrew: And that flag becomes associated with a global variable or a piece of hardware--
Salomon: --with something we call the "shared resource."
Andrew: Right.
Salomon: So there is a one-to-one relationship between a mutex and a shared resource. One mutex protects one shared resource. If you have two shared resources that you need to protect, you would need two mutexes. One paired shared resource.
Andrew: Okay. All right.
And then of course semaphore. That's another type of RTOS synchronization of primitive. When is a semaphore - what is a semaphore? How is it different from a mutex? When is it used?
Salomon: Yes, that's a very good question.
First of all, it's a synchronization tool to let one task know that an event happened. What event that's up to the sender and the receiver to agree.
Typically, some kind of hardware event. Like what? Like, a user presses button "A" or maybe you won't receive a character and we want to handle--we want to pass the information along to a task so that it can handle the character that came in that you want.
And so, implementation wise, a semaphore and mutex are very very similar.
Andrew: Right.
Salomon: But you need to forget that I said so because most of us are not always implementers, we're just always users--we use the OS as a tool. And so, you use mutexes only to protect the shared resource. And you use semaphores only to communicate to a task that an event--an awaited event has happened.
Andrew: So, in general, in real-time systems, multitasking with multiple shared resources, whether they be global variables or pieces of hardware or whatever, mutexes or semaphores provide the tools to allow all those things to work in a multitasking system.
Salomon: Absolutely. You have to be extremely careful not to use a semaphore when a mutex is the tool that needs to be used.
There are a couple of huge differences between a mutex and a semaphore. The two biggest differences are, one, that a mutex has the concept of an owner. If you have requested the mutex and the OS has granted it to you, you are now, on file as being the owner. And so, nobody else can now free or post to a mutex that they don't previously acquire the ownership for.
Andrew: Sure.
Salomon: That concept does not apply to semaphores. Just the mutexes. The second thing that is built into mutexes is some kind of algorithm--I don't want to get into the details right now--
Andrew: Sure.
Salomon: --to prevent priority inversions.
Andrew: Okay.
Salomon: If you implement mutual exclusion with the semaphore, you don't get the algorithm and you might get into situations where you have priority inversion.
Andrew: Priority inversion is obviously its own topic.
Salomon: Correct.
Andrew: But in general, obviously if, you know, real-time synchronization issues could be some of the most difficult issues to debug in an embedded system that, I guess, if you want to take a look at your mutexes and your semaphores and how you're using them, if you're having problems, and make sure you're using them properly and I presume you cover that in the Embedded Software Boot Camp and some of our training courses.
Salomon: Yes, exactly. That's exactly where I was going right now. We spend a fair amount of time during the Boot Camp talking about the differences between mutexes and semaphores and teaching the students which applications are suitable for each. I also did a webinar about a year ago that talks about this topic in a little more detail.
Andrew: In a little more detail. Right. And that's available on our website.
Salomon: Correct.
Andrew: Okay, great. Thank you, Salomon.
Salomon: You're welcome.