Documentation ¶
Overview ¶
Package time provides a calibrated clock synchronized to a system reference clock.
Index ¶
Constants ¶
const ( // ApproxUpdateInterval is the approximate interval that parameters // should be updated at. // // Error correction assumes that the next update will occur after this // much time. // // If an update occurs before ApproxUpdateInterval passes, it has no // adverse effect on error correction behavior. // // If an update occurs after ApproxUpdateInterval passes, the clock // will overshoot its error correction target and begin accumulating // error in the other direction. // // If updates occur after more than 2*ApproxUpdateInterval passes, the // clock becomes unstable, accumulating more error than it had // originally. Repeated updates after more than 2*ApproxUpdateInterval // will cause unbounded increases in error. // // These statements assume that the host clock does not change. Actual // error will depend upon host clock changes. // // TODO(b/68779214): make error correction more robust to delayed // updates. ApproxUpdateInterval = 1 * time.Second // MaxClockError is the maximum amount of error that the clocks will // try to correct. // // This limit: // // * Puts a limit on cases of otherwise unbounded increases in error. // // * Avoids unreasonably large frequency adjustments required to // correct large errors over a single update interval. MaxClockError = ReferenceNS(ApproxUpdateInterval) / 4 )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CalibratedClock ¶
type CalibratedClock struct {
// contains filtered or unexported fields
}
CalibratedClock implements a clock that tracks a reference clock.
Users should call Update at regular intervals of around approxUpdateInterval to ensure that the clock does not drift significantly from the reference clock.
func NewCalibratedClock ¶
func NewCalibratedClock(c ClockID) *CalibratedClock
NewCalibratedClock creates a CalibratedClock that tracks the given ClockID.
func (*CalibratedClock) Debugf ¶
func (c *CalibratedClock) Debugf(format string, v ...any)
Debugf logs at debug level.
func (*CalibratedClock) GetTime ¶
func (c *CalibratedClock) GetTime() (int64, error)
GetTime returns the current time based on the clock calibration.
func (*CalibratedClock) Infof ¶
func (c *CalibratedClock) Infof(format string, v ...any)
Infof logs at debug level.
func (*CalibratedClock) Update ¶
func (c *CalibratedClock) Update() (Parameters, bool)
Update runs the update step of the clock, updating its synchronization with the reference clock.
Update returns timekeeping and true with the new timekeeping parameters if the clock is calibrated. Update should be called regularly to prevent the clock from getting significantly out of sync from the reference clock.
The returned timekeeping parameters are invalidated on the next call to Update.
func (*CalibratedClock) Warningf ¶
func (c *CalibratedClock) Warningf(format string, v ...any)
Warningf logs at debug level.
type CalibratedClocks ¶
type CalibratedClocks struct {
// contains filtered or unexported fields
}
CalibratedClocks contains calibrated monotonic and realtime clocks.
TODO(mpratt): We know that Linux runs the monotonic and realtime clocks at the same rate, so rather than tracking both individually, we could do one calibration for both clocks.
func NewCalibratedClocks ¶
func NewCalibratedClocks() *CalibratedClocks
NewCalibratedClocks creates a CalibratedClocks.
func (*CalibratedClocks) GetTime ¶
func (c *CalibratedClocks) GetTime(id ClockID) (int64, error)
GetTime implements Clocks.GetTime.
func (*CalibratedClocks) Update ¶
func (c *CalibratedClocks) Update() (Parameters, bool, Parameters, bool)
Update implements Clocks.Update.
type Clocks ¶
type Clocks interface { // Update performs an update step, keeping the clocks in sync with the // reference host clocks, and returning the new timekeeping parameters. // // Update should be called at approximately ApproxUpdateInterval. Update() (monotonicParams Parameters, monotonicOk bool, realtimeParam Parameters, realtimeOk bool) // GetTime returns the current time in nanoseconds for the given clock. // // Clocks implementations must support at least Monotonic and // Realtime. GetTime(c ClockID) (int64, error) }
Clocks represents a clock source that contains both a monotonic and realtime clock.
type Parameters ¶
type Parameters struct { // BaseCycles was the TSC counter value when the time was BaseRef. BaseCycles TSCValue // BaseRef is the reference clock time in nanoseconds corresponding to // BaseCycles. BaseRef ReferenceNS // Frequency is the frequency of the cycle clock in Hertz. Frequency uint64 }
Parameters are the timekeeping parameters needed to compute the current time.
func SeqAtomicLoadParameters ¶
func SeqAtomicLoadParameters(seq *sync.SeqCount, ptr *Parameters) Parameters
SeqAtomicLoad returns a copy of *ptr, ensuring that the read does not race with any writer critical sections in seq.
func SeqAtomicTryLoadParameters ¶
func SeqAtomicTryLoadParameters(seq *sync.SeqCount, epoch sync.SeqCountEpoch, ptr *Parameters) (val Parameters, ok bool)
SeqAtomicTryLoad returns a copy of *ptr while in a reader critical section in seq initiated by a call to seq.BeginRead() that returned epoch. If the read would race with a writer critical section, SeqAtomicTryLoad returns (unspecified, false).
func (Parameters) ComputeTime ¶
func (p Parameters) ComputeTime(nowCycles TSCValue) (int64, bool)
ComputeTime calculates the current time from a "now" TSC value.
time = ref + (now - base) / f
type ReferenceNS ¶
type ReferenceNS int64
ReferenceNS are nanoseconds in the reference clock domain. int64 gives us ~290 years before this overflows.
func (ReferenceNS) Magnitude ¶
func (r ReferenceNS) Magnitude() ReferenceNS
Magnitude returns the absolute value of r.
type TSCValue ¶
type TSCValue int64
TSCValue is a value from the TSC.
func Rdtsc ¶
func Rdtsc() TSCValue
Rdtsc reads the TSC.
Intel SDM, Vol 3, Ch 17.15: "The RDTSC instruction reads the time-stamp counter and is guaranteed to return a monotonically increasing unique value whenever executed, except for a 64-bit counter wraparound. Intel guarantees that the time-stamp counter will not wraparound within 10 years after being reset."
We use int64, so we have 5 years before wrap-around.