79

I've heard the phrase 'priority inversion' in reference to development of operating systems.

What exactly is priority inversion?

What is the problem it's meant to solve, and how does it solve it?

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953

11 Answers11

77

Imagine three (3) tasks of different priority: tLow, tMed and tHigh. tLow and tHigh access the same critical resource at different times; tMed does its own thing.

  1. tLow is running, tMed and tHigh are presently blocked (but not in critical section).
  2. tLow comes along and enters the critical section.
  3. tHigh unblocks and since it is the highest priority task in the system, it runs.
  4. tHigh then attempts to enter the critical resource but blocks as tLow is in there.
  5. tMed unblocks and since it is now the highest priority task in the system, it runs.

tHigh can not run until tLow gives up the resource. tLow can not run until tMed blocks or ends. The priority of the tasks has been inverted; tHigh though it has the highest priority is at the bottom of the execution chain.

To "solve" priority inversion, the priority of tLow must be bumped up to be at least as high as tHigh. Some may bump its priority to the highest possible priority level. Just as important as bumping up the priority level of tLow, is dropping the priority level of tLow at the appropriate time(s). Different systems will take different approaches.

When to drop the priority of tLow ...

  1. No other tasks are blocked on any of the resources that tLow has. This may be due to timeouts or the releasing of resources.
  2. No other tasks contributing to the raising the priority level of tLow are blocked on the resources that tLow has. This may be due to timeouts or the releasing of resources.
  3. When there is a change in which tasks are waiting for the resource(s), drop the priority of tLow to match the priority of the highest priority level task blocked on its resource(s).

Method #2 is an improvement over method #1 in that it shortens the length of time that tLow has had its priority level bumped. Note that its priority level stays bumped at tHigh's priority level during this period.

Method #3 allows the priority level of tLow to step down in increments if necessary instead of in one all-or-nothing step.

Different systems will implement different methods depending upon what factors they consider important.

  • memory footprint
  • complexity
  • real time responsiveness
  • developer knowledge

Hope this helps.

thegreendroid
  • 3,239
  • 6
  • 31
  • 40
Sparky
  • 13,505
  • 4
  • 26
  • 27
  • 1
    Thanks. I was once responsible for implementing a priority inheritance algorithm for a commercial RTOS--fun times. :) – Sparky Jan 09 '13 at 18:57
  • @Sparky So is it correct that in Step 4 tLow would be given the priority of tHigh until tLow unblocks the critical section? – JohnnyFromBF Jun 10 '15 at 16:24
  • @Ian - When there is priority inversion protection, you can expect that tLow will be given a priority that is at least as high as tHigh. It will keep that priority until tHigh is no longer blocked on that resource (and possibly longer). – Sparky Jun 10 '15 at 19:47
  • Very nice explanation, but I would bring the scheduler explicitly to the picture as it makes the complete problem possible. – avp Mar 13 '18 at 09:44
65

Priority inversion is a problem, not a solution. The typical example is a low priority process acquiring a resource that a high priority process needs, and then being preempted by a medium priority process, so the high priority process is blocked on the resource while the medium priority one finishes (effectively being executed with a lower priority).

A rather famous example was the problem experienced by the Mars Pathfinder rover: http://www.cs.duke.edu/~carla/mars.html, it's a pretty interesting read.

