doc: kernel: timeutil: add documentation for timespec apis
Add documentation in the timeutil group for recently added functions
for validating, comparing, and manipulating `struct timespec`
objects as well as functions for converting between representation
of time durations as either `struct timespec` or `k_timeout_t`.
Signed-off-by: Chris Friedt <cfriedt@tenstorrent.com>
@ -28,6 +28,7 @@ The time utilities API supports:
@@ -28,6 +28,7 @@ The time utilities API supports:
* :ref:`converting between time representations <timeutil_repr>`
* :ref:`synchronizing and aligning time scales <timeutil_sync>`
* :ref:`comparing, adding, and subtracting representations <timeutil_manip>`
For terminology and concepts that support these functions see
:ref:`timeutil_concepts`.
@ -65,6 +66,20 @@ The inverse transformation is not standardized: APIs like ``mktime()`` expect
@@ -65,6 +66,20 @@ The inverse transformation is not standardized: APIs like ``mktime()`` expect
information about time zones. Zephyr provides this transformation with
:c:func:`timeutil_timegm` and :c:func:`timeutil_timegm64`.
To convert between ``struct timespec`` and ``k_timeout_t`` durations,
use :c:func:`timespec_to_timeout` and :c:func:`timespec_from_timeout`.
..code-block:: c
k_timeout_t to;
struct timespec ts;
timespec_from_timeout(K_FOREVER, &ts);
to = timespec_to_timeout(&ts); /* to == K_FOREVER */
timespec_from_timeout(K_MSEC(100), &ts);
to = timespec_to_timeout(&ts); /* to == K_MSEC(100) */
It is possible to compare two ``timespec`` objects for equality using :c:func:`timespec_equal`.
..code-block:: c
if (timespec_equal(then, now)) {
/* time is up! */
}
It is possible to compare and fully order (valid) ``timespec`` objects using
:c:func:`timespec_compare`.
..code-block:: c
int cmp = timespec_compare(a, b);
switch (cmp) {
case 0:
/* a == b */
break;
case -1:
/* a < b */
break;
case +1:
/* a > b */
break;
}
It is possible to add, subtract, and negate ``timespec`` objects using
:c:func:`timespec_add`, :c:func:`timespec_sub`, and :c:func:`timespec_negate`,
respectively. Like :c:func:`timespec_normalize`, these functions will output
a normalized ``timespec`` when doing so would not result in overflow.
On success, these functions return ``true``. If overflow would occur, the
functions return ``false``.
..code-block:: c
/* a += b */
if (!timespec_add(&a, &b)) {
/* overflow */
}
/* a -= b */
if (!timespec_sub(&a, &b)) {
/* overflow */
}
/* a = -a */
if (!timespec_negate(&a)) {
/* overflow */
}
..doxygengroup:: timeutil_timespec_apis
.._timeutil_concepts:
Concepts Underlying Time Support in Zephyr
@ -236,3 +335,29 @@ The mechanism used to populate synchronization points is not relevant: it may
@@ -236,3 +335,29 @@ The mechanism used to populate synchronization points is not relevant: it may
involve reading from a local high-precision RTC peripheral, exchanging packets
over a network using a protocol like NTP or PTP, or processing NMEA messages
received a GPS with or without a 1pps signal.
``timespec`` Concepts
=====================
Originally from POSIX, ``struct timespec`` has been a part of the C standard
since C11. The definition of ``struct timespec`` is as shown below.
..code-block:: c
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
.._note:
The C standard does not define the size of ``time_t``. However, Zephyr
uses 64-bits for ``time_t``. The ``long`` type is required to be at least
32-bits, but usually matches the word size of the architecture. Both
elements of ``struct timespec`` are signed integers. ``time_t`` is defined
to be 64-bits both for historical reasons and to be robust enough to
represent times in the future.
The ``tv_nsec`` field is only valid with values in the range ``[0, 999999999]``. The
``tv_sec`` field is the number of seconds since the epoch. If ``struct timespec`` is
used to express a difference, the ``tv_sec`` field may fall into a negative range.