From 472c71d3f47caaf390054202a1613b5df2a74bec Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Fri, 25 Oct 2024 11:17:26 -0700 Subject: [PATCH] kernel: Add method to dequeue from a dlist Dequeuing from a doubly linked list is similar to removing an item except that it does not re-initialize the dequeued node. This comes in handy when sorting a doubly linked list (where the node gets removed and re-added). In that circumstance, re-initializing the node is required. Furthermore, the compiler does not always 'understand' this. Thus, when performance is critical, dequeuing may be preferred to removing. Signed-off-by: Peter Mitsis --- include/zephyr/sys/dlist.h | 23 +++++++++++++++++++++++ kernel/include/priority_q.h | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/zephyr/sys/dlist.h b/include/zephyr/sys/dlist.h index c7c5c5553ad..2e1a9e741d2 100644 --- a/include/zephyr/sys/dlist.h +++ b/include/zephyr/sys/dlist.h @@ -492,6 +492,29 @@ static inline void sys_dlist_insert_at(sys_dlist_t *list, sys_dnode_t *node, } } +/** + * @brief remove a specific node from a list + * + * Like :c:func:`sys_dlist_remove()`, this routine removes a specific node + * from a list. However, unlike :c:func:`sys_dlist_remove()`, this routine + * does not re-initialize the removed node. One significant implication of + * this difference is that the function :c:func`sys_dnode_is_linked()` will + * not work on a dequeued node. + * + * The list is implicit from the node. The node must be part of a list. + * This and other sys_dlist_*() functions are not thread safe. + * + * @param node the node to dequeue + */ +static inline void sys_dlist_dequeue(sys_dnode_t *node) +{ + sys_dnode_t *const prev = node->prev; + sys_dnode_t *const next = node->next; + + prev->next = next; + next->prev = prev; +} + /** * @brief remove a specific node from a list * diff --git a/kernel/include/priority_q.h b/kernel/include/priority_q.h index ed5c839decc..c4c95a7aeaa 100644 --- a/kernel/include/priority_q.h +++ b/kernel/include/priority_q.h @@ -241,8 +241,8 @@ static ALWAYS_INLINE void z_priq_mq_remove(struct _priq_mq *pq, { struct prio_info pos = get_prio_info(thread->base.prio); - sys_dlist_remove(&thread->base.qnode_dlist); - if (sys_dlist_is_empty(&pq->queues[pos.offset_prio])) { + sys_dlist_dequeue(&thread->base.qnode_dlist); + if (unlikely(sys_dlist_is_empty(&pq->queues[pos.offset_prio]))) { pq->bitmask[pos.idx] &= ~BIT(pos.bit); } }