背景:
今天一个学员在群里有个提问如下图,怎么有两个joinThread,会执行么?joinThread不是死循环等待数据吗?
/frameworks/av/media/mediaserver/main_mediaserver.cpp
当开始看到这个时候确实也觉得最后的hw的join根本不会执行哈
为了验证我加入了如下日志:
看看主线程执行到哪了:
看看joinThreadPool是否会退出:
结果执行如下:
明显log看到没有任何执行::android::hardware::joinRpcThreadpool()
为啥会有这个的joinRpcThreadpool
这里就得查一下相关的提交日志了
相关提交如下:
commit a4c39654219a7ed7ee6bb3ef5acbb1afd32a4a48
Author: Pawin Vongmasa <pawin@google.com>
Date: Tue Jun 30 09:30:58 2020 -0700
mediaserver: add more hwbinder threads
Since we're now using HIDL IGraphicBufferSource in CCodec, the
existence of a callstack with mixed binder and hwbinder calls can cause
a stall when all threads are in use. (b/35283480) The recommended
workaround was to increase the number of threads. This CL does that.
Test: atest CtsMediaTestCases
Test: atest CtsCameraTestCases
Bug: 153828976
Change-Id: I37f02b6237ad032e311a8219b209713d2e4463a6
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
+#include <hidl/HidlTransportSupport.h>
#include <utils/Log.h>
#include "RegisterExtensions.h"
@@ -42,6 +43,8 @@ int main(int argc __unused, char **argv __unused)
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
registerExtensions();
+ ::android::hardware::configureRpcThreadpool(16, false);
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
+ ::android::hardware::joinRpcThreadpool();
}
可以明显看出这个joinRpcThreadpool只是为了和前面的configureRpcThreadpool成对出现加入的,并没说添加这个joinRpcThreadpool是为了单独修复什么。明显这个地方的::android::hardware::joinRpcThreadpool()方法并没有见到他的执行,故这个地方的::android::hardware::joinRpcThreadpool()显得很多余
扩展hwbinder相关的joinRpcThreadpool如何进入
上面代码是显式调用进入hwbinder的循环接受消息,上面joinRpcThreadpool代码居然没有执行,那么疑问来了?请问又是在哪里进入的循环接受消息呢?
比如拿SurfaceFlinger来举例,SurfaceFlinger代码中也从来没见到有调用joinRpcThreadpool,但是他依然可以hidl通讯,抓取trace还发现有对于的hwbinder线程,比如硬件vsync的校准
这到底是为啥?都没有见到有Hwbinder的IPCThreadState.joinRpcThreadpool和ProcessState.startThreadPool的调用,哪来的hw线binder程。。。。死活找不到对于的代码调用端啊。
(IPCThreadState.joinRpcThreadpool和ProcessState.startThreadPool为啥启动线程,这个可以看马哥的跨进程专题课程)
哈哈,这里马哥本来想去Hwbinder的IPCThreadState或ProcessState中加个CallStack不就好了么。。。可以使理想很美好,实际发现libutilscallstack库加入不进去,会导致一堆bp编译错误。。。哎,懒着折腾这个编译相关错误,这个方便堆栈路封死了。。。那么就只能采用其他线索摸索啦,终于经过漫长摸索发现在hidl的自动生成代码中有相关的线索:
这里可以经过日志和额外加trace可以确定就是这个地方启动了hwbinder线程池:
上面是不是展示了在跨进程调用HIDL::IComposerClient::registerCallback::client方法时候进行的hwbinder线程池启动
总结
所以很多时候并不需要在自己的业务代码中显式调用的相关的joinRpcThreadpool和startThreadPool相关方法,因为在hidl相关生成的代码中会调用相关读取hwbinder线程池启动。所以大家在看代码时候发现自己业务代码中没有hwbinder相关的线程池启动,但实际有相关hwbinder线程则可以考虑去相关的hidl生成代码中查找
更多framework干货课程如下(需要的可以私聊马哥 获取优惠 +V :androidframework007):