Mutex Priority Inversion Anamoly

preetkang wrote on Saturday, March 02, 2013:

Richard,

I’m making videos of FreeRTOS tutorial (http://www.socialledge.com/sjsu/index.php?title=FreeRTOS_Tutorial) and I’ve noticed the priority inversion anomaly in FreeRTOS.  In my demo program below, it makes no difference if the semaphore is a mutex or a binary semaphore.  In either case, I see the same output, but I think it lower priority tasks should get equal access.

Output (regardless if semaphore is a mutex or semaphore):
task4 got sem.  Will use it …
task3 got sem.  Will use it …
task4 got sem.  Will use it …
task3 got sem.  Will use it …
task4 got sem.  Will use it …

xSemaphoreHandle sd_card_lock = 0;
void my_task(void *p)
{
    while(1) {
        if(xSemaphoreTake(sd_card_lock, 999999)) {
            printf("%s got sem.  Will use it … \n", (char*)p);
            xSemaphoreGive(sd_card_lock);
        }
        vTaskDelay(1);
    }
}
void main( void )
{
    sd_card_lock = xSemaphoreCreateMutex();
    //vSemaphoreCreateBinary(sd_card_lock);

    xTaskCreate(my_task, (signed char*) “t1”, 1024, (void*)“task1”, 2, NULL );
    xTaskCreate(my_task, (signed char*) “t2”, 1024, (void*)“task2”, 2, NULL );
    xTaskCreate(my_task, (signed char*) “t3”, 1024, (void*)“task3”, 3, NULL );
    xTaskCreate(my_task, (signed char*) “t4”, 1024, (void*)“task4”, 3, NULL );
    vTaskStartScheduler();
}

If all tasks have the same priority, then we see every task taking turn, again regardless if the semaphore is a mutex or binary.  But with a mutex, it should be the same behavior but it’s not :(   Can you please educate me?

Preet

richard_damon wrote on Saturday, March 02, 2013:

Why would you expect the priority 1 or 2 task to every get the semaphore?

When Task 4 gets the semaphore, everyone else lines up on it and waits for it.
When Task 4 gives the semaphore back, Task3, since it is the highest priority task will get it.
While Task 3 is outputing its message, my guess is that Task 4 finishes its 1 tick wait, and then puts itself in line for the semaphore.
When Task 3 finishes, task 4 get the semaphore because it is the highest priority task waiting on the semaphore.

Making the semaphore into a mutex just says that when Task 4 starts its wait on the semaphore, Task 3 gets a temporary boost in priority to that of Task 4 (the priority inversion logic) .

If all tasks are the same priority, then the priority doesn’t select which task gets chosen, and among equal priority tasks, the one waiting the longest it chosen first.