kernel/time/timekeeping.c
Source file repositories/reference/linux-study-clean/kernel/time/timekeeping.c
File Facts
- System
- Linux kernel
- Corpus path
kernel/time/timekeeping.c- Extension
.c- Size
- 96933 bytes
- Lines
- 3352
- Domain
- Core OS
- Bucket
- Scheduler, Processes, Timers, Sync, And Syscalls
- Inferred role
- Core OS: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/audit.hlinux/clocksource.hlinux/compiler.hlinux/jiffies.hlinux/kobject.hlinux/module.hlinux/nmi.hlinux/pvclock_gtod.hlinux/random.hlinux/sched/clock.hlinux/sched/loadavg.hlinux/static_key.hlinux/stop_machine.hlinux/syscore_ops.hlinux/tick.hlinux/time.hlinux/timex.hlinux/timekeeper_internal.hvdso/auxclock.htick-internal.htimekeeping_internal.hntp_internal.hasm/clock_inlined.hposix-timers.h
Detected Declarations
struct tk_datastruct tk_faststruct adjtimex_resultenum timekeeping_adv_modefunction tk_get_aux_ts64function tk_is_auxfunction tk_get_aux_ts64function tk_is_auxfunction tk_update_aux_offsfunction dummy_clock_readfunction tk_aux_setupfunction timekeeper_unlock_irqrestorefunction tk_normalize_xtimefunction tk_xtimefunction tk_xtime_coarsefunction timekeeping_apply_adjustmentfunction tk_set_xtimefunction tk_xtime_addfunction tk_set_wall_to_monofunction tk_update_sleep_timefunction tk_clock_readfunction clocksource_disable_inline_readfunction clocksource_enable_inline_readfunction tk_clock_readfunction clocksource_disable_inline_readfunction delta_to_ns_safefunction timekeeping_cycles_to_nsfunction timekeeping_get_nsfunction timestampfunction __ktime_get_fast_nsfunction ktime_get_mono_fast_nsfunction ktime_get_mono_fast_nsfunction ktime_get_boot_fast_nsfunction ktime_get_boot_fast_nsfunction ktime_get_mono_fast_nsfunction halt_fast_timekeeperfunction update_pvclock_gtodfunction pvclock_gtod_register_notifierfunction pvclock_gtod_unregister_notifierfunction tk_update_leap_statefunction memcpyfunction tk_update_ktime_datafunction tk_update_ns_to_cycfunction timekeeping_restore_shadowfunction timekeeping_update_from_shadowfunction update_wall_timefunction ktime_getfunction timespec64
Annotated Snippet
device_initcall(timekeeping_init_ops);
/*
* Apply a multiplier adjustment to the timekeeper
*/
static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,
s64 offset,
s32 mult_adj)
{
s64 interval = tk->cycle_interval;
if (mult_adj == 0) {
return;
} else if (mult_adj == -1) {
interval = -interval;
offset = -offset;
} else if (mult_adj != 1) {
interval *= mult_adj;
offset *= mult_adj;
}
/*
* So the following can be confusing.
*
* To keep things simple, lets assume mult_adj == 1 for now.
*
* When mult_adj != 1, remember that the interval and offset values
* have been appropriately scaled so the math is the same.
*
* The basic idea here is that we're increasing the multiplier
* by one, this causes the xtime_interval to be incremented by
* one cycle_interval. This is because:
* xtime_interval = cycle_interval * mult
* So if mult is being incremented by one:
* xtime_interval = cycle_interval * (mult + 1)
* Its the same as:
* xtime_interval = (cycle_interval * mult) + cycle_interval
* Which can be shortened to:
* xtime_interval += cycle_interval
*
* So offset stores the non-accumulated cycles. Thus the current
* time (in shifted nanoseconds) is:
* now = (offset * adj) + xtime_nsec
* Now, even though we're adjusting the clock frequency, we have
* to keep time consistent. In other words, we can't jump back
* in time, and we also want to avoid jumping forward in time.
*
* So given the same offset value, we need the time to be the same
* both before and after the freq adjustment.
* now = (offset * adj_1) + xtime_nsec_1
* now = (offset * adj_2) + xtime_nsec_2
* So:
* (offset * adj_1) + xtime_nsec_1 =
* (offset * adj_2) + xtime_nsec_2
* And we know:
* adj_2 = adj_1 + 1
* So:
* (offset * adj_1) + xtime_nsec_1 =
* (offset * (adj_1+1)) + xtime_nsec_2
* (offset * adj_1) + xtime_nsec_1 =
* (offset * adj_1) + offset + xtime_nsec_2
* Canceling the sides:
* xtime_nsec_1 = offset + xtime_nsec_2
* Which gives us:
* xtime_nsec_2 = xtime_nsec_1 - offset
* Which simplifies to:
* xtime_nsec -= offset
*/
if ((mult_adj > 0) && (tk->tkr_mono.mult + mult_adj < mult_adj)) {
/* NTP adjustment caused clocksource mult overflow */
WARN_ON_ONCE(1);
return;
}
tk->tkr_mono.mult += mult_adj;
tk->xtime_interval += interval;
tk->tkr_mono.xtime_nsec -= offset;
}
/*
* Adjust the timekeeper's multiplier to the correct frequency
* and also to reduce the accumulated error value.
*/
static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
{
u64 ntp_tl = ntp_tick_length(tk->id);
u32 mult;
/*
* Determine the multiplier from the current NTP tick length.
Annotation
- Immediate include surface: `linux/audit.h`, `linux/clocksource.h`, `linux/compiler.h`, `linux/jiffies.h`, `linux/kobject.h`, `linux/module.h`, `linux/nmi.h`, `linux/pvclock_gtod.h`.
- Detected declarations: `struct tk_data`, `struct tk_fast`, `struct adjtimex_result`, `enum timekeeping_adv_mode`, `function tk_get_aux_ts64`, `function tk_is_aux`, `function tk_get_aux_ts64`, `function tk_is_aux`, `function tk_update_aux_offs`, `function dummy_clock_read`.
- Atlas domain: Core OS / Scheduler, Processes, Timers, Sync, And Syscalls.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.