FastMM documentation
FastMM C++ API 0.6.0
Public headers, tier 1 and tier 2
Loading...
Searching...
No Matches
fastmm::TscClock Class Reference

Periodic recalibration (see docs/explanation/architecture.md, "Clock calibration"): a calibrator thread measures with calibrate_tsc() and publishes into a Seqlocked<TscCalibration>; every TscClock user keeps its own copy and calls refresh() from its loop. More...

#include <fastmm/core/time.hpp>

Public Member Functions

 TscClock () noexcept=default
 
 TscClock (const TscCalibration &c) noexcept
 
void calibrate (Duration window=milliseconds(50)) noexcept
 Blocking; call once at startup, before the clock is shared with another thread.
 
void set_calibration (const TscCalibration &c) noexcept
 
const TscCalibration & calibration () const noexcept
 
void attach_calibration_source (const Seqlocked< TscCalibration > *src, Duration step_threshold=kDefaultStepThreshold, Duration slew_horizon=kDefaultSlewHorizon) noexcept
 Subscribes to published calibrations.
 
const Seqlocked< TscCalibration > * calibration_source () const noexcept
 
FASTMM_FORCE_INLINE TscRefresh refresh () noexcept
 Cheap when nothing changed (one atomic load); copies and re-anchors on a new version.
 
TscRefresh reanchor (const TscCalibration &fresh, Cycles at) noexcept
 Switches to fresh at TSC reading at (refresh() passes rdtsc()).
 
std::uint64_t steps () const noexcept
 Diagnostics (owner thread, or after the owner stopped).
 
std::uint64_t reanchors () const noexcept
 
std::int64_t last_offset_ns () const noexcept
 fresh - old at the last re-anchor or step, in ns.
 
Duration step_threshold () const noexcept
 
Duration slew_horizon () const noexcept
 
std::int64_t slew_ppb () const noexcept
 Rate correction applied at the last re-anchor, in parts per billion of the fresh rate.
 
FASTMM_FORCE_INLINE Timestamp now () const noexcept
 
FASTMM_FORCE_INLINE Cycles cycles () const noexcept
 TSC cycles whenever the rate is known (also without an invariant TSC), so that they share a time base with the network threads' rdtscp stamps; wall ns without a rate.
 
FASTMM_FORCE_INLINE Timestamp to_timestamp (Cycles c) const noexcept
 
FASTMM_FORCE_INLINE std::int64_t cycles_to_ns (std::uint64_t dc) const noexcept
 

Static Public Attributes

static constexpr Duration kDefaultStepThreshold = milliseconds(1)
 
static constexpr Duration kDefaultSlewHorizon = seconds(10)
 
static constexpr std::int64_t kMaxSlewPpm = 500
 Upper bound on the rate adjustment used to absorb an offset (a clock servo, not a jump).
 

Detailed Description

Periodic recalibration (see docs/explanation/architecture.md, "Clock calibration"): a calibrator thread measures with calibrate_tsc() and publishes into a Seqlocked<TscCalibration>; every TscClock user keeps its own copy and calls refresh() from its loop.

A clock is owned by one thread: refresh() and the time accessors must not race.

Constructor & Destructor Documentation

◆ TscClock() [1/2]

fastmm::TscClock::TscClock ( )
defaultnoexcept

◆ TscClock() [2/2]

fastmm::TscClock::TscClock ( const TscCalibration &  c)
inlineexplicitnoexcept

Member Function Documentation

◆ calibrate()

void fastmm::TscClock::calibrate ( Duration  window = milliseconds(50))
inlinenoexcept

Blocking; call once at startup, before the clock is shared with another thread.

◆ set_calibration()

void fastmm::TscClock::set_calibration ( const TscCalibration &  c)
inlinenoexcept

◆ calibration()

const TscCalibration & fastmm::TscClock::calibration ( ) const
inlinenoexcept

◆ attach_calibration_source()

void fastmm::TscClock::attach_calibration_source ( const Seqlocked< TscCalibration > *  src,
Duration  step_threshold = kDefaultStepThreshold,
Duration  slew_horizon = kDefaultSlewHorizon 
)
inlinenoexcept

Subscribes to published calibrations.

The next refresh() takes whatever is published (even the version that was current at attach time); after that only new versions. slew_horizon should match the calibrator's period: each re-anchor absorbs the measured offset over that horizon (see reanchor()); zero disables slewing.

◆ calibration_source()

const Seqlocked< TscCalibration > * fastmm::TscClock::calibration_source ( ) const
inlinenoexcept

◆ refresh()

FASTMM_FORCE_INLINE TscRefresh fastmm::TscClock::refresh ( )
inlinenoexcept

Cheap when nothing changed (one atomic load); copies and re-anchors on a new version.

A write in progress is skipped and picked up by a later call.

◆ reanchor()

TscRefresh fastmm::TscClock::reanchor ( const TscCalibration &  fresh,
Cycles  at 
)
inlinenoexcept

Switches to fresh at TSC reading at (refresh() passes rdtsc()).

If both mappings use the TSC and agree at at within the step threshold, the clock re-anchors at the old mapping's time for at, so time never jumps, and runs at the fresh rate plus a bounded correction that absorbs the measured offset over the slew horizon: offset * rate / horizon, so after horizon ns the mapping agrees with fresh (clamped to kMaxSlewPpm). Without the correction the offset would accumulate across re-anchors until it forced a step. If the offset exceeds the threshold the clock steps to fresh instead.

◆ steps()

std::uint64_t fastmm::TscClock::steps ( ) const
inlinenoexcept

Diagnostics (owner thread, or after the owner stopped).

◆ reanchors()

std::uint64_t fastmm::TscClock::reanchors ( ) const
inlinenoexcept

◆ last_offset_ns()

std::int64_t fastmm::TscClock::last_offset_ns ( ) const
inlinenoexcept

fresh - old at the last re-anchor or step, in ns.

◆ step_threshold()

Duration fastmm::TscClock::step_threshold ( ) const
inlinenoexcept

◆ slew_horizon()

Duration fastmm::TscClock::slew_horizon ( ) const
inlinenoexcept

◆ slew_ppb()

std::int64_t fastmm::TscClock::slew_ppb ( ) const
inlinenoexcept

Rate correction applied at the last re-anchor, in parts per billion of the fresh rate.

◆ now()

FASTMM_FORCE_INLINE Timestamp fastmm::TscClock::now ( ) const
inlinenoexcept

◆ cycles()

FASTMM_FORCE_INLINE Cycles fastmm::TscClock::cycles ( ) const
inlinenoexcept

TSC cycles whenever the rate is known (also without an invariant TSC), so that they share a time base with the network threads' rdtscp stamps; wall ns without a rate.

◆ to_timestamp()

FASTMM_FORCE_INLINE Timestamp fastmm::TscClock::to_timestamp ( Cycles  c) const
inlinenoexcept

◆ cycles_to_ns()

FASTMM_FORCE_INLINE std::int64_t fastmm::TscClock::cycles_to_ns ( std::uint64_t  dc) const
inlinenoexcept

Member Data Documentation

◆ kDefaultStepThreshold

constexpr Duration fastmm::TscClock::kDefaultStepThreshold = milliseconds(1)
staticconstexpr

◆ kDefaultSlewHorizon

constexpr Duration fastmm::TscClock::kDefaultSlewHorizon = seconds(10)
staticconstexpr

◆ kMaxSlewPpm

constexpr std::int64_t fastmm::TscClock::kMaxSlewPpm = 500
staticconstexpr

Upper bound on the rate adjustment used to absorb an offset (a clock servo, not a jump).