Deep understanding replaces simple memory

Priority inversion

For priority inversion, the Resources section “The Thing about Priority Inversion” is quite clear. I’ll just paste it here

  • Thread A is working at A lower priority, let’s say 10. Then at point T1, thread A locks A mutex and starts manipulating the mutex data.
  • At this point, a high-priority line-level thread C (priority 20, for example) is awakened at T2 and also needs to operate on mutex data. When it locks the mutex, because the mutex is locked at T1 by thread A, thread C abandons the CPU and blocks, while thread A can occupy the CPU and continue executing.
  • This is still true. Although priority 10 THREAD A seems to steal priority 20 thread C’s time, because of the program logic, C does need to exit the CPU and complete the mutex operation before it can get the CPU.
  • However, suppose we have A thread B at priority 15 that wakes up at T3 because it has A higher priority than thread A currently executing, so it immediately grabs the CPU. Thread A is forced to wait in the READY state.
  • At T4, thread B abandons the CPU, at which point priority 10 thread A is the only READY thread, which occupies the CPU again and continues executing, finally unlocking the mutex at T5.
  • At T5, the moment thread A unlocks, thread C immediately acquires the mutex and waits for the CPU on priority 20. Because it has A higher priority than thread A, the system immediately dispatches thread C for execution, and thread A is READY again.

The behavior of thread B occupying the CPU from T3 to T4 in the sequence above is a de facto priority inversion. A priority 15 thread B, by suppressing priority 10 thread A, effectively causes high-priority thread C to get the CPU incorrectly. This time is uncontrollable because thread B can occupy the CPU for A long time (even though thread A and THREAD B are both executable when the rotation time slice expires, thread B can still occupy the CPU because of its high priority). As A result, high-priority thread C may not receive CPU for A long time.

Priority inversion vs spin locking

  • The priority inversion problem has nothing to do with spin locks
  • Priority inversion can also occur when spin-locks are not used. Whenever a thread or task has more than one priority, inversion is theoretically possible
  • Operating systems usually have automatic solutions when priority inversion occurs, such as increasing the priority of low-priority threads
  • In iOSOSSpinLockwhen
    • Since this lock does not record information about the thread that holds it, when priority inversion occurs, the system cannot find the low-priority thread and may therefore not be able to solve the priority inversion problem by increasing the priority
    • In addition, high-priority threads occupy CPU time slices when they use spin locks to train and wait for locks, which reduces the probability of low-priority threads getting time slices
  • To sum it up
    • The priority inversion problem has nothing to do with spin locks
    • But when priority inversion does occur, spin locks can make priority inversion difficult to solve, and even cause more serious thread waiting problems

Atomic and os_unfair_lock

  • Os_unfair_lock is recommended to replace OSSpinLock.
  • Os_unfair_lock is actually a mutex (mentioned in Resources)
  • In older versions, atomic internals were also spinlocks, but they have since been changed to mutex

confusion

  1. How to solve the priority inversion problem in iOS? — The Official Apple documentation in Resources

reference

  • Talking about iOS lock
  • That whole priority reversal thing
  • OSSpinLock is no longer secure
  • Dispatch_semaphore causes priority reversal, use with caution!
  • Prioritize Work with Quality of Service Classes