Dmitri
  • 8,999
  • 5
  • 36
  • 43
  • 19
    I'm confused! Why cannot the high priority process preempt the low priority process from the beginning? The medium priority process can do this, surely the high priority process must be able to also do that? I've read numerous explanations on the subject now, but I feel there's something missing. – Viktor Oct 18 '13 at 13:01
  • 2
    The assumption is that the HP process yields periodically, so other processes do run. It's only when it tries to acquire a resource that the LP already has, that the problem arises. – Dmitri Oct 19 '13 at 01:04
  • 22
    @Viktor The high priority task doesn't run 100% of the time. And when it doesn't run, a low priority task could come along and grab a mutex. In the middle of the work, a medium process comes along and preempts the low running task. Then the high priority task wakes up and wants to grab the mutex that the low priority task now owns. But the high priority task cant acquire the mutex now - it's owned by the low priority process - so now there's a problem, the high priority task can't get any further. – nos Jan 11 '14 at 00:29
  • 19
    @Viktor I was confused too, but the key piece of information is that the high priority thread and the low priority thread have a mutex in common. The high priority thread cannot preempt the low because they are trying to make use of the same resource and it must wait for the low to complete. The medium priority thread on the other hand can take control as it does not depend on the same shared resource. So the medium priority thread puts the low priority thread to sleep and takes over. – Nattrass May 16 '15 at 17:21
  • @Dmitri can you define "preempted" in this context? – CodyBugstein Jul 14 '15 at 17:19
  • 1
    The answer of nos + Nattrass is perfect! – camino Sep 03 '15 at 17:00
  • that was the perfect description by Nattrass .H and L priority task share same mutex while M priority task runs on totally different mutex lock , so M priority preamts the L priority task and hence H priority task doesn't get executed.Thats Priority Inversion. – DUDE_MXP Nov 24 '15 at 12:36
  • @Viktor I belonged to the same confusion club. Nattrass's answer cleared most of it, but what CodyBugstein asked is still not answered. What is "preempted" in this context? Does it mean that the preempted process is made to relinquish control of the CPU and moved to the ready queue? Further, can processes be preempted even if they are in their critical section? – Meathead Oct 09 '16 at 04:06
  • without @nos comment, answer is incomplete. Please add it into the answer! Thanks btw – Kaushal28 Jul 21 '17 at 16:49
  • @Nattrass p(m) could pre-empt p(l) because they don't have shared resource :nos p(m) could pre-empt p(l), even if it had shared resource, it did so because p(h) wasn't running when p(m) pre-empted Can anyone clarify on this? – Sudip Bhandari Jan 29 '18 at 19:31
  • Good answers but I think there is one thing is missing. I was not clear like Viktor and nos's answer helped little bit but I couldn't answer why high priority process can't run? It's because, if one process needs I/O operation or something like that, it goes into wait queue and until it finished it's operation it cannot go into schedule queue so it cannot be scheduled by processor. If it finished it's operation and goes into schedule queue, processor runs the process in the next cycle(if it's priority is higher than the others) – PeerNet Mar 10 '19 at 12:37
  • What is an example of a 'resource'? – craigB Apr 05 '20 at 12:01
24

Suppose an application has three threads:

Thread 1 has high priority.
Thread 2 has medium priority.
Thread 3 has low priority.

Let's assume that Thread 1 and Thread 3 share the same critical section code

Thread 1 and thread 2 are sleeping or blocked at the beginning of the example. Thread 3 runs and enters a critical section.

At that moment, thread 2 starts running, preempting thread 3 because thread 2 has a higher priority. So, thread 3 continues to own a critical section.

Later, thread 1 starts running, preempting thread 2. Thread 1 tries to enter the critical section that thread 3 owns, but because it is owned by another thread, thread 1 blocks, waiting for the critical section.

At that point, thread 2 starts running because it has a higher priority than thread 3 and thread 1 is not running. Thread 3 never releases the critical section that thread 1 is waiting for because thread 2 continues to run.

Therefore, the highest-priority thread in the system, thread 1, becomes blocked waiting for lower-priority threads to run.

Pratik Bhat
  • 7,166
  • 2
  • 35
  • 57
  • 4
    Better explanation than all the above examples – aknon Jul 31 '14 at 08:29
  • And how exactly is this problem beeing solved. I guess thread 3 would be given priority of thread 1 in the moment when thread 1 wants to enter the critical section. Because then not thread 2 would be scheduled but thread 3, right? – JohnnyFromBF Jun 10 '15 at 16:51
  • 2
    It's worth noting that Thread 2 doesn't have to wait because it has its own block of code to execute and doesn't have the same critical section code to execute as threads 1 and 3. – Abhishek Balaji R Sep 28 '16 at 15:23
18

It is the problem rather than the solution.

It describes the situation that when low-priority threads obtain locks during their work, high-priority threads will have to wait for them to finish (which might take especially long since they are low-priority). The inversion here is that the high-priority thread cannot continue until the low-priority thread does, so in effect it also has low priority now.

A common solution is to have the low-priority threads temporarily inherit the high priority of everyone who is waiting on locks they hold.

Thilo
  • 257,207
  • 101
  • 511
  • 656
5

[ Assume, Low process = LP, Medium Process = MP, High process = HP ]

LP is executing a critical section. While entering the critical section, LP must have acquired a lock on some object, say OBJ. LP is now inside the critical section.

Meanwhile, HP is created. Because of higher priority, CPU does a context switch, and HP is now executing (not the same critical section, but some other code). At some point during HP's execution, it needs a lock on the same OBJ (may or may not be on the same critical section), but the lock on OBJ is still held by LP, since it was pre-empted while executing the critical section. LP cannot relinquish now because the process is in READY state, not RUNNING. Now HP is moved to BLOCKED / WAITING state.

Now, MP comes in, and executes its own code. MP does not need a lock on OBJ, so it keeps executing normally. HP waits for LP to release lock, and LP waits for MP to finish executing so that LP can come back to RUNNING state (.. and execute and release lock). Only after LP has released lock can HP come back to READY (and then go to RUNNING by pre-empting the low priority tasks.)

So, effectively it means that until MP finishes, LP cannot execute and hence HP cannot execute. So, it seems like HP is waiting for MP, even though they are not directly related through any OBJ locks. -> Priority Inversion.

A solution to Priority Inversion is Priority Inheritance -

increase the priority of a process (A) to the maximum priority of any other process waiting for any resource on which A has a resource lock.

Ashok Bijoy Debnath
  • 1,493
  • 1
  • 17
  • 27
4

Let me make it very simple and clear. (This answer is based on the answers above but presented in crisp way).

Say there is a resource R and 3 processes. L, M, H. where p(L) < p(M) < p(H) (where p(X) is priority of X).

Say

  • L starts executing first and catch holds on R. (exclusive access to R)
  • H comes later and also want exclusive access to R and since L is holding it, H has to wait.
  • M comes after H and it doesn't need R. And since M has got everything it wants to execute it forces L to leave as it has high priority compared to L. But H cannot do this as it has a resource locked by L which it needs for execution.

Now making the problem more clear, actually the M should wait for H to complete as p(H) > p(M) which didn't happen and this itself is the problem. If many processes such as M come along and don't allow the L to execute and release the lock H will never execute. Which can be hazardous in time critical applications

And for solutions refer the above answers :)

