kernel: timeout: add syscall for runtime clk freq

If the system sets its clock frequency at runtime, this is
stored in a variable that can't be directly read by user
mode. For this case only, add a system call to fetch its
value and modify the definition of
sys_clock_hw_cycles_per_sec() to use it.

Since this is now a system call, store in a temporary variable
inside z_ms_to_ticks(). The syscall overhead only applies
when called from user mode, other contexts are completely
inlined.

Added stub syscall header for mocking framework, to get rid
of inclusion errors.

Fixes: #16238

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2019-05-21 14:02:26 -07:00 committed by Carles Cufí
commit fd49cf7d02
3 changed files with 28 additions and 7 deletions

View file

@ -31,12 +31,21 @@ extern int _sys_clock_always_on;
extern void z_enable_sys_clock(void);
#endif
static inline int sys_clock_hw_cycles_per_sec(void)
{
#if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME)
__syscall int z_clock_hw_cycles_per_sec_runtime_get(void);
static inline int z_impl_z_clock_hw_cycles_per_sec_runtime_get(void)
{
extern int z_clock_hw_cycles_per_sec;
return z_clock_hw_cycles_per_sec;
}
#endif /* CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME */
static inline int sys_clock_hw_cycles_per_sec(void)
{
#if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME)
return z_clock_hw_cycles_per_sec_runtime_get();
#else
return CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
#endif
@ -100,11 +109,11 @@ static ALWAYS_INLINE s32_t z_ms_to_ticks(s32_t ms)
#ifdef CONFIG_SYS_CLOCK_EXISTS
#ifdef _NEED_PRECISE_TICK_MS_CONVERSION
int cyc = sys_clock_hw_cycles_per_sec();
/* use 64-bit math to keep precision */
return (s32_t)ceiling_fraction(
(s64_t)ms * sys_clock_hw_cycles_per_sec(),
((s64_t)MSEC_PER_SEC * sys_clock_hw_cycles_per_sec()) /
CONFIG_SYS_CLOCK_TICKS_PER_SEC);
return (s32_t)ceiling_fraction((s64_t)ms * cyc,
((s64_t)MSEC_PER_SEC * cyc) / CONFIG_SYS_CLOCK_TICKS_PER_SEC);
#else
/* simple division keeps precision */
s32_t ms_per_tick = MSEC_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC;
@ -234,4 +243,6 @@ struct _timeout {
}
#endif
#include <syscalls/sys_clock.h>
#endif /* ZEPHYR_INCLUDE_SYS_CLOCK_H_ */

View file

@ -28,7 +28,14 @@ static int announce_remaining;
#if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME)
int z_clock_hw_cycles_per_sec = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
#endif
#ifdef CONFIG_USERSPACE
Z_SYSCALL_HANDLER(z_clock_hw_cycles_per_sec_runtime_get)
{
return z_impl_z_clock_hw_cycles_per_sec_runtime_get();
}
#endif /* CONFIG_USERSPACE */
#endif /* CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME */
static struct _timeout *first(void)
{

View file

@ -0,0 +1,3 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/