Skip to content

[components][ipc][workqueue] 完善 workqueue 同步语义、生命周期收敛与 delayed 队列处理#11285

Open
Ryan-CW-Code wants to merge 1 commit intoRT-Thread:masterfrom
Ryan-CW-Code:workqueue
Open

[components][ipc][workqueue] 完善 workqueue 同步语义、生命周期收敛与 delayed 队列处理#11285
Ryan-CW-Code wants to merge 1 commit intoRT-Thread:masterfrom
Ryan-CW-Code:workqueue

Conversation

@Ryan-CW-Code
Copy link
Contributor

拉取/合并请求描述:(PR description)

workqueue 我在非RTT平台使用的比较多,这次结合之前的经验配合 Codex 尝试进行优化
本PR核心内容由 Codex 完成,我仅引导和审查。

Workqueue PR 说明

  • 更新时间:2026-03-21
  • 适用范围:components/drivers/ipc/workqueue.ccomponents/drivers/include/ipc/workqueue.hcomponents/drivers/ipc/utest
  • 变更目标:补齐 workqueue 同步语义与并发边界,收敛 delayed/cancel/destroy 热路径,并保证 API 语义稳定

1. 背景

现有 workqueue 在 running work 生命周期、同步取消、同步销毁、跨队列操作和 delayed 队列处理上存在语义空洞与边界不清的问题。典型问题包括:

  1. work 进入 running 后过早解绑,跨队列提交/取消无法稳定识别。
  2. cancel_work_sync()destroy_sync() 缺少完整的等待语义与上下文约束。
  3. delayed 队列和批量清理路径存在较多锁内逐节点处理,关键路径偏长。
  4. system workqueue 与普通 workqueue 的接口能力不对齐,缺少同步取消和状态查询能力。

2. 问题描述

本次变更重点解决以下问题:

  1. 明确 running work 的绑定关系,避免跨队列误操作。
  2. 明确 cancel_work_sync()destroy_sync() 的合法调用上下文、阻塞条件与返回值。
  3. 收敛 delayed/cancel/destroy 路径中的锁内操作,减少 irq-off 时间。
  4. 补齐状态查询与 system workqueue 对应封装,便于统一使用和测试。

3. 方案概述

3.1 生命周期与队列绑定

  1. work 被 worker 取出执行后不再立即解绑。
  2. work 在 running 期间保持 work->workqueue 绑定。
  3. submiturgentcancelcancel_sync 遇到“work 已绑定其他 queue”统一返回 -RT_EBUSY

3.2 同步取消

  1. 引入 RT_WORK_STATE_CANCELING
  2. cancel_work_sync() 命中 running work 时,先标记 canceling,再等待当前执行结束。
  3. work 回调内若尝试重新提交当前 work,同步取消路径会阻止该 requeue 生效。
  4. cancel_work_sync() 仅在“真的需要等待 running work”时才要求 scheduler 可用。

3.3 同步销毁

  1. 新增 rt_workqueue_destroy_sync()
  2. destroy 路径统一先摘掉 queued/delayed work,再根据同步/异步语义决定立即返回或等待 worker 退出。
  3. 不使用 thread->cleanup 或外部强删 worker,而由 worker 在线程入口自然收敛退出。

3.4 delayed 队列与热路径

  1. delayed 队列使用 wrap-safe tick 比较。
  2. delayed 插入增加 head/tail 快路径。
  3. 到期提升仅处理连续到期前缀,并通过一次 splice 挂到 work_list
  4. cancel_alldestroydestroy_sync 采用“锁内摘链、锁外逐项清理”。
  5. wakeup_completion 保持在锁外执行,避免拉长锁内路径。

3.5 状态与系统接口

  1. 新增 rt_workqueue_get_work_status()
  2. 补齐 rt_work_cancel_sync()rt_work_get_status()
  3. urgent 与立即 submit 共用提交核心,仅保留插队位置差异。

4. 行为变化与兼容性

4.1 行为变化

  1. running work 期间 work->workqueue 保持非空。
  2. cancel_work_sync()destroy_sync() 仅允许线程上下文调用,且禁止在对应 worker 线程内调用。
  3. destroy() 保持异步语义,destroy_sync() 保持同步等待 worker 退出语义。
  4. cancel_all() 仅清理 queued/delayed work,不等待 running work 完成。
  5. 相同 timeout 的 delayed work 明确保留 FIFO 顺序。

4.2 兼容性说明

  1. 依赖“running 期间 work->workqueue == RT_NULL”旧行为的代码需要调整。
  2. 依赖“跨队列提交/取消未显式报错”旧行为的代码需要处理 -RT_EBUSY
  3. 未新增 struct rt_workstruct rt_workqueue 字段,不引入结构体 ABI 膨胀。

5. 资源与实现取舍

  1. 未引入 ref_count
  2. 未新增结构体字段,RAM 不增加。
  3. 生命周期并发仍由调用方保证;queue 进入 destroying 后的内部收尾由 worker 和 destroy_sync() 完成。
  4. 同步 API 的上下文限制使用显式返回实现,而不是额外叠加运行时 debug 断言语义。

6. 风险与注意事项

  1. rt_workqueue_destroy() 返回后,调用方仍不能继续使用原 queue 指针。
  2. rt_workqueue_cancel_all_work() 不是同步屏障,不保证当前 running work 已经结束。
  3. 业务侧若忽略 -RT_EBUSY,可能误判同步取消、销毁或跨队列操作已成功。
  4. queue 生命周期并发仍由调用方负责;destroy() 返回后继续并发访问旧 queue 仍属于越界使用。

7. 测试覆盖

