core27 min studyLesson 136 in Engineering

Trace priority through a lock dependency

Trace a high-priority task through a lock dependency, then understand both the power and limits of priority inheritance.

On this page

What you’ll understand

  • Construct the dependency chain that produces priority inversion.
  • Explain temporary priority donation through a priority-inheritance mutex.
  • Bound a simplified blocking interval while identifying assumptions that invalidate the bound.

A scheduler cannot run a blocked task merely because that task has the highest priority. If a low-priority owner holds the resource it needs, progress depends on the owner completing and releasing that resource. Now add an unrelated medium-priority task that can repeatedly preempt the owner: the high-priority task's delay is indirectly controlled by work that should have ranked below it. Priority inheritance addresses this scheduling dependency by temporarily raising the owner's effective priority. Its usefulness becomes clear only when we also state what it cannot repair: arbitrary resource delay, cyclic deadlock, or unlimited critical-section execution.

Follow ownership rather than CPU priority alone

Use three tasks on one CPU, with priorities ordered high, medium, and low. The low task first acquires a mutex. The high task later requests the same mutex and blocks because mutual exclusion prevents simultaneous ownership. The medium task then becomes runnable. Without an appropriate inheritance protocol, it can run ahead of the low owner even though the high task depends on that owner's progress. The high task is not merely waiting for the remaining protected computation; it is also exposed to interference from the medium task. Increasing the high task's base priority changes neither the lock ownership nor that indirect dependency.

Some blocking is intrinsic to sharing. Even with perfect inheritance, the owner generally must finish the relevant protected work before the waiting task can enter safely. The engineering question is whether unrelated lower-priority activity can stretch that wait beyond a justified bound. Draw a dependency edge from each blocked task to the current owner of the lock it needs. This graph makes a hidden relationship visible: delaying an owner can delay every task upstream of it. A trace that shows the high task sleeping and the medium task running is therefore incomplete until you know which task owns the contested resource.

BH=CL,remaining+IM+δB_H=C_{L,\mathrm{remaining}}+I_M+\delta
In the simplified single-lock, one-CPU example without inheritance, high-task blocking B_H in milliseconds contains remaining owner CPU work, medium-task interference, and explicit handoff overhead delta. This is an example decomposition, not a universal response-time formula.↔ Scroll wide equations horizontally.

Donate effective priority along the chain

With an inheritance-capable mutex, a blocked high-priority waiter can cause its low-priority owner to execute at an effective priority reflecting that waiter. The medium task can no longer preempt the owner solely because its base priority exceeds the owner's original priority. Once the ownership dependency changes, the effective priority must be recomputed from remaining waiters and owned locks; blindly resetting to the original value would be wrong when another high-priority waiter still depends on the same task. Base priority expresses normal scheduling intent, while effective priority incorporates temporary dependencies. Treating the boost as a permanent promotion misunderstands both fairness and correctness.

Dependencies can extend beyond one mutex. If the boosted owner is itself blocked on another inheritance-capable mutex, progress may require propagation to the next owner. A complete analysis must inspect the chain, not just the first lock named by the delayed task. Linux rt-mutex documentation explains this mechanism, and userspace mutex protocols can request priority inheritance where supported. A regular mutex should not be assumed to provide the protocol automatically. Check initialization, return values, platform support, and the deployed implementation. For real-time design, verify the entire dependency path; one unexamined lock or resource wait can invalidate a reassuring diagram.

State the bound and challenge its assumptions

Consider a deliberately narrow bound: one CPU, one relevant owner, no nested locks, bounded remaining protected CPU execution, an operational inheritance protocol, and no higher-priority interference or blocking inside the critical section. The wait then consists of the owner's remaining work plus measured protocol and dispatch overhead. Relaxing these assumptions changes the calculation. An owner sleeping on storage may need the storage device rather than additional CPU priority. A nonpreemptible kernel interval or another higher-priority task may still delay dispatch. A cycle in which two owners wait for each other's locks is deadlock; donating priority cannot make either release a lock it will never reach code to release.

Reduce avoidable critical-section work, define a consistent lock acquisition order, and avoid performing unbounded external operations while holding locks on timing-sensitive paths. Then instrument actual contention, ownership transitions, and dispatch events instead of inferring safety from the word inheritance. The queue lab illustrates only a related capacity lesson: available service must be sufficient for arriving work. Its backlog has no mutex owner, priority values, inheritance chain, or deadlock state, so it cannot test the protocol. To inspect aggregate pressure, compare separate fixed-rate runs at arrival 4, service 3 and arrival 2, service 3. Before each run, press Reset, re-set both rates, predict the direction from four work units, then press Play or Step; the second run does not inherit the first run's backlog. Keep this capacity comparison separate from the ownership mechanism, and use the numerical exercise here to assemble a narrowly specified blocking bound.

