Skip to content

Commit 4c62d76

Browse files
nordic-krchcfriedt
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]> (cherry picked from commit 50c7c7b)
1 parent 6f8f9b5 commit 4c62d76

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

include/sys/time_units.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,21 @@ static TIME_CONSTEXPR inline int sys_clock_hw_cycles_per_sec(void)
5959
#endif
6060
}
6161

62+
/** @internal
63+
* Macro determines if fast conversion algorithm can be used. It checks if
64+
* maximum timeout represented in source frequency domain and multiplied by
65+
* target frequency fits in 64 bits.
66+
*
67+
* @param from_hz Source frequency.
68+
* @param to_hz Target frequency.
69+
*
70+
* @retval true Use faster algorithm.
71+
* @retval false Use algorithm preventing overflow of intermediate value.
72+
*/
73+
#define Z_TMCVT_USE_FAST_ALGO(from_hz, to_hz) \
74+
((ceiling_fraction(CONFIG_SYS_CLOCK_MAX_TIMEOUT_DAYS * 24ULL * 3600ULL * from_hz, \
75+
UINT32_MAX) * to_hz) <= UINT32_MAX)
76+
6277
/* Time converter generator gadget. Selects from one of three
6378
* conversion algorithms: ones that take advantage when the
6479
* frequencies are an integer ratio (in either direction), or a full
@@ -126,8 +141,18 @@ static TIME_CONSTEXPR ALWAYS_INLINE uint64_t z_tmcvt(uint64_t t, uint32_t from_h
126141
} else {
127142
if (result32) {
128143
return (uint32_t)((t * to_hz + off) / from_hz);
144+
} else if (const_hz && Z_TMCVT_USE_FAST_ALGO(from_hz, to_hz)) {
145+
/* Faster algorithm but source is first multiplied by target frequency
146+
* and it can overflow even though final result would not overflow.
147+
* Kconfig option shall prevent use of this algorithm when there is a
148+
* risk of overflow.
149+
*/
150+
return ((t * to_hz + off) / from_hz);
129151
} else {
130-
return (t * to_hz + off) / from_hz;
152+
/* Slower algorithm but input is first divided before being multiplied
153+
* which prevents overflow of intermediate value.
154+
*/
155+
return (t / from_hz) * to_hz + ((t % from_hz) * to_hz + off) / from_hz;
131156
}
132157
}
133158
}

kernel/Kconfig

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

616+
config SYS_CLOCK_MAX_TIMEOUT_DAYS
617+
int "Max timeout (in days) used in conversions"
618+
default 365
619+
help
620+
Value is used in the time conversion static inline function to determine
621+
at compile time which algorithm to use. One algorithm is faster, takes
622+
less code but may overflow if multiplication of source and target
623+
frequency exceeds 64 bits. Second algorithm prevents that. Faster
624+
algorithm is selected for conversion if maximum timeout represented in
625+
source frequency domain multiplied by target frequency fits in 64 bits.
626+
616627
config XIP
617628
bool "Execute in place"
618629
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)