Recursive mutexes clarification needed

sasikalaswathi wrote on Wednesday, November 20, 2019:

Hi All,

I am currently working in the recursive mutexes.Here was my understanding regarding recursive mutexes

  1. Able to take the mutexes continuously by using the* xSemaphoreTakeRecursive* without using the mutex give API “xSemaphoreGiveRecursive” . In this case value of the variable pxMutex->u.uxRecursiveCallCount (inside the queue.c file) keep on increasing. Here what is the maximum number /limit of “xSemaphoreTakeRecursive” available?

  2. If two tasks tries to take the recursive mutexes with the same priority at round robin fashion, only one of the task able to get the recursive mutexes.

But in other task, while checked the behvaiour via putting breakpoints, else condition of (if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) in xQueueTakeMutexRecursive) was executing. While context switch occurs at every time slice, recursive mutex was not given back other recursive mutex waiting tasks, eventhough i was released the recursive mutex using xSemaphoreGiveRecursive function.

All tasks get the chance to access the recursive mutex whenever, i used the xSemaphoreGiveRecursive function along with the taskYIELD API at every task. So I need to use the taskyiled and xSemaphoreGiveRecursive necessarily in order to get the recursive mutexes for all tasks?

Attached the code for reference. For trying out the different options mentioned above, I comment out few lines then executed.

richard_damon wrote on Wednesday, November 20, 2019:

The maximum number of nesting for a recursive mutex would be the maximum number that can be stored in a variable of the type of uxRecursiveCallCount, I don’t have the code in front of me at the moment, but even if that was as small as a byte, that would be at least 127, which should be way more than any reasonable program is going to need, unless it is explicitly trying to stress test the mutex.

In you scenerio, if two tasks of the same priority try to take a mutex, one will start and get it, and the other will block and wait for it. When the task holding the mutex releases it, the one blocking will be removed from the block state, but since it isn’t higher in priority, it won’t be switched to. If the first task then quickly takes the mutex back, it will still be available, and the other task will find it not available and continue waiting. If you want the tasks to share the resource, add a vTaskYield() call after the give, so that the other task will get a chance to run. The other option is if the task that gave does something else that either uses enough time for the tick interrupt to come around (and time sliceing is enabled) or does something which causes it to block or yield, then the other task will get its chance (and it needs to do something similar to give control back).

A basic design rule when working with real time systems is that generally most tasks should be blocking waiting for something to happen that needs them to do their work. (and while blocking and waiting they normally shouldn’t be holding any shared resources). Any tasks that don’t follow this model, but just continually run should be at the lowest priority, and should at least yield at a point or points when they don’t hold shared resources.

richard_damon wrote on Wednesday, November 20, 2019:

(Duplicate deleted)

sasikalaswathi wrote on Wednesday, November 20, 2019:

Hi Richard,

Thanks forquick detailed response.

It is advisable to take the recursive mutexes continuously without using the give API “xSemaphoreGiveRecursive” ?

richard_damon wrote on Wednesday, November 20, 2019:

I wouldn’t ‘continuously’ grab a mutex, if you know you have it, don’t grab it again. The idea of what you seem to describe leads to the issue of trying to figure out how many times to give it when you are done.

Where I use recursive mutexs is where I naturally want to take it at different layers of a process. For example, when outputing a character to a serial port, I grab the mutex for the port, send the character, and then give the mutex back. I may want to send a message, and not let someo other task inject characters in the middle of the message, so I grab the mutex at the beginning of the message and release it at the end, and let the character routine take it recursively within the operation, and do its give without releasing the mutex, thus the nesting count reflects the number of layers that are grouping things they want to keep together, naturally a fairly small number.

sasikalaswathi wrote on Thursday, November 21, 2019:

Thank you for the reply

sasikalaswathi wrote on Thursday, November 21, 2019:

Hi Richard,

I have another doubt in recursive mutex. Can I able to call the xSemaphoreGiveRecursive API, before the call to xSemaphoreTakeRecursive API? while I tried that, i always get the pdFAIL result. Generally in binary semaphore, taking of semaphore will be successful only after the giving of semaphore was successful right. but here it was like that.

void Task1(void *p)
{
while(1)
{
if(xSemaphoreTakeRecursive( xMutex))
{
//did some other work
}
}

void Task2(void *p)
{
while(1)
{
xSemaphoreGiveRecursive( xMutex);
}
}

richard_damon wrote on Thursday, November 21, 2019:

Mutexes are somewhat differnt than semaphores, because they have some features that semaphores don’t have, mainly the priority inheretance to avoid priority inversion.

One consequence of this is that only the task that took a mutex is supposed to give the mutex (the strictness of the checking of this has changed over versions). Because of this, mutexes are always made in the state where they are ready to be taken.

Semaphores don’t have this pairing requirement on take and give, and in fact one very common usage is one task gives while another task takes. Depending on the function you use to create the binary semaphore will control whether it starts in the taken state or the given state.

Just because mutexes use functions with semaphore in their name doesn’t mean you can treat mutexs just like a semaphore. They have special abilities, and extra usage rules.

sasikalaswathi wrote on Thursday, November 21, 2019:

Hi Richard,

Got the point, thanks for the reply