BHPI≤CL,remaining+δboundB_H^{\mathrm{PI}}\le C_{L,\mathrm{remaining}}+\delta_{\mathrm{bound}}
This bound applies only to the explicitly stated one-owner, bounded-critical-section example with no higher-priority interference or external blocking. Delta_bound is an assumed verified upper bound on protocol and dispatch overhead in the same time units.↔ Scroll wide equations horizontally.

Removing unrelated medium-priority interference

Assume a single CPU and one mutex. When H blocks, low-priority owner L has 2 ms of protected CPU work remaining. An unrelated medium-priority task would execute for 8 ms before L without inheritance. Assume 0.1 ms total handoff overhead, no other arrivals, no nested locks, and no external blocking. Compare the blocking intervals.

  1. Without inheritance, the stated execution order gives 8 ms of medium-task work before L finishes its remaining 2 ms. Add 0.1 ms overhead: 10.1 ms.

  2. With operational inheritance, L runs ahead of the unrelated medium task once H blocks. Its protected work still takes 2 ms.

  3. Add the same assumed 0.1 ms total overhead: the simplified inherited case blocks H for 2.1 ms, reducing the interval by 8 ms.

BHno PI=8+2+0.1=10.1 ms,BHPI=2+0.1=2.1 msB_H^{\mathrm{no\ PI}}=8+2+0.1=10.1\,\mathrm{ms},\qquad B_H^{\mathrm{PI}}=2+0.1=2.1\,\mathrm{ms}
The arithmetic follows the supplied deterministic timeline and excludes other sources of interference.↔ Scroll wide equations horizontally.
The result

The example changes H's blocking from 10.1 ms to 2.1 ms. It removes the stated medium-task interference, not the resource owner's necessary work.

Explore the model

Interactive lab

Interactive lab · queue

Capacity is separate from lock ownership

Compare separate fixed-rate runs with λ=4, μ=3 and λ=2, μ=3. Each time: Reset, re-set both rates, predict the direction from four work units, then Play or Step. Editing λ alone retains elapsed time and does not continue an accumulated backlog under a new arrival rate. This illustrates capacity only; it contains no priority inheritance, tasks, mutex ownership, or deadlock state.

Capacity is separate from lock ownershipFluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Current readings: Fluid backlog: 4; Net rate · λ − μ: −1 /s; M/M/1 mean residence: 1 s. All parameters are adjustable with the labeled controls below.02.557.51001.534.56Elapsed time · sFluid backlogλ < μ
Fluid backlogCurrent time
Fluid backlog
4
Net rate · λ − μ
−1 /s
M/M/1 mean residence
1 s
t = 0 s

Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forA capacity diagram cannot establish a lock-blocking bound. Use an ownership graph and measured critical-section assumptions for the inheritance analysis.

Check your understanding

Why does priority inheritance fail to resolve a deadlock in which A holds mutex X while waiting for Y, and B holds Y while waiting for X?

Try it yourself

Under the same narrow assumptions as the worked example, the owner has 3.5 ms remaining, medium-priority interference would be 12 ms, and bounded total handoff overhead is 0.2 ms. Compute both intervals and identify one assumption that would invalidate the inherited estimate.

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

Keep the owner's required work in both cases. Remove only the stated unrelated medium-priority interference.

Compare with the solution

Without inheritance the example gives 12 + 3.5 + 0.2 = 15.7 ms. With inheritance it gives 3.5 + 0.2 = 3.7 ms. If the owner blocks on an unbounded external operation, the assumed bound no longer accounts for the complete delay.

Bwithout=15.7 ms,Bwith=3.7 msB_{\mathrm{without}}=15.7\,\mathrm{ms},\qquad B_{\mathrm{with}}=3.7\,\mathrm{ms}
The 12 ms difference is the specifically removed medium-priority interference, conditional on the stated timeline.↔ Scroll wide equations horizontally.

Take it with you

  • Priority inversion follows a resource dependency that task priority alone cannot bypass.
  • Inheritance adjusts effective priority and may propagate through a chain of participating mutexes.
  • Bounded critical sections and explicit interference assumptions remain necessary; inheritance does not cure deadlock or arbitrary external waits.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.