From 7c39134d5d3bab79274ea3affbef62202c54d570 Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser <kaspar@schleiser.de> Date: Sat, 17 Jan 2015 15:17:19 +0100 Subject: [PATCH] core: introduce intrusive singly linked list --- core/include/list.h | 77 +++++++++++++++++++++++++++++++++++++++++++ core/include/thread.h | 16 +++++++++ core/thread.c | 20 +++++++++++ 3 files changed, 113 insertions(+) create mode 100644 core/include/list.h diff --git a/core/include/list.h b/core/include/list.h new file mode 100644 index 0000000000..375827696a --- /dev/null +++ b/core/include/list.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de> + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + + /** + * @addtogroup core_util + * @{ + * + * @file + * @brief Intrusive linked list + * + * Lists are represented as element pointing to the first actual list element. + * + * @author Kaspar Schleiser <kaspar@schleiser.de> + */ + +#ifndef LIST_H +#define LIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief List node structure + * + * Used as is as reference to a list, or as member of any data structure that + * should be member of a list. + * + * Actual list objects should have a @c list_node_t as member and then use + * the container_of() macro in list operations. + * See @ref thread_add_to_list() as example. + */ +typedef struct list_node { + struct list_node *next; /**< pointer to next list entry */ +} list_node_t; + +/** + * @brief Insert object into list + * + * If called with a list reference as node, the new node will become the new + * list head. + * + * @param[in] node list node before new entry + * @param[in] new_node list node to insert + */ +static inline void list_add(list_node_t *node, list_node_t *new_node) { + new_node->next = node->next; + node->next = new_node; +} + +/** + * @brief Removes the head of the list and returns it + * + * @param[in] list Pointer to the list itself, where list->next points + * to the root node + * + * @return removed old list head, or NULL if empty + */ +static inline list_node_t* list_remove_head(list_node_t *list) { + list_node_t* head = list->next; + if (head) { + list->next = head->next; + } + return head; +} + +#ifdef __cplusplus +} +#endif + +#endif /* LIST_H */ +/** @} */ diff --git a/core/include/thread.h b/core/include/thread.h index cec1b7bcdb..68ca58fedc 100644 --- a/core/include/thread.h +++ b/core/include/thread.h @@ -29,6 +29,7 @@ #include "arch/thread_arch.h" #include "cpu_conf.h" #include "sched.h" +#include "list.h" #ifdef __cplusplus extern "C" { @@ -315,6 +316,21 @@ char *thread_stack_init(thread_task_func_t task_func, void *arg, void *stack_sta */ void thread_print_msg_queue(void); +/** + * @brief Add thread to list, sorted by priority (internal) + * + * This will add @p thread to @p list sorted by the thread priority. + * It reuses the thread's rq_entry field. + * Used internally by msg and mutex implementations. + * + * @note Only use for threads *not on any runqueue* and with interrupts + * disabled. + * + * @param[in] list ptr to list root node + * @param[in] thread thread to add + */ +void thread_add_to_list(list_node_t *list, thread_t *thread); + #ifdef DEVELHELP /** * @brief Returns the name of a process diff --git a/core/thread.c b/core/thread.c index 4fadbf3014..a1c1ab56a8 100644 --- a/core/thread.c +++ b/core/thread.c @@ -21,6 +21,7 @@ #include <errno.h> #include <stdio.h> +#include "assert.h" #include "thread.h" #include "irq.h" @@ -104,6 +105,25 @@ void thread_yield(void) thread_yield_higher(); } +void thread_add_to_list(list_node_t *list, thread_t *thread) +{ + assert (thread->status < STATUS_ON_RUNQUEUE); + + uint16_t my_prio = thread->priority; + list_node_t *new_node = (list_node_t*)&thread->rq_entry; + + while (list->next) { + thread_t *list_entry = container_of((clist_node_t*)list->next, thread_t, rq_entry); + if (list_entry->priority > my_prio) { + break; + } + list = list->next; + } + + new_node->next = list->next; + list->next = new_node; +} + #ifdef DEVELHELP uintptr_t thread_measure_stack_free(char *stack) { -- GitLab