STRUCT TIMEKEEPER(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’« struct timekeeper(9) πŸ’«

okay so bestie, welcome to the Kernel API Manual β€” we're doing the deep kernel lore today and honestly? it's giving main character energy πŸŽ€


🌸 NAME 🌸

struct timekeeper β€” the structure that holds all the internal timekeeping values. yes. THE timekeeping values. the whole clock vibe lives here πŸ’…


✨ SYNOPSIS ✨

struct timekeeper {
    struct tk_read_base     tkr_mono;
    u64 xtime_sec;
    unsigned long           ktime_sec;
    struct timespec64       wall_to_monotonic;
    ktime_t offs_real;
    ktime_t offs_boot;
    union {
      ktime_t offs_tai;
      ktime_t offs_aux;
    };
    u32 coarse_nsec;
    enum timekeeper_ids     id;
    struct tk_read_base     tkr_raw;
    u64 raw_sec;
    enum clocksource_ids    cs_id;
    u32 cs_ns_to_cyc_mult;
    u32 cs_ns_to_cyc_shift;
    u64 cs_ns_to_cyc_maxns;
    u32 clock_was_set_seq;
    u8 cs_was_changed_seq;
    u8 clock_valid;
    union {
      struct timespec64       monotonic_to_boot;
      struct timespec64       monotonic_to_aux;
    };
    u64 cycle_interval;
    u64 xtime_interval;
    u64 raw_interval;
    ktime_t next_leap_ktime;
    u64 ntp_tick;
    s64 ntp_error;
    u32 ntp_error_shift;
    u32 ntp_err_mult;
    s64 cs_tick_adj;
    u32 skip_second_overflow;
    s64 skew_delta;
    s32 tai_offset;
 };

no cap, that's the whole thing. let's get into it 🫢


πŸ¦‹ Members πŸ¦‹

okay so every single field, one by one, we're not skipping anyone, everyone's invited to the party πŸ’–

  • tkr_mono β€” the readout base structure for CLOCK_MONOTONIC. literally the monochrome clock's whole foundation ✨
  • xtime_sec β€” current CLOCK_REALTIME time, in seconds.
  • ktime_sec β€” current CLOCK_MONOTONIC time, in seconds.
  • wall_to_monotonic β€” the CLOCK_REALTIME to CLOCK_MONOTONIC offset.
  • offs_real β€” offset going from clock monotonic β†’ clock realtime.
  • offs_boot β€” offset going from clock monotonic β†’ clock boottime.
  • {unnamed_union} β€” anonymous. it has no name, it's mysterious, it's that girl πŸ™ˆ
  • offs_tai β€” offset going from clock monotonic β†’ clock tai.
  • offs_aux β€” offset going from clock monotonic β†’ clock AUX.
  • coarse_nsec β€” the nanoseconds part, but for the coarse time getters (the low-effort, high-speed girlies).
  • id β€” the timekeeper ID.
  • tkr_raw β€” the readout base structure for CLOCK_MONOTONIC_RAW.
  • raw_sec β€” CLOCK_MONOTONIC_RAW time, in seconds.
  • cs_id β€” the ID of the current clocksource.
  • cs_ns_to_cyc_mult β€” the multiplicator for nanoseconds to cycles conversion.
  • cs_ns_to_cyc_shift β€” the shift value for nanoseconds to cycles conversion.
  • cs_ns_to_cyc_maxns β€” the maximum nanoseconds to cyles conversion range. (yes, "cyles" β€” that's the original spelling, we don't fix, we respect 😌)
  • clock_was_set_seq β€” the sequence number of clock was set events.
  • cs_was_changed_seq β€” the sequence number of clocksource change events.
  • clock_valid β€” indicator for valid clock.
  • {unnamed_union} β€” anonymous, again. two mysterious unions. iconic behavior πŸ’…
  • monotonic_to_boot β€” CLOCK_MONOTONIC to CLOCK_BOOTTIME offset.
  • monotonic_to_aux β€” CLOCK_MONOTONIC to CLOCK_AUX offset.
  • cycle_interval β€” number of clock cycles in one NTP interval.
  • xtime_interval β€” number of clock shifted nano seconds in one NTP interval.
  • raw_interval β€” shifted raw nano seconds accumulated per NTP interval.
  • next_leap_ktime β€” the CLOCK_MONOTONIC time value of a pending leap-second.
  • ntp_tick β€” the ntp_tick_length value currently being used. this cached copy ensures we consistently apply the tick length for an entire tick, because ntp_tick_length may change mid-tick, and we do NOT want to apply that new value to the tick in progress. fr fr, no mid-tick surprises πŸ”₯
  • ntp_error β€” difference between accumulated time and NTP time, in ntp shifted nano seconds.
  • ntp_error_shift β€” shift conversion between clock shifted nano seconds and ntp shifted nano seconds.
  • ntp_err_mult β€” multiplication factor for scaled math conversion.
  • cs_tick_adj β€” per-second adjustment handed to NTP via ntp_clear accounting for the difference between the nominal NTP interval and the real time taken by the clocksource's integer cycle_interval (upscaled).
  • skip_second_overflow β€” flag used to avoid updating NTP twice with the same second. we love a girl who avoids double-updates πŸ’€
  • tai_offset β€” the current UTC to TAI offset, in seconds.

🧚 Note 🧚

bestie, listen, this part is important so put your phone down for a sec:

for timespec(64) based interfaces, wall_to_monotonic is what we need to add to xtime (or xtime corrected for sub jiffy times) to get to monotonic time. Monotonic is pegged at zero at system boot time, so wall_to_monotonic will be negative β€” however, we will ALWAYS keep the tv_nsec part positive so we can use the usual normalization. periodt ✨

wall_to_monotonic is moved after resume from suspend for the monotonic time not to jump. we need to add total_sleep_time to wall_to_monotonic to get the real boot based time offset.

wall_to_monotonic is no longer the boot time β€” getboottime must be used instead. okay so it's giving deprecated, lowkey. don't come for her, use getboottime πŸ™

monotonic_to_boottime is a timespec64 representation of offs_boot to accelerate the VDSO update for CLOCK_BOOTTIME.

offs_aux is used by the auxiliary timekeepers which do not utilize any of the regular timekeeper offset fields. they're on their own little journey 🌈

monotonic_to_aux is a timespec64 representation of offs_aux to accelerate the VDSO update for CLOCK_AUX.


πŸŽ€ cacheline layout πŸŽ€

the cacheline ordering of the structure is optimized for in kernel usage of the ktime_get and ktime_get_ts64 family of time accessors. struct timekeeper is prepended in the core timekeeping code with a sequence count, which results in the following cacheline layout:

0:   seqcount, tkr_mono 1:   xtime_sec ... id 2:   tkr_raw, raw_sec 3,4:
Internal variables

cacheline 0,1 contain the data which is used for accessing CLOCK_MONOTONIC/REALTIME/BOOTTIME/TAI, while cacheline 2 contains the data for accessing CLOCK_MONOTONIC_RAW. cacheline 3,4 are internal variables which are only accessed during timekeeper updates once per tick. like, they show up once a tick and then leave. mysterious. elusive. main character energy πŸ‘‘


πŸ’œ SEE ALSO πŸ’œ

  • Kernel file ./include/linux/timekeeper_internal.h
  • struct tk_read_base(9)

okay that's the whole page, you ate that, i'm obsessed with you πŸ“

this little transmission came from ./include/linux, dated October 2026, and it's officially signed struct timekeeper(9) β€” stay cunty, stay synchronized πŸ’–

πŸ“¦ where this page comes from