Skip to content

Commit eba3022

Browse files
author
Thomas Gleixner
committed
timekeeping: Provide ktime_get_snapshot_id()
ktime_get_snapshot() provides a snapshot of the underlying clocksource counter value and the corresponding CLOCK_MONOTONIC_RAW, CLOCK_REALTIME and CLOCK_BOOTTIME timestamps. There is no usage of CLOCK_REALTIME and CLOCK_BOOTTIME at the same time and CLOCK_BOOTTIME support was just added for the ARM64 KVM tracing mechanism, which needs CLOCK_BOOTTIME and the underlying clocksource counter value. ktime_get_snapshot() is also not suitable for usage with CLOCK_AUX, but that's a prerequisite to support PTP hardware timestamping for CLOCK_AUX steering. As a first step, rename ktime_get_snapshot() to ktime_get_snapshot_id(), which now takes a clockid argument to select the clock which needs to be captured. The result is stored in system_time_snapshot::systime, which will replace the system_time_snapshot::real/boot members once all usage sites have been converted. ktime_get_snapshot() is a simple wrapper which hands in CLOCK_REALTIME as clockid argument for the conversion period. That means CLOCK_REALTIME is now captured twice, but that redunancy is only temporary. As all usage sites of struct system_time_snapshot has to be updated anyway, rename the 'raw' member to 'monoraw' for clarity. No functional change vs. current users of ktime_get_snapshot() Signed-off-by: Thomas Gleixner <tglx@kernel.org> Tested-by: David Woodhouse <dwmw@amazon.co.uk> Tested-by: Arthur Kiyanovski <akiyano@amazon.com> Reviewed-by: David Woodhouse <dwmw@amazon.co.uk> Reviewed-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de> Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> Link: https://patch.msgid.link/20260529195556.971591633@kernel.org
1 parent 7fd2df2 commit eba3022

2 files changed

Lines changed: 90 additions & 33 deletions

File tree

include/linux/timekeeping.h

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -276,24 +276,32 @@ static inline bool ktime_get_aux_ts64(clockid_t id, struct timespec64 *kt) { ret
276276
#endif
277277

278278
/**
279-
* struct system_time_snapshot - simultaneous raw/real time capture with
280-
* counter value
281-
* @cycles: Clocksource counter value to produce the system times
282-
* @real: Realtime system time
283-
* @boot: Boot time
284-
* @raw: Monotonic raw system time
285-
* @cs_id: Clocksource ID
279+
* struct system_time_snapshot - Simultaneous time capture of CLOCK_MONOTONIC_RAW,
280+
* a selected CLOCK_* and the clocksource counter value
281+
* @cycles: Clocksource counter value to produce the system times
282+
* @systime: The system time of the selected CLOCK ID
283+
* @real: Realtime system time
284+
* @boot: Boot time
285+
* @raw: Monotonic raw system time
286+
* @monoraw: Monotonic raw system time
287+
* @cs_id: Clocksource ID
286288
* @clock_was_set_seq: The sequence number of clock-was-set events
287289
* @cs_was_changed_seq: The sequence number of clocksource change events
290+
* @valid: True if the snapshot is valid
288291
*/
289292
struct system_time_snapshot {
290293
u64 cycles;
294+
ktime_t systime;
291295
ktime_t real;
292296
ktime_t boot;
293-
ktime_t raw;
297+
union {
298+
ktime_t raw;
299+
ktime_t monoraw;
300+
};
294301
enum clocksource_ids cs_id;
295302
unsigned int clock_was_set_seq;
296303
u8 cs_was_changed_seq;
304+
u8 valid;
297305
};
298306

299307
/**
@@ -341,9 +349,15 @@ extern int get_device_system_crosststamp(
341349
struct system_device_crosststamp *xtstamp);
342350

343351
/*
344-
* Simultaneously snapshot realtime and monotonic raw clocks
352+
* Simultaneously snapshot a given clock with MONOTONIC_RAW and the underlying
353+
* clocksource counter value.
345354
*/
346-
extern void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot);
355+
extern void ktime_get_snapshot_id(clockid_t clock_id, struct system_time_snapshot *systime_snapshot);
356+
357+
static inline void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot)
358+
{
359+
ktime_get_snapshot_id(CLOCK_REALTIME, systime_snapshot);
360+
}
347361

