From cfeb07ededa388a6958d39f079247262ab5f8008 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Thu, 5 Mar 2020 21:14:02 -0800 Subject: [PATCH] kernel/timeout: Enable 64 bit timeout precision Add a CONFIG_TIMEOUT_64BIT kconfig that, when selected, makes the k_ticks_t used in timeout computations pervasively 64 bit. This will allow much longer timeouts and much faster (i.e. more precise) tick rates. It also enables the use of absolute (not delta) timeouts in an upcoming commit. Signed-off-by: Andy Ross --- CMakeLists.txt | 5 +++++ include/sys_clock.h | 13 +++++++++++++ include/timeout_q.h | 2 +- kernel/Kconfig | 10 ++++++++++ kernel/sched.c | 2 +- kernel/timeout.c | 2 +- tests/kernel/lifo/lifo_usage/src/main.c | 3 ++- 7 files changed, 33 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ece51e7eef..80b8964d1f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -604,6 +604,10 @@ if(CONFIG_64BIT) set(SYSCALL_LONG_REGISTERS_ARG --long-registers) endif() +if(CONFIG_TIMEOUT_64BIT) + set(SYSCALL_SPLIT_TIMEOUT_ARG --split-type k_timeout_t) +endif() + add_custom_command(OUTPUT include/generated/syscall_dispatch.c ${syscall_list_h} # Also, some files are written to include/generated/syscalls/ COMMAND @@ -614,6 +618,7 @@ add_custom_command(OUTPUT include/generated/syscall_dispatch.c ${syscall_list_h} --syscall-dispatch include/generated/syscall_dispatch.c # Write this file --syscall-list ${syscall_list_h} ${SYSCALL_LONG_REGISTERS_ARG} + ${SYSCALL_SPLIT_TIMEOUT_ARG} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${PARSE_SYSCALLS_TARGET} ${syscalls_json} diff --git a/include/sys_clock.h b/include/sys_clock.h index 123ad8235fc..69b73579dee 100644 --- a/include/sys_clock.h +++ b/include/sys_clock.h @@ -33,7 +33,20 @@ extern "C" { * @{ */ +/** + * @brief Tick precision used in timeout APIs + * + * This type defines the word size of the timeout values used in + * k_timeout_t objects, and thus defines an upper bound on maximum + * timeout length (or equivalently minimum tick duration). Note that + * this does not affect the size of the system uptime counter, which + * is always a 64 bit count of ticks. + */ +#ifdef CONFIG_TIMEOUT_64BIT +typedef s64_t k_ticks_t; +#else typedef u32_t k_ticks_t; +#endif #define K_TICKS_FOREVER ((k_ticks_t) -1) diff --git a/include/timeout_q.h b/include/timeout_q.h index 061be6d8999..7acae45c113 100644 --- a/include/timeout_q.h +++ b/include/timeout_q.h @@ -66,7 +66,7 @@ s32_t z_timeout_remaining(struct _timeout *timeout); #define z_init_thread_timeout(t) do {} while (false) #define z_abort_thread_timeout(t) (0) #define z_is_inactive_timeout(t) 0 -#define z_get_next_timeout_expiry() (K_TICKS_FOREVER) +#define z_get_next_timeout_expiry() ((s32_t) K_TICKS_FOREVER) #define z_set_timeout_expiry(t, i) do {} while (false) static inline void z_add_thread_timeout(struct k_thread *th, k_timeout_t ticks) diff --git a/kernel/Kconfig b/kernel/Kconfig index 90125a6f8b5..5261b9c0552 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -579,6 +579,16 @@ config LEGACY_TIMEOUT_API (which were s32_t counts of milliseconds), at the cost of not being able to use new features. +config TIMEOUT_64BIT + bool + depends on !LEGACY_TIMEOUT_API + default y + help + When this option is true, the k_ticks_t values passed to + kernel APIs will be a 64 bit quantity, allowing the use of + larger values (and higher precision tick rates) without fear + of overflowing the 32 bit word. + config XIP bool "Execute in place" help diff --git a/kernel/sched.c b/kernel/sched.c index d4a55945ee9..f5315489cd7 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1202,7 +1202,7 @@ s32_t z_impl_k_sleep(k_timeout_t timeout) if (K_TIMEOUT_EQ(timeout, K_FOREVER)) { k_thread_suspend(_current); - return K_TICKS_FOREVER; + return (s32_t) K_TICKS_FOREVER; } #ifdef CONFIG_LEGACY_TIMEOUT_API diff --git a/kernel/timeout.c b/kernel/timeout.c index 11aeed765aa..6f8efa4a76e 100644 --- a/kernel/timeout.c +++ b/kernel/timeout.c @@ -157,7 +157,7 @@ s32_t z_timeout_remaining(struct _timeout *timeout) s32_t z_get_next_timeout_expiry(void) { - s32_t ret = K_TICKS_FOREVER; + s32_t ret = (s32_t) K_TICKS_FOREVER; LOCKED(&timeout_lock) { ret = next_timeout(); diff --git a/tests/kernel/lifo/lifo_usage/src/main.c b/tests/kernel/lifo/lifo_usage/src/main.c index d5ea87abba7..d40f89224f3 100644 --- a/tests/kernel/lifo/lifo_usage/src/main.c +++ b/tests/kernel/lifo/lifo_usage/src/main.c @@ -134,7 +134,8 @@ static int test_multiple_threads_pending(struct timeout_order_data *test_data, if (data->timeout_order == ii) { TC_PRINT(" thread (q order: %d, t/o: %d, lifo %p)\n", - data->q_order, data->timeout, data->klifo); + data->q_order, (int) data->timeout, + data->klifo); } else { zassert_equal(data->timeout_order, ii, " *** thread %d " "woke up, expected %d\n",