RFC-0237: Signalling Clock Updates With ZX_CLOCK_UPDATED | |
---|---|
Status | Accepted |
Areas |
|
Description | Add a new type of signal which is sent when a Zircon clock is updated |
Gerrit change | |
Authors | |
Reviewers | |
Date submitted (year-month-day) | 2023-09-26 |
Date reviewed (year-month-day) | 2024-01-03 |
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 is a one dimensional affine transformation of the clock monotonic 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 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 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
or zx_object_wait_many
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
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
- /docs/concepts/kernel/time/utc/behavior.md
- /reference/kernel_objects/clock.md
- /reference/syscalls/clock_update.md
Drawbacks, and alternatives
Drawbacks
The issue of performance decreasing as the number of observers of the signal increases is described in the 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.