Skip to content

Commit fcaf775

Browse files
committed
sys: clock: additional constants and macros for timespec conversion
Define additional constants and macros for converting between timespec objects and k_timeout_t. There are four semantically important durations identified with new constants identified via '. 1. K_NO_WAIT / K_TS_NO_WAIT' * duration of zero 2. K_TICK_MIN' / K_TS_MIN' * minimum number of ticks strictly greater than K_NO_WAIT 3. K_TICK_MAX' / K_TS_MAX' * maximum number of ticks strictly and semantically less than K_FOREVER 4. K_FOREVER / K_TS_FOREVER' * the familiar non-expiring number of ticks (i.e. infinity) With these definitions, there are 3 meaningful regions for conversion between timespec and k_timeout_t representation: 1. < K_TS_NO_WAIT (i.e. a negative timespec) * should be rounded up to K_TS_NO_WAIT * < K_NO_WAIT in ticks is an absolute time point in 64-bit representation should no be permitted in the affected conversion routines, as they are explicitly for converting time durations rather than absolute time points. 2. K_TS_NO_WAIT < x < K_TS_MAX * should be rounded-up to the next tick boundary * must be represented as the minimal non-zero duration in ticks 3. K_TS_MAX <= x < K_TS_FOREVER * must be represented as the maximum expiring duration in ticks * should be rounded-down to K_TS_MAX Signed-off-by: Chris Friedt <cfriedt@tenstorrent.com>
1 parent 970c715 commit fcaf775

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

include/zephyr/sys/clock.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,49 @@ typedef struct {
166166
/* added tick needed to account for tick in progress */
167167
#define _TICK_ALIGN 1
168168

169+
/* Maximum and minimum value TIME_T can hold (accounting for 32-bit time_t in glibc.h) */
170+
#define SYS_TIME_T_MAX ((((time_t)1 << (8 * sizeof(time_t) - 2)) - 1) * 2 + 1)
171+
#define SYS_TIME_T_MIN (-SYS_TIME_T_MAX - 1)
172+
173+
/* Converts ticks to seconds, discarding any fractional seconds */
174+
#define K_TICKS_TO_SECS(ticks) \
175+
(((uint64_t)(ticks) >= (uint64_t)K_TICKS_FOREVER) ? SYS_TIME_T_MAX \
176+
: k_ticks_to_sec_floor64(ticks))
177+
178+
/* Converts ticks to nanoseconds, modulo NSEC_PER_SEC */
179+
#define K_TICKS_TO_NSECS(ticks) \
180+
(((uint64_t)(ticks) >= (uint64_t)K_TICKS_FOREVER) \
181+
? (NSEC_PER_SEC - 1) \
182+
: k_ticks_to_ns_floor32((uint64_t)(ticks) % CONFIG_SYS_CLOCK_TICKS_PER_SEC))
183+
184+
/* Define a timespec */
185+
#define K_TIMESPEC(sec, nsec) \
186+
((struct timespec){ \
187+
.tv_sec = (time_t)(sec), \
188+
.tv_nsec = (long)(nsec), \
189+
})
190+
191+
/* Initialize a struct timespec object from a tick count */
192+
#define K_TICKS_TO_TIMESPEC(ticks) K_TIMESPEC(K_TICKS_TO_SECS(ticks), K_TICKS_TO_NSECS(ticks))
193+
194+
/* The minimum duration in ticks strictly greater than that of K_NO_WAIT */
195+
#define K_TICK_MIN ((k_ticks_t)1)
196+
197+
/* The maximum duration in ticks strictly and semantically "less than" K_FOREVER */
198+
#define K_TICK_MAX ((k_ticks_t)(IS_ENABLED(CONFIG_TIMEOUT_64BIT) ? INT64_MAX : UINT32_MAX - 1))
199+
200+
/* The semantic equivalent of K_NO_WAIT but expressed as a timespec object*/
201+
#define K_TS_NO_WAIT K_TICKS_TO_TIMESPEC(0)
202+
203+
/* The semantic equivalent of K_TICK_MIN but expressed as a timespec object */
204+
#define K_TS_MIN K_TICKS_TO_TIMESPEC(K_TICK_MIN)
205+
206+
/* The semantic equivalent of K_TICK_MAX but expressed as a timespec object */
207+
#define K_TS_MAX K_TICKS_TO_TIMESPEC(K_TICK_MAX)
208+
209+
/* The semantic equivalent of K_FOREVER but expressed as a timespec object*/
210+
#define K_TS_FOREVER K_TIMESPEC(SYS_TIME_T_MAX, NSEC_PER_SEC - 1)
211+
169212
/** @endcond */
170213

171214
#ifndef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME

tests/lib/timespec_util/src/main.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,6 @@ ZTEST(timeutil_api, test_timespec_equal)
268268
zexpect_false(timespec_equal(&a, &b));
269269
}
270270

271-
#define K_TICK_MAX ((uint64_t)(CONFIG_TIMEOUT_64BIT ? (INT64_MAX) : (UINT32_MAX)))
272271
#define NS_PER_TICK (NSEC_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
273272

274273
/* 0 := lower limit, 2 := upper limit */
@@ -280,8 +279,10 @@ static const struct timespec k_timeout_limits[] = {
280279
},
281280
/* K_FOREVER - 1 tick */
282281
{
283-
.tv_sec = CLAMP((NS_PER_TICK * K_TICK_MAX) / NSEC_PER_SEC, 0, INT64_MAX),
284-
.tv_nsec = CLAMP((NS_PER_TICK * K_TICK_MAX) % NSEC_PER_SEC, 0, NSEC_PER_SEC - 1),
282+
.tv_sec = (time_t)CLAMP((NS_PER_TICK * (uint64_t)K_TICK_MAX) / NSEC_PER_SEC, 0,
283+
INT64_MAX),
284+
.tv_nsec = (long)CLAMP((NS_PER_TICK * (uint64_t)K_TICK_MAX) % NSEC_PER_SEC, 0,
285+
NSEC_PER_SEC - 1),
285286
},
286287
};
287288

0 commit comments

Comments
 (0)