RFC-0142:zx_thread_legacy_yield | |
---|---|
状态 | 已接受 |
区域 |
|
说明 | 引入了专用于 yield 的系统调用。 |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2021-11-29 |
审核日期(年-月-日) | 2021-10-13 |
摘要
我们建议添加一个新的系统调用 zx_thread_legacy_yield
,该调用会导致调用线程将 CPU 让出给另一个等待线程。此外,当截止期限等于零时,我们会移除 zx_nanosleep
的特殊情况。系统调用名称中的 legacy
表示有更合适的机制可用于实现所需行为。
设计初衷
zx_nanosleep
的行为与所有其他系统调用中对截止期限的处理方式不同,即如果截止期限早于当前时间,则立即返回。目前,这是特殊情况,其中截止期限值为零表示让出。
此外,在运行时,无法确定截止期限是故意设为零,还是计算结果。这会简化 zx_nanosleep
的运作方式,减少开发者需要注意的特殊情况。可以手动将截止期限设为零,以使线程让出,也可以在下次唤醒后将其设为零(这意味着立即继续)。
利益相关方
哪些人对此 RFC 的接受与否有利益相关?(此部分为可选部分,但建议填写。)
教员:
由 FEC 任命的负责引导此 RFC 完成 RFC 流程的人员。
Reviewers:
咨询了:
社交:此设计最初是在设计文档中讨论的。
设计
此提案对 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
时,系统会将调用线程置于休眠状态,直到达到截止期限(加上空闲时间)为止。另一方面,如果截止期限的值等于或早于单调时钟中的时间,则会立即返回。但是,如果截止期限为零,则会导致调用线程让出。引入 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(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
通常表示某些操作执行有误。遗憾的是,在硬件缺少适当信号模式的驱动程序中,出现此问题并不罕见。