Priority inheritance

Priority inversion is a situation where a high-priority transaction is delayed by a low-priority task because the low-priority task holds a resource needed by the high-priority task. To mitigate priority inversion, Android supports running threads at different priorities through three different forms of priority inheritance: transaction priority inheritance, node priority inheritance, and real-time priority inheritance.

This page explains these different forms of priority inheritance.

Transaction priority inheritance

When making a synchronous binder call, a high-priority thread can be blocked by a low-priority thread until the low-priority thread has sent a reply. For example, a thread with a nice value of -19 can become blocked by a thread with a default nice value of 0.

Transaction priority inheritance fixes this issue because the binder driver temporarily changes the priority of the binder thread handling the transaction to match the priority of the caller. When the transaction is done, the binder driver restores the priority of the binder thread to its previous value.

Node priority inheritance

In some situations, such as those that require low latency, the priority of asynchronous transactions matters.

Node priority inheritance lets you configure the minimum priority that all transactions on a node should run at. After node priority inheritance is configured, all transactions on the node run at this minimum priority.

The rules for node priority inheritance are:

  • If the transaction is synchronous, the priority becomes max(min_node_priority, caller_priority);.

  • If the transaction is asynchronous, the priority becomes max(default_priority (nice 0), min_node_priority);.

Configure node priority inheritance

To configure node priority inheritance, use BBinder::setMinSchedulerPolicy.

Real-time priority inheritance

Android uses real-time scheduling policies, such as SCHED_FIFO, to cause latency-critical threads to complete their work in time. Additionally, some of Android's latency-critical work is split over two or more processes.

Real-time priority inheritance works identically to nice values, except:

  • Real-time priority inheritance is disabled by default.
  • Greater real-time priority values have higher priority than smaller values.

Enable real-time priority inheritance

Real-time priority inheritance must be enabled for individual nodes using the BBinder::setInheritRt(true) call.