blob: 126d6945b4096f1c3086c24763eb272fdc2666de [file] [log] [blame] [view]
# Basic Usage
## Preventing system suspension in a data processing pipeline
There are many scenarios where an event requires multiple components
to participate in its processing. Imagine that you are a driver that receives
an event which may wake the system or, if it is received while the system is
awake, should prevent the system from suspending. It is very common that an
interrupt-handling driver may not know the significance of the event and passes
it along to another driver or component.
There are a few options for how to manage this handoff. For the sake of
discussion let's imagine that Driver X receives the interrupt and hands the
event off to Driver Y via a FIDL message. **The options are equally relevant if
X is a driver and Y is a non-driver component.**
### Baton passing
One way to solve this problem is by passing a baton along with the event data.
"Baton passing" alludes to the idea of a relay race where participants pass an
object from one to another to complete the task (ie. race).
Our baton could be [`LeaseToken`][lease_token] (which we talked about
previously) or a [fuchsia.power.broker/LeaseControl][lease_control] channel.
We'll use a `LeaseToken` because we've already talked about them and because
they are easier to work with than `LeaseControl`.
When X receives an interrupt it:
* Calls `ActivityGovernor.AcquireWakeLease`
* ACKs the interrupt
* Does any processing on the event, maybe converting it to a new type
* Passes the event and the `LeaseToken` obtained from `AcquireWakeLease` to Y
This approach requires changes to the protocol used between X and Y. Using
protocol interlocks, described below, does not require this, but has other
downsides.
Systems with high event rates may find the IPC overhead of calling
`ActivityGovernor.AcquireWakeLease` too high to do on _every_ event. In these
cases, instead of simply moving the `LeaseToken` from X to Y, Driver X could
duplicate `LeaseToken` (since it is really just a handle to a Zircon event
pair), pass on the duplicate, and retain the original for some timeout period.
If choosing to use a timeout, **choose your timeout carefully** because the
system will not be able to suspend until all copies of `LeaseToken` are dropped.
Long timeouts are strongly discouraged, the reason to use a timeout is because
you have relatively high event rates, which means you should be able to pick a
short timeout. If you are writing C++ you can use the
[`TimeoutWakeLease`][wake_lease] class for managing leases and extending
timeouts based on the arrival of new events. Use the helper by calling
`AcquireWakeLease` instead of talking to the `ActivityGovernor` capability
yourself.
### Protocol interlocks
"Protocol interlocks" are an option if Driver X and Driver Y's protocol for
event passing contains an acknowledgement or this acknowledgement is added.
The protocol interlock is implemented by Y calling
`ActivityGovernor.AcquireWakeLease` before acknowledging to X that Y received
the event.
The steps for this approach are:
* X calls `ActivityGovernor.AcquireWakeLease`
* ACKs the interrupt
* X does any necessary processing on the event, maybe converting it to a new
type
* Passes the event to Y
* Y calls `ActivityGovernor.AcquireWakeLease`
* Y acknowledges to X that it received the event
* X drops its `LeaseToken`
* Y does any processing on the event
* Y drops its `LeaseToken`
The protocol interlock does **not** require changing the protocol used between X
and Y if the protocol already has an acknowledgement. This strategy **does**
increase the number of IPC calls to System Activity Governor. Whether or not the
increase in calls is meaningful depends on the rate of events and whether or not
X and Y are retaining their `LeaseToken` for a timeout period. If you choose to
use a timeout, **choose your timeout carefully** because the system will not be
able to suspend until the `LeaseToken` is dropped. Long timeouts are strongly
discouraged, the reason to use a timeout is because you have relatively high
event rates, which means you should be able to pick a short timeout. If you are
writing C++ the [`TimeoutWakeLease`][wake_lease] class is available for managing
leases and extending timeouts based on the arrival of new events. Use the
helper by calling `AcquireWakeLease` instead of talking to the
`ActivityGovernor` capability yourself.
### Timeouts
Using timeouts to ensure system correctness is not the preferred option for
integrating with power framework. The other options use timeouts as an
optimization only. Timeouts can lead to unpredictable behavior because finding a
good timeout value is difficult. Additionally, timeouts usually must be tuned
for each use case, product configuration, and hardware configuration combination
making managing the timeouts a substantial task. Timeouts are inherently racy,
so for any given timeout value it might allow you to win the race most of the
time until it suddenly doesn't. Failures are often discovered only once the
software is deployed to a large test or user population and result in confusion
when observed.
Timeouts are sometimes the only feasible option. With a timeout we'll have
Driver X call `ActivityGovernor.AcquireWakeLease`, ACK the interrupt, and then
hold the lease until we reach the timeout, Driver Y never sees the lease. If
another interrupt arrives before the timeout, Driver X can just extend its
timeout instead of acquiring an additional lease. If you are writing C++ there
is a [helper][wake_lease] class available for managing leases and extending
timeouts based on the arrival of new interrupts. Use the helper by calling
`AcquireWakeLease` instead of talking to the `ActivityGovernor` capability
ourself.
[lease_control]: https://cs.opensource.google/fuchsia/fuchsia/+/39b9a242c6e2b09731a426cdcf9f1353206fd034:sdk/fidl/fuchsia.power.broker/broker.fidl;l=272
[lease_token]: https://cs.opensource.google/fuchsia/fuchsia/+/39b9a242c6e2b09731a426cdcf9f1353206fd034:sdk/fidl/fuchsia.power.system/system.fidl;l=72
[wake_lease]: https://cs.opensource.google/fuchsia/fuchsia/+/39b9a242c6e2b09731a426cdcf9f1353206fd034:sdk/lib/driver/power/cpp/wake-lease.h