Description
Describe the bug
The function timespec_to_timeout()
in sys/timeutil.h
truncates or rounds input timespec
values without providing any indication to the caller or any remainder to indicate how much truncation or rounding occurred.
It's not always the desired behaviour to e.g. round up to the nearest tick boundary, which is the default behaviour. For example, when computing a timeout for sleeping, yes, we generally do want to round up to the next tick boundary (except if it rounds to K_FOREVER
). However, when computing a timeout for a deadline for e.g. a GPIO interrupt, we generally want to be more conservative and round down.
Additionally, and most especially for a Real-Time OS, any time there is an approximation of a duration or time point, it's really best practice to provide the error or deviation from the requested value back to the calller. This is quite evident when looking at the very tight time margins that must be captured e.g. in radio stacks, and how time deviations must be accumulated and accounted for for periodic signals.
From my perspective, this is a functional requirement for an RTOS.
- What target platform are you using? all
- What have you tried to diagnose or workaround this issue? The workaround is to separately call this after calling
timeout = timespec_to_timeout(req)
timespec_from_timeout(timeout, rem);
timespec_sub(rem, req);
timespec_negate(rem);
- Is this a regression? No
Regression
- This is a regression.
Steps to reproduce
Steps to reproduce the behaviour:
gh pr checkout 92709
git rebase -i HEAD~2
(switchpick
tod
to delete the commit 8b9e097)- edit
tests/lib/timespec_util/src/main.c
and add#define timespec_to_timeout_rem(req, rem) timespec_to_timeout(req)
twister -T tests/lib/timespec_util
Relevant log output
*** Booting Zephyr OS build v4.2.0-rc2-39-gd31c2b6a24f0 ***
Running TESTSUITE timeutil_api
===================================================================
CONFIG_SYS_CLOCK_TICKS_PER_SEC=100
CONFIG_TIMEOUT_64BIT=n
K_TICK_MIN: 1
K_TICK_MAX: 4294967294
K_TS_MIN: {0, 10000000}
K_TS_MAX: {42949672, 940000000}
SYS_TIME_T_MIN: -9223372036854775808
SYS_TIME_T_MAX: 9223372036854775807
===================================================================
START - test_K_TICKS_TO_NSECS
PASS - test_K_TICKS_TO_NSECS in 0.001 seconds
===================================================================
START - test_K_TICKS_TO_SECS
PASS - test_K_TICKS_TO_SECS in 0.001 seconds
===================================================================
START - test_timespec_add
PASS - test_timespec_add in 0.001 seconds
===================================================================
START - test_timespec_compare
PASS - test_timespec_compare in 0.001 seconds
===================================================================
START - test_timespec_equal
PASS - test_timespec_equal in 0.001 seconds
===================================================================
START - test_timespec_from_timeout
PASS - test_timespec_from_timeout in 0.001 seconds
===================================================================
START - test_timespec_is_valid
PASS - test_timespec_is_valid in 0.001 seconds
===================================================================
START - test_timespec_negate
PASS - test_timespec_negate in 0.001 seconds
===================================================================
START - test_timespec_normalize
PASS - test_timespec_normalize in 0.001 seconds
===================================================================
START - test_timespec_sub
PASS - test_timespec_sub in 0.001 seconds
===================================================================
START - test_timespec_to_timeout
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
0: {0, 0} and {0, -2147483648} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
1: {0, 0} and {0, -1} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
2: {0, 0} and {0, -1} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
7: {0, 0} and {10000000, 0} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
8: {0, 0} and {10000000, 0} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
10: {0, 0} and {10000000, 0} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
11: {0, 0} and {10000000, 0} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
12: {0, 0} and {10000000, 0} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
13: {0, 0} and {20000000, 0} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
14: {0, 0} and {20000000, 0} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
15: {0, 0} and {20000000, 0} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
23: {0, 10} and {0, 0} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
24: {0, 10} and {0, 0} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:519: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &tspec->tspec) is false)
25: {0, 10} and {0, 0} are unexpectedly different
Expectation failed at WEST_TOPDIR/zephyr/tests/lib/timespec_util/src/main.c:510: timeutil_api_test_timespec_to_timeout: (timespec_equal(&tick_ts, &workaround) is false)
27: {0, 42949672} and {940000000, 0} are unexpectedly different
FAIL - test_timespec_to_timeout in 0.014 seconds
===================================================================
TESTSUITE timeutil_api failed.
------ TESTSUITE SUMMARY START ------
SUITE FAIL - 90.91% [timeutil_api]: pass = 10, fail = 1, skip = 0, total = 11 duration = 0.024 seconds
- PASS - [timeutil_api.test_K_TICKS_TO_NSECS] duration = 0.001 seconds
- PASS - [timeutil_api.test_K_TICKS_TO_SECS] duration = 0.001 seconds
- PASS - [timeutil_api.test_timespec_add] duration = 0.001 seconds
- PASS - [timeutil_api.test_timespec_compare] duration = 0.001 seconds
- PASS - [timeutil_api.test_timespec_equal] duration = 0.001 seconds
- PASS - [timeutil_api.test_timespec_from_timeout] duration = 0.001 seconds
- PASS - [timeutil_api.test_timespec_is_valid] duration = 0.001 seconds
- PASS - [timeutil_api.test_timespec_negate] duration = 0.001 seconds
- PASS - [timeutil_api.test_timespec_normalize] duration = 0.001 seconds
- PASS - [timeutil_api.test_timespec_sub] duration = 0.001 seconds
- FAIL - [timeutil_api.test_timespec_to_timeout] duration = 0.014 seconds
------ TESTSUITE SUMMARY END ------
===================================================================
RunID: d84614d788819d0cd4da2827ca76e1fd
PROJECT EXECUTION FAILED
Impact
Functional Limitation – Some features not working as expected, but system usable.
Environment
- OS: all
- Toolchain: Zephyr SDK v0.17.2
v4.2.0-rc2
Additional Context
No response