RFC-0142:zx_thread_legacy_yield

RFC-0142:zx_thread_legacy_yield
状态已接受
领域
  • 内核
说明

为收益引入专用系统调用。

Gerrit 更改
  • 590273
作者
审核人
提交日期(年-月-日)2021-11-29
审核日期(年-月-日)2021-10-13

总结

我们建议添加新的系统调用 zx_thread_legacy_yield,使发起调用的线程将 CPU 让给另一个等待线程。此外,当截止期限等于零时,我们会移除 zx_nanosleep 的特殊情况。系统调用名称中的 legacy 表示存在更合适的机制来实现预期行为。

设计初衷

zx_nanosleep 的行为不同于所有其他系统调用中截止时间的处理方式,也就是说,如果截止时间早于当前时间,它会立即返回。目前,这是一种特殊情况,其中截止期限值为零表示收益。

此外,在运行时无法确定截止时间是有意设置为零还是由计算结果得出。这样可以简化 zx_nanosleep 的工作原理,从而减少开发者需要注意的特殊情况。截止时间可以手动设置为零,以便线程让步;也可以因下一次唤醒(即立即继续)而将截止时间设置为零。

利益相关方

谁与此 RFC 被接受是否相关?(本部分为可选内容,但建议阅读。)

教员

FEC 指定的人员,通过 RFC 流程照管此 RFC。

审核者

咨询人员

社交:设计最初是在设计文档中讨论的。

设计

此方案包含对 Zircon 系统调用 API 的以下更改:

  1. 添加 zx_thread_legacy_yield
  2. 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 中。

  1. 引入了新的系统调用 zx_thread_legacy_yield
  2. 将树内用户迁移到 zx_thread_legacy_yield
  3. 从树状用户中迁出。
  4. 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 的代码通常表示出现了问题。遗憾的是,在硬件缺少适当信号模式的驱动程序中也经常出现此类问题。