Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e3fd810 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Jonathan Corbet
Browse files

Documentation: document ktime_get_*() APIs

As Dave Chinner points out, we don't have a proper documentation for the
ktime_get() family of interfaces, making it rather unclear which of the
over 30 (!) interfaces one should actually use in a driver or elsewhere
in the kernel.

I wrote up an explanation from how I personally see the interfaces,
documenting what each of the functions do and hopefully making it a bit
clearer which should be used where.

This is the first time I tried writing .rst format documentation, so
in addition to any mistakes in the content, I probably also introduce
nonstandard formatting ;-)

I first tried to add an extra section to
Documentation/timers/timekeeping.txt, but this is currently not included
in the generated API, and it seems useful to have the API docs as part
of what gets generated in
https://www.kernel.org/doc/html/latest/core-api/index.html#core-utilities


instead, so I started a new file there.

I also considered adding the documentation inline in the
include/linux/timekeeping.h header, but couldn't figure out how to do
that in a way that would result both in helpful inline comments as
well as readable html output, so I settled for the latter, with
a small note pointing to it from the header.

Cc: Dave Chinner <david@fromorbit.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Stephen Boyd <sboyd@kernel.org>
Tested-by: default avatarRandy Dunlap <rdunlap@infradead.org>
Reviewed-by: default avatarRandy Dunlap <rdunlap@infradead.org>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarJonathan Corbet <corbet@lwn.net>
parent 6b4c1360
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ Core utilities
   printk-formats
   circular-buffers
   gfp_mask-from-fs-io
   timekeeping

Interfaces for kernel debugging
===============================
+185 −0
Original line number Diff line number Diff line
ktime accessors
===============

Device drivers can read the current time using ktime_get() and the many
related functions declared in linux/timekeeping.h. As a rule of thumb,
using an accessor with a shorter name is preferred over one with a longer
name if both are equally fit for a particular use case.

Basic ktime_t based interfaces
------------------------------

The recommended simplest form returns an opaque ktime_t, with variants
that return time for different clock references:


.. c:function:: ktime_t ktime_get( void )

	CLOCK_MONOTONIC

	Useful for reliable timestamps and measuring short time intervals
	accurately. Starts at system boot time but stops during suspend.

.. c:function:: ktime_t ktime_get_boottime( void )

	CLOCK_BOOTTIME

	Like ktime_get(), but does not stop when suspended. This can be
	used e.g. for key expiration times that need to be synchronized
	with other machines across a suspend operation.

.. c:function:: ktime_t ktime_get_real( void )

	CLOCK_REALTIME

	Returns the time in relative to the UNIX epoch starting in 1970
	using the Coordinated Universal Time (UTC), same as gettimeofday()
	user space. This is used for all timestamps that need to
	persist across a reboot, like inode times, but should be avoided
	for internal uses, since it can jump backwards due to a leap
	second update, NTP adjustment settimeofday() operation from user
	space.

.. c:function:: ktime_t ktime_get_clocktai( void )

	 CLOCK_TAI

	Like ktime_get_real(), but uses the International Atomic Time (TAI)
	reference instead of UTC to avoid jumping on leap second updates.
	This is rarely useful in the kernel.

.. c:function:: ktime_t ktime_get_raw( void )

	CLOCK_MONOTONIC_RAW

	Like ktime_get(), but runs at the same rate as the hardware
	clocksource without (NTP) adjustments for clock drift. This is
	also rarely needed in the kernel.

nanosecond, timespec64, and second output
-----------------------------------------

For all of the above, there are variants that return the time in a
different format depending on what is required by the user:

.. c:function:: u64 ktime_get_ns( void )
		u64 ktime_get_boottime_ns( void )
		u64 ktime_get_real_ns( void )
		u64 ktime_get_tai_ns( void )
		u64 ktime_get_raw_ns( void )

	Same as the plain ktime_get functions, but returning a u64 number
	of nanoseconds in the respective time reference, which may be
	more convenient for some callers.

.. c:function:: void ktime_get_ts64( struct timespec64 * )
		void ktime_get_boottime_ts64( struct timespec64 * )
		void ktime_get_real_ts64( struct timespec64 * )
		void ktime_get_clocktai_ts64( struct timespec64 * )
		void ktime_get_raw_ts64( struct timespec64 * )

	Same above, but returns the time in a 'struct timespec64', split
	into seconds and nanoseconds. This can avoid an extra division
	when printing the time, or when passing it into an external
	interface that expects a 'timespec' or 'timeval' structure.

.. c:function:: time64_t ktime_get_seconds( void )
		time64_t ktime_get_boottime_seconds( void )
		time64_t ktime_get_real_seconds( void )
		time64_t ktime_get_clocktai_seconds( void )
		time64_t ktime_get_raw_seconds( void )

	Return a coarse-grained version of the time as a scalar
	time64_t. This avoids accessing the clock hardware and rounds
	down the seconds to the full seconds of the last timer tick
	using the respective reference.