348362
/*
349363
* Persistent clock related interfaces

kernel/time/timekeeping.c

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,43 +1183,86 @@ noinstr time64_t __ktime_get_real_seconds(void)
11831183
}
11841184

11851185
/**
1186-
* ktime_get_snapshot - snapshots the realtime/monotonic raw clocks with counter
1187-
* @systime_snapshot: pointer to struct receiving the system time snapshot
1188-
*/
1189-
void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot)
1190-
{
1191-
struct timekeeper *tk = &tk_core.timekeeper;
1186+
* ktime_get_snapshot_id - Simultaneously snapshot a given clock ID with
1187+
* CLOCK_MONOTONIC_RAW and the underlying
1188+
* clocksource counter value.
1189+
* @clock_id: The clock ID to snapshot
1190+
* @systime_snapshot: Pointer to struct receiving the system time snapshot
1191+
*/
1192+
void ktime_get_snapshot_id(clockid_t clock_id, struct system_time_snapshot *systime_snapshot)
1193+
{
1194+
ktime_t base_raw, base_sys, offs_sys, *offs, offs_zero = 0;
1195+
u64 nsec_raw, nsec_sys, now;
1196+
struct timekeeper *tk;
1197+
struct tk_data *tkd;
11921198
unsigned int seq;
1193-
ktime_t base_raw;
11941199
ktime_t base_real;
11951200
ktime_t base_boot;
1196-
u64 nsec_raw;
1197-
u64 nsec_real;
1198-
u64 now;
11991201

1200-
WARN_ON_ONCE(timekeeping_suspended);
1202+
/* Invalidate the snapshot for all failure cases */
1203+
systime_snapshot->valid = false;
1204+
1205+
if (WARN_ON_ONCE(timekeeping_suspended))
1206+
return;
1207+
1208+
switch (clock_id) {
1209+
case CLOCK_REALTIME:
1210+
tkd = &tk_core;
1211+
offs = &tk_core.timekeeper.offs_real;
1212+
break;
1213+
/* Map RAW to MONOTONIC so the loop below is trivial */
1214+
case CLOCK_MONOTONIC_RAW:
1215+
case CLOCK_MONOTONIC:
1216+
tkd = &tk_core;
1217+
offs = &offs_zero;
1218+
break;
1219+
case CLOCK_BOOTTIME:
1220+
tkd = &tk_core;
1221+
offs = &tk_core.timekeeper.offs_boot;
1222+
break;
1223+
default:
1224+
WARN_ON_ONCE(1);
1225+
return;
1226+
}
1227+
1228+
tk = &tkd->timekeeper;
12011229

12021230
do {
1203-
seq = read_seqcount_begin(&tk_core.seq);
1231+
seq = read_seqcount_begin(&tkd->seq);
1232+
12041233
now = tk_clock_read(&tk->tkr_mono);
12051234
systime_snapshot->cs_id = tk->tkr_mono.clock->id;
12061235
systime_snapshot->cs_was_changed_seq = tk->cs_was_changed_seq;
12071236
systime_snapshot->clock_was_set_seq = tk->clock_was_set_seq;
1208-
base_real = ktime_add(tk->tkr_mono.base,
1209-
tk_core.timekeeper.offs_real);
1210-
base_boot = ktime_add(tk->tkr_mono.base,
1211-
tk_core.timekeeper.offs_boot);
1237+
1238+
base_sys = tk->tkr_mono.base;
1239+
offs_sys = *offs;
12121240
base_raw = tk->tkr_raw.base;
1213-
nsec_real = timekeeping_cycles_to_ns(&tk->tkr_mono, now);
1214-
nsec_raw = timekeeping_cycles_to_ns(&tk->tkr_raw, now);
1215-
} while (read_seqcount_retry(&tk_core.seq, seq));
1241+
1242+
/* Kept around until the callers are fixed up */
1243+
base_real = ktime_add(base_sys, tk_core.timekeeper.offs_real);
1244+
base_boot = ktime_add(base_sys, tk_core.timekeeper.offs_boot);
1245+
1246+
nsec_sys = timekeeping_cycles_to_ns(&tk->tkr_mono, now);
1247+
nsec_raw = timekeeping_cycles_to_ns(&tk->tkr_raw, now);
1248+
} while (read_seqcount_retry(&tkd->seq, seq));
12161249

12171250
systime_snapshot->cycles = now;
1218-
systime_snapshot->real = ktime_add_ns(base_real, nsec_real);
1219-
systime_snapshot->boot = ktime_add_ns(base_boot, nsec_real);
1220-
systime_snapshot->raw = ktime_add_ns(base_raw, nsec_raw);
1251+
systime_snapshot->systime = ktime_add_ns(base_sys, offs_sys + nsec_sys);
1252+
systime_snapshot->real = ktime_add_ns(base_real, nsec_sys);
1253+
systime_snapshot->boot = ktime_add_ns(base_boot, nsec_sys);
1254+
systime_snapshot->monoraw = ktime_add_ns(base_raw, nsec_raw);
1255+
1256+
/*
1257+
* Special case for PTP. Just transfer the raw time into sys,
1258+
* so the call sites can consistently use snap::systime.
1259+
*/
1260+
if (clock_id == CLOCK_MONOTONIC_RAW)
1261+
systime_snapshot->systime = systime_snapshot->monoraw;
1262+
/* Tell the consumer that this snapshot is valid */
1263+
systime_snapshot->valid = true;
12211264
}
1222-
EXPORT_SYMBOL_GPL(ktime_get_snapshot);
1265+
EXPORT_SYMBOL_GPL(ktime_get_snapshot_id);
12231266

12241267
/* Scale base by mult/div checking for overflow */
12251268
static int scale64_check_overflow(u64 mult, u64 div, u64 *base)

0 commit comments

Comments
 (0)