分享一个简单的有意思案例
实际项目上,不止一次遇到Sf 中的线程从RT 掉到CFS 120
比如这段:Launcher 主线程binder call 到Sf,但是由于Sf binder 线程被抢占,导致整个binder 耗时较长,从而导致Launcher 侧掉了几帧
往前追溯,看下这个Sf binder 线程何时被降级以及降级原因
正是由于这次的HWC async binder call到Sf 侧,导致Sf binder 线程被降级到了120
对应Ftrace 日志
binder:1060_3-1496 ( 1060) [002] .... 58582.132796: binder_set_priority: proc=1060 thread=1496 old_prio=97 new_prio=120 desired_prio=120
对应降级的code
到这里,看起来似乎是Aosp 的自身逻辑导致
inherit_rt
@inherit_rt: inherit RT scheduling policy from caller
翻下了历史提交
[PATCH 06/13] ANDROID: binder: add RT inheritance flag to node. - Martijn Coenen
inherit_rt 这个属性通常是由上层调用setInheritRt 传递下来的
js
void BBinder::setInheritRt(bool inheritRt) {
LOG_ALWAYS_FATAL_IF(mParceled,
"setInheritRt() should not be called after a binder object "
"is parceled/sent to another process");
Extras* e = mExtras.load(std::memory_order_acquire);
if (!e) {
if (!inheritRt) {
return;
}
e = getOrCreateExtras();
if (!e) return; // out of memory
}
e->mInheritRt = inheritRt;
}
默认情况下,AIDL 不会继承实时优先级。必须根据 binder 使用
setInheritRt
函数才能启用实时优先级继承
ref: 适用于 HAL 的 AIDL | Android Open Source Project
目前全局搜使用的地方,只有audio 等少数对实时性要求高的场景下会将该属性置为true
再回过头来看这个问题,整理下:
最初是Launcher binder 同步call 到Sf binder 线程,但是Sf binder 线程被抢占导致Launcher 掉帧 而Sf binder 线程被抢占的原因,在于前面HWC 一次async binder call
之后,Sf binder 掉到binder 默认优先级120.
那么如何先临时改掉这个问题呢?
临时改法其实有多种,上层或kernel 中都可以规避这个问题,比如可以通过trace_android_vh_binder_priority_skip
接口做一些预判处理,针对这种场景提前skip 掉。
Google 对于AIDL binder 默认不支持RT 继承的本意也是出于对过多RT 会影响性能的考虑,这样修改是否有side effect?这个还有待斟酌.