Coarse and fast_ns access
-------------------------

Some additional variants exist for more specialized cases:

.. c:function:: ktime_t ktime_get_coarse_boottime( void )
		ktime_t ktime_get_coarse_real( void )
		ktime_t ktime_get_coarse_clocktai( void )
		ktime_t ktime_get_coarse_raw( void )

.. c:function:: void ktime_get_coarse_ts64( struct timespec64 * )
		void ktime_get_coarse_boottime_ts64( struct timespec64 * )
		void ktime_get_coarse_real_ts64( struct timespec64 * )
		void ktime_get_coarse_clocktai_ts64( struct timespec64 * )
		void ktime_get_coarse_raw_ts64( struct timespec64 * )

	These are quicker than the non-coarse versions, but less accurate,
	corresponding to CLOCK_MONONOTNIC_COARSE and CLOCK_REALTIME_COARSE
	in user space, along with the equivalent boottime/tai/raw
	timebase not available in user space.

	The time returned here corresponds to the last timer tick, which
	may be as much as 10ms in the past (for CONFIG_HZ=100), same as
	reading the 'jiffies' variable.  These are only useful when called
	in a fast path and one still expects better than second accuracy,
	but can't easily use 'jiffies', e.g. for inode timestamps.
	Skipping the hardware clock access saves around 100 CPU cycles
	on most modern machines with a reliable cycle counter, but
	up to several microseconds on older hardware with an external
	clocksource.

.. c:function:: u64 ktime_get_mono_fast_ns( void )
		u64 ktime_get_raw_fast_ns( void )
		u64 ktime_get_boot_fast_ns( void )
		u64 ktime_get_real_fast_ns( void )

	These variants are safe to call from any context, including from
	a non-maskable interrupt (NMI) during a timekeeper update, and
	while we are entering suspend with the clocksource powered down.
	This is useful in some tracing or debugging code as well as
	machine check reporting, but most drivers should never call them,
	since the time is allowed to jump under certain conditions.

Deprecated time interfaces
--------------------------

Older kernels used some other interfaces that are now being phased out
but may appear in third-party drivers being ported here. In particular,
all interfaces returning a 'struct timeval' or 'struct timespec' have
been replaced because the tv_sec member overflows in year 2038 on 32-bit
architectures. These are the recommended replacements:

.. c:function:: void ktime_get_ts( struct timespec * )

	Use ktime_get() or ktime_get_ts64() instead.

.. c:function:: struct timeval do_gettimeofday( void )
		struct timespec getnstimeofday( void )
		struct timespec64 getnstimeofday64( void )
		void ktime_get_real_ts( struct timespec * )

	ktime_get_real_ts64() is a direct replacement, but consider using
	monotonic time (ktime_get_ts64()) and/or a ktime_t based interface
	(ktime_get()/ktime_get_real()).

.. c:function:: struct timespec current_kernel_time( void )
		struct timespec64 current_kernel_time64( void )
		struct timespec get_monotonic_coarse( void )
		struct timespec64 get_monotonic_coarse64( void )

	These are replaced by ktime_get_coarse_real_ts64() and
	ktime_get_coarse_ts64(). However, A lot of code that wants
	coarse-grained times can use the simple 'jiffies' instead, while
	some drivers may actually want the higher resolution accessors
	these days.

.. c:function:: struct timespec getrawmonotonic( void )
		struct timespec64 getrawmonotonic64( void )
		struct timespec timekeeping_clocktai( void )
		struct timespec64 timekeeping_clocktai64( void )
		struct timespec get_monotonic_boottime( void )
		struct timespec64 get_monotonic_boottime64( void )

	These are replaced by ktime_get_raw()/ktime_get_raw_ts64(),
	ktime_get_clocktai()/ktime_get_clocktai_ts64() as well
	as ktime_get_boottime()/ktime_get_boottime_ts64().
	However, if the particular choice of clock source is not
	important for the user, consider converting to
	ktime_get()/ktime_get_ts64() instead for consistency.
+15 −0
Original line number Diff line number Diff line
@@ -20,6 +20,21 @@ extern int do_settimeofday64(const struct timespec64 *ts);
extern int do_sys_settimeofday64(const struct timespec64 *tv,
				 const struct timezone *tz);

/*
 * ktime_get() family: read the current time in a multitude of ways,
 *
 * The default time reference is CLOCK_MONOTONIC, starting at
 * boot time but not counting the time spent in suspend.
 * For other references, use the functions with "real", "clocktai",
 * "boottime" and "raw" suffixes.
 *
 * To get the time in a different format, use the ones wit
 * "ns", "ts64" and "seconds" suffix.
 *
 * See Documentation/core-api/timekeeping.rst for more details.
 */


/*
 * timespec64 based interfaces
 */