diff --git a/include/kernel.h b/include/kernel.h index faa03f6a3cfd5..5c28cf73cfcf1 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -389,7 +389,7 @@ struct _thread_base { /* this thread's entry in a ready/wait queue */ union { - sys_dlist_t qnode_dlist; + sys_dnode_t qnode_dlist; struct rbnode qnode_rb; }; @@ -874,9 +874,6 @@ __syscall void k_thread_start(k_tid_t thread); /* timeout has timed out and is not on _timeout_q anymore */ #define _EXPIRED (-2) -/* timeout is not in use */ -#define _INACTIVE (-1) - struct _static_thread_data { struct k_thread *init_thread; k_thread_stack_t *init_stack; @@ -1335,7 +1332,7 @@ struct k_timer { #define _K_TIMER_INITIALIZER(obj, expiry, stop) \ { \ - .timeout.dticks = _INACTIVE, \ + .timeout.dticks = 0, \ .timeout.fn = _timer_expiration_handler, \ .wait_q = _WAIT_Q_INIT(&obj.wait_q), \ .expiry_fn = expiry, \ diff --git a/include/misc/dlist.h b/include/misc/dlist.h index 937a55c28f18b..ba0795233edc1 100644 --- a/include/misc/dlist.h +++ b/include/misc/dlist.h @@ -181,7 +181,7 @@ typedef struct _dnode sys_dnode_t; __cns = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n)) /** - * @brief initialize list + * @brief initialize list to its empty state * * @param list the doubly-linked list * @@ -196,6 +196,33 @@ static inline void sys_dlist_init(sys_dlist_t *list) #define SYS_DLIST_STATIC_INIT(ptr_to_list) { {(ptr_to_list)}, {(ptr_to_list)} } +/** + * @brief initialize node to its state when not in a list + * + * @param node the node + * + * @return N/A + */ + +static inline void sys_dnode_init(sys_dnode_t *node) +{ + node->next = NULL; + node->prev = NULL; +} + +/** + * @brief check if a node is a member of any list + * + * @param node the node + * + * @return true if node is linked into a list, false if it is not + */ + +static inline bool sys_dnode_is_linked(const sys_dnode_t *node) +{ + return node->next != NULL; +} + /** * @brief check if a node is the list's head * @@ -500,6 +527,7 @@ static inline void sys_dlist_remove(sys_dnode_t *node) { node->prev->next = node->next; node->next->prev = node->prev; + sys_dnode_init(node); } /** diff --git a/kernel/include/ksched.h b/kernel/include/ksched.h index f44e88da2708f..f44df94894d77 100644 --- a/kernel/include/ksched.h +++ b/kernel/include/ksched.h @@ -8,6 +8,7 @@ #define ZEPHYR_KERNEL_INCLUDE_KSCHED_H_ #include +#include #include #include @@ -83,11 +84,7 @@ static inline int _is_thread_prevented_from_running(struct k_thread *thread) static inline bool _is_thread_timeout_active(struct k_thread *thread) { -#ifdef CONFIG_SYS_CLOCK_EXISTS - return thread->base.timeout.dticks != _INACTIVE; -#else - return false; -#endif + return !_is_inactive_timeout(&thread->base.timeout); } static inline bool _is_thread_ready(struct k_thread *thread) diff --git a/kernel/include/timeout_q.h b/kernel/include/timeout_q.h index a8d6428c91f10..3438957f0ff7d 100644 --- a/kernel/include/timeout_q.h +++ b/kernel/include/timeout_q.h @@ -22,13 +22,18 @@ extern "C" { static inline void _init_timeout(struct _timeout *t, _timeout_func_t fn) { - t->dticks = _INACTIVE; + sys_dnode_init(&t->node); } void _add_timeout(struct _timeout *to, _timeout_func_t fn, s32_t ticks); int _abort_timeout(struct _timeout *to); +static inline bool _is_inactive_timeout(struct _timeout *t) +{ + return !sys_dnode_is_linked(&t->node); +} + static inline void _init_thread_timeout(struct _thread_base *thread_base) { _init_timeout(&thread_base->timeout, NULL); @@ -58,6 +63,7 @@ s32_t z_timeout_remaining(struct _timeout *timeout); #define _init_thread_timeout(t) do {} while (0) #define _add_thread_timeout(th, to) do {} while (0 && (void *)to && (void *)th) #define _abort_thread_timeout(t) (0) +#define _is_inactive_timeout(t) 0 #define _get_next_timeout_expiry() (K_FOREVER) #define z_set_timeout_expiry(t, i) do {} while (0) diff --git a/kernel/poll.c b/kernel/poll.c index 4ff876e67b796..6c0dff797b079 100644 --- a/kernel/poll.c +++ b/kernel/poll.c @@ -133,20 +133,22 @@ static inline int register_event(struct k_poll_event *event, /* must be called with interrupts locked */ static inline void clear_event_registration(struct k_poll_event *event) { + bool remove = false; + event->poller = NULL; switch (event->type) { case K_POLL_TYPE_SEM_AVAILABLE: __ASSERT(event->sem != NULL, "invalid semaphore\n"); - sys_dlist_remove(&event->_node); + remove = true; break; case K_POLL_TYPE_DATA_AVAILABLE: __ASSERT(event->queue != NULL, "invalid queue\n"); - sys_dlist_remove(&event->_node); + remove = true; break; case K_POLL_TYPE_SIGNAL: __ASSERT(event->signal != NULL, "invalid poll signal\n"); - sys_dlist_remove(&event->_node); + remove = true; break; case K_POLL_TYPE_IGNORE: /* nothing to do */ @@ -155,6 +157,9 @@ static inline void clear_event_registration(struct k_poll_event *event) __ASSERT(false, "invalid event type\n"); break; } + if (remove && sys_dnode_is_linked(&event->_node)) { + sys_dlist_remove(&event->_node); + } } /* must be called with interrupts locked */ diff --git a/kernel/sched.c b/kernel/sched.c index b3e4bd33563f7..e757624ee0eb2 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -591,9 +591,13 @@ void _priq_dumb_remove(sys_dlist_t *pq, struct k_thread *thread) struct k_thread *_priq_dumb_best(sys_dlist_t *pq) { + struct k_thread *t = NULL; sys_dnode_t *n = sys_dlist_peek_head(pq); - return CONTAINER_OF(n, struct k_thread, base.qnode_dlist); + if (n != NULL) { + t = CONTAINER_OF(n, struct k_thread, base.qnode_dlist); + } + return t; } bool _priq_rb_lessthan(struct rbnode *a, struct rbnode *b) @@ -648,9 +652,13 @@ void _priq_rb_remove(struct _priq_rb *pq, struct k_thread *thread) struct k_thread *_priq_rb_best(struct _priq_rb *pq) { + struct k_thread *t = NULL; struct rbnode *n = rb_get_min(&pq->tree); - return CONTAINER_OF(n, struct k_thread, base.qnode_rb); + if (n != NULL) { + t = CONTAINER_OF(n, struct k_thread, base.qnode_rb); + } + return t; } #ifdef CONFIG_SCHED_MULTIQ @@ -683,10 +691,14 @@ struct k_thread *_priq_mq_best(struct _priq_mq *pq) return NULL; } + struct k_thread *t = NULL; sys_dlist_t *l = &pq->queues[__builtin_ctz(pq->bitmask)]; sys_dnode_t *n = sys_dlist_peek_head(l); - return CONTAINER_OF(n, struct k_thread, base.qnode_dlist); + if (n != NULL) { + t = CONTAINER_OF(n, struct k_thread, base.qnode_dlist); + } + return t; } int _unpend_all(_wait_q_t *wait_q) @@ -884,7 +896,7 @@ void _impl_k_wakeup(k_tid_t thread) return; } - if (_abort_thread_timeout(thread) == _INACTIVE) { + if (_abort_thread_timeout(thread) < 0) { irq_unlock(key); return; } diff --git a/kernel/timeout.c b/kernel/timeout.c index e435acff4dc80..2ce1296a54ad3 100644 --- a/kernel/timeout.c +++ b/kernel/timeout.c @@ -46,15 +46,11 @@ static struct _timeout *next(struct _timeout *t) static void remove_timeout(struct _timeout *t) { - if (t->node.next != NULL && t->node.prev != NULL) { - if (next(t) != NULL) { - next(t)->dticks += t->dticks; - } - - sys_dlist_remove(&t->node); + if (next(t) != NULL) { + next(t)->dticks += t->dticks; } - t->node.next = t->node.prev = NULL; - t->dticks = _INACTIVE; + + sys_dlist_remove(&t->node); } static s32_t elapsed(void) @@ -64,7 +60,7 @@ static s32_t elapsed(void) void _add_timeout(struct _timeout *to, _timeout_func_t fn, s32_t ticks) { - __ASSERT(to->dticks < 0, ""); + __ASSERT(!sys_dnode_is_linked(&to->node), ""); to->fn = fn; ticks = max(1, ticks); @@ -96,10 +92,10 @@ void _add_timeout(struct _timeout *to, _timeout_func_t fn, s32_t ticks) int _abort_timeout(struct _timeout *to) { - int ret = _INACTIVE; + int ret = -EINVAL; LOCKED(&timeout_lock) { - if (to->dticks != _INACTIVE) { + if (sys_dnode_is_linked(&to->node)) { remove_timeout(to); ret = 0; } @@ -112,7 +108,7 @@ s32_t z_timeout_remaining(struct _timeout *timeout) { s32_t ticks = 0; - if (timeout->dticks == _INACTIVE) { + if (_is_inactive_timeout(timeout)) { return 0; } diff --git a/kernel/timer.c b/kernel/timer.c index 544c5b1731f87..ce49859b732b5 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -150,7 +150,7 @@ Z_SYSCALL_HANDLER(k_timer_start, timer, duration_p, period_p) void _impl_k_timer_stop(struct k_timer *timer) { unsigned int key = irq_lock(); - bool inactive = (_abort_timeout(&timer->timeout) == _INACTIVE); + int inactive = _abort_timeout(&timer->timeout) != 0; irq_unlock(key); @@ -203,7 +203,7 @@ u32_t _impl_k_timer_status_sync(struct k_timer *timer) u32_t result = timer->status; if (result == 0) { - if (timer->timeout.dticks != _INACTIVE) { + if (!_is_inactive_timeout(&timer->timeout)) { /* wait for timer to expire or stop */ (void)_pend_current_thread(key, &timer->wait_q, K_FOREVER); diff --git a/tests/kernel/common/src/dlist.c b/tests/kernel/common/src/dlist.c index 686f4396833f8..95ba0eaa98c62 100644 --- a/tests/kernel/common/src/dlist.c +++ b/tests/kernel/common/src/dlist.c @@ -189,9 +189,13 @@ void test_dlist(void) "test_list head/tail are wrong"); /* Finding and removing node 1 */ + zassert_true(sys_dnode_is_linked(&test_node_1.node), + "node1 is not linked"); sys_dlist_remove(&test_node_1.node); zassert_true((verify_emptyness(&test_list)), "test_list should be empty"); + zassert_false(sys_dnode_is_linked(&test_node_1.node), + "node1 is still linked"); /* Prepending node 1 */ sys_dlist_prepend(&test_list, &test_node_1.node);