π Introduction #
Priority inversion is a common issue in real-time systems where a low-priority task blocks a high-priority task, causing unpredictable delays.
This can severely affect system responsiveness and even lead to failure in safety-critical applications.
VxWorks addresses this problem with priority inheritance, ensuring that resource sharing doesnβt break real-time guarantees.
π§© What is Priority Inversion? #
Imagine:
- A low-priority task holds a shared resource (e.g., a semaphore).
- A high-priority task needs that resource and is blocked.
- Meanwhile, a medium-priority task (which doesnβt need the resource) keeps running.
Result:
- The high-priority task is stuck, even though the resource is only held by a low-priority task.
- This βinversionβ can cause missed deadlines.
π‘ Solution: Priority Inheritance in VxWorks #
VxWorks automatically elevates the priority of a low-priority task holding a resource to match that of the highest-priority task waiting.
This ensures:
- The low-priority task runs to completion.
- It releases the resource quickly.
- The high-priority task resumes execution.
π» Example: Simulating Priority Inversion #
Code Example #
#include <vxWorks.h>
#include <semLib.h>
#include <taskLib.h>
#include <stdio.h>
SEM_ID semId;
// Low-priority task (holds the resource)
void lowPriorityTask()
{
semTake(semId, WAIT_FOREVER);
printf("Low priority task got the resource\n");
// Simulate long operation
taskDelay(200); // ~2s
printf("Low priority task releasing the resource\n");
semGive(semId);
}
// Medium-priority task (runs freely)
void mediumPriorityTask()
{
while (1)
{
printf("Medium priority task running\n");
taskDelay(50);
}
}
// High-priority task (needs the resource)
void highPriorityTask()
{
taskDelay(20); // Let low task take resource first
printf("High priority task waiting for the resource...\n");
semTake(semId, WAIT_FOREVER);
printf("High priority task got the resource!\n");
semGive(semId);
}
void usrAppInit(void)
{
semId = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
taskSpawn("tLow", 150, 0, 4000, (FUNCPTR)lowPriorityTask,
0,0,0,0,0,0,0,0,0,0);
taskSpawn("tMed", 100, 0, 4000, (FUNCPTR)mediumPriorityTask,
0,0,0,0,0,0,0,0,0,0);
taskSpawn("tHigh", 50, 0, 4000, (FUNCPTR)highPriorityTask,
0,0,0,0,0,0,0,0,0,0);
}
π Explanation of the Code #
-
Semaphore Creation
semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE)ensures priority inheritance.
-
Low-Priority Task
- Grabs the resource and holds it for ~2s.
-
High-Priority Task
- Tries to take the resource but gets blocked.
-
Medium-Priority Task
- Runs continuously, but due to priority inheritance, the low-priority task is boosted and finishes quickly.
β‘ Without Priority Inheritance #
If SEM_INVERSION_SAFE is not used:
- The low-priority task stays at low priority.
- The medium-priority task runs continuously.
- The high-priority task waits much longer, suffering priority inversion.
π Key Takeaways #
- Priority inversion can delay high-priority tasks unpredictably.
- VxWorks provides priority inheritance to solve the problem.
- Always use
SEM_INVERSION_SAFEwhen creating semaphores for shared resources.
β Wrap-Up #
In this tutorial, you learned:
- What priority inversion is.
- How VxWorks prevents it with priority inheritance.
- Why
SEM_INVERSION_SAFEis important for real-time correctness.
In the next blog, weβll explore Task Synchronization with Events in VxWorks.