kernel: sched: Optimize sleeping function
Accessing system timer registers can be costly and it shall be avoided if possible. When thread is waken up in z_tick_sleep it may be because timeout expired or because thread was waken up before sleeping period passed. Add function to detect if timeout is aborted (before it was expired). Use it in the sleep function and avoid reading system ticks if timeout was not aborted. Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
3c2d2a6ee5
commit
6d35969a55
3 changed files with 22 additions and 0 deletions
|
@ -22,6 +22,9 @@ extern "C" {
|
|||
|
||||
#ifdef CONFIG_SYS_CLOCK_EXISTS
|
||||
|
||||
/* Value written to dticks when timeout is aborted. */
|
||||
#define TIMEOUT_DTICKS_ABORTED (IS_ENABLED(CONFIG_TIMEOUT_64BIT) ? INT64_MIN : INT32_MIN)
|
||||
|
||||
static inline void z_init_timeout(struct _timeout *to)
|
||||
{
|
||||
sys_dnode_init(&to->node);
|
||||
|
@ -37,6 +40,12 @@ static inline bool z_is_inactive_timeout(const struct _timeout *to)
|
|||
return !sys_dnode_is_linked(&to->node);
|
||||
}
|
||||
|
||||
static inline bool z_is_aborted_timeout(const struct _timeout *to)
|
||||
{
|
||||
/* When timeout is aborted then dticks is set to special value. */
|
||||
return to->dticks == TIMEOUT_DTICKS_ABORTED;
|
||||
}
|
||||
|
||||
static inline void z_init_thread_timeout(struct _thread_base *thread_base)
|
||||
{
|
||||
z_init_timeout(&thread_base->timeout);
|
||||
|
@ -54,6 +63,12 @@ static inline void z_abort_thread_timeout(struct k_thread *thread)
|
|||
z_abort_timeout(&thread->base.timeout);
|
||||
}
|
||||
|
||||
static inline bool z_is_aborted_thread_timeout(struct k_thread *thread)
|
||||
{
|
||||
|
||||
return z_is_aborted_timeout(&thread->base.timeout);
|
||||
}
|
||||
|
||||
int32_t z_get_next_timeout_expiry(void);
|
||||
|
||||
k_ticks_t z_timeout_remaining(const struct _timeout *timeout);
|
||||
|
@ -63,7 +78,9 @@ k_ticks_t z_timeout_remaining(const struct _timeout *timeout);
|
|||
/* Stubs when !CONFIG_SYS_CLOCK_EXISTS */
|
||||
#define z_init_thread_timeout(thread_base) do {} while (false)
|
||||
#define z_abort_thread_timeout(to) do {} while (false)
|
||||
#define z_is_aborted_thread_timeout(to) false
|
||||
#define z_is_inactive_timeout(to) 1
|
||||
#define z_is_aborted_timeout(to) false
|
||||
#define z_get_next_timeout_expiry() ((int32_t) K_TICKS_FOREVER)
|
||||
#define z_set_timeout_expiry(ticks, is_idle) do {} while (false)
|
||||
|
||||
|
|
|
@ -1108,6 +1108,10 @@ static int32_t z_tick_sleep(k_timeout_t timeout)
|
|||
|
||||
(void)z_swap(&_sched_spinlock, key);
|
||||
|
||||
if (!z_is_aborted_thread_timeout(_current)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We require a 32 bit unsigned subtraction to care a wraparound */
|
||||
uint32_t left_ticks = expected_wakeup_ticks - sys_clock_tick_get_32();
|
||||
|
||||
|
|
|
@ -162,6 +162,7 @@ int z_abort_timeout(struct _timeout *to)
|
|||
bool is_first = (to == first());
|
||||
|
||||
remove_timeout(to);
|
||||
to->dticks = TIMEOUT_DTICKS_ABORTED;
|
||||
ret = 0;
|
||||
if (is_first) {
|
||||
sys_clock_set_timeout(next_timeout(elapsed()), false);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue