| RFC-0272:唤醒源报告 | |
|---|---|
| 状态 | 已接受 |
| 区域 |
|
| 说明 | 提议扩展 zx_system_suspend_enter,以提供有关挂起操作最终结束原因的更多详细信息 |
| 问题 | |
| Gerrit 更改 | |
| 作者 | |
| 审核人 | |
| 提交日期(年-月-日) | 2025-05-23 |
| 审核日期(年-月-日) | 2025-06-24 |
摘要
一项提案,旨在扩展 zx_system_suspend_enter 以提供用户模式,其中包含系统调用返回的所有具体原因,无论是刚刚退出暂停状态,还是从未进入暂停状态。
背景
作为进入低功耗状态的最后一步,在为低功耗状态配置了平台专用驱动程序和组件后,用户模式目前可能会通过调用 zx_system_suspend_enter 请求内核进入其低功耗状态。然后,内核将采取必要的步骤来暂停调度并将 CPU 置于低功耗状态,直到发生以下两种情况之一:用户提供的截止期限到达,或者一个或多个系统“唤醒源”发出信号。
唤醒源
唤醒源是内核对象,当它们处于适当的信号状态时,可用于将系统从挂起状态唤醒(或防止系统进入挂起状态)。目前,Zircon 内核定义的唯一唤醒源对象是使用 zx_interrupt_create 创建的物理中断对象,同时在选项字段中传递 ZX_INTERRUPT_WAKE_VECTOR 标志。当与对象关联的硬件中断触发时,中断唤醒源会发出信号,并且会一直发出信号,直到它们被销毁,或者通过向对象发布新的异步等待操作或通过阻塞对象上的线程来显式确认它们为止。
zx_system_suspend_enter 的当前行为。
zx_system_suspend_enter 目前接受 2 个参数。资源令牌和截止时间(在启动时间轴上指定)。请求内核进入挂起状态是一项特权操作,需要通过访问资源令牌(必须是系统 CPU 资源)来中介。如果未能传递有效的资源令牌,则会导致错误,并且不会尝试进入暂停状态。
如果尝试使用已过期的时限调用 zx_system_suspend_enter,系统会立即返回状态代码 ZX_ERR_TIMED_OUT。如果尝试调用 zx_system_suspend_enter 时,截止时间在未来,并且任何唤醒源对象已处于已发出信号的状态,则会立即返回状态代码 ZX_ERR_BAD_STATE。最后,尝试调用 zx_system_suspend_enter 并指定未来的截止时间,且没有已发出信号的唤醒源,将开始暂停所有 CPU 的进程。在此过程开始期间或之后的任何时间点,如果到达指定截止时间或任何唤醒源发出信号,都会导致 CPU 从挂起状态中退出,并返回状态代码 ZX_OK。
术语
唤醒源:系统中的任何对象,当收到信号时,可使系统退出挂起状态,或防止系统进入挂起状态。
截止时间唤醒源:一种仅存在于内核中的特殊唤醒源,当用户在对
zx_system_suspend_enter的调用中提供的截止时间到达时,该唤醒源可能会导致进入挂起状态。唤醒源报告条目:有关特定唤醒源的信息,详细说明了可能导致结束或未能进入暂停状态的活动。
唤醒源报告:一组信息,包括一个标头和一个唤醒源报告条目数组,可能从对
zx_system_suspend_enter的调用返回,用于告知用户退出或未能进入挂起状态的原因。唤醒报告/唤醒报告条目:唤醒源报告和唤醒源报告条目的简写版本。
问题陈述
目前,虽然截止时间或任何唤醒源都可以使内核退出挂起状态,但用户模式无法确定挂起操作完成的具体原因。
这会带来问题,尤其是在高度并发和异步的系统中,即使仅从调试/诊断的角度来看也是如此。鉴于 Zircon 内核是所有这些逻辑的中心点,并且始终知道系统从挂起状态释放的确切原因,因此它应该在帮助用户模式了解挂起被阻止或终止的原因方面发挥作用。
利益相关方
辅导员:
- jamesr@google.com
审核者:
- eieio@google.com
- fmil@google.com
- jmatt@google.com
已咨询:
- maniscalco@google.com
- surajmalhotra@google.com
- jaeheon@google.com
- mcgrathr@google.com
共同化:
我们于 2024 年底发布了一份旨在明确要求的初始文档,并收到了反馈。后来,我们发布了一份更具体的 API 提案,并与各种利益相关者进行了多轮反馈,最终形成了此 RFC 的基础。
要求
需求可划分为两种类型。功能要求(用户模式需要什么)和实现要求(内核代码需要遵守的规则)。虽然本文档不讨论特定内核实现的细节,但列出内核要求对于为某些设计决策提供背景信息非常重要。
功能性
1) 每次内核从对 zx_system_suspend_enter 的调用返回时,都必须提供一种机制,让调用者了解每个已发出信号并阻止系统进入挂起状态或最终触发挂起状态结束的唤醒源(包括截止时间唤醒源)。
2) 必须告知 zx_system_suspend_enter 的用户模式调用方有关已发出信号但报告机制生成报告时已被确认的唤醒源。换句话说,必须报告唤醒源变为有信号状态并被确认为调用展开的事实
3) 未确认的唤醒源的存在会阻止系统进入挂起状态。等待报告的唤醒源报告条目(针对已确认的唤醒源)不会阻止系统进入挂起状态。
实现
1) 生成唤醒报告所需的内存开销对于系统中的每个唤醒源都必须是恒定的。换句话说,在报告之前多次发出信号并确认的唤醒源不得需要无限量的存储空间。相反,唤醒源报告的存储空间要求在创建唤醒源时已从逻辑上支付,并且不会随着时间的推移而无限增长。 2) 可以使用互斥来序列化唤醒报告的生成,并花费 O(N) 时间,其中 N 是系统中的唤醒源数量。 3) 生成唤醒报告的时间不得超过 O(1)。 4) 典型系统中的唤醒源总数预计在 10-20 之间。如果遇到超过 100 个的系统,则会令人感到意外。
设计
概览
zx_system_suspend_enter 将得到扩展,以允许用户向内核传递一对缓冲区,内核可以使用典型的 out 参数模式向用户模式报告唤醒事件。内核将被修改为跟踪仍处于已发出信号状态或仍在等待报告的唤醒源(或两者兼而有之)。为了防止出现无限制的内存需求,唤醒源将跟踪以下信息:
- 首次成为信号源的时间。
- 上次变为有信号状态的时间。
- 上次被确认的时间(如果有)。
- 它们变为有信号状态的次数。
这样一来,唤醒源就可以被任意次数地发出信号和确认,并且仍然可以报告,而无需任意数量的内存来存储各个信号事件。内核还将跟踪哪些唤醒报告条目已被报告,并在以下情况下向用户模式指示这一点:唤醒源被发出信号、报告,然后再次报告,但未先被确认。
API 更改
对内核 API 的更改包括定义几个结构和标志,以及更改 zx_system_suspend_enter 系统调用的定义。
结构和标志
#define ZX_SYSTEM_SUSPEND_OPTION_DISCARD ((uint64_t)(1u << 0))
#define ZX_SYSTEM_SUSPEND_OPTION_REPORT_ONLY ((uint64_t)(1u << 1))
typedef struct zx_wake_source_report_header {
zx_instant_boot_t report_time;
zx_instant_boot_t suspend_start_time;
uint32_t total_wake_sources;
uint32_t unreported_wake_report_entries;
} zx_wake_source_report_header_t;
#define ZX_SYSTEM_WAKE_REPORT_ENTRY_FLAG_SIGNALED ((uint32_t)(1u << 0))
#define ZX_SYSTEM_WAKE_REPORT_ENTRY_FLAG_PREVIOUSLY_REPORTED ((uint32_t)(1u << 1))
typedef struct zx_wake_source_report_entry {
zx_koid_t koid;
char name[ZX_MAX_NAME_LEN];
zx_instant_boot_t initial_signal_time;
zx_instant_boot_t last_signal_time;
zx_instant_boot_t last_ack_time;
uint32_t signal_count;
uint32_t flags;
} zx_wake_source_report_entry_t;
系统调用变更
zx_system_suspend_enter 的定义将从以下内容更改为:
zx_status_t zx_system_suspend_enter(zx_handle_t resource,
zx_instant_boot_t resume_deadline);
收件人
zx_status_t zx_system_suspend_enter(zx_handle_t resource,
zx_instant_boot_t resume_deadline,
uint64_t options,
zx_wake_source_report_header_t* out_header,
zx_wake_source_report_entry_t* out_entries,
uint32_t num_entries,
uint32_t* actual_entries);
此外,状态代码报告行为也会发生变化。截至目前,如果传递给调用的 resume_deadline 在挂起操作开始时已过时,则返回 ZX_ERR_TIMED_OUT;但如果截止时间在系统挂起过程中或在系统完全挂起时已过时,则返回 ZX_OK。此外,如果在挂起操作开始时有任何已发出信号的唤醒源,则返回 ZX_ERR_BAD_STATE;但如果在系统处于挂起过程中或完全挂起后,有唤醒源发出信号,则返回 ZX_OK。
今后,在所有情况下都会返回 ZX_OK。报告标题中会返回一个时间戳 (suspend_start_time),告知用户我们实际开始中止的时间(在所有参数检查都已完成之后)。用户可以根据报告中内部截止时间唤醒源是否存在唤醒事件来检测是否发生了超时,还可以通过将用户提供的截止时间值与 suspend_start_time 进行比较来了解截止时间是否已过。同样,用户可以通过检查唤醒源的唤醒报告条目的 last_signaled_time 和 last_ack_time(如果已定义)并将其与返回的 suspend_start_time 进行比较,来了解在挂起操作开始之前是否已发出唤醒源信号。
索取报告
在请求内核进入挂起状态时,用户可以通过 out_header 参数传递包含唤醒报告标头的缓冲区,请求生成唤醒报告。用户还可以传递一个缓冲区,其中包含要由内核填充的唤醒源报告条目数组,但不是必需的;如果只需要标头,则只需传递标头缓冲区。
目前,您需要提供三个参数才能接收报告条目:
out_entries:指向条目存储空间的指针。num_entries:一个数字,表示条目存储空间的大小。actual_entries:指向缓冲区中实际填充的条目数的 out 形参指针。
虽然传递包含唤醒报告条目的缓冲区是可选的,但传递一组不一致的实参来执行此操作是不合法的。换句话说,用户必须为 out_entries 和 actual_entries 传递有效指针,并为 num_entries 传递非零值;或者必须为 out_entries 和 actual_entries 传递 nullptr,并为 num_entries 传递零。最后,虽然允许用户仅请求标头(通过传递非 null 的 out_header 和 out_entries, num_entries, actual_entries 的 (nullptr, 0,
nullptr)),但如果未同时传递 out_header 的有效指针,则传递用于保存报告条目的有效参数是不合法的。如果不遵循这些规则,系统将返回状态代码 ZX_ERR_INVALID_ARGS,不会尝试进入暂停状态,也不会生成报告。
当用户请求唤醒报告时,报告标题中会显示两个计数。首先,total_wake_sources 将报告系统中存在的唤醒源总数(包括内部截止时间唤醒源),无论报告生成时这些唤醒源处于何种状态。
当用户传递用于保存报告的唤醒报告条目的缓冲区时,报告最多只能报告用户缓冲区中的 num_entries 个条目。报告的实际数量将存储在 actual_entries 实参中。用户可以通过检查标头中的第二个计数器 unreported_wake_report_entries 来了解是否还有其他事件等待报告(由于用户缓冲区中没有足够的空间来存储这些事件)。
unreported_wake_report_entries 将报告在报告生成开始时需要报告但未放入用户缓冲区中,因此未报告的唤醒报告条目数。可以使用对 zx_system_suspend_enter 的后续调用来检索这些条目(请参阅下文中的“请求报告而不暂停”)。
请注意,在生成报告后,唤醒源可能会在调用挂起展开时创建或销毁,这意味着在调用返回时,total_wake_sources 可能不再反映系统范围内的唤醒源的精确数量。同样,在展开期间,唤醒源可能会发出信号(或重新发出信号),从而导致等待报告的唤醒报告条目数量超出 unreported_wake_report_entries 在进程中指示的数量。
在不暂停的情况下请求报告。
用户还可以通过在选项中传递 ZX_SYSTEM_SUSPEND_OPTION_REPORT_ONLY 标志来请求仅生成报告。传递此标志后,系统不会尝试暂停,并且标头中返回的 suspend_start_time 将为 ZX_TIME_INFINITE。此外,传递此标志时,用户(至少)需要传递一个用于保存报告标头的缓冲区。否则,系统会返回 ZX_ERR_INVALID_ARGS 错误。另请注意,即使仅请求报告,仍需要中介系统 CPU 资源。
此标志的主要用途之一是支持以下情况:调用方可能只有有限或固定数量的内存用于其事件缓冲区,而需要报告的事件数量超过了缓冲区空间。假设某个系统在其缓冲区中只能容纳 2 个事件。它会调用 suspend,并且在 suspend 调用展开时,10 个来源会发出信号并得到确认。系统会生成报告,并将 10 个事件中的 2 个返回给用户。为了耗尽剩余的事件,用户需要多次回调到挂起操作。没有主动发出信号的唤醒源来阻止系统挂起,因此用户被迫传递过去的截止时间,以防止系统意外地重新挂起。 每次发生这种情况时,系统都会发出截止时间唤醒源信号并进行确认,并且可能会重新报告(也可能不会,具体取决于事件的枚举顺序,而这是未指定的)。
在极端情况下,如果用户缓冲区中只剩下一个事件的空间,他们甚至可能无法取得进展,因为截止时间来源的事件可能会被反复报告。
报告标题时间戳
报告标头将包含启动时间轴上的两个时间戳。report_time 是报告实际生成的时间(在启动时间轴上),即系统调用展开时和返回到用户模式之前的时间。suspend_start_time 表示系统调用提交到挂起操作的时间。如果唤醒事件表明来源是在此时间之后最后一次发出信号,或者表明来源是在此时间之前最后一次发出信号,但在此时间之后得到确认,则这些来源必须在唤醒系统或防止系统进入挂起状态方面发挥了某种作用。
如果出于任何原因,系统调用生成了报告,但根本没有尝试进入挂起状态,则 suspend_start_time 将为 ZX_TIME_INFINITE。
舍弃已确认的事件。
如果用户不想接收在调用 zx_system_suspend_enter 之前已发出信号但已被确认的来源的唤醒报告条目,则可以在调用 zx_system_suspend_enter 时在 options 字段中传递 ZX_SYSTEM_SUSPEND_OPTION_DISCARD 位。在挂起操作开始时,任何尚未报告但当前未发出信号(例如,未确认)的唤醒源的任何唤醒报告条目都将被舍弃,就好像它已被报告一样。
请注意,舍弃条目不会将当前已发出信号的来源(无论之前是否已确认)的条目标记为“已报告”。发出信号的来源将阻止系统进入挂起状态,并且即使来源在尝试进入挂起状态之后但在生成报告之前被确认,也会报告给用户(如果空间允许)。
在正常运行过程中,某些唤醒源可能会在系统尝试挂起之前多次发出信号并得到确认。选择在操作开始时舍弃这些事件可能有助于减少实际上并未在唤醒系统方面发挥作用但需要报告的事件数量,不过这样做是可选的。
报告了每次唤醒事件的信息。
报告给用户的每个唤醒事件都将包含以下字段:
koid- 这是配置为唤醒源且已发出信号的内核对象的 KOID。作为 KOID,它在系统生命周期内唯一标识特定对象。name- 一个ZX_MAX_NAME_LEN字符数组,其中包含旨在帮助调试的直观易懂的字符串。名称的具体格式未指定,不应在生产逻辑中使用。它仅用于内部开发和调试。由于 Zircon 中断对象目前无法重命名,因此中断对象的名称将自动生成。initial_signal_time- 在启动时间轴上,此唤醒源首次发出信号的时间。如果来源在报告之前被确认并重新发出信号多次,initial_signal_time将保持不变,记录首次发出信号事件的时间。last_signal_time- 在报告之前,此唤醒源在启动时间轴上发出信号的最近时间。如果来源在被报告之前多次被确认并重新发出信号,last_signal_time每次都会更新,始终记录唤醒来源发出信号的最新时间。last_ack_time- 在启动时间轴上,相应唤醒源最近一次被确认的时间。如果来源在报告之前从未被确认过,则此字段的值为ZX_TIME_INFINITE。如果唤醒源被多次发出信号并确认,然后在报告之前再次发出信号,则last_ack_time可能小于last_signal_time,但始终大于或等于initial_signal_time。signal_count- 包含从初始信号时间到最后信号时间之间唤醒源发出信号的次数。signal_count将始终至少为 1,如果signal_count正好为 1,则初始信号时间和最后一个信号时间将是相同的值。flags- 包含两个当前已定义标志的组合。ZX_SYSTEM_WAKE_REPORT_ENTRY_FLAG_SIGNALED- Indicates that the wake source for this wake report entry was still signaled (has not yet been acknowledged) at the time that the wake report containing this entry was generated.ZX_SYSTEM_WAKE_REPORT_ENTRY_FLAG_PREVIOUSLY_REPORTED- 表示此唤醒报告条目已出现在之前的报告中。请注意,您无法查看之前举报过但目前未标记的条目。若要加入等待报告的唤醒报告条目集,必须发出唤醒信号,并且一旦唤醒报告条目的唤醒源被确认(清除信号位)和报告(设置报告位),就会从该集中移除。
报告截止时间唤醒源。
当对 zx_system_suspend_enter 的调用包含未来的 resume_deadline,并且系统进入挂起状态,仅在截止时间计时器唤醒时才恢复,系统会以特殊唤醒报告条目的形式向用户报告此情况。相应条目的 koid 字段将包含值 ZX_KOID_KERNEL。内核会自动确认此唤醒源;无需采取特殊的用户模式操作来管理截止时间唤醒源。
销毁唤醒源。
当用户模式创建的唤醒源被销毁时,系统会隐式确认该唤醒源,以便它不会阻止系统进入挂起状态。此外,如果存在等待报告的已销毁唤醒源的唤醒报告条目,则会立即从等待报告的唤醒报告条目集中移除该条目。
测试
唤醒报告生成测试将在核心测试环境中使用单元测试完成。这些单元测试只能作为核心测试可靠地运行,因为平台特定的唤醒源(以物理中断的形式)的存在可能会使报告生成的结果不确定。
除了在核心测试环境中运行之外,我们还需要添加一项内容来方便测试:非平台特定的唤醒源,该唤醒源可由测试代码发出信号和确认。物理中断不满足这些要求。系统中的物理中断是平台特定的详细信息,我们不能依赖于任意平台的任何特定中断集。此外,物理中断对象不是用户模式可以强制触发的东西。只能由其关联的硬件触发。
由于无法使用物理中断,并且目前系统中没有定义其他类型的唤醒源(截止时间唤醒源这一特殊情况除外),我们计划引入一种专门用于测试的新型唤醒源。
虚拟中断唤醒源。
除了物理中断对象之外,Zircon 还支持“虚拟”中断对象。虚拟中断对象与物理中断一样参与相同的特殊情况信号处理,通常用于需要对中断块进行解复用的情况,以便在某个驱动程序拥有中断块时保持进程隔离,而其他几个不相关的驱动程序使用该块中的中断。目前,配置为中断的 GPIO 块是最常见的这种情况,但并非唯一的情况(例如,USB 中断也可能会使用这些对象)。
与物理中断不同,虚拟中断只能由用户模式代码以编程方式触发(通过调用 zx_interrupt_trigger)。它们是使用与物理中断相同的系统调用 (zx_interrupt_create) 创建的,但目前不需要有效的系统 IRQ 资源句柄即可创建(物理中断需要),并且明确禁止将它们创建为唤醒源。
接下来,我们将更改这些限制。具体而言,用户将能够创建虚拟中断对象作为唤醒源,但前提是他们向系统 IRQ 资源提供有效的句柄。换句话说,创建虚拟中断唤醒源将被视为一种特权操作,由控制创建物理中断对象能力的同一系统资源来中介。非唤醒源虚拟中断将继续可在没有任何特殊权限的情况下构建。
这样一来,就可以在核心测试环境中编写和运行一整套确定性的单元测试
性能
预计对效果的影响微乎其微。如果中断导致唤醒源变为已发出信号状态,则在极少数情况下,当生成报告的同时唤醒源变为已发出信号状态时,中断需要与锁争用。不过,报告生成永远不会将锁保持 O(N) 时间,只会保持足够长的时间来评估单个关联的唤醒报告条目的状态,并将内容复制到本地缓冲区,然后释放锁并尝试复制到用户提供的缓冲区。
报告生成本身将需要 O(N) 时间(这是必然的),在此期间,系统无法创建或销毁新的唤醒源。预计这不会造成任何有意义的性能问题,因为预计绝大多数唤醒源将在系统初始化期间创建,并且将在系统生命周期内存在。
向后兼容性
此方法直接修改现有系统调用,因此从 ABI 角度来看不向后兼容。不过,正在修改的系统调用目前是 @next 的成员,并且仍在开发中,这意味着不应存在需要使用明确的弃用周期来处理的外部依赖项。
代码库中的现有调用点可能会被修改为传递 0, nullptr,
nullptr, 0, nullptr 作为调用的默认值,这(除了返回的状态代码行为的更改)将保留系统的当前行为。唤醒报告条目会在内部累积,但不会产生显著的费用。
安全注意事项
预计不会出现严重的安全问题。虚拟唤醒源中断的引入由与物理唤醒源中断创建相同的资源令牌来调解。此外,对 zx_system_suspend_enter 的所有调用都已通过对系统 CPU 令牌的访问进行中介,从而自动使生成唤醒源报告的能力通过相同的令牌进行中介。
隐私注意事项
无论是暂停系统还是报告系统从暂停状态恢复的原因,都不会涉及任何 PII,因此不存在已知的隐私问题。如果唤醒源的触发时间和确认时间被视为“私密”信息,那么用户可以放心,因为生成报告的能力是由资源令牌介导的特权操作。
文档
目前,zx_system_suspend_enter 是一个正在开发的 API,位于 @next 下。因此,没有正式的公开文档。在短期内,唤醒源报告的内部用户将能够使用内部设计文档、此 RFC 和单元测试作为指定行为和使用示例的参考。
在 Zircon 对进入/退出挂起状态和报告特定唤醒原因的支持稳定后,将编写子系统最终形式的正式公开文档。假设在当时,这种唤醒源报告机制仍然存在,那么预计会编写反映此 RFC 中规定的规则以及在此期间所做任何更改的文档。
考虑的替代方案
计时器唤醒源
除了中断之外,能够创建配置为唤醒源的 Zircon Timer 对象也可能很有用。用户可以在启动时间轴上安排截止时间,当其计时器对象变为已发出信号时,唤醒源将被视为已发出信号,并且会一直保持这种状态,直到计时器被取消或在未来重新安排。
不过,出于以下几个原因,我们目前已决定不这样做。
1) 唤醒源是强大的对象,可能会阻止系统进入挂起状态,因此很有可能被滥用。目前,与中断不同,创建计时器不需要提供任何显式功能,这意味着没有立即可用的方法将计时器唤醒源的构建视为由句柄形式的功能介导的特权操作。2) zx_system_suspend_enter 调用已支持截止时间。如果用户模式需要支持任意数量的可以将系统从挂起状态唤醒的计时器,则可以在具有调用 zx_system_suspend_enter 功能的组件级别实现一个简单的计时器队列。这样一来,任何所需的功能模型都完全由用户模式下的电源管理子系统控制。3) 最后,我们也可以稍后再回来执行此操作。我们需要编写新的 RFC 来解决如何中介唤醒源计时器创建的问题,但此处显示的唤醒报告条目报告结构应该足以报告由计时器触发的唤醒源,就像报告中断一样。
基于联合或 TLV 的唤醒报告条目。
目前,唤醒报告条目的建议结构已固定。在一个系统中存在许多不同类型的唤醒源的世界中,每个唤醒源都具有高度区分的重要细节集,可以想象,在这样的世界中,存在一些不重叠的信息集,需要针对系统中的不同类型的唤醒源进行报告。
在这样的世界中,唤醒报告条目对象会是什么样的?一种可能性是将结构定义为具有类型枚举和各种不重叠的数据集的并集。基本上,std::variant 的 C ABI 版本。虽然可以这样做,但会显得相当尴尬。目前,系统中只有一种用户可构建的唤醒源,因此无需使用联合。
如果我们想为未来的(未知)唤醒源类型做好准备,就需要将联合填充到最大可能的大小(也是未知的),以便在最终添加新的唤醒报告条目类型时,希望能够保持联合大小不变。但到了那天,我们可能没有预留足够的空间,不得不对接口进行版本升级,而在那天到来之前,预留的空间只会白白浪费。
同样,我们也可以采用类型-长度-值 (TLV) 方法来对唤醒报告条目进行编码。这种方法不需要猜测“编码唤醒事件的最大可能大小”,但会引入使用可变长度对象源的内核 ABI,从而使序列化报告所需的内核代码和处理报告所需的用户模式代码变得复杂。
总而言之,当前的固定唤醒报告条目定义足以满足现有用例(中断唤醒报告条目)以及唯一已确定的潜在未来用例(计时器唤醒源),因此目前没有令人信服的理由采用更复杂的方法来使事情变得复杂。
其他用户模式信息。
根据用户模式计划如何利用报告的唤醒报告条目,允许用户模式将二进制 blob(最大大小固定)与唤醒源相关联可能是有利的,这样在生成报告期间,二进制 blob 就会在唤醒报告条目中报告。这样一来,用户模式就可以通过唤醒源对象将任意簿记信息“隧道化”到报告的唤醒报告条目中。
虽然可能有用,但使用唤醒报告功能的现有客户表示他们不需要此类功能。报告的 KOID 就足够了;它可以充当唯一键,必要时可用于查找用户模式的簿记信息。
不这样做还意味着,我们不必担心设计用于控制此类信息的权限模型,也不必担心恶意行为者通过唤醒源报告获取私密账簿信息而带来的潜在安全风险。
报告已销毁唤醒源的唤醒事件。
如前所述,当唤醒源被销毁时,任何等待报告的相关唤醒报告条目信息都会立即被销毁,并且永远不会被报告。我们是否应该坚持报告已销毁的唤醒源的唤醒报告条目?
虽然提议的行为意味着在技术上可能无法向用户模式报告唤醒报告条目,但在典型使用情形下,预计这不会造成任何严重问题。截至目前,唤醒源始终是中断,这些中断往往在系统启动期间很早就被分配,并且在整个系统的生命周期内都存在,这意味着它们在正常运行期间不会被销毁。选择立即移除任何等待报告的唤醒报告条目,是一种简单的方法,可确保如果系统中的某些内容开始执行以下操作,唤醒报告的内存要求不会无限增长:
创建唤醒源 + 发出信号。+ 销毁它。 + 永久重复。
未来,如果引入了在常规操作期间经常创建和销毁的新类型的唤醒源,并且销毁的源可能会丢失唤醒报告条目信息,从而导致问题,则可以重新考虑此决定。