Hi all ,
I thought the only differences between a Mutex and a semaphore are the count(Semaphore Capability) and priority inversion(Semaphore Capability) . Today , I’ve encountered something strange which maybe is related to the priority inversion capability or something else .
Getting and releasing Mutex or Semaphores between different tasks is clear but when I use them in just one task , their behavior is different . Using semaphore the task is locked but using Mutex the task is not locked . Imagine there is just one task called APP_TestTask
__task void APP_TestTask (void) { for (;;) { os_dly_wait (20); os_sem_wait(Sem_Test,0xffff); os_sem_send(Sem_Test); os_sem_wait(Sem_Test,0xffff); os_sem_wait(Sem_Test,0xffff); Test_Function(); } }
__task void APP_TestTask (void) { for (;;) { os_dly_wait (20); os_mut_wait(Mut_Test,0xffff); os_mut_release(Mut_Test); os_mut_wait(Mut_Test,0xffff); os_mut_wait(Mut_Test,0xffff); Test_Function(); } }
Is it something natural or a bug ? Thanks in advanced
Note that the RTX knows who owns the mutex, and are using a counter for number of times it has been locked.
So the same task can claim the mutex multiple times without getting locked.
www.keil.com/.../rlarm_os_mut_release.htm
The goal with the mutex is just locked or not locked. So the internal counter just keeps track of number of times the same thread have locked it - expecting the same number of release calls before the mutex is released. This allows you to put the mutex lock/unlock inside a function, and then make lock/unlock outside that function call and perform multiple function calls while still owning the mutex.
A semaphore on the other hand counts the availability of a limited resource. So for a semaphore it really do matter the number of times you claim it - it's irrelevant who claims a resource.
Thanks a lot ,
So the point is calling lower level functions which have the same mutex too . Ok ?
I always had a problem :
Imagine GLCD_Put_String Function has a Sub function called GLCD_Put_Char If both of these functions has the same semaphore (Getting the semaphore at their first line and Releasing it at their last line) , Whenever GLCD_Put_String calls GLCD_Put_Char , the task would get locked and the only way to solve this problem is removing the semaphore from the lower level functions and whenever we want to use lower level functions independently , we’re forced to use the semaphore outside (before and after) of the functions .
but using mutex instead of semaphore , the problem is solved and there is no need to be worried of anything at all .
Note that the specific thing about semaphores is to count resources. Unless you have the capability of having n concurrent print threads, I would not use a semaphore.
Why not using a mutex in concurrent print threads ?
You can. It's just a question of who should be responsible.
Should every code section wanting to print claim the print resource. Or should the print resource itself be designed thread-safe.
There is a very important difference to consider. Let's say the threads wants to do two calls each time something should be written.
So thread A wants to print "A1\n" and "A2\n". Thread B wants to print "B1\n" and "B2\n".
If the threads takes the lock, then nothing can get between A1 and A2, and nothing can get in between B1 and B2.
If the print routines takes the lock, then you could get output that looks like: A1 B1 B2 A1
Or maybe A1 B1 A2 B2
In the end, this is your design decision.
Would you please show the use of a semaphore to print A1 => A2 => B1 => B2 for sure ?
Thanks
It's just a question if you take the mutex outside of the print calls, then you can have multiple print calls within the same critical section.
If the print functions internally uses a mutex, then they guarantee to not garble the output of the individual calls. But two calls to that function can have the output from another thread in between.
Since the mutex keeps track of which thread owns it, and allows multiple calls from same thread (as long as you unlock the same number of times), you can even do both.
So your print() functions can make use of a mutex, and single calls to print() can manage without issues. When a task needs to perform multiple print() without someone getting in between, that task can use the same mutex as your print() function.