ThreadManager概述
一、概述
Camera HAL 中存在 两套独立的 ThreadManager 实现,分别服务于不同的框架层:
| 特性 | CamX ThreadManager | CHI ThreadManager |
|---|---|---|
| 适用层 | CamX 核心框架 | CHI Feature2 框架 |
| 最大线程数 | 15 | 16 |
| 最大注册作业 | 512 | 256 |
| 最大运行时作业 | 4096 | - |
| 同步作业 | 不支持 | 支持(Sync Thread) |
| 顺序添加 | 不支持 | 支持(addInOrder) |
| 作业分割 | 支持(isSplitable) | 不支持 |
| 序列化执行 | 支持(isSerialize) | 不支持 |
二、CamX ThreadManager 架构
2.1 组件层次图
┌─────────────────────────────────────────────────────────────────┐
│ ThreadManager │
│ (对外 API 门面) │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ JobRegistry │ │ JobList │ │ ThreadCore │ │
│ │ 作业注册表 │ │ 运行时作业池 │ │ 线程核心引擎 │ │
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
│ │ │
│ ┌─────────┐ │
│ │JobQueue │ │
│ │优先级队列│ │
│ └─────────┘ │
└─────────────────────────────────────────────────────────────────┘
2.2 核心数据结构
JobHandle 编码格式
┌─────────────────────────────────────┬─────────────────────────────┐
│ 高 32 位: uniqueCounter │ 低 32 位: slot │
│ (唯一标识计数器) │ (注册表槽位索引) │
└─────────────────────────────────────┴─────────────────────────────┘
RegisteredJob(已注册作业族)
cpp
struct RegisteredJob {
JobFunc funcAddr; // 作业函数地址
CHAR name[128]; // 作业名称
JobCb flushDoneCb; // Flush 完成回调
JobPriority priority; // 优先级 (Critical/High/Normal)
BOOL isSerial; // 是否序列化执行
UINT32 uniqueCounter; // 唯一计数器
UINT32 slot; // 注册表槽位
UINT32 jobCount; // 挂起作业数
UINT32 inflightCount; // 正在执行数
UINT32 holdCount; // 等待中的作业数
UINT32 submittedCount; // 已提交待执行数
FlushStatus flushStatus; // Flush 状态
RuntimeJob* pFirstJob; // 链表头
RuntimeJob* pLastJob; // 链表尾
UINT32 cameraId; // 相机 ID
};
RuntimeJob(运行时作业)
cpp
struct RuntimeJob {
UINT64 hJob; // 作业族句柄
CHAR name[256]; // 作业名称
JobCb stoppedCb; // 停止回调
VOID* pData[MaxDataPartition]; // 数据分区数组
BOOL isSplitable; // 是否可分割
BOOL isBlocking; // 是否阻塞执行
UINT32 numPartitions; // 数据分区数
JobStatus status; // 作业状态
UINT32 slot; // JobList 槽位索引
Semaphore* pJobSemaphore; // 阻塞信号量
RuntimeJob* pNext; // 下一个串行作业
};
作业状态机
┌───────────────────────────────────────────────┐
│ │
┌─────────┐ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│Submitted│──┼─>│ Ready │──>│On Hold │──>│Stopped │ │
└─────────┘ │ └─────────┘ └─────────┘ └─────────┘ │
入队 │ 可执行 等待前置作业 Flush 停止 │
│ │
└───────────────────────────────────────────────┘
2.3 各组件职责
JobRegistry(作业注册表)
- 职责 :
- 管理所有已注册的作业族
- 提供注册/注销接口
- 维护作业计数统计(jobCount/inflightCount/holdCount/submittedCount)
- 实现 Handle 编解码
cpp
class JobRegistry {
RegisteredJob m_registeredJobs[512]; // 作业族数组
BOOL m_registeredSlots[512]; // 槽位占用标记
UINT32 m_counter; // 唯一计数器
Mutex* m_pRegistryLock; // 注册表锁
Mutex* m_pFlushJobSubmitLock; // Flush 与提交的同步锁
};
JobList(运行时作业池)
- 职责 :
- 提供 RuntimeJob 对象的分配/回收
- 使用空闲链表管理可用槽位
- 避免频繁的内存分配/释放
cpp
class JobList {
RuntimeJob m_jobList[4096]; // 运行时作业数组
JobSlot m_freeList[4096]; // 空闲链表
UINT32 m_freeHead; // 链表头
UINT32 m_freeTail; // 链表尾
UINT32 m_jobOccupancy; // 当前占用数
};
ThreadCore(线程核心)
- 职责 :
- 创建/销毁工作线程
- 管理优先级队列
- 分发作业执行
- 处理 Flush/Sync 操作
- 集成健康监控
cpp
class ThreadCore {
JobQueue m_jobQueues[3]; // Critical/High/Normal 三个优先级队列
ThreadConfig m_workers[15]; // 工作线程配置
Condition* m_pReadOK; // 线程唤醒条件变量
volatile BOOL m_stopped; // 停止标志
volatile BOOL m_jobPending; // 新作业标志
};
JobQueue(优先级队列)
- 职责 :
- 实现作业入队/出队
- 支持条件出队
- 队列加锁保护
2.4 核心流程
创建流程
ThreadManager::Create()
└─ new ThreadManager()
└─ Initialize()
├─ new JobRegistry() -> Initialize()
├─ new JobList() -> Initialize()
└─ new ThreadCore() -> Initialize()
└─ StartThreads()
└─ 创建 numThreads 个工作线程
注册作业族流程
ThreadManager::RegisterJobFamily()
└─ JobRegistry::RegisterNewJob()
├─ 检查是否已注册
├─ 查找空闲槽位
├─ 填充 RegisteredJob 结构
└─ 生成 JobHandle (counter << 32 | slot)
提交作业流程
ThreadManager::PostJob(hJob, stoppedCb, ppData, isSplitable, isBlocking)
└─ ThreadCore::AcceptNewJob()
├─ JobList::AcquireJobEntry() // 分配 RuntimeJob
├─ 处理作业分割(isSplitable)
├─ JobQueue::Enqueue() // 加入优先级队列
└─ Trigger() // 唤醒工作线程
└─ m_pReadOK->Broadcast()
工作线程执行流程
ThreadCore::WorkerThreadBody()
└─ DoWork(threadIndex)
while (!m_stopped) {
// 等待新作业
m_pReadOK->Wait()
// ProcessJobQueue
ProcessJobQueue(threadIndex)
├─ 从高优先级队列开始取作业
├─ JobQueue::CheckAndDequeue()
│ ├─ 检查 Flush 状态
│ ├─ 检查 Serial 依赖
│ └─ 返回符合条件的作业
├─ 健康监控处理
└─ DispatchJob(pJob)
└─ func(pData) // 执行作业函数
}
Flush/Sync 流程
ThreadManager::FlushJobFamily(hJob, pUserData, isBlocking)
└─ ThreadCore::SyncOrFlushJob(hJob, pUserData, isBlocking, FlushRequested)
├─ JobRegistry::StartSyncOrFlush()
│ ├─ 设置 flushStatus = FlushRequested
│ └─ 设置 blockFlush = TRUE
├─ 唤醒所有工作线程处理剩余作业
├─ JobRegistry::WaitForSyncOrFlush()
│ └─ pFlushSemaphore->Wait()
└─ JobRegistry::CheckAllFlushDone()
├─ 检查 inflight count == 0
├─ 调用 flushDoneCb
└─ Signal() 释放等待者
2.5 CamX 特有特性
作业分割(Job Splitting)
cpp
// PostJob 时可以指定 isSplitable = TRUE
// 系统会将 ppData 数组中的每个分区作为独立子作业执行
// 所有子作业完成后视为整个作业完成
m_pCore->AcceptNewJob(hJob, stoppedCb, ppData,
TRUE, // isSplitable
isBlocking, maxExecTime, pJobName);
序列化执行(Serialization)
cpp
// 注册时指定 isSerialize = TRUE
// 同一家族的作业必须串行执行
// JobQueue::CheckAndDequeue 会检查:
// - 如果上一个作业仍在执行,则当前作业进入 OnHold 状态
// - 只有前驱作业完成后,后继作业才能进入 Ready 状态
阻塞调用(Blocking)
cpp
// PostJob 时指定 isBlocking = TRUE
// 调用方会阻塞等待作业完成
// ThreadCore 会为该作业创建 Semaphore
pJob->pJobSemaphore = Semaphore::Create();
// 作业执行完成后 Signal
pJob->pJobSemaphore->Signal();
// 调用方 Wait
pJob->pJobSemaphore->Wait();
三、CHI ThreadManager 架构
3.1 组件结构
CHI ThreadManager 没有 将组件拆分为独立的类,而是将所有逻辑集成在 CHIThreadManager 类中。
cpp
class CHIThreadManager : public IMonitorClient {
ChiRegisteredJob m_registeredJobs[256]; // 已注册作业数组
ChiThreadConfig m_workers[16]; // 工作线程配置数组
std::deque<ChiRuntimeJob*> m_pq; // 全局异步作业队列
std::array<..., 50> m_inflightJobs; // HMS 监控的进行中作业
};
3.2 核心数据结构
ChiRuntimeJob(运行时作业)
cpp
struct ChiRuntimeJob {
UINT64 hJob; // 作业句柄
VOID* pData; // 作业数据
UINT64 sequenceNum; // 序列号
ChiJobStatus status; // Submitted/Stopped/Invalid
BOOL isSync; // 是否同步作业
ChiJobPriority priority; // Default/Critical
UINT32 threadId; // 执行线程 ID(Sync 作业)
UINT64 execStartTime; // 执行开始时间
UINT64 maxExecTime; // 最大执行时间
pid_t pid; // 进程 ID
pid_t tid; // 线程 ID
};
ChiRegisteredJob(已注册作业族)
cpp
struct ChiRegisteredJob {
JobFunc funcAddr; // 作业函数地址
CHAR name[255]; // 作业名称
BOOL isSync; // 是否同步作业
BOOL isUsed; // 槽位是否占用
UINT64 hRegister; // 注册句柄
volatile UINT32 inFlight; // 进行中作业数
volatile UINT32 jobPending; // 队列中是否有作业
JobFlushStatus flushStatus; // Flush 状态
Condition* pSyncJobCondn; // Sync 线程条件变量
Condition* pFlushOK; // Flush 完成条件
Condition* pSyncOK; // Sync 完成条件
Mutex* pQueueLock; // 主队列锁
Mutex* pHelperPQLock; // 辅助队列锁
BOOL addInOrder; // 是否按序添加
UINT64 sequenceCounter; // 序列号计数器
UINT32 cameraId; // 相机 ID
ChiThreadConfig worker; // Sync 线程配置
std::deque<ChiRuntimeJob*> pq; // 主作业队列
std::deque<ChiRuntimeJob*> helperPQ; // 辅助作业队列(乱序时使用)
};
ChiThreadConfig(线程配置)
cpp
struct ChiThreadConfig {
UINT32 threadId; // 逻辑线程号
OSThreadHandle hWorkThread; // 系统线程句柄
JobFunc workThreadFunc; // 线程入口函数
VOID* pContext; // 上下文指针
Mutex* pQueueLock; // 队列锁
ChiThreadStatus status; // 线程状态
BOOL isUsed; // 是否被 Sync 作业占用
Condition* pJobCondn; // 唤醒条件变量
JobHandle hJob; // 关联的作业句柄
std::deque<ChiRuntimeJob*>* pq; // 关联的作业队列
};
3.3 CHI 特有特性
同步作业(Sync Job)
cpp
// 注册时指定 isSync = TRUE
// 系统会为该作业族创建独立的线程
CHIThreadManager::CreateSyncThread(rRegJob)
├─ 创建专用 Condition (pSyncJobCondn)
├─ 配置 ChiThreadConfig
└─ ThreadCreate() 创建独立线程
// 同步作业线程独立于线程池,专门处理该作业族
顺序添加(addInOrder)
cpp
// 注册时指定 addInOrder = TRUE
// 作业必须按 sequenceNum 递增执行
// 乱序到达的作业会暂存到 helperPQ
CHIThreadManager::AddToHelperQueue(pJob)
├─ 如果 sequenceNum <= sequenceCounter + 1
│ └─ 直接加入主队列
└─ 否则
└─ 加入 helperPQ 并排序
CHIThreadManager::PostJob(hJob, pData, sequenceNum)
├─ AddToHelperQueue(pRuntimeJob)
└─ 如果 helperPQ 头部可接受
└─ 移入主队列并触发执行
双队列模型
┌─────────────────────────────────────────────────────┐
│ CHIThreadManager │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ 异步线程池 (m_workers) │ │
│ │ │ │
│ │ m_pAsyncCondn ──> 唤醒所有异步线程 │ │
│ │ │ │
│ │ ┌────────────────────────────────────┐ │ │
│ │ │ 全局异步队列 (m_pq) │ │ │
│ │ │ ┌───┐ ┌───┐ ┌───┐ │ │ │
│ │ │ │Job│ │Job│ │Job│ ... │ │ │
│ │ │ └───┘ └───┘ └───┘ │ │ │
│ │ └────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Sync 线程(每个 Sync 作业族独立) │ │
│ │ │ │
│ │ pSyncJobCondn ──> 唤醒指定 Sync 线程 │ │
│ │ │ │
│ │ ┌────────────────────────────────────┐ │ │
│ │ │ 每个作业族独立队列 (regJob.pq) │ │ │
│ │ │ ┌───┐ ┌───┐ ┌───┐ │ │ │
│ │ │ │Job│ │Job│ │Job│ ... │ │ │
│ │ │ └───┘ └───┘ └───┘ │ │ │
│ │ └────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
3.4 CHI 核心流程
创建与启动
CHIThreadManager::Create(ppInstance, pName, numThreads)
└─ new CHIThreadManager(numThreads)
└─ Initialize(pName)
├─ 创建 Mutex/Condition 同步原语
└─ StartThreads()
└─ 创建 numThreads 个异步工作线程
注册流程
CHIThreadManager::RegisterJobFamily(jobFunc, name, phJob, isSync, addInOrder)
├─ 加锁 m_pRegisteredJobLock
├─ 检查是否已注册
├─ 查找空闲槽位
├─ 初始化 ChiRegisteredJob
│ ├─ 创建 Condition/Mutex
│ ├─ 设置 isSync / addInOrder
│ └─ 生成 hRegister (Handle)
├─ 如果 isSync == TRUE
│ └─ CreateSyncThread() // 创建专属线程
└─ 设置 flushStatus = Noflush
工作线程执行
CHIThreadManager::DoWork(pConfig)
while (status != Stopped) {
while (status != Stopped &&
(isUsed && !jobPending || !isUsed && !m_jobPending)) {
pJobCondn->Wait(); // 等待新作业
}
// ProcessJobQueue
ProcessJobQueue(pConfig)
├─ 遍历 pq 中的作业
├─ 检查 flushStatus
│ ├─ FlushRequested -> 弹出作业并释放
│ └─ Noflush/SyncRequested -> DispatchJob
├─ MonitorAndDispatchJob (如果启用 HMS)
│ ├─ 记录执行时间
│ ├─ 加入 inflight 集合
│ ├─ func(pData)
│ └─ 从 inflight 集合移除
└─ DispatchJob (无 HMS)
└─ func(pData)
}
Sync/Flush 流程
CHIThreadManager::Sync(hJob, timeout)
└─ SynchronizeBody(hJob, SyncRequested, timeout)
├─ 加锁
├─ 如果 addInOrder,处理 helperPQ
├─ 检查是否有进行中的作业
├─ 设置 flushStatus = SyncRequested/FlushRequested
├─ 触发所有相关线程处理剩余作业
│ ├─ AsyncTrigger(TRUE) // 广播所有异步线程
│ └─ SyncTrigger(rRegJob) // 唤醒 Sync 线程
├─ 等待所有作业完成
│ └─ pFlushOK->TimedWait(timeout)
└─ 重置 flushStatus = Noflush
四、两套实现对比
4.1 架构差异
| 维度 | CamX ThreadManager | CHI ThreadManager |
|---|---|---|
| 设计模式 | 组件化(Registry/List/Core/Queue 分离) | 单体式(所有逻辑在一个类中) |
| 队列模型 | 3个优先级队列 + 链表 | 全局队列 + 每作业族独立队列 |
| 线程模型 | 纯线程池(无专属线程) | 线程池 + Sync 专属线程 |
| 作业调度 | 优先级 + 序列号 | FIFO + 可选顺序 |
| 序列化 | 支持(isSerialize) | 不支持 |
| 作业分割 | 支持(isSplitable) | 不支持 |
4.2 适用场景
CamX ThreadManager 适用于:
- 需要作业并行执行的场景(如图像处理)
- 需要优先级调度的场景
- 需要序列化保证的场景
- 需要作业分割的场景
CHI ThreadManager 适用于:
- 需要同步作业族独立线程的场景
- 需要严格顺序执行的场景
- Feature2 层的算法处理
4.3 API 映射
| 功能 | CamX | CHI |
|---|---|---|
| 创建 | Create(ppInstance, name, numThreads) |
Create(ppInstance, name, numThreads=50) |
| 注册 | RegisterJobFamily(func, name, flushCb, priority, isSerialize, phJob, cameraId) |
RegisterJobFamily(func, name, phJob, isSync, addInOrder, cameraId) |
| 提交 | PostJob(hJob, stopCb, ppData, isSplitable, isBlocking, maxTime, name) |
PostJob(hJob, pData, seqNum, maxTime, priority) |
| 注销 | UnregisterJobFamily(hJob) |
UnregisterJobFamily(hJob) |
| Flush | FlushJobFamily(hJob, userData, blocking) |
FlushJob(hJob) (内部调用) |
| Sync | SyncJobFamily(hJob) |
Sync(hJob, timeout) |
| 恢复 | ResumeJobFamily(hJob) |
ResumeJobFamily(hJob) (需实现) |
五、关键设计总结
5.1 线程安全
- 所有共享数据访问都有 Mutex 保护
- 状态标志使用原子操作
- Condition 变量用于线程间通知
5.2 健康监控集成
- 两套实现都继承
IMonitorClient - 支持作业超时检测
- 支持暂停/恢复监控
- 通过
OnScanAllJobs上报失败作业
5.3 性能优化
- 对象池模式(JobList 预分配 RuntimeJob)
- 条件变量通知(避免忙等待)
- 优先级队列(重要作业优先执行)
- 批量唤醒(Broadcast vs Signal)
5.4 容错设计
- Flush/Sync 超时机制
- 作业停止回调
- 状态机保护(非法状态转换检查)
- 资源泄漏保护(析构函数中清理所有资源)