RFC-0142:zx_thread_legacy_yield

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 的以下更改:

  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 参数可用于稍后引入提示。

如果调用 zx_thread_legacy_yieldoptions 等于零,则保证返回 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。

  1. 引入新的系统调用 zx_thread_legacy_yield
  2. 将树内用户迁移到 zx_thread_legacy_yield
  3. 迁移树外用户。
  4. 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 通常表示存在错误。 遗憾的是,在硬件缺少适当信号模式的驱动程序中,这种情况并不少见。