| RFC-0142:zx_thread_legacy_yield | |
|---|---|
| 状态 | 已接受 |
| 区域 |
|
| 说明 | 引入了用于让出的专用系统调用。 |
| Gerrit 更改 | |
| 作者 | |
| 审核人 | |
| 提交日期(年-月-日) | 2021-11-29 |
| 审核日期(年-月-日) | 2021-10-13 |
摘要
我们建议添加一个新的系统调用 zx_thread_legacy_yield,该调用会导致调用线程将 CPU 让给另一个等待线程。此外,我们还会移除截止时间等于零时的特殊情况 zx_nanosleep。系统调用名称中的 legacy 表示有更合适的机制来实现所需行为。
设计初衷
zx_nanosleep 的行为与所有其他系统调用中处理截止时间的方式不同,即如果截止时间早于当前时间,则立即返回。目前,这是一种特殊情况,其中截止时间值为零表示让步。
此外,在运行时无法确定截止时间是故意设置为零还是计算结果。这将简化 zx_nanosleep 的工作方式,减少开发者需要注意的特殊情况。可以将截止时间手动设置为零,以使线程让出 CPU,也可以将截止时间设置为零作为下一次唤醒的结果(这意味着立即继续)。
利益相关方
哪些人会受到此 RFC 是否被接受的影响?(此部分为可选,但建议填写。)
辅导员:
由 FEC 指派负责引导此 RFC 完成 RFC 流程的人员。
审核者:
已咨询:
社会化:最初在设计文档中讨论了该设计。
设计
此提案包含对 Zircon 系统调用 API 的以下更改:
- 添加了
zx_thread_legacy_yield zx_nanosleep的简化
其中,zx_thread_legacy_yield 的定义如下:
/// Yields cpu to another waiting thread.
/// `options`: Reserved for future extension. Must be zero.
/// @blocking
zx_status_t zx_thread_legacy_yield(uint32_t options);
当在用户空间应用上调用 zx_thread_legacy_yield 时,调用线程会放弃 CPU。options 参数可用于稍后引入提示。
如果调用 zx_thread_legacy_yield 时 options 等于零,则保证返回 ZX_OK。
如果使用大于单调时钟时间的截止时间调用 zx_nanosleep,则调用线程会进入休眠状态,直到达到截止时间(加上宽限时间)为止。另一方面,如果截止时间的价值等于或早于单调时钟中的时间,则会立即返回。但如果截止时间为零,则会导致调用线程让步。引入 zx_thread_legacy_yield 后,目标是移除对零期限的特殊处理。
此外,必须移除 syscalls_zx_nanosleep_zero_duration 内核计数器,同时引入 syscalls_zx_thread_legacy_yield 计数器。
实现
zx_nanosleep(0) 在 Fuchsia 树之外有 2 个调用点(提供 sched_yield 的实现),在树内有 7 个调用点。这需要将工作拆分为四个 CL。
- 引入新的系统调用
zx_thread_legacy_yield。 - 将树内用户迁移到
zx_thread_legacy_yield。 - 迁移树外用户。
- 从
zx_nanosleep中移除了 yield 重载。
CL (1) 将包含文档、语言绑定更新,CL (4) 也将更新文档。(1) 和 (2) 可以合并为一个 CL,但将实现与迁移分开似乎是更清晰的路径。
性能
除了略微改进 zx_nanosleep 路径(因为移除了一个分支)之外,对性能没有其他已知影响。
向后兼容性
zx_nanosleep(0)的用户不限于词干库。
安全注意事项
现有代码和新代码的行为完全相同,因为 zx_nanosleep(0)(现在)等同于 zx_thread_legacy_yield(0)。为防止出现任何安全问题,zx_nanosleep 将保持不变,直到 zx_nanosleep(0) 的所有使用情形都已迁移到 zx_thread_legacy_yield(0)。
隐私注意事项
此提案不会影响隐私权。
测试
zx_thread_legacy_yield 的性质使得难以进行可靠的测试,但至少我们可以验证返回代码是否符合预期。
文档
我们将为 zx_thread_legacy_yield 添加更多文档,并更新 zx_nanosleep 的条目,以移除有关零截止日期是特殊情况的说明。
缺点、替代方案和未知因素
最大的缺点和担忧是存在鼓励忙等待模式的 zx_thread_legacy_yield,但 sched_yield 已经提供了这种机制。通过适当的文档和最佳实践,可以缓解这些担忧。由于此系统调用的目标用户是驱动程序,因此应仔细检查任何其他用法。
我们还考虑了另一种替代方案,即将 magic 值更改为另一个值(例如 INT_MIN)。这确实可以解决计算出的截止时间问题,但仍会留下一个特殊情况。此替代方案还需要更新树外的用户,因此需要与添加新系统调用相同的工作量。最大的缺点是,这样做会使 zx_nanosleep 截止期限处理与其他处理截止期限的操作(例如 zx_object_wait)不同。
在先技术和参考资料
zx_nanosleep使用 0 作为特殊值,表示“收益率”。问题在于,有一段代码实际上会进行截止时间计算,并可能计算出 0。在这种情况下,代码的意图并非让步,而是恰恰相反:立即执行下一条语句。代码中出现
yield通常表示存在错误。 遗憾的是,在硬件缺少适当信号模式的驱动程序中,这种情况并不少见。