@@ -28,6 +28,7 @@ The time utilities API supports:
2828
2929* :ref: `converting between time representations <timeutil_repr >`
3030* :ref: `synchronizing and aligning time scales <timeutil_sync >`
31+ * :ref: `comparing, adding, and subtracting representations <timeutil_manip >`
3132
3233For terminology and concepts that support these functions see
3334:ref: `timeutil_concepts `.
@@ -106,6 +107,90 @@ process:
106107
107108.. doxygengroup :: timeutil_sync_apis
108109
110+ .. _timeutil_manip :
111+
112+ ``timespec `` Manipulation
113+ =========================
114+
115+ Checking the validity of a ``timespec `` can be done with :c:func: `timespec_is_valid `.
116+
117+ .. code-block :: c
118+
119+ struct timespec ts = {
120+ .tv_sec = 0,
121+ .tv_nsec = -1, /* out of range! */
122+ };
123+
124+ if (!timespec_is_valid(&ts)) {
125+ /* error-handing code */
126+ }
127+
128+ In some cases, invalid ``timespec `` objects may be re-normalized using
129+ :c:func: `timespec_normalize `.
130+
131+ .. code-block :: c
132+
133+ if (!timespec_normalize(&ts)) {
134+ /* error-handling code */
135+ }
136+
137+ /* ts should be normalized */
138+ __ASSERT(timespec_is_valid(&ts) == true, "expected normalized timespec");
139+
140+ It is possible to compare two ``timespec `` objects for equality using :c:func: `timespec_equal `.
141+
142+ .. code-block :: c
143+
144+ if (timespec_equal(then, now)) {
145+ /* time is up! */
146+ }
147+
148+ It is possible to compare and fully order (valid) ``timespec `` objects using
149+ :c:func: `timespec_compare `.
150+
151+ .. code-block :: c
152+
153+ int cmp = timespec_compare(a, b);
154+
155+ switch (cmp) {
156+ case 0:
157+ /* a == b */
158+ break;
159+ case -1:
160+ /* a < b */
161+ break;
162+ case +1:
163+ /* a > b */
164+ break;
165+ }
166+
167+ It is possible to add, subtract, and negate ``timespec `` objects using
168+ :c:func: `timespec_add `, :c:func: `timespec_sub `, and :c:func: `timespec_negate `,
169+ respectively. Like :c:func: `timespec_normalize `, these functions will output
170+ a normalized ``timespec `` when doing so would not result in overflow.
171+ On success, these functions return ``true ``. If overflow would occur, the
172+ functions return ``false ``.
173+
174+ .. code-block :: c
175+
176+ /* a += b */
177+ if (!timespec_add(&a, &b)) {
178+ /* overflow */
179+ }
180+
181+ /* a -= b */
182+ if (!timespec_sub(&a, &b)) {
183+ /* overflow */
184+ }
185+
186+ /* a = -a */
187+ if (!timespec_negate(&a)) {
188+ /* overflow */
189+ }
190+
191+ .. doxygengroup :: timeutil_timespec_apis
192+
193+
109194.. _timeutil_concepts :
110195
111196Concepts Underlying Time Support in Zephyr
@@ -236,3 +321,29 @@ The mechanism used to populate synchronization points is not relevant: it may
236321involve reading from a local high-precision RTC peripheral, exchanging packets
237322over a network using a protocol like NTP or PTP, or processing NMEA messages
238323received a GPS with or without a 1pps signal.
324+
325+ ``timespec `` Concepts
326+ =====================
327+
328+ Originally from POSIX, ``struct timespec `` has been a part of the C standard
329+ since C11. The definition of ``struct timespec `` is as shown below.
330+
331+ .. code-block :: c
332+
333+ struct timespec {
334+ time_t tv_sec; /* seconds */
335+ long tv_nsec; /* nanoseconds */
336+ };
337+
338+ .. _note :
339+
340+ The C standard does not define the size of ``time_t ``. However, Zephyr
341+ uses 64-bits for ``time_t ``. The ``long `` type is required to be at least
342+ 32-bits, but usually matches the word size of the architecture. Both
343+ elements of ``struct timespec `` are signed integers. ``time_t `` is defined
344+ to be 64-bits both for historical reasons and to be robust enough to
345+ represent times in the future.
346+
347+ The ``tv_nsec `` field is only valid with values in the range ``[0, 999999999] ``. The
348+ ``tv_sec `` field is the number of seconds since the epoch. If ``struct timespec `` is
349+ used to express a difference, the ``tv_sec `` field may fall into a negative range.
0 commit comments