Use xSemaphoreTakeRecursive()

I can not image there is a situation, need use this style of mutex,can you help me by using a simple example.

One simple one that I have is that I have a serial driver that starts at the bottom level acquiring the mutex for the serial port before sending the character. Higher level operations might want to make sure that their message isn’t interrupted by the output of another task, so they also take the mutex. Since the mutex is recursive, this works.

If I didn’t have a built in recursive mutex, then I would need to build something like one around the current non-recursive mutex.

The general case where you want this tend to be cases where inside an area that wants to use a protected resource, you want to call a routine that also wants to use that same protected resource, but it can’t assume you already have the mutex.

Thank you for your guidence ,Sir.
I can understand this: possible two way using this sytle mutex.
1, same task take it some times. like this,

        if( xSemaphoreTakeRecursive( xMutex, 10 ) == pdTRUE ) 
        { 
            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); 
            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); 
     
        
            xSemaphoreGiveRecursive( xMutex ); 
            xSemaphoreGiveRecursive( xMutex ); 
            xSemaphoreGiveRecursive( xMutex ); 
     
            /* Now the mutex can be taken by other tasks. */ 
        }

2,different task take it like this,

void vTaskA(void *pvPara)
{
    for(;;)
   {
        if( xSemaphoreTakeRecursive( xMutex, 10 ) == pdTRUE ) 
        { 
            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); 
     
        
            xSemaphoreGiveRecursive( xMutex ); 
            xSemaphoreGiveRecursive( xMutex ); 
     
            /* Now the mutex can be taken by other tasks. */ 
        }
   }
}
void vTaskB(void *pvPara)
{
    for(;;)
   {
        if( xSemaphoreTakeRecursive( xMutex, 10 ) == pdTRUE ) 
        { 
            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); 
     
        
            xSemaphoreGiveRecursive( xMutex ); 
            xSemaphoreGiveRecursive( xMutex ); 
     
            /* Now the mutex can be taken by other tasks. */ 
        }
   }
}

I thought ,can use different mutex for different source, like you said,serial port be protect by A mutex, message want to be protect, so give another mutex for it,Must I use recursive mutex for the two different source?
I havn’t use recursive mutex,and I thought different mutex can use recursively,though I haven’t used like this.Is the thought right? e.g.

void vTaskC( void *pvPara )
{
    for( ;; )
   {
       if( xSemaphoreTakeRecursive( xMutexA, 10 ) == pdTRUE ) 
        { 
             if( xSemaphoreTakeRecursive( xMutexB, 10 ) == pdTRUE)
            {
                 xSemaphoreGiveRecursive( xMutexB );
            }
            xSemaphoreGiveRecursive( xMutexA );
        }
   }
}

Your first example, since it takes the same mutex multiple times, is a case that shows the need for a recursive mutex. In that particular case, there is no reason to actually need to take the mutex the second (or third) time, as it is clear from the situation, that you have the mutex. The example I gave was more like:

void send_char(char c){
xSemaphoreTakeRecursive(xMutex, portMAXDELAY);
/* code to send character out the serial port */
xSemaphoreGiveRecursive(xMutex);
}

void send_string(char* str) {
xSemaphoreTakeRecursive(xMutex, portMAXDELAY);
while(*str) send_char(s++);
xSemaphoreGiveRecursive(xMutex);
}

Where here send_char hold the mutex to avoid two different tasks calling the code at the same time, and send_string extends that lock so that two tasks don’t get messages intertwined.

send_string can’t use a different mutex, as that wouldn’t protect from another task adding just a character to the output (or using some other message building function that didn’t use the same mutex as send_string). The mutex can’t be a non-recursive mutex, as then when send_char tries to take it, it will not be able to take it as it already taken by send_string, so we deadlock.

You don’t need a recursive mutex to take multiple different mutexes, only to take a give mutex in a nested fashion, so your vTaskC doesn’t need recursive mutexes (unless some other part of the program will need the recursiveness).

Thanks,Sir.
Well,I still confused about the use.
at your example, if I designed this ,I will just use one mutex for void send_string();and use normal mutex, I still no clear understand the meaning of recursive mutex. sorry for too foolish.

If there was just a mutex in send_string, then if one task calls send_string while another task calls send_char, that character may end up in the middle of the string.

Thus the first task runs a sequence something like:

TaskA
  send_string
     take
        send_char
           take
           do I/O
           give
       send_char
           take
           do I/O
          give
    give
return to taskA

taskB
  send_char
    take
    do I/O
    give
return to TaskB

If send_char and send_string use different semaphores, then Task B’s call could happen between to two Task A send_char calls

If send_char and send_string use the same semaphore, it needs to be recursive, or the take in send_char will fail (as the semaphore is in the taken state).

This is the difference between a normal semaphore and a recursive semaphore. A normal semaphore can only be taken if the last operation was a give, otherwise, it waits for the give. A recursive semaphore, on the other hand, will succeed if the last operation was a take by the same task as currently own it, and it keeps track of the depth and doesn’t actually ‘give’ the semaphore back so another task can take it until it has been given as many times as it was taken.

The example is some special, I got some understand, it is about one char and one string case.Thank you sir,I will take more thinking about recursive mutex.