Commit 6d35969a authored by Krzysztof Chruściński's avatar Krzysztof Chruściński Committed by Benjamin Cabé
Browse files

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: default avatarKrzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
parent 3c2d2a6e
Loading
Loading
Loading
Loading
+17 −0
Changes for kernel/include/timeout_q.h: 17 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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)

+4 −0
Changes for kernel/sched.c: 4 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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();

+1 −0
Changes for kernel/timeout.c: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -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);