QEMU/AioContext 线程池

把线程池待处理工作按 FIFO 交给 worker

QEMU 线程池用尾队列组织待处理请求:提交时尾插,worker 持锁从头部领取,然后在锁外执行工作。

v9.2.0调度与资源分配核验 2026-10-08
相关概念

工程问题#

AioContext 需要把会阻塞的工作交给后台线程,同时让多个 worker 安全领取不同请求,并把完成通知送回事件循环。

实际实现#

thread_pool_submit_aio 对 request_list 执行 QTAILQ_INSERT_TAIL;worker_thread 取 QTAILQ_FIRST 并移除,更新状态后解锁执行。完成状态通过内存屏障与 bottom half 通知衔接。

处理流程#

  1. 创建请求并标记为 THREAD_QUEUED
  2. 持锁把请求放到队尾并唤醒 worker
  3. worker 持锁领取队头并在锁外执行
  4. 记录结果并安排完成通知

源码片段#

固定版本 · 原文摘录
util/thread-pool.cv9.2.0 · L106–L119
查看原文件
106        req = QTAILQ_FIRST(&pool->request_list);107        QTAILQ_REMOVE(&pool->request_list, req, reqs);108        req->state = THREAD_ACTIVE;109        qemu_mutex_unlock(&pool->lock);110111        ret = req->func(req->arg);112113        req->ret = ret;114        /* Write ret before state.  */115        smp_wmb();116        req->state = THREAD_DONE;117118        qemu_bh_schedule(pool->completion_bh);119        qemu_mutex_lock(&pool->lock);
worker_thread

worker 在已持有 pool->lock 的上下文中领取并摘除队头,随后释放锁执行函数。尾插证据在同文件第 265 行;此片段同时说明线程并行执行与 FIFO 领取并不等同于 FIFO 完成。

连续摘录 worker 循环的领取与执行分支;完整文件保留其加锁、等待和提交端尾插的上下文。

收益与取舍#

工程分析

带来的收益

  • 队尾插入与队头摘除不需要扫描待处理集合
  • 锁外执行工作避免整个任务期间占用队列锁

付出的代价

  • 工程分析:共享队列锁在高并发时可能形成竞争
  • FIFO 领取不代表开始执行或完成回调严格同序

可比较的选择

有界环形队列可紧凑存放任务,但需要明确容量耗尽策略,任意取消已排队请求也更难处理。

版本与适用范围#

对应 QEMU v9.2.0 通用线程池的 request_list,不是所有 QEMU I/O 的统一队列。取消可移除尚未领取的请求;多 worker 会并行运行,因此只按队列出队顺序解释 FIFO。

参考来源#

源码、官方文档与原始论文
01
qemu · thread_pool_submit_aio

util/thread-pool.c · thread_pool_submit_aio

源码v9.2.0
02
qemu · worker_thread

util/thread-pool.c · worker_thread

源码v9.2.0

相关实现与比较#

1 个相关案例
11 个匹配案例