Subversion Repositories HelenOS

Rev

Rev 2446 | Rev 2632 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2446 Rev 2504
Line 44... Line 44...
44
#include <atomic.h>
44
#include <atomic.h>
45
#include <synch/spinlock.h>
45
#include <synch/spinlock.h>
46
#include <synch/waitq.h>
46
#include <synch/waitq.h>
47
#include <arch.h>
47
#include <arch.h>
48
#include <panic.h>
48
#include <panic.h>
-
 
49
#include <adt/avl.h>
49
#include <adt/btree.h>
50
#include <adt/btree.h>
50
#include <adt/list.h>
51
#include <adt/list.h>
51
#include <ipc/ipc.h>
52
#include <ipc/ipc.h>
52
#include <security/cap.h>
53
#include <security/cap.h>
53
#include <memstr.h>
54
#include <memstr.h>
Line 59... Line 60...
59
 
60
 
60
#ifndef LOADED_PROG_STACK_PAGES_NO
61
#ifndef LOADED_PROG_STACK_PAGES_NO
61
#define LOADED_PROG_STACK_PAGES_NO 1
62
#define LOADED_PROG_STACK_PAGES_NO 1
62
#endif
63
#endif
63
 
64
 
64
/** Spinlock protecting the tasks_btree B+tree. */
65
/** Spinlock protecting the tasks_tree AVL tree. */
65
SPINLOCK_INITIALIZE(tasks_lock);
66
SPINLOCK_INITIALIZE(tasks_lock);
66
 
67
 
67
/** B+tree of active tasks.
68
/** AVL tree of active tasks.
68
 *
69
 *
69
 * The task is guaranteed to exist after it was found in the tasks_btree as
70
 * The task is guaranteed to exist after it was found in the tasks_tree as
70
 * long as:
71
 * long as:
71
 * @li the tasks_lock is held,
72
 * @li the tasks_lock is held,
72
 * @li the task's lock is held when task's lock is acquired before releasing
73
 * @li the task's lock is held when task's lock is acquired before releasing
73
 *     tasks_lock or
74
 *     tasks_lock or
74
 * @li the task's refcount is greater than 0
75
 * @li the task's refcount is greater than 0
75
 *
76
 *
76
 */
77
 */
77
btree_t tasks_btree;
78
avltree_t tasks_tree;
78
 
79
 
79
static task_id_t task_counter = 0;
80
static task_id_t task_counter = 0;
80
 
81
 
81
/** Initialize tasks
82
/** Initialize tasks
82
 *
83
 *
Line 84... Line 85...
84
 *
85
 *
85
 */
86
 */
86
void task_init(void)
87
void task_init(void)
87
{
88
{
88
    TASK = NULL;
89
    TASK = NULL;
89
    btree_create(&tasks_btree);
90
    avltree_create(&tasks_tree);
-
 
91
}
-
 
92
 
-
 
93
/*
-
 
94
 * The idea behind this walker is to remember a single task different from TASK.
-
 
95
 */
-
 
96
static bool task_done_walker(avltree_node_t *node, void *arg)
-
 
97
{
-
 
98
    task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
-
 
99
    task_t **tp = (task_t **) arg;
-
 
100
 
-
 
101
    if (t != TASK) {
-
 
102
        *tp = t;
-
 
103
        return false;   /* stop walking */
-
 
104
    }
-
 
105
 
-
 
106
    return true;    /* continue the walk */
90
}
107
}
91
 
108
 
92
/** Kill all tasks except the current task.
109
/** Kill all tasks except the current task.
93
 *
110
 *
94
 */
111
 */
Line 100... Line 117...
100
        /* Messing with task structures, avoid deadlock */
117
        /* Messing with task structures, avoid deadlock */
101
        ipl_t ipl = interrupts_disable();
118
        ipl_t ipl = interrupts_disable();
102
        spinlock_lock(&tasks_lock);
119
        spinlock_lock(&tasks_lock);
103
       
120
       
104
        t = NULL;
