diff --git a/core/clist.c b/core/clist.c
deleted file mode 100644
index f5da2f73752e0ef5ed3d06483f34aca9d20b7269..0000000000000000000000000000000000000000
--- a/core/clist.c
+++ /dev/null
@@ -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
diff --git a/core/include/clist.h b/core/include/clist.h
index 8ab57e034ce742bcda66e8cbc178ad417f53e72f..beda190a5af640166071a4bbd8e2deb5b762f074 100644
--- a/core/include/clist.h
+++ b/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
diff --git a/core/include/sched.h b/core/include/sched.h
index b179a636b7e5dc9df13df06383f1567bd5f38a4b..346f4d66823d73d86db2574e9be70b91cc445f25 100644
--- a/core/include/sched.h
+++ b/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
diff --git a/core/include/thread.h b/core/include/thread.h
index 68ca58fedc71289a337cdad21ab1aab8e0222132..fdcb444a055eb5696ab104299b50aa39ed43ce71 100644
--- a/core/include/thread.h
+++ b/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            */
 
diff --git a/core/mutex.c b/core/mutex.c
index f97e088eb8d02ea9e818661213744c56baf0c622..8bfae23d282b01a4a22d854920828113a1a12d09 100644
--- a/core/mutex.c
+++ b/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);
 
diff --git a/core/sched.c b/core/sched.c
index d3fe4e116f795ea303e9b03f5a41b2a0d3dfda2c..151649aad2b300fa3ad13ff2c424a3b9ec9dff1f 100644
--- a/core/sched.c
+++ b/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);
             }
         }
diff --git a/core/thread.c b/core/thread.c
index a1c1ab56a8a1bfa4541c1745946fe5f3cbcc68f3..1cac0574b7a4f2d4a38b313a739b69d878bfd52a 100644
--- a/core/thread.c
+++ b/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;