-
Notifications
You must be signed in to change notification settings - Fork 6.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
kernel: introduce scalar nanosecond time representation
Introduces a well-defined intermediate concept of scalar nanosecond resolution time with overflow protection above low-level counters/cycles/ticks and below higher level time abstractions (timescales, calenders, etc.). See #19030 (comment) for its embedding in a larger clock subsystem architecture relevant to the network stack, IEEE 802.15.4 and the POSIX roadmap. The rationale of this type has been extensively documented and contrasted to already existing time representations to ensure that it fills a well defined gap without overlap. This change prepares for an upcoming change set that will unify the usage of time across the network subsystem (RX/TX timestamps, timed TX, CSL, scheduled reception windows, (g)PTP integration, etc.). Signed-off-by: Florian Grandel <[email protected]>
- Loading branch information
Showing
2 changed files
with
139 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
/* | ||
* Copyright (c) 2023 Zephyr Project | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/** | ||
* @file | ||
* @brief Representation and conversion of nanosecond resolution time and | ||
* timestamps. | ||
* | ||
* Declare types and utilities to represent high resolution time and timers used | ||
* by the kernel as well as by applications. | ||
* | ||
* Inspired by | ||
* https://github.com/torvalds/linux/blob/master/include/linux/ktime.h and | ||
* https://github.com/torvalds/linux/blob/master/[tools/]include/linux/time64.h | ||
*/ | ||
|
||
#ifndef ZEPHYR_INCLUDE_SYS_KTIME_H_ | ||
#define ZEPHYR_INCLUDE_SYS_KTIME_H_ | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** @cond INTERNAL_HIDDEN */ | ||
|
||
/* number of nsec per usec */ | ||
#define NSEC_PER_USEC 1000U | ||
|
||
/* number of nsec per msec */ | ||
#define NSEC_PER_MSEC 1000000U | ||
|
||
/* number of microseconds per millisecond */ | ||
#define USEC_PER_MSEC 1000U | ||
|
||
/* number of milliseconds per second */ | ||
#define MSEC_PER_SEC 1000U | ||
|
||
/* number of microseconds per second */ | ||
#define USEC_PER_SEC ((USEC_PER_MSEC) * (MSEC_PER_SEC)) | ||
|
||
/* number of nanoseconds per second */ | ||
#define NSEC_PER_SEC ((NSEC_PER_USEC) * (USEC_PER_MSEC) * (MSEC_PER_SEC)) | ||
|
||
/** @endcond */ | ||
|
||
/** | ||
* @defgroup timeutil_ktime_apis Scalar Nanosecond Time Representation APIs | ||
* @ingroup timeutil_apis | ||
* @{ | ||
*/ | ||
|
||
/** | ||
* @brief Any occurrence of ktime_t specifies a well defined concept of | ||
* nanosecond resolution scalar time span, future (positive) or past (negative) | ||
* relative time or absolute timestamp referred to some local nanosecond clock | ||
* that does not wrap during uptime. | ||
* | ||
* @details This concept is strictly reserved for low-level scalar nanosecond | ||
* resolution time representation. | ||
* | ||
* ktime_t cannot represent general clocks referred to an arbitrary epoch as it | ||
* only covers roughly +/- ~290 years. It also cannot be used to represent time | ||
* according to a more complex timescale (e.g. including leap seconds, time | ||
* adjustments, complex calendars or time zones). In these cases you may use | ||
* @ref timespec (C11, POSIX.1-2001), @ref timeval (POSIX.1-2001) or broken down | ||
* time as in @ref tm (C90). The advantage of ktime_t over these structured time | ||
* representations is lower memory footprint, faster and simpler scalar | ||
* arithmetics and easier conversion from/to low-level hardware counter values. | ||
* Also ktime_t can be used in the kernel as well as in applications while POSIX | ||
* concepts cannot. Converting ktime_t from/to structured time representations | ||
* is possible in a limited way but - except for @ref timespec - requires | ||
* concepts that must be implemented by higher-level APIs. Utility functions | ||
* converting from to @ref timespec are provided as part of the ktime_t API as | ||
* and when needed. | ||
* | ||
* If you want to represent more coarse grained scalar time, use @ref time_t | ||
* (C99, POSIX.1-2001) which is specified to represent seconds or | ||
* @ref suseconds_t (POSIX.1-2001) for microsecond resolution. Kernel | ||
* @ref k_ticks_t and cycles (both specific to Zephyr) have an unspecified | ||
* resolution but are useful to represent kernel timer values and high | ||
* resolution spinning. The advantage of ktime_t over these alternative scalar | ||
* time representations in certain applications is obviously its higher and/or | ||
* well-defined resolution. Any of these concepts can easily be converted | ||
* from/to ktime_t as long as the values are within ktime_t's range. Utility | ||
* functions for such conversions are provided as part of the ktime_t API as and | ||
* when needed. | ||
* | ||
* If you need even finer grained time resolution, you may want to look at | ||
* (g)PTP concepts, see @ref net_ptp_extended_time. | ||
* | ||
* A prototypical application of ktime_t would be to represent a monotonic, | ||
* continuous low level clock source with well defined resolution and overflow | ||
* protection above a potentially overflowing raw counter (e.g. a counter.h | ||
* compatible driver or kernel ticks/cycles) and below high level (e.g. POSIX) | ||
* clock, timescale or calendar representations. Another typical application is | ||
* for high resolution timers or representation of relatively short high | ||
* resolution time spans. | ||
* | ||
* The reason why we don't use int64_t directly to represent nanosecond | ||
* resolution times is that it has been shown in the past that fields using this | ||
* type will often not be used correctly (e.g. with the wrong resolution or to | ||
* represent underspecified timestamp concepts with unclear semantics). | ||
* | ||
* Any API that exposes or consumes ktime_t values SHALL ensure that it | ||
* maintains the specified contract and therefore clients can rely on common | ||
* semantics of this type. This makes times coming from different hardware | ||
* peripherals, clock sources and timer implementations comparable and therefore | ||
* ktime_t is the ideal intermediate building block for higher-level time | ||
* concepts. | ||
*/ | ||
typedef int64_t ktime_t; | ||
|
||
/** The largest positive time value that can be represented by ktime_t */ | ||
#define KTIME_MAX INT64_MAX | ||
|
||
/** The smallest negative time value that can be represented by ktime_t */ | ||
#define KTIME_MIN INT64_MIN | ||
|
||
/** The largest positive number of seconds that can be safely represented by ktime_t */ | ||
#define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) | ||
|
||
/** The smallest negative number of seconds that can be safely represented by ktime_t */ | ||
#define KTIME_SEC_MIN (KTIME_MIN / NSEC_PER_SEC) | ||
|
||
/* TODO: define conversion utilities as required in practice */ | ||
|
||
/** | ||
* @} | ||
*/ | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif /* ZEPHYR_INCLUDE_SYS_KTIME_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters