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 | ||