Browse Source

core: clist: make singly linked

pr/gpio
Kaspar Schleiser 7 years ago
parent
commit
f9f6adb48d
  1. 79
      core/clist.c
  2. 91
      core/include/clist.h
  3. 2
      core/include/sched.h
  4. 5
      core/include/thread.h
  5. 2
      core/mutex.c
  6. 10
      core/sched.c
  7. 1
      core/thread.c

79
core/clist.c

@ -1,79 +0,0 @@
/*
* Copyright (C) 2013 Freie Universität Berlin
*
* 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.
*/
/**
* @ingroup core_util
* @{
*
* @file
* @brief Circular linked list implementation
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*
* @}
*/
#include <stddef.h>
#include "clist.h"
#include <stdio.h>
/* inserts new_node after node */
void clist_add(clist_node_t **node, clist_node_t *new_node)
{
if (*node != NULL) {
new_node->next = (*node);
new_node->prev = (*node)->prev;
(*node)->prev->next = new_node;
(*node)->prev = new_node;
if ((*node)->prev == *node) {
(*node)->prev = new_node;
}
}
else {
*node = new_node;
new_node->next = new_node;
new_node->prev = new_node;
}
}
/* removes node. */
void clist_remove(clist_node_t **list, clist_node_t *node)
{
if (node->next != node) {
node->prev->next = node->next;
node->next->prev = node->prev;
if (node == *list) {
*list = node->next;
}
}
else {
*list = NULL;
}
}
#if ENABLE_DEBUG
void clist_print(clist_node_t *clist)
{
clist_node_t *start = clist, *node = start;
if (!start) {
return;
}
do {
printf("list entry: %p: prev=%p next=%p\n",
(void *)clist, (void *)clist->prev, (void *)clist->next);
clist = clist->next;
if (clist == start) {
break;
}
} while (node != start);
}
#endif

91
core/include/clist.h

@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 Freie Universität Berlin
* Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
* 2013 Freie Universität Berlin
*
* 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
@ -13,6 +14,14 @@
* @file
* @brief Circular linked list
*
* This file contains a circularly linked list implementation.
*
* clist_insert(), clist_remove_head() and clist_advance() take constant time.
*
* Each list is represented as a "clist_node_t". It's only member, the "next"
* pointer, points to the last entry in the list, whose "next" pointer points to
* the first entry.
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
@ -20,51 +29,67 @@
#define CLIST_H
#include "kernel_defines.h"
#include "list.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @def clist_get_container(NODE, TYPE, MEMBER)
* @brief Returns the container of the circular list
* @details For a struct `TYPE` with a member `MEMBER`, which is a `clist_node_t`,
* given a pointer `NODE` to `TYPE::MEMBER` this function returns a pointer
* to the instance of `TYPE`.
* @details E.g. for `struct my_struct_t { ...; clist_node_t n; ... } my_struct;`,
* `&my_struct == clist_get_container(&my_struct.n, struct my_struct_t, n)`.
* @param[in] NODE pointer to a member
* @param[in] TYPE a type name (a struct or union), container of NODE
* @param[in] MEMBER name of the member of TYPE which NODE points to
* @return Pointer to the container of NODE.
*/
#define clist_get_container(NODE, TYPE, MEMBER) container_of(NODE, TYPE, MEMBER)
/**
* @brief Structure representing a node in the clist.
* @brief List node structure
*
* Used as is as reference to a list.
*
* clist stores a pointer to the last element of a list. That way, both
* appending to end of list and removing head can be done in constant time.
*
* Actual list objects should have a @c clist_node_t as member and then use
* the container_of() macro in list operations.
* See @ref thread_add_to_list() as example.
*/
typedef struct clist_node_t {
struct clist_node_t *next; /**< pointer to next node */
struct clist_node_t *prev; /**< pointer to the previous node */
} clist_node_t;
typedef list_node_t clist_node_t;
/**
* @brief Inserts *new_node* after *node* into list
* @brief inserts *new_node* into *list*
*
* @param[in,out] node Node after which *new_node* gets inserted
* @param[in,out] new_node Node which gets inserted after *node*.
* @param[in,out] list Ptr to clist
* @param[in,out] new_node Node which gets inserted.
* Must not be NULL.
*/
void clist_add(clist_node_t **node, clist_node_t *new_node);
static inline void clist_insert(clist_node_t *list, clist_node_t *new_node)
{
if (list->next) {
new_node->next = list->next->next;
list->next->next = new_node;
}
else {
new_node->next = new_node;
}
list->next = new_node;
}
/**
* @brief Removes *node* from list
* @brief Removes and returns first element from list
*
* @param[in,out] list Pointer to the *list* to remove *node* from.
* @param[in] node Node to remove from *list*
* Must not be NULL.
* @param[in,out] list Pointer to the *list* to remove first element
* from.
*/
void clist_remove(clist_node_t **list, clist_node_t *node);
static inline clist_node_t *clist_remove_head(clist_node_t *list)
{
if (list->next) {
clist_node_t *first = list->next->next;
if (list->next == first) {
list->next = NULL;
}
else {
list->next->next = first->next;
}
return first;
}
else {
return NULL;
}
}
/**
* @brief Advances the circle list.
@ -75,9 +100,11 @@ void clist_remove(clist_node_t **list, clist_node_t *node);
*
* @param[in,out] list The list to work upon.
*/
static inline void clist_advance(clist_node_t **list)
static inline void clist_advance(clist_node_t *list)
{
*list = (*list)->next;
if (list->next) {
list->next = list->next->next;
}
}
#if ENABLE_DEBUG

