The full picture
- The inversion triangle: H waits on L's lock; M preempts L; therefore M > H in practice. It needs three parties — with only H and L, L would run and release.
- Fixes: priority inheritance (holder boosted to max waiter priority — pthreads
PTHREAD_PRIO_INHERIT, RT-mutexes in Linux), priority ceiling (lock has a fixed high ceiling), or design-level: don't share locks across priority classes at all. - Pathfinder details worth citing: VxWorks RTOS, the mutex had a priority-inheritance flag defaulted off, JPL debugged from Earth via a replica and toggled it live — the canonical 'observability + remote config saves the mission' story.
- Where you meet it off Mars: GC threads vs application threads, a low-priority batch job holding a DB row lock a latency-critical request needs (DBs don't do priority inheritance — your 'priority' design must avoid cross-tier lock sharing), and cgroup-throttled containers holding futexes.