Madhusoodan P
  • 681
  • 9
  • 20
2

Priority inversion is where a lower priority process gets ahold of a resource that a higher priority process needs, preventing the higher priority process from proceeding till the resource is freed.

eg: FileA needs to be accessed by Proc1 and Proc2. Proc 1 has a higher priority than Proc2, but Proc2 manages to open FileA first.

Normally Proc1 would run maybe 10 times as often as Proc2, but won't be able to do anything because Proc2 is holding the file.

So what ends up happening is that Proc1 blocks until Proc2 finishes with FileA, essentially their priorities are 'inverted' while Proc2 holds FileA's handle.

As far as 'Solving a problem' goes, priority inversion is a problem in itself if it keeps happening. The worst case (most operating systems won't let this happen though) is if Proc2 wasn't allowed to run until Proc1 had. This would cause the system to lock as Proc1 would keep getting assigned CPU time, and Proc2 will never get CPU time, so the file will never be released.

david
  • 17,925
  • 4
  • 43
  • 57
  • 1
    I think you are explaining blocking and not priority inversion. Priority inversion occurs when a medium priority process runs ahead of a higher priority process because of a lower priority process holding up a resource needed by the higher priority process. Also, you conclude "file will never be released". Your example has only 2 processes. If Proc1 is done with FileA, it will release the file. If it forgets to do so, its a problem of bad programming than of priority inversion. – Pavan Manjunath Feb 21 '14 at 02:22
1

Priority inversion occurs as such: Given processes H, M and L where the names stand for high, medium and low priorities, only H and L share a common resource.

Say, L acquires the resource first and starts running. Since H also needs that resource, it enters the waiting queue. M doesn't share the resource and can start to run, hence it does. When L is interrupted by any means, M takes the running state since it has higher priority and it is running on the instant that interrupt happens. Although H has higher priority than M, since it is on the waiting queue, it cannot acquire the resource, implying a lower priority than even M. After M finishes, L will again take over CPU causing H to wait the whole time.

starsail0r
  • 11
  • 1
0

Priority Inversion can be avoided if the blocked high priority thread transfers its high priority to the low priority thread that is holding onto the resource.

Musky
  • 91
  • 1
  • 6
0

A scheduling challenge arises when a higher-priority process needs to read or modify kernel data that are currently being accessed by a lower-priority process—or a chain of lower-priority processes. Since kernel data are typically protected with a lock, the higher-priority process will have to wait for a lower-priority one to finish with the resource. The situation becomes more complicated if the lower-priority process is preempted in favor of another process with a higher priority. As an example, assume we have three processes—L, M, and H—whose priorities follow the order L < M < H. Assume that process H requires resource R,which is currently being accessed by process L.Ordinarily,process H would wait for L to finish using resource R. However, now suppose that process M becomes runnable, thereby preempting process L. Indirectly, a process with a lower priority—process M—has affected how long process H must wait for L to relinquish resource R. This problem is known as priority inversion.It occurs only in systems with more than two priorities,so one solution is to have only two priorities.That is insufficient for most general-purpose operating systems, however. Typically these systems solve the problem by implementing a priority-inheritance protocol. According to this protocol, all processes that are accessing resources needed by a higher-priority process inherit the higher priority until they are finished with the resources in question.When they are finished,their priorities revert to their original values. In the example above, a priority-inheritance protocol would allow process L to temporarily inherit the priority of process H,thereby preventing process M from preempting its execution. When process L had finished using resource R,it would relinquish its inherited priority from H and assume its original priority.Because resource R would now be available, process H—not M—would run next. Reference :ABRAHAM SILBERSCHATZ

0

Consider a system with two processes,H with high priority and L with low priority. The scheduling rules are such that H is run whenever it is in ready state because of its high priority. At a certain moment, with L in its critical region, H becomes ready to run (e.g., an I/O operation completes). H now begins busy waiting, but since L is never scheduled while H is running, L never gets the chance to leave the critical section. So H loops forever.

This situation is called Priority Inversion. Because higher priority process is waiting on lower priority process.

Kaushal28
  • 5,377
  • 5
  • 41
  • 72