7.1 用例统计

  1. workqueue_tc_basic.c:13 个用例
  2. workqueue_tc_cancel.c:18 个用例
  3. workqueue_tc_destroy.c:8 个用例
  4. 合计:39 个 workqueue 相关用例

7.2 覆盖场景汇总

类别 覆盖场景
基础提交 立即提交、非法 tick、普通 FIFO 顺序
delayed 行为 delayed 顺序、相同 timeout FIFO、delayed head 刷新
urgent 行为 urgent 插队、urgent 与 delayed 交互
重复提交 pending/running/delayed 的重复提交、延迟重提、requeue 限制
状态查询 idle、pending、submitting、running、canceling、done、canceled、other queue
system API rt_work_submit()rt_work_urgent()rt_work_cancel()rt_work_cancel_sync()rt_work_get_status()
cancel 基础 cancel pending、cancel delayed、cancel after done、cancel not queued
cancel_sync cancel pending、cancel running、复用 completion、running requeue、early requeue
cancel 并发保护 double waiter busy、callback 中调用 busy、scheduler unavailable 条件分支
cancel_all 保留 running、清理 queued/delayed、保留 canceling 语义
跨队列保护 running work 跨队列操作拒绝
压力路径 submit/cancel 压力回归
destroy 基础 destroy、destroy_sync、sync waiter busy、destroying busy
destroy 并发保护 worker 线程内调用 busy、scheduler unavailable busy
destroying 状态 destroying 后拒绝 submit/urgent
destroy 状态 running 期间 destroy_sync 不错误标记 canceled
生命周期压力 4 个并发 workqueue 控制线程各执行 100 轮 create/submit running+delayed/destroy_sync 压力回归

7.3 当前未覆盖项

  1. ISR 上下文直接调用同步 API 的黑盒验证。

8. 验证方式

  1. menuconfig 中启用对应 utest
  2. 编译并启动目标 BSP。
  3. 在 msh 中执行:
msh /> utest_run components.drivers.ipc.workqueue_tc

当前拉取/合并请求的状态 Intent for your PR

必须选择一项 Choose one (Mandatory):

  • 本拉取/合并请求是一个草稿版本 This PR is for a code-review and is intended to get feedback
  • 本拉取/合并请求是一个成熟版本 This PR is mature, and ready to be integrated into the repo

代码质量 Code Quality:

我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:

  • 已经仔细查看过代码改动的对比 Already check the difference between PR and old code
  • 代码风格正确,包括缩进空格,命名及其他风格 Style guide is adhered to, including spacing, naming and other styles
  • 没有垃圾代码,代码尽量精简,不包含#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up
  • 所有变更均有原因及合理的,并且不会影响到其他软件组件代码或BSP All modifications are justified and not affect other components or BSP
  • 对难懂代码均提供对应的注释 I've commented appropriately where code is tricky
  • 代码是高质量的 Code in this PR is of high quality
  • 已经使用formatting 等源码格式化工具确保格式符合RT-Thread代码规范 This PR complies with RT-Thread code specification
  • 如果是新增bsp, 已经添加ci检查到.github/ALL_BSP_COMPILE.json 详细请参考链接BSP自查

@github-actions
Copy link

👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread!

为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。
To ensure your code complies with RT-Thread's coding style, please run the code formatting workflow by following the steps below (If the formatting of CI fails to run).


🛠 操作步骤 | Steps

  1. 前往 Actions 页面 | Go to the Actions page
    点击进入工作流 → | Click to open workflow →

  2. 点击 Run workflow | Click Run workflow

  • 设置需排除的文件/目录(目录请以"/"结尾)
    Set files/directories to exclude (directories should end with "/")
  • 将目标分支设置为 \ Set the target branch to:workqueue
  • 设置PR number为 \ Set the PR number to:11285
  1. 等待工作流完成 | Wait for the workflow to complete
    格式化后的代码将自动推送至你的分支。
    The formatted code will be automatically pushed to your branch.

完成后,提交将自动更新至 workqueue 分支,关联的 Pull Request 也会同步更新。
Once completed, commits will be pushed to the workqueue branch automatically, and the related Pull Request will be updated.

如有问题欢迎联系我们,再次感谢您的贡献!💐
If you have any questions, feel free to reach out. Thanks again for your contribution!

@github-actions
Copy link

📌 Code Review Assignment

🏷️ Tag: components

Reviewers: @Maihuanyi

Changed Files (Click to expand)
  • components/drivers/include/ipc/workqueue.h
  • components/drivers/ipc/utest/SConscript
  • components/drivers/ipc/utest/workqueue_tc.c
  • components/drivers/ipc/utest/workqueue_tc_basic.c
  • components/drivers/ipc/utest/workqueue_tc_cancel.c
  • components/drivers/ipc/utest/workqueue_tc_destroy.c
  • components/drivers/ipc/workqueue.c

📊 Current Review Status (Last Updated: 2026-03-21 18:20 CST)


📝 Review Instructions

  1. 维护者可以通过单击此处来刷新审查状态: 🔄 刷新状态
    Maintainers can refresh the review status by clicking here: 🔄 Refresh Status

  2. 确认审核通过后评论 LGTM/lgtm
    Comment LGTM/lgtm after confirming approval

  3. PR合并前需至少一位维护者确认
    PR must be confirmed by at least one maintainer before merging

ℹ️ 刷新CI状态操作需要具备仓库写入权限。
ℹ️ Refresh CI status operation requires repository Write permission.

@Ryan-CW-Code
Copy link
Contributor Author

#11144

@Ryan-CW-Code
Copy link
Contributor Author

#8477

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant