Priority inversion is a bug where the task with a high priority is blocked indirectly by a task with a lower priority that runs longer period than the high priority task. This example is a demonstration of the priority inversion using the mutex semaphore.

Code Example:

#include "bsp.h"

SemaphoreHandle_t  xMutex;  /* Mutex semaphore 1 */

static void Task_HP( void *pvParameters );   /* Task high priority function */
static void Task_LP( void *pvParameters );   /* Task low priority function */

int main( void )
{
    HAL_Init();

    SEGGER_SYSVIEW_Conf( );
    SEGGER_SYSVIEW_Start( );

    xMutex = xSemaphoreCreateMutex();                       /* Create the Mutex Semaphore */
    
    xTaskCreate( Task_HP, "Task_HP", 240, NULL, 2, NULL );  /* Register Task1 to turn on LEDs */
    xTaskCreate( Task_LP, "Task_LP", 240, NULL, 1, NULL );  /* Register Task2 to turn off LEDs */
    
    vTaskStartScheduler();                                  /* Init the Kernel */
}

void Task_HP( void *pvParameters )
{
    for(;;)
    {
        xSemaphoreTake( xMutex, portMAX_DELAY );            /* High priority task take the mutex */     
        SEGGER_SYSVIEW_PrintfHost( "Task HP takes mutex" );
        vTaskDelay(250);                                    /* Duration of code protection */
        SEGGER_SYSVIEW_PrintfHost( "Task HP gives mutex" );
        xSemaphoreGive(xMutex);                             /* High priority task gives the mutex */
        vTaskDelay(250);
    }
}

void Task_LP( void *pvParameters )
{
    for(;;)
    {
        xSemaphoreTake( xMutex, portMAX_DELAY );            /* Low priority task take the mutex */
        SEGGER_SYSVIEW_PrintfHost( "Task LP takes mutex" );
        vTaskDelay(1000);                                   /* Duration of code protection */
        SEGGER_SYSVIEW_PrintfHost( "Task LP gives mutex" );
        xSemaphoreGive(xMutex);                             /* Low priority task gives the mutex */
        vTaskDelay(250);
    }   
}

Two Tasks are registered in the application, Task_HP is registered with a priority of 2, and Task_LP is registered with a priority of 1.

This tasks take first the mutex semaphore and block it until the period elapsed, when Task_LP runs the mutex is taken blocking the execution of the high priority task Task_HP for 1000 ticks, causing that Task_HP execute as a low priority task.

SystemView Output:

Observe in the terminal that task_LP ( Task low priority ) is executed blocking the execution of the task_HP ( Task high priority ), when Task_LP finished the Task_HP executes for just a brief period to after execute again the Task_LP blocking the other task, ignoring the task priority.

Document

TimeLine:

Document

Observe in the timeline the execution of Task, put attention to the start time of the "Task_LP", the task take the mutex blocking a part of the code, after a vtask_delay function is executed to simulate a long period execution of mutex protection. When time is elapsed the mutex is released and other task can use it.

Observe that "Task_HP" runs again but is blocked for the mutex that is taken by the "Task_LP".

When the "Task_LP" period elapsed, "Task_HP" takes the mutex semaphore for a short period, finishing soon its execution.