Skip to content
Permalink
Browse files

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>
  • Loading branch information...
andrewboie authored and carlescufi committed May 21, 2019
1 parent e541b16 commit fd49cf7d02914669df8d86b67a1c7f1a0de76a52
Showing with 28 additions and 7 deletions.
  1. +17 −6 include/sys_clock.h
  2. +8 −1 kernel/timeout.c
  3. +3 −0 subsys/testsuite/ztest/include/syscalls/sys_clock.h
@@ -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_ */
@@ -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)
{
@@ -0,0 +1,3 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/

0 comments on commit fd49cf7

Please sign in to comment.
You can’t perform that action at this time.