基本用法

防止数据处理流水线中的系统暂停

在许多情况下,事件需要多个组件参与处理。假设您是一名司机,收到一个可能会唤醒系统的事件;如果是在系统唤醒时收到该事件,则应防止系统暂停。中断处理驱动程序可能不知道事件的重要性,并将其传递给另一个驱动程序或组件,这种情况非常常见。

有几种方法可以管理这种移交。为了便于讨论,我们假设驱动程序 X 收到中断,并通过 FIDL 消息将事件移交给驱动程序 Y。如果 X 是驱动程序,而 Y 是非驱动程序组件,这些选项同样适用。

接力

解决此问题的一种方法是随事件数据传递接力棒。“接力”是指接力赛,参与者将一个物体从一个传递给另一个,以完成任务(即比赛)。 “接力棒传递”是指接力赛中参赛者将物品从一个人传递给另一个人以完成任务(即比赛)的概念。

我们的接力棒是 LeaseToken,例如 ActivityGovernor.AcquireWakeLease 或 fuchsia.power.broker/Topology.Lease 返回的接力棒。

当 X 收到中断时,它会执行以下操作:

  • 调用 ActivityGovernor.AcquireWakeLease
  • 确认中断
  • 对事件执行任何处理,可能会将其转换为新类型
  • 将事件和从 AcquireWakeLease 获取的 LeaseToken 传递给 Y

此方法需要更改 X 和 Y 之间使用的协议。使用下文介绍的协议互锁不需要这样做,但有其他缺点。

事件速率较高的系统可能会发现,对每个事件调用 ActivityGovernor.AcquireWakeLease 的 IPC 开销过高。 在这些情况下,驱动程序 X 可以复制 LeaseToken(因为它实际上只是 Zircon 事件对的句柄),传递副本,并在某个超时期限内保留原始副本,而不是简单地将 LeaseToken 从 X 移到 Y。 如果选择使用超时,请仔细选择超时 ,因为系统在所有 LeaseToken 副本被丢弃之前都无法暂停。 强烈建议不要使用过长的超时,使用超时的原因是事件速率相对较高,这意味着您应该能够选择较短的超时。如果您编写的是 C++,则可以使用 TimeoutWakeLease 类来管理租约并根据新事件的到达时间延长 超时。通过调用 AcquireWakeLease 而不是自行与 ActivityGovernor 功能进行通信来使用帮助程序。

协议互锁

如果驱动程序 X 和驱动程序 Y 的事件传递协议包含确认,或者添加了此确认,则可以选择“协议互锁”。 协议互锁由 Y 在向 X 确认收到事件之前调用 ActivityGovernor.AcquireWakeLease 来实现。

此方法的步骤如下:

  • X 调用 ActivityGovernor.AcquireWakeLease
  • 确认中断
  • X 对事件执行任何必要的处理,可能会将其转换为新类型
  • 将事件传递给 Y
  • Y 调用 ActivityGovernor.AcquireWakeLease
  • Y 向 X 确认已收到事件
  • X 丢弃其 LeaseToken
  • Y 对事件执行任何处理
  • Y 丢弃其 LeaseToken

如果协议已有确认,则协议互锁不需要 更改 X 和 Y 之间使用的协议。此策略确实 增加了对系统活动调控器的 IPC 调用次数。调用次数的增加是否有意义取决于事件速率,以及 X 和 Y 是否在超时期限内保留其 LeaseToken。如果选择使用超时,请仔细选择超时 ,因为系统在 LeaseToken 被丢弃之前都无法暂停。强烈建议不要使用过长的超时,使用超时的原因是事件速率相对较高,这意味着您应该能够选择较短的超时。如果您编写的是 C++,则可以使用 TimeoutWakeLease 类来管理 租约并根据新事件的到达时间延长超时。通过调用 AcquireWakeLease 而不是自行与 ActivityGovernor 功能进行通信来使用帮助程序。

超时

使用超时来确保系统正确性不是与电源框架集成的首选方案。其他选项仅将超时作为优化手段。超时可能会导致不可预测的行为,因为很难找到合适的超时值。此外,超时通常必须针对每种用例、产品配置和硬件配置组合进行调整,这使得管理超时成为一项艰巨的任务。超时本质上是竞争性的,因此对于任何给定的超时值,它可能允许您在大多数情况下赢得竞争,直到突然失败。通常只有在软件部署到大型测试或用户群体后才会发现故障,并且在观察到故障时会导致混乱。

有时,超时是唯一可行的选择。使用超时,我们将让驱动程序 X 调用 ActivityGovernor.AcquireWakeLease,确认中断,然后持有租约,直到达到超时时间,驱动程序 Y 永远不会看到租约。如果在超时之前收到另一个中断,驱动程序 X 可以直接延长其超时时间,而不是获取额外的租约。如果您编写的是 C++,则 可以使用帮助程序类来管理租约并根据新中断的到达时间延长 超时。通过调用 AcquireWakeLease 而不是自行与 ActivityGovernor 功能进行通信来使用帮助程序。