2
core/include/sched.h

@ -167,7 +167,7 @@ extern volatile kernel_pid_t sched_active_pid;
/**
* List of runqueues per priority level
*/
extern clist_node_t *sched_runqueues[SCHED_PRIO_LEVELS];
extern clist_node_t sched_runqueues[SCHED_PRIO_LEVELS];
/**
* @brief Removes thread from scheduler and set status to #STATUS_STOPPED

5
core/include/thread.h

@ -30,6 +30,7 @@
#include "cpu_conf.h"
#include "sched.h"
#include "list.h"
#include "clist.h"
#ifdef __cplusplus
extern "C" {
@ -68,8 +69,8 @@
*/
struct _thread {
char *sp; /**< thread's stack pointer */
uint8_t status; /**< thread's status */
uint8_t priority; /**< thread's priority */
uint8_t status; /**< thread's status */
uint8_t priority; /**< thread's priority */
kernel_pid_t pid; /**< thread's process id */

2
core/mutex.c

@ -89,7 +89,7 @@ void mutex_unlock(mutex_t *mutex)
return;
}
list_node_t *next = (list_node_t*) list_remove_head(&mutex->queue);
list_node_t *next = list_remove_head(&mutex->queue);
thread_t *process = container_of((clist_node_t*)next, thread_t, rq_entry);

10
core/sched.c

@ -50,7 +50,7 @@ volatile thread_t *sched_active_thread;
volatile kernel_pid_t sched_active_pid = KERNEL_PID_UNDEF;
clist_node_t *sched_runqueues[SCHED_PRIO_LEVELS];
clist_node_t sched_runqueues[SCHED_PRIO_LEVELS];
static uint32_t runqueue_bitcache = 0;
#ifdef MODULE_SCHEDSTATISTICS
@ -68,7 +68,7 @@ int sched_run(void)
* since the threading should not be started before at least the idle thread was started.
*/
int nextrq = bitarithm_lsb(runqueue_bitcache);
thread_t *next_thread = clist_get_container(sched_runqueues[nextrq], thread_t, rq_entry);
thread_t *next_thread = container_of(sched_runqueues[nextrq].next->next, thread_t, rq_entry);
DEBUG("sched_run: active thread: %" PRIkernel_pid ", next thread: %" PRIkernel_pid "\n",
(active_thread == NULL) ? KERNEL_PID_UNDEF : active_thread->pid,
@ -133,7 +133,7 @@ void sched_set_status(thread_t *process, unsigned int status)
if (!(process->status >= STATUS_ON_RUNQUEUE)) {
DEBUG("sched_set_status: adding thread %" PRIkernel_pid " to runqueue %" PRIu16 ".\n",
process->pid, process->priority);
clist_add(&sched_runqueues[process->priority], &(process->rq_entry));
clist_insert(&sched_runqueues[process->priority], &(process->rq_entry));
runqueue_bitcache |= 1 << process->priority;
}
}
@ -141,9 +141,9 @@ void sched_set_status(thread_t *process, unsigned int status)
if (process->status >= STATUS_ON_RUNQUEUE) {
DEBUG("sched_set_status: removing thread %" PRIkernel_pid " to runqueue %" PRIu16 ".\n",
process->pid, process->priority);
clist_remove(&sched_runqueues[process->priority], &(process->rq_entry));
clist_remove_head(&sched_runqueues[process->priority]);
if (!sched_runqueues[process->priority]) {
if (!sched_runqueues[process->priority].next) {
runqueue_bitcache &= ~(1 << process->priority);
}
}

1
core/thread.c

@ -224,7 +224,6 @@ kernel_pid_t thread_create(char *stack, int stacksize, char priority, int flags,
cb->status = 0;
cb->rq_entry.next = NULL;
cb->rq_entry.prev = NULL;
cb->wait_data = NULL;

Loading…
Cancel
Save