Skip to content

Commit 50c7c7b

Browse files
nordic-krchnashif
authored andcommitted
sys: time_units: Add Kconfig option for algorithm selection
Add maximum timeout used for conversion to Kconfig. Option is used to determine which conversion algorithm to use: faster but overflowing earlier or slower without early overflow. Signed-off-by: Krzysztof Chruscinski <[email protected]>
1 parent fb5334d commit 50c7c7b

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

include/sys/time_units.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,21 @@ static TIME_CONSTEXPR inline int sys_clock_hw_cycles_per_sec(void)
6464
#endif
6565
}
6666

67+
/** @internal
68+
* Macro determines if fast conversion algorithm can be used. It checks if
69+
* maximum timeout represented in source frequency domain and multiplied by
70+
* target frequency fits in 64 bits.
71+
*
72+
* @param from_hz Source frequency.
73+
* @param to_hz Target frequency.
74+
*
75+
* @retval true Use faster algorithm.
76+
* @retval false Use algorithm preventing overflow of intermediate value.
77+
*/
78+
#define Z_TMCVT_USE_FAST_ALGO(from_hz, to_hz) \
79+
((ceiling_fraction(CONFIG_SYS_CLOCK_MAX_TIMEOUT_DAYS * 24ULL * 3600ULL * from_hz, \
80+
UINT32_MAX) * to_hz) <= UINT32_MAX)
81+
6782
/* Time converter generator gadget. Selects from one of three
6883
* conversion algorithms: ones that take advantage when the
6984
* frequencies are an integer ratio (in either direction), or a full
@@ -131,7 +146,17 @@ static TIME_CONSTEXPR ALWAYS_INLINE uint64_t z_tmcvt(uint64_t t, uint32_t from_h
131146
} else {
132147
if (result32) {
133148
return (uint32_t)((t * to_hz + off) / from_hz);
149+
} else if (const_hz && Z_TMCVT_USE_FAST_ALGO(from_hz, to_hz)) {
150+
/* Faster algorithm but source is first multiplied by target frequency
151+
* and it can overflow even though final result would not overflow.
152+
* Kconfig option shall prevent use of this algorithm when there is a
153+
* risk of overflow.
154+
*/
155+
return ((t * to_hz + off) / from_hz);
134156
} else {
157+
/* Slower algorithm but input is first divided before being multiplied
158+
* which prevents overflow of intermediate value.
159+
*/
135160
return (t / from_hz) * to_hz + ((t % from_hz) * to_hz + off) / from_hz;
136161
}
137162
}

kernel/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,17 @@ config TIMEOUT_64BIT
644644
availability of absolute timeout values (which require the
645645
extra precision).
646646

647+
config SYS_CLOCK_MAX_TIMEOUT_DAYS
648+
int "Max timeout (in days) used in conversions"
649+
default 365
650+
help
651+
Value is used in the time conversion static inline function to determine
652+
at compile time which algorithm to use. One algorithm is faster, takes
653+
less code but may overflow if multiplication of source and target
654+
frequency exceeds 64 bits. Second algorithm prevents that. Faster
655+
algorithm is selected for conversion if maximum timeout represented in
656+
source frequency domain multiplied by target frequency fits in 64 bits.
657+
647658
config XIP
648659
bool "Execute in place"
649660
help

subsys/testsuite/ztest/include/ztest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#define CONFIG_MP_NUM_CPUS 1
3939
#define CONFIG_SYS_CLOCK_TICKS_PER_SEC 100
4040
#define CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC 10000000
41+
#define CONFIG_SYS_CLOCK_MAX_TIMEOUT_DAYS 365
4142
#define ARCH_STACK_PTR_ALIGN 8
4243
/* FIXME: Properly integrate with Zephyr's arch specific code */
4344
#define CONFIG_X86 1

0 commit comments

Comments
 (0)