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
的工作原理,从而减少开发者需要注意的特殊情况。截止时间可以手动设置为零,以便线程让步;也可以因下一次唤醒(即立即继续)而将截止时间设置为零。
利益相关方
谁与此 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
参数可用于稍后引入提示。
在 options
等于零的情况下调用 zx_thread_legacy_yield
一定会返回 ZX_OK
。
当使用截止时间大于单调时钟的时间调用 zx_nanosleep
时,调用线程会进入休眠状态,直到截止时间(加上 Slack)为止。另一方面,当截止期限的值等于或早于单调时钟的时间时,它会立即返回。但是,如果截止时间为零,则会导致发起调用的线程让步。引入 zx_thread_legacy_yield
后,目标是移除对零期限的特殊处理。
此外,必须移除 syscalls_zx_nanosleep_zero_duration
内核计数器,同时引入 syscalls_zx_thread_legacy_yield
计数器。
实现
zx_nanosleep(0)
在紫红色树外有 2 个调用点(提供 sched_yield
的实现),在树内有 7 个调用点。这涉及将工作拆分到四个 CL 中。
- 引入了新的系统调用
zx_thread_legacy_yield
。 - 将树内用户迁移到
zx_thread_legacy_yield
。 - 从树状用户中迁出。
- 从
zx_nanosleep
中移除了收益过载。
CL (1) 将包括文档、语言绑定更新,CL (4) 也将更新文档。(1) 和 (2) 可以合并到单个 CL 中,但将实现与迁移分开似乎是一个更简洁的路径。
性能
由于移除了分支,因此除了 zx_nanosleep
路径略有提升之外,对性能的影响尚无已知的影响。
向后兼容性
zx_nanosleep(0)
的用户不限于 Stem 代码库。
安全注意事项
现有代码和新代码的行为将完全相同,因为 zx_nanosleep(0)
(现在)等同于 zx_thread_legacy_yield(0)
。为了防止出现任何安全问题,在 zx_nanosleep(0)
的所有用例都迁移到 zx_thread_legacy_yield(0)
之前,zx_nanosleep
将保持不变。
隐私注意事项
此方案对隐私权没有任何影响。
测试
zx_thread_legacy_yield
的性质导致难以进行可靠的测试,但至少我们可以验证返回代码是否符合预期。
文档
我们将针对 zx_thread_legacy_yield
添加其他文档,并更新 zx_nanosleep
的条目,以消除提及零期限这种特殊情况的情况。
缺点、替代方案和未知情况
最大的缺点和顾虑是存在 zx_thread_legacy_yield
鼓励繁忙等待模式,但 sched_yield
已经提供了这种机制。您可以通过适当的文档和最佳做法缓解这些问题。由于此系统调用的目标用户是驱动程序,因此任何其他用法都应谨慎。
所考虑的另一种替代方案是将魔法值更改为另一个值(例如 INT_MIN
)。这样确实解决了计算出的截止时间问题,但仍然留下了一个特殊情况。此替代方案也需要在树状用户之外进行更新,因此需要执行与添加新系统调用相同的工作。最大的缺点是,如果这样做,会使 zx_nanosleep
截止时间处理与其他处理截止时间的操作(如 zx_object_wait
)区分开来。
早期技术和参考资料
zx_nanosleep
使用 0 作为特殊值来表示“退让”。问题在于,有些代码可有效执行期限计算,而计算结果为 0。在这种情况下,意图不会产生结果,与其相反:立即执行下一个语句。包含
yield
的代码通常表示出现了问题。遗憾的是,在硬件缺少适当信号模式的驱动程序中也经常出现此类问题。