From e77e048187f2633ad5dd84f8ff9a2dbf153039ec Mon Sep 17 00:00:00 2001 From: Peter Bigot Date: Thu, 31 Oct 2019 06:16:00 -0500 Subject: [PATCH 1/3] kernel: move time_units into sys subdirectory This isn't something the user will ever include directory, so take steps to hide it. Signed-off-by: Peter Bigot --- include/{ => sys}/time_units.h | 0 include/sys_clock.h | 2 +- tests/kernel/timer/timer_api/src/timer_convert.c | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename include/{ => sys}/time_units.h (100%) diff --git a/include/time_units.h b/include/sys/time_units.h similarity index 100% rename from include/time_units.h rename to include/sys/time_units.h diff --git a/include/sys_clock.h b/include/sys_clock.h index 08d87f764a974..681061ea51c85 100644 --- a/include/sys_clock.h +++ b/include/sys_clock.h @@ -22,7 +22,7 @@ #include #include -#include +#include #ifdef __cplusplus extern "C" { diff --git a/tests/kernel/timer/timer_api/src/timer_convert.c b/tests/kernel/timer/timer_api/src/timer_convert.c index 8aa4c5c0814e0..6a712b7e67828 100644 --- a/tests/kernel/timer/timer_api/src/timer_convert.c +++ b/tests/kernel/timer/timer_api/src/timer_convert.c @@ -5,7 +5,7 @@ */ #include #include -#include +#include #define NUM_RANDOM 100 From 540ac6dbfbb6617c9ea51aaaa38c9436dfb59f4f Mon Sep 17 00:00:00 2001 From: Peter Bigot Date: Thu, 31 Oct 2019 06:21:53 -0500 Subject: [PATCH 2/3] kernel: extend time unit conversion to high resolution scales Some use cases require using high-resolution tick or cycle clocks to measure sub-millisecond durations. Generate the corresponding 32-bit conversions to avoid the cost of 64-bit math in the common case where the duration fits in 32 bits in both original and converted scale. Signed-off-by: Peter Bigot --- include/sys/time_units.h | 337 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 336 insertions(+), 1 deletion(-) diff --git a/include/sys/time_units.h b/include/sys/time_units.h index ec48f2e0c8f86..77a5d4549cacf 100644 --- a/include/sys/time_units.h +++ b/include/sys/time_units.h @@ -132,7 +132,6 @@ static ALWAYS_INLINE u64_t z_tmcvt(u64_t t, u32_t from_hz, u32_t to_hz, * next if prefix($from_unit) && prefix($to_unit); * for my $round ("floor", "near", "ceil") { * for(my $big=0; $big <= 1; $big++) { - * next if !$big && (big($from_unit) || big($to_unit)); * my $sz = $big ? 64 : 32; * my $sym = "k_${from_unit}_to_${to_unit}_$round$sz"; * my $type = "u${sz}_t"; @@ -348,6 +347,20 @@ static inline u64_t k_ms_to_ticks_ceil64(u64_t t) return z_tmcvt(t, Z_HZ_ms, Z_HZ_ticks, true, false, true, false); } +/** @brief Convert microseconds to hardware cycles + * + * Converts time values in microseconds to hardware cycles. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @return The converted time value + */ +static inline u32_t k_us_to_cyc_floor32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, true, false, false); +} + /** @brief Convert microseconds to hardware cycles * * Converts time values in microseconds to hardware cycles. @@ -362,6 +375,20 @@ static inline u64_t k_us_to_cyc_floor64(u64_t t) return z_tmcvt(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, false, false); } +/** @brief Convert microseconds to hardware cycles + * + * Converts time values in microseconds to hardware cycles. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @return The converted time value + */ +static inline u32_t k_us_to_cyc_near32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, true, false, true); +} + /** @brief Convert microseconds to hardware cycles * * Converts time values in microseconds to hardware cycles. @@ -376,6 +403,20 @@ static inline u64_t k_us_to_cyc_near64(u64_t t) return z_tmcvt(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, false, true); } +/** @brief Convert microseconds to hardware cycles + * + * Converts time values in microseconds to hardware cycles. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @return The converted time value + */ +static inline u32_t k_us_to_cyc_ceil32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, true, true, false); +} + /** @brief Convert microseconds to hardware cycles * * Converts time values in microseconds to hardware cycles. @@ -390,6 +431,20 @@ static inline u64_t k_us_to_cyc_ceil64(u64_t t) return z_tmcvt(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, true, false); } +/** @brief Convert microseconds to ticks + * + * Converts time values in microseconds to ticks. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @return The converted time value + */ +static inline u32_t k_us_to_ticks_floor32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_us, Z_HZ_ticks, true, true, false, false); +} + /** @brief Convert microseconds to ticks * * Converts time values in microseconds to ticks. @@ -404,6 +459,20 @@ static inline u64_t k_us_to_ticks_floor64(u64_t t) return z_tmcvt(t, Z_HZ_us, Z_HZ_ticks, true, false, false, false); } +/** @brief Convert microseconds to ticks + * + * Converts time values in microseconds to ticks. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @return The converted time value + */ +static inline u32_t k_us_to_ticks_near32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_us, Z_HZ_ticks, true, true, false, true); +} + /** @brief Convert microseconds to ticks * * Converts time values in microseconds to ticks. @@ -418,6 +487,20 @@ static inline u64_t k_us_to_ticks_near64(u64_t t) return z_tmcvt(t, Z_HZ_us, Z_HZ_ticks, true, false, false, true); } +/** @brief Convert microseconds to ticks + * + * Converts time values in microseconds to ticks. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @return The converted time value + */ +static inline u32_t k_us_to_ticks_ceil32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_us, Z_HZ_ticks, true, true, true, false); +} + /** @brief Convert microseconds to ticks * * Converts time values in microseconds to ticks. @@ -432,6 +515,20 @@ static inline u64_t k_us_to_ticks_ceil64(u64_t t) return z_tmcvt(t, Z_HZ_us, Z_HZ_ticks, true, false, true, false); } +/** @brief Convert nanoseconds to hardware cycles + * + * Converts time values in nanoseconds to hardware cycles. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @return The converted time value + */ +static inline u32_t k_ns_to_cyc_floor32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, true, false, false); +} + /** @brief Convert nanoseconds to hardware cycles * * Converts time values in nanoseconds to hardware cycles. @@ -446,6 +543,20 @@ static inline u64_t k_ns_to_cyc_floor64(u64_t t) return z_tmcvt(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, false, false); } +/** @brief Convert nanoseconds to hardware cycles + * + * Converts time values in nanoseconds to hardware cycles. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @return The converted time value + */ +static inline u32_t k_ns_to_cyc_near32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, true, false, true); +} + /** @brief Convert nanoseconds to hardware cycles * * Converts time values in nanoseconds to hardware cycles. @@ -460,6 +571,20 @@ static inline u64_t k_ns_to_cyc_near64(u64_t t) return z_tmcvt(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, false, true); } +/** @brief Convert nanoseconds to hardware cycles + * + * Converts time values in nanoseconds to hardware cycles. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @return The converted time value + */ +static inline u32_t k_ns_to_cyc_ceil32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, true, true, false); +} + /** @brief Convert nanoseconds to hardware cycles * * Converts time values in nanoseconds to hardware cycles. @@ -474,6 +599,20 @@ static inline u64_t k_ns_to_cyc_ceil64(u64_t t) return z_tmcvt(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, true, false); } +/** @brief Convert nanoseconds to ticks + * + * Converts time values in nanoseconds to ticks. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @return The converted time value + */ +static inline u32_t k_ns_to_ticks_floor32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_ns, Z_HZ_ticks, true, true, false, false); +} + /** @brief Convert nanoseconds to ticks * * Converts time values in nanoseconds to ticks. @@ -488,6 +627,20 @@ static inline u64_t k_ns_to_ticks_floor64(u64_t t) return z_tmcvt(t, Z_HZ_ns, Z_HZ_ticks, true, false, false, false); } +/** @brief Convert nanoseconds to ticks + * + * Converts time values in nanoseconds to ticks. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @return The converted time value + */ +static inline u32_t k_ns_to_ticks_near32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_ns, Z_HZ_ticks, true, true, false, true); +} + /** @brief Convert nanoseconds to ticks * * Converts time values in nanoseconds to ticks. @@ -502,6 +655,20 @@ static inline u64_t k_ns_to_ticks_near64(u64_t t) return z_tmcvt(t, Z_HZ_ns, Z_HZ_ticks, true, false, false, true); } +/** @brief Convert nanoseconds to ticks + * + * Converts time values in nanoseconds to ticks. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @return The converted time value + */ +static inline u32_t k_ns_to_ticks_ceil32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_ns, Z_HZ_ticks, true, true, true, false); +} + /** @brief Convert nanoseconds to ticks * * Converts time values in nanoseconds to ticks. @@ -600,6 +767,20 @@ static inline u64_t k_cyc_to_ms_ceil64(u64_t t) return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, true, false); } +/** @brief Convert hardware cycles to microseconds + * + * Converts time values in hardware cycles to microseconds. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @return The converted time value + */ +static inline u32_t k_cyc_to_us_floor32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, true, false, false); +} + /** @brief Convert hardware cycles to microseconds * * Converts time values in hardware cycles to microseconds. @@ -614,6 +795,20 @@ static inline u64_t k_cyc_to_us_floor64(u64_t t) return z_tmcvt(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, false, false); } +/** @brief Convert hardware cycles to microseconds + * + * Converts time values in hardware cycles to microseconds. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @return The converted time value + */ +static inline u32_t k_cyc_to_us_near32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, true, false, true); +} + /** @brief Convert hardware cycles to microseconds * * Converts time values in hardware cycles to microseconds. @@ -628,6 +823,20 @@ static inline u64_t k_cyc_to_us_near64(u64_t t) return z_tmcvt(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, false, true); } +/** @brief Convert hardware cycles to microseconds + * + * Converts time values in hardware cycles to microseconds. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @return The converted time value + */ +static inline u32_t k_cyc_to_us_ceil32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, true, true, false); +} + /** @brief Convert hardware cycles to microseconds * * Converts time values in hardware cycles to microseconds. @@ -642,6 +851,20 @@ static inline u64_t k_cyc_to_us_ceil64(u64_t t) return z_tmcvt(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, true, false); } +/** @brief Convert hardware cycles to nanoseconds + * + * Converts time values in hardware cycles to nanoseconds. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @return The converted time value + */ +static inline u32_t k_cyc_to_ns_floor32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, true, false, false); +} + /** @brief Convert hardware cycles to nanoseconds * * Converts time values in hardware cycles to nanoseconds. @@ -656,6 +879,20 @@ static inline u64_t k_cyc_to_ns_floor64(u64_t t) return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, false, false); } +/** @brief Convert hardware cycles to nanoseconds + * + * Converts time values in hardware cycles to nanoseconds. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @return The converted time value + */ +static inline u32_t k_cyc_to_ns_near32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, true, false, true); +} + /** @brief Convert hardware cycles to nanoseconds * * Converts time values in hardware cycles to nanoseconds. @@ -670,6 +907,20 @@ static inline u64_t k_cyc_to_ns_near64(u64_t t) return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, false, true); } +/** @brief Convert hardware cycles to nanoseconds + * + * Converts time values in hardware cycles to nanoseconds. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @return The converted time value + */ +static inline u32_t k_cyc_to_ns_ceil32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, true, true, false); +} + /** @brief Convert hardware cycles to nanoseconds * * Converts time values in hardware cycles to nanoseconds. @@ -852,6 +1103,20 @@ static inline u64_t k_ticks_to_ms_ceil64(u64_t t) return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ms, true, false, true, false); } +/** @brief Convert ticks to microseconds + * + * Converts time values in ticks to microseconds. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @return The converted time value + */ +static inline u32_t k_ticks_to_us_floor32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_ticks, Z_HZ_us, true, true, false, false); +} + /** @brief Convert ticks to microseconds * * Converts time values in ticks to microseconds. @@ -866,6 +1131,20 @@ static inline u64_t k_ticks_to_us_floor64(u64_t t) return z_tmcvt(t, Z_HZ_ticks, Z_HZ_us, true, false, false, false); } +/** @brief Convert ticks to microseconds + * + * Converts time values in ticks to microseconds. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @return The converted time value + */ +static inline u32_t k_ticks_to_us_near32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_ticks, Z_HZ_us, true, true, false, true); +} + /** @brief Convert ticks to microseconds * * Converts time values in ticks to microseconds. @@ -880,6 +1159,20 @@ static inline u64_t k_ticks_to_us_near64(u64_t t) return z_tmcvt(t, Z_HZ_ticks, Z_HZ_us, true, false, false, true); } +/** @brief Convert ticks to microseconds + * + * Converts time values in ticks to microseconds. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @return The converted time value + */ +static inline u32_t k_ticks_to_us_ceil32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_ticks, Z_HZ_us, true, true, true, false); +} + /** @brief Convert ticks to microseconds * * Converts time values in ticks to microseconds. @@ -894,6 +1187,20 @@ static inline u64_t k_ticks_to_us_ceil64(u64_t t) return z_tmcvt(t, Z_HZ_ticks, Z_HZ_us, true, false, true, false); } +/** @brief Convert ticks to nanoseconds + * + * Converts time values in ticks to nanoseconds. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @return The converted time value + */ +static inline u32_t k_ticks_to_ns_floor32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ns, true, true, false, false); +} + /** @brief Convert ticks to nanoseconds * * Converts time values in ticks to nanoseconds. @@ -908,6 +1215,20 @@ static inline u64_t k_ticks_to_ns_floor64(u64_t t) return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ns, true, false, false, false); } +/** @brief Convert ticks to nanoseconds + * + * Converts time values in ticks to nanoseconds. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @return The converted time value + */ +static inline u32_t k_ticks_to_ns_near32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ns, true, true, false, true); +} + /** @brief Convert ticks to nanoseconds * * Converts time values in ticks to nanoseconds. @@ -922,6 +1243,20 @@ static inline u64_t k_ticks_to_ns_near64(u64_t t) return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ns, true, false, false, true); } +/** @brief Convert ticks to nanoseconds + * + * Converts time values in ticks to nanoseconds. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @return The converted time value + */ +static inline u32_t k_ticks_to_ns_ceil32(u32_t t) +{ + /* Generated. Do not edit. See above. */ + return z_tmcvt(t, Z_HZ_ticks, Z_HZ_ns, true, true, true, false); +} + /** @brief Convert ticks to nanoseconds * * Converts time values in ticks to nanoseconds. From ac4d20bec1575812d281840b0655d0db9246a3e6 Mon Sep 17 00:00:00 2001 From: Peter Bigot Date: Thu, 31 Oct 2019 06:36:10 -0500 Subject: [PATCH 3/3] kernel: restore size and signedness behavior in deprecated time-related API The addition of API to correctly handle conversion between durations in different clocks inadvertently changed the type of the value produced by the API. Specific changes were: s32_t z_ms_to_ticks(s32_t t) => u32_t k_ms_to_ticks_ceil32(u32_t t) : signedness change s32_t __ticks_to_us(s32_t t) => u64_t k_ticks_to_us_floor64(u64_t t) : signedness and rank change s32_t z_us_to_ticks(s32_t t) => u64_t k_us_to_ticks_ceil64(u64_t t) : signedness and rank change int sys_clock_hw_cycles_per_tick() => u32_t k_ticks_to_cyc_floor32(1) : signedness change The effect of this is to change the essential type of operands in existing expressions, potentially resulting in behavior changes when calculations were promoted to unsigned types, or code size by requiring 64-bot arithmetic. Add casts as necessary to preserve the original return type, and to explicitly recognize impact of passing macro parameters into a context where a specific type will be used. Signed-off-by: Peter Bigot --- include/sys_clock.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/sys_clock.h b/include/sys_clock.h index 681061ea51c85..ff5da04498468 100644 --- a/include/sys_clock.h +++ b/include/sys_clock.h @@ -73,17 +73,17 @@ extern void z_enable_sys_clock(void); #endif #define __ticks_to_ms(t) __DEPRECATED_MACRO \ - k_ticks_to_ms_floor64(t) + k_ticks_to_ms_floor64((u64_t)(t)) #define z_ms_to_ticks(t) \ - k_ms_to_ticks_ceil32(t) + ((s32_t)k_ms_to_ticks_ceil32((u32_t)(t))) #define __ticks_to_us(t) __DEPRECATED_MACRO \ - k_ticks_to_us_floor64(t) + ((s32_t)k_ticks_to_us_floor32((u32_t)(t))) #define z_us_to_ticks(t) __DEPRECATED_MACRO \ - k_us_to_ticks_ceil64(t) + ((s32_t)k_us_to_ticks_ceil32((u32_t)(t))) #define sys_clock_hw_cycles_per_tick() __DEPRECATED_MACRO \ - k_ticks_to_cyc_floor32(1) + ((int)k_ticks_to_cyc_floor32(1U)) #define SYS_CLOCK_HW_CYCLES_TO_NS64(t) __DEPRECATED_MACRO \ - k_cyc_to_ns_floor64(t) + k_cyc_to_ns_floor64((u64_t)(X)) #define SYS_CLOCK_HW_CYCLES_TO_NS(t) __DEPRECATED_MACRO \ ((u32_t)k_cyc_to_ns_floor64(t))