Changeset ef1eab7 in mainline for kernel/generic/src/proc/task.c


Ignore:
Timestamp:
2018-11-03T21:36:39Z (5 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
aab5e46
Parents:
ad2cf04
Message:

Replace AVL trees in kernel with ordered dictionary.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/proc/task.c

    rad2cf04 ref1eab7  
    11/*
    22 * Copyright (c) 2010 Jakub Jermar
     3 * Copyright (c) 2018 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    4748#include <arch.h>
    4849#include <barrier.h>
    49 #include <adt/avl.h>
    5050#include <adt/btree.h>
    5151#include <adt/list.h>
     52#include <adt/odict.h>
    5253#include <cap/cap.h>
    5354#include <ipc/ipc.h>
     
    6162#include <macros.h>
    6263
    63 /** Spinlock protecting the tasks_tree AVL tree. */
     64/** Spinlock protecting the @c tasks ordered dictionary. */
    6465IRQ_SPINLOCK_INITIALIZE(tasks_lock);
    6566
    66 /** AVL tree of active tasks.
    67  *
    68  * The task is guaranteed to exist after it was found in the tasks_tree as
    69  * long as:
     67/** Ordered dictionary of active tasks.
     68 *
     69 * The task is guaranteed to exist after it was found in the @c tasks
     70 * dictionary as long as:
    7071 *
    7172 * @li the tasks_lock is held,
     
    7576 *
    7677 */
    77 avltree_t tasks_tree;
     78odict_t tasks;
    7879
    7980static task_id_t task_counter = 0;
     
    8485static void task_kill_internal(task_t *);
    8586static errno_t tsk_constructor(void *, unsigned int);
    86 static size_t tsk_destructor(void *obj);
     87static size_t tsk_destructor(void *);
     88
     89static void *tasks_getkey(odlink_t *);
     90static int tasks_cmp(void *, void *);
    8791
    8892/** Initialize kernel tasks support.
     
    9296{
    9397        TASK = NULL;
    94         avltree_create(&tasks_tree);
     98        odict_initialize(&tasks, tasks_getkey, tasks_cmp);
    9599        task_cache = slab_cache_create("task_t", sizeof(task_t), 0,
    96100            tsk_constructor, tsk_destructor, 0);
    97101}
    98102
    99 /** Task finish walker.
    100  *
    101  * The idea behind this walker is to kill and count all tasks different from
    102  * TASK.
    103  *
    104  */
    105 static bool task_done_walker(avltree_node_t *node, void *arg)
    106 {
    107         task_t *task = avltree_get_instance(node, task_t, tasks_tree_node);
    108         size_t *cnt = (size_t *) arg;
    109 
    110         if (task != TASK) {
    111                 (*cnt)++;
    112 
    113 #ifdef CONFIG_DEBUG
    114                 printf("[%" PRIu64 "] ", task->taskid);
    115 #endif
    116 
    117                 task_kill_internal(task);
    118         }
    119 
    120         /* Continue the walk */
    121         return true;
    122 }
    123 
    124103/** Kill all tasks except the current task.
    125104 *
     
    128107{
    129108        size_t tasks_left;
     109        odlink_t *odlink;
     110        task_t *task;
    130111
    131112        if (ipc_box_0) {
     
    144125                printf("Killing tasks... ");
    145126#endif
    146 
    147127                irq_spinlock_lock(&tasks_lock, true);
    148128                tasks_left = 0;
    149                 avltree_walk(&tasks_tree, task_done_walker, &tasks_left);
     129
     130                odlink = odict_first(&tasks);
     131                while (odlink != NULL) {
     132                        task = odict_get_instance(odlink, task_t, ltasks);
     133
     134                        if (task != TASK) {
     135                                tasks_left++;
     136#ifdef CONFIG_DEBUG
     137                                printf("[%" PRIu64 "] ", task->taskid);
     138#endif
     139                                task_kill_internal(task);
     140                        }
     141
     142                        odlink = odict_next(odlink, &tasks);
     143                }
     144
    150145                irq_spinlock_unlock(&tasks_lock, true);
    151146
     
    269264
    270265        task->taskid = ++task_counter;
    271         avltree_node_initialize(&task->tasks_tree_node);
    272         task->tasks_tree_node.key = task->taskid;
    273         avltree_insert(&tasks_tree, &task->tasks_tree_node);
     266        odlink_initialize(&task->ltasks);
     267        odict_insert(&task->ltasks, &tasks, NULL);
    274268
    275269        irq_spinlock_unlock(&tasks_lock, true);
     
    289283         */
    290284        irq_spinlock_lock(&tasks_lock, true);
    291         avltree_delete(&tasks_tree, &task->tasks_tree_node);
     285        odict_remove(&task->ltasks);
    292286        irq_spinlock_unlock(&tasks_lock, true);
    293287
     
    451445        assert(irq_spinlock_locked(&tasks_lock));
    452446
    453         avltree_node_t *node =
    454             avltree_search(&tasks_tree, (avltree_key_t) id);
    455 
    456         if (node)
    457                 return avltree_get_instance(node, task_t, tasks_tree_node);
     447        odlink_t *odlink = odict_find_eq(&tasks, &id, NULL);
     448        if (odlink != NULL)
     449                return odict_get_instance(odlink, task_t, ltasks);
    458450
    459451        return NULL;
     
    604596}
    605597
    606 static bool task_print_walker(avltree_node_t *node, void *arg)
    607 {
    608         bool *additional = (bool *) arg;
    609         task_t *task = avltree_get_instance(node, task_t, tasks_tree_node);
     598static void task_print(task_t *task, bool additional)
     599{
    610600        irq_spinlock_lock(&task->lock, false);
    611601
     
    618608
    619609#ifdef __32_BITS__
    620         if (*additional)
     610        if (additional)
    621611                printf("%-8" PRIu64 " %9zu", task->taskid,
    622612                    atomic_load(&task->refcount));
     
    629619
    630620#ifdef __64_BITS__
    631         if (*additional)
     621        if (additional)
    632622                printf("%-8" PRIu64 " %9" PRIu64 "%c %9" PRIu64 "%c "
    633623                    "%9zu\n", task->taskid, ucycles, usuffix, kcycles,
     
    639629
    640630        irq_spinlock_unlock(&task->lock, false);
    641         return true;
    642631}
    643632
     
    669658#endif
    670659
    671         avltree_walk(&tasks_tree, task_print_walker, &additional);
     660        odlink_t *odlink;
     661        task_t *task;
     662
     663        odlink = odict_first(&tasks);
     664        while (odlink != NULL) {
     665                task = odict_get_instance(odlink, task_t, ltasks);
     666                task_print(task, additional);
     667                odlink = odict_next(odlink, &tasks);
     668        }
    672669
    673670        irq_spinlock_unlock(&tasks_lock, true);
    674671}
    675672
     673/** Get key function for the @c tasks ordered dictionary.
     674 *
     675 * @param odlink Link
     676 * @return Pointer to task ID cast as 'void *'
     677 */
     678static void *tasks_getkey(odlink_t *odlink)
     679{
     680        task_t *task = odict_get_instance(odlink, task_t, ltasks);
     681        return (void *) &task->taskid;
     682}
     683
     684/** Key comparison function for the @c tasks ordered dictionary.
     685 *
     686 * @param a Pointer to thread A ID
     687 * @param b Pointer to thread B ID
     688 * @return -1, 0, 1 iff ID A is less than, equal to, greater than B
     689 */
     690static int tasks_cmp(void *a, void *b)
     691{
     692        task_id_t ida = *(task_id_t *)a;
     693        task_id_t idb = *(task_id_t *)b;
     694
     695        if (ida < idb)
     696                return -1;
     697        else if (ida == idb)
     698                return 0;
     699        else
     700                return +1;
     701}
     702
    676703/** @}
    677704 */
Note: See TracChangeset for help on using the changeset viewer.