RFC-0237:使用 ZX_CLOCK_UPDATED 发送时钟更新信号

RFC-0237:使用 ZX_CLOCK_UPDATED 发送时钟更新信号
状态已接受
领域
  • 内核
说明

添加一种在 Zircon 时钟更新时发送的新信号类型

Gerrit 更改
  • 922132
作者
审核人
提交日期(年-月-日)2023-09-26
审核日期(年-月-日)2024-01-03

摘要

此 RFC 建议为 Zircon 时钟引入一个新的时钟信号 ZX_CLOCK_UPDATED,它会在每次时钟更新时频闪。

设计初衷

时钟时钟单调参考时间轴的一维仿射转换,用于定义如何将“参考”时间(即设备的单调时钟)转换为时钟输出的“合成”时间。因此,UTC 时钟是一个不断调整的转换,当应用于设备单调时钟的当前值时,会生成当前 UTC 时间。

Zircon 中世界协调时间 (UTC) 时钟的仿射转换仅由 Timekeeper 使用系统调用 zx_clock_update 进行更新,并且可由任何时钟用户使用系统调用 zx_clock_get_details 读取。

为了让 Starnix 上运行的 Linux 程序使用 vDSO 函数 clock_gettimegettimeofday 计算世界协调时间 (UTC),Starnix vDSO 必须有权访问从单调时间到世界协调时间 (UTC) 的最新时钟转换。目前,Starnix 内核能够通过以下方式提供此访问权限:使用 zx_clock_get_details 定期轮询 Zircon UTC 时钟以进行时钟转换,然后将此转换加载到由 Starnix 内核和 Starnix 上运行的 Linux 程序的用户空间共享的内存页面中。

频闪是对信号的快速断言和断言。这意味着,等待时钟信号变化的观察者可以检测到频闪,但任何观察者都不会读取要断言的时钟信号的值。通过引入 ZX_CLOCK_UPDATED(一个在时钟更新时频闪的时钟信号),Starnix 内核可以收到世界协调时间 (UTC) 时钟的更新通知,并在收到这些通知后立即从 Zircon 获取最新的转换,然后更新 Linux 程序使用的时钟转换。这会缩短 Zircon 中的时钟转换变化与 Linux 程序计算世界协调时间 (UTC) 时使用这一新转换之间的潜在延迟时间。

利益相关方

谁能决定此 RFC 是否被接受?(此部分为可选内容,但我们建议您。)

教员

  • cpu@google.com

审核者

  • abarth@google.com
  • maniscalco@google.com
  • johngro@google.com

咨询人员

  • mariagl@google.com
  • fdurso@google.com
  • qsr@google.com

社交

与上面列出的所有评估人员和顾问进行讨论。本文档开头前先附上了设计文档,并收到了所有利益相关方的非正式反馈。

本文档中的信息已包含在此 RFC 中(若相关)。

设计

Zircon 时钟包含一个信号:ZX_CLOCK_STARTED,该信号在时钟开始时被断言。该设计添加了一个新的时钟信号 ZX_CLOCK_UPDATED,该信号在每次时钟更新时都会进行频闪。

为了能够频闪地扫描信号,该设计还涉及对 Dispatcher::UpdateState(当前用于更新 Zircon 信号)的修改。目前,该函数接受两种输入:set_maskclear_mask,用于指定要设置(断言)和清除(取消断言)的信号。除了更新 set_maskclear_mask 指定的信号之外,该函数还会使用函数 NotifyObservers 通知所有从非活跃状态转换为活跃的信号。

修改是向 UpdateState 添加第三个名为 strobe_mask 的输入(默认为 0)。这会指定频闪的所有信号。指定为频闪的信号不会改变值,但 NotifyObservers 调用会修改为也通知所有观察者由 strobe_mask 指定的任何信号,以便观察者知道信号有更新。

为了使用此信号获知时钟转换的更新,以免用户错过更新,用户不应使用 zx_object_wait_onezx_object_wait_many 等待信号频闪。如果用户读取当前时钟详细信息,然后调用 zx_object_wait_one 以等待时钟更新,则 Zircon 可能在读取当前时钟详细信息和调用等待期间更新了时钟,因此不会注册此更新。

应改用 zx_object_wait_async。在读取当前转换之前,用户应针对时钟发布异步等待。然后,在读取时钟详细信息后,用户可以等待发布了异步等待请求的端口。这可以防止错过对时钟详情的更新。

此机制的影响是,如果在创建异步等待和读取时钟详情期间时钟更新,则会导致在等待端口时立即唤醒,尽管读取的时钟转换是最新的。未来的工作可以改进此信号,以消除这些虚假唤醒的可能性。

实现

此设计可在一个小型 CL 中实现。CL 定义了新信号,并修改了 UpdateState 以包含新的 strobe_mask 输入。

性能

Starnix 内核将利用以下新信号来减少在 Starnix 上运行的 Linux 程序的世界协调时间 (UTC) 时钟的潜在误差。

目前,Starnix 是唯一提议使用此信号的用户,不过,将来可能有其他用户使用此信号(例如,C++ 运行时的实现,以支持 C++ 标准库在 UTC 截止时间之前阻塞线程的能力)。使用 UpdateState 频闪信号的时间复杂度与信号的观察者数量成线性关系。这意味着,当 ZX_CLOCK_UPDATED 的观察者数量庞大时,会出现性能问题。

向后兼容性

任何现有信号的行为都不会发生任何变化,因此预计不会出现向后兼容性问题。

安全注意事项

此方案预计不会产生任何安全影响。

隐私注意事项

此方案预计不会对隐私保护造成任何影响。

测试

将添加用于验证设计中指定的行为的测试。这些测试将确保时钟用户无法手动更改信号,在时钟更新时,等待时钟的 ZX_CLOCK_UPDATED 信号频闪的任何观察者都会收到通知,并且在没有时钟更新时不会通知信号的观察者(这意味着,当没有时钟更新时,系统永远不会断言 ZX_CLOCK_UPDATED)。

文档

以下文档将更新,以介绍 ZX_CLOCK_UPDATED,以及时钟用户使用此信号时应遵循的方法,以免错过更新。

缺点和替代方案

缺点

本文档的性能部分介绍了性能随着信号观察者数量的增加而下降的问题。如果时钟信号的观察者数量增加到很大数量,则可能需要采取进一步措施来缓解这些性能问题。

替代选项

该动机提出的问题的替代解决方案是将 Zircon UTC 时钟的时钟详细信息直接映射到 Starnix 内核。然后,Starnix 内核可以将此内存直接映射到 Linux 进程的空间。这意味着,对 Zircon 中时钟对象的任何更新都会立即传播到 Starnix 和 Linux 进程。这样就无需引入新信号,并且不需要缩短时钟更新传播到 Starnix 的延迟时间,而是完全消除这种延迟。不过,这需要对 Zircon 内核进行大规模更改。