121
        t = NULL;
105
        link_t *cur;
-
 
106
        for (cur = tasks_btree.leaf_head.next;
122
        avltree_walk(&tasks_tree, task_done_walker, &t);
107
            cur != &tasks_btree.leaf_head; cur = cur->next) {
-
 
108
            btree_node_t *node;
-
 
109
           
-
 
110
            node = list_get_instance(cur, btree_node_t, leaf_link);
-
 
111
           
-
 
112
            unsigned int i;
-
 
113
            for (i = 0; i < node->keys; i++) {
-
 
114
                if ((task_t *) node->value[i] != TASK) {
-
 
115
                    t = (task_t *) node->value[i];
-
 
116
                    break;
-
 
117
                }
-
 
118
            }
-
 
119
        }
-
 
120
       
123
       
121
        if (t != NULL) {
124
        if (t != NULL) {
122
            task_id_t id = t->taskid;
125
            task_id_t id = t->taskid;
123
           
126
           
124
            spinlock_unlock(&tasks_lock);
127
            spinlock_unlock(&tasks_lock);
Line 185... Line 188...
185
     */
188
     */
186
    atomic_inc(&as->refcount);
189
    atomic_inc(&as->refcount);
187
 
190
 
188
    spinlock_lock(&tasks_lock);
191
    spinlock_lock(&tasks_lock);
189
    ta->taskid = ++task_counter;
192
    ta->taskid = ++task_counter;
-
 
193
    avltree_node_initialize(&ta->tasks_tree_node);
-
 
194
    ta->tasks_tree_node.key = ta->taskid;
190
    btree_insert(&tasks_btree, (btree_key_t) ta->taskid, (void *) ta, NULL);
195
    avltree_insert(&tasks_tree, &ta->tasks_tree_node);
191
    spinlock_unlock(&tasks_lock);
196
    spinlock_unlock(&tasks_lock);
192
    interrupts_restore(ipl);
197
    interrupts_restore(ipl);
193
 
198
 
194
    return ta;
199
    return ta;
195
}
200
}
Line 202... Line 207...
202
{
207
{
203
    /*
208
    /*
204
     * Remove the task from the task B+tree.
209
     * Remove the task from the task B+tree.
205
     */
210
     */
206
    spinlock_lock(&tasks_lock);
211
    spinlock_lock(&tasks_lock);
207
    btree_remove(&tasks_btree, t->taskid, NULL);
212
    avltree_delete(&tasks_tree, &t->tasks_tree_node);
208
    spinlock_unlock(&tasks_lock);
213
    spinlock_unlock(&tasks_lock);
209
 
214
 
210
    /*
215
    /*
211
     * Perform architecture specific task destruction.
216
     * Perform architecture specific task destruction.
212
     */
217
     */
Line 308... Line 313...
308
 *
313
 *
309
 * @return Task structure address or NULL if there is no such task ID.
314
 * @return Task structure address or NULL if there is no such task ID.
310
 */
315
 */
311
task_t *task_find_by_id(task_id_t id)
316
task_t *task_find_by_id(task_id_t id)
312
{
317
{
313
    btree_node_t *leaf;
318
    avltree_node_t *node;
314
   
319
   
315
    return (task_t *) btree_search(&tasks_btree, (btree_key_t) id, &leaf);
320
    node = avltree_search(&tasks_tree, (avltree_key_t) id);
-
 
321
 
-
 
322
    if (node)
-
 
323
        return avltree_get_instance(node, task_t, tasks_tree_node);
-
 
324
    return NULL;
316
}
325
}
317
 
326
 
318
/** Get accounting data of given task.
327
/** Get accounting data of given task.
319
 *
328
 *
320
 * Note that task lock of 't' must be already held and
329
 * Note that task lock of 't' must be already held and
Line 398... Line 407...
398
    interrupts_restore(ipl);
407
    interrupts_restore(ipl);
399
   
408
   
400
    return 0;
409
    return 0;
401
}
410
}
402
 
411
 
-
 
412
static bool task_print_walker(avltree_node_t *node, void *arg)
-
 
413
{
-
 
414
    task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
-
 
415
    int j;
-
 
416
       
-
 
417
    spinlock_lock(&t->lock);
-
 
418
           
-
 
419
    uint64_t cycles;
-
 
420
    char suffix;
-
 
421
    order(task_get_accounting(t), &cycles, &suffix);
-
 
422
           
-
 
423
    printf("%-6llu %-10s %-3ld %#10zx %#10zx %9llu%c %7zd %6zd",
-
 
424
        t->taskid, t->name, t->context, t, t->as, cycles, suffix,
-
 
425
        t->refcount, atomic_get(&t->active_calls));
-
 
426
    for (j = 0; j < IPC_MAX_PHONES; j++) {
-
 
427
        if (t->phones[j].callee)
-
 
428
            printf(" %zd:%#zx", j, t->phones[j].callee);
-
 
429
    }
-
 
430
    printf("\n");
-
 
431
           
-
 
432
    spinlock_unlock(&t->lock);
-
 
433
    return true;
-
 
434
}
-
 
435
 
403
/** Print task list */
436
/** Print task list */
404
void task_print_list(void)
437
void task_print_list(void)
405
{
438
{
406
    link_t *cur;
-
 
407
    ipl_t ipl;
439
    ipl_t ipl;
408
   
440
   
409
    /* Messing with task structures, avoid deadlock */
441
    /* Messing with task structures, avoid deadlock */
410
    ipl = interrupts_disable();
442
    ipl = interrupts_disable();
411
    spinlock_lock(&tasks_lock);
443
    spinlock_lock(&tasks_lock);
Line 413... Line 445...
413
    printf("taskid name       ctx address    as         cycles     threads "
445
    printf("taskid name       ctx address    as         cycles     threads "
414
        "calls  callee\n");
446
        "calls  callee\n");
415
    printf("------ ---------- --- ---------- ---------- ---------- ------- "
447
    printf("------ ---------- --- ---------- ---------- ---------- ------- "
416
        "------ ------>\n");
448
        "------ ------>\n");
417
 
449
 
418
    for (cur = tasks_btree.leaf_head.next; cur != &tasks_btree.leaf_head;
-
 
419
        cur = cur->next) {
-
 
420
        btree_node_t *node;
-
 
421
        unsigned int i;
-
 
422
       
-
 
423
        node = list_get_instance(cur, btree_node_t, leaf_link);
-
 
424
        for (i = 0; i < node->keys; i++) {
-
 
425
            task_t *t;
-
 
426
            int j;
-
 
427
 
-
 
428
            t = (task_t *) node->value[i];
-
 
429
       
-
 
430
            spinlock_lock(&t->lock);
-
 
431
           
-
 
432
            uint64_t cycles;
-
 
433
            char suffix;
-
 
434
            order(task_get_accounting(t), &cycles, &suffix);
450
    avltree_walk(&tasks_tree, task_print_walker, NULL);
435
           
-
 
436
            printf("%-6llu %-10s %-3ld %#10zx %#10zx %9llu%c %7zd "
-
 
437
                "%6zd", t->taskid, t->name, t->context, t, t->as,
-
 
438
                cycles, suffix, t->refcount,
-
 
439
                atomic_get(&t->active_calls));
-
 
440
            for (j = 0; j < IPC_MAX_PHONES; j++) {
-
 
441
                if (t->phones[j].callee)
-
 
442
                    printf(" %zd:%#zx", j,
-
 
443
                        t->phones[j].callee);
-
 
444
            }
-
 
445
            printf("\n");
-
 
446
           
-
 
447
            spinlock_unlock(&t->lock);
-
 
448
        }
-
 
449
    }
-
 
450
 
451
 
451
    spinlock_unlock(&tasks_lock);
452
    spinlock_unlock(&tasks_lock);
452
    interrupts_restore(ipl);
453
    interrupts_restore(ipl);
453
}
454
}
454
 
455