| RFC-0237: Signalling Clock Updates With ZX_CLOCK_UPDATED ||
|---|---|
| Status | Accepted |
| Areas | - Kernel |
| Description | Add a new type of signal which is sent when a Zircon clock is updated |
| Gerrit change | - [922132](https://fuchsia-review.googlesource.com/c/fuchsia/+/922132) |
| Authors | - [anthonyjon@google.com](https://fuchsia-review.googlesource.com/q/owner:anthonyjon@google.com) - [mariagl@google.com](https://fuchsia-review.googlesource.com/q/owner:mariagl@google.com) |
| Reviewers | - [abarth@google.com](https://fuchsia-review.googlesource.com/q/owner:abarth@google.com) - [johngro@google.com](https://fuchsia-review.googlesource.com/q/owner:johngro@google.com) - [maniscalco@google.com](https://fuchsia-review.googlesource.com/q/owner:maniscalco@google.com) - [fdurso@google.com](https://fuchsia-review.googlesource.com/q/owner:fdurso@google.com) |
| Date submitted (year-month-day) | 2023-09-26 |
| Date reviewed (year-month-day) | 2024-01-03 |

[Edit this RFC](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/contribute/governance/rfcs/0237_signalling_clock_updates_with_zx_clock_updated.md)
[Edit RFC metadata](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/contribute/governance/rfcs/_rfcs.yaml&searchAndJump=-+name:+'RFC-0237')

## Summary

This RFC proposes introducing a new clock signal `ZX_CLOCK_UPDATED` to Zircon
clocks, which strobes each time the clock updates.

## Motivation

A [clock](https://fuchsia.dev/reference/kernel_objects/clock) is a
[one dimensional affine transformation](https://fuchsia.dev/docs/concepts/kernel/clock_transformations)
of the
[clock monotonic](https://fuchsia.dev/reference/syscalls/clock_get_monotonic.md.txt) reference
timeline, defining how the "reference" time (i.e. the device's monotonic clock)
should be translated to the "synthetic" time output by the clock. Thus, a [UTC](https://fuchsia.dev/docs/concepts/kernel/time/utc/overview)
clock is a constantly adjusting transform which, when applied to the current
value of the device's monotonic clock, produces the current UTC time.

The affine transform of the UTC clock in Zircon is updated by Timekeeper only
using the syscall `zx_clock_update` and can be read by any clock user using
the syscall `zx_clock_get_details`.

In order for a Linux program running on Starnix to calculate UTC time using
the vDSO function `clock_gettime` or `gettimeofday`, the Starnix vDSO must have
access to the most up to date clock transform from monotonic to UTC time.
Currently the Starnix kernel is able to provide this access by regularly
polling the Zircon UTC clock for the clock transform, using
`zx_clock_get_details`, then loading this transform into a page in memory that
is shared by the Starnix kernel and the userspace of Linux programs running on
Starnix.

A strobe is an infinitely fast assertion and deassertion of a signal. This
means that observers waiting for a change to the clock signal can detect a
strobe, but no observer will ever read the value of the clock signal to be
asserted. By introducing `ZX_CLOCK_UPDATED`, a clock signal which strobes
when the clock updates, the Starnix kernel can instead be notified of updates
to the UTC clock, and get the most up to date transform from Zircon then update
the clock transform used by Linux programs, immediately after these
notifications. This would reduce the potential latency between the clock
transform changing in Zircon and this new transform being used when Linux
programs calculate UTC time.

## Stakeholders

Who has a stake in whether this RFC is accepted? (This section is optional but
encouraged.)

*Facilitator:*

- cpu@google.com

*Reviewers:*

- abarth@google.com
- maniscalco@google.com
- johngro@google.com

*Consulted:*

- mariagl@google.com
- fdurso@google.com
- qsr@google.com

*Socialization:*

Discussed with all reviewers and consultants listed above. A
[design doc](https://docs.google.com/document/d/1-P5XSHMZdo4CO3DQmS795peJnKJdeGvPDVu3k_X5V0U/edit#heading=h.b2iwbvv6cjzw)
preceded this document and received informal feedback from all stakeholders.

Information from this document has been incorporated into this RFC,
where relevant.

## Design

Zircon clocks contain one signal: `ZX_CLOCK_STARTED` which is asserted when the
clock starts. The design adds a new clock signal, `ZX_CLOCK_UPDATED` which is
strobed each time the clock is updated.

In order to be able to strobe a signal, the design also involves the
modification of `Dispatcher::UpdateState` which is currently used to update
Zircon signals. Currently, the function takes two inputs, a `set_mask` and a
`clear_mask`, which specify the signals to set (assert) and clear (deassert).
Alongside updating the signals specified by the `set_mask` and `clear_mask`,
the function notifies all observers of any signals which have transitioned
from inactive to active, using the function `NotifyObservers`.

The modification is to add a third input, defaulted to zero, to `UpdateState`,
named `strobe_mask`. This specifies all of the signals to strobe. Signals which
are specified to strobe do not change value, but the `NotifyObservers` call is
modified to also notify all observers of any signals specified by
`strobe_mask`, so that the observers are informed that there has been an update
to the signal.

In order to use this signal to be informed of updates to the clock transform in
a way which will prevent the user from missing updates, users should not use
[`zx_object_wait_one`](https://fuchsia.dev/reference/syscalls/object_wait_one.md.txt)
or [`zx_object_wait_many`](https://fuchsia.dev/reference/syscalls/object_wait_many.md.txt)
to wait for a signal strobe. If a user reads the current clock details, then
calls `zx_object_wait_one` to wait for an update to the clock, the clock may
have been updated by Zircon in between the reading of the current clock details
and the call of the wait, and so this update will not be registered.

Instead, [`zx_object_wait_async`](https://fuchsia.dev/reference/syscalls/object_wait_many.md.txt)
should be used. Before reading the current transform, the user should post an
async wait against the clock. Then, after reading the clock details, the user
can wait on the port that the async wait was posted to. This prevents an update
to clock details being missed.

A result of this mechanism is that if the clock is updated in between the async
wait being created and the clock details being read, this leads to an immediate
wakeup when waiting on the port, despite the fact that the clock transform that
was read is up to date. Future work could be to evolve this signal to remove
the possibility of these spurious wakeups.

## Implementation

This design can be implemented in one small CL. The CL defines the new signal
and modifies UpdateState to include a new `strobe_mask` input.

## Performance

This new signal will be used by Starnix kernel to reduce the potential error of
the UTC clock of Linux programs running on Starnix.

At the moment, Starnix is the only proposed user of this signal, however there
may be other users of this signal in the future (for example, implementations
of the C++ runtime in order to support the C++ standard library's ability to
block threads until a UTC deadline). The time complexity of strobing a signal
using `UpdateState` is linear with respect to the number of observers of the
signal. This means that when the number of observers of `ZX_CLOCK_UPDATED`
becomes large, there will be performance issues.

## Backwards Compatibility

There is no change to the behavior of any existing signals, so no backwards
compatibility issues are anticipated.

## Security considerations

No security ramifications from this proposal are anticipated.

## Privacy considerations

No privacy ramifications from this proposal are anticipated.

## Testing

Tests will be added which verify the behaviors specified in the design. The
tests will ensure that no users of the clock can change the signal manually,
that any observers waiting for a strobe on a clock's `ZX_CLOCK_UPDATED` signal
are notified when the clock updates, and that observers of the signal are not
notified when there has been no clock update (meaning ZX_CLOCK_UPDATED is never
asserted when there is no clock update).

## Documentation

The following docs will be updated to describe `ZX_CLOCK_UPDATED`, and the
method clock users should follow to not miss an update when using this signal.

- [/docs/concepts/kernel/time/utc/architecture.md](https://fuchsia.dev/docs/concepts/kernel/time/utc/architecture)
- [/docs/concepts/kernel/time/utc/behavior.md](https://fuchsia.dev/docs/concepts/kernel/time/utc/behavior)
- [/reference/kernel_objects/clock.md](https://fuchsia.dev/reference/kernel_objects/clock)
- [/reference/syscalls/clock_update.md](https://fuchsia.dev/reference/syscalls/clock_update.md.txt)

## Drawbacks, and alternatives

### Drawbacks

The issue of performance decreasing as the number of observers of the signal
increases is described in the [Performance](https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0237_signalling_clock_updates_with_zx_clock_updated.md.txt#Performance) section of this
document. If the number of observers of the clock signal increases to a large
number, further work may need to be done to mitigate these performance issues.

### Alternatives

An alternative solution to the problem posed by the motivation is to map the
clock details of the Zircon UTC clock directly into Starnix kernel.
The Starnix kernel then can map this memory directly into the Linux processes'
space. This means that any updates to the clock object in Zircon are
immediately propagated to Starnix and to the Linux processes. This would remove
the need to introduce a new signal, and instead of reducing the latency of
clock updates being propagated to Starnix, it would remove this latency
entirely. However, this would require a sizable change to the Zircon kernel.
[](https://issues.fuchsia.dev/issues/new?component=1439230&template=1881640&description=Issue+on:+https://fuchsia.dev/docs/contribute/governance/rfcs/0237_signalling_clock_updates_with_zx_clock_updated.md "Report a bug or suggest improvements on this page") [](https://cs.opensource.google/fuchsia/fuchsia/+/main:docs/contribute/governance/rfcs/0237_signalling_clock_updates_with_zx_clock_updated.md "View the source code of this page") [](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/contribute/governance/rfcs/0237_signalling_clock_updates_with_zx_clock_updated.md&cloneRepo=fuchsia/fuchsia:refs/heads/main&fullPath=fuchsia/docs/contribute/governance/rfcs/0237_signalling_clock_updates_with_zx_clock_updated.md "Edit the source code of this page")