Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2503 → Rev 2504

/trunk/kernel/generic/include/proc/task.h
41,6 → 41,7
#include <synch/mutex.h>
#include <synch/rwlock.h>
#include <synch/futex.h>
#include <adt/avl.h>
#include <adt/btree.h>
#include <adt/list.h>
#include <security/cap.h>
56,6 → 57,9
 
/** Task structure. */
typedef struct task {
/** Task's linkage for the tasks_tree AVL tree. */
avltree_node_t tasks_tree_node;
/** Task lock.
*
* Must be acquired before threads_lock and thread lock of any of its
106,7 → 110,7
} task_t;
 
SPINLOCK_EXTERN(tasks_lock);
extern btree_t tasks_btree;
extern avltree_t tasks_tree;
 
extern void task_init(void);
extern void task_done(void);
/trunk/kernel/generic/include/adt/avl.h
53,7 → 53,7
 
typedef uint64_t avltree_key_t;
 
typedef void (* avltree_walker_t)(avltree_node_t *);
typedef bool (* avltree_walker_t)(avltree_node_t *, void *);
 
/** AVL tree node structure. */
struct avltree_node
133,7 → 133,7
extern void avltree_insert(avltree_t *t, avltree_node_t *newnode);
extern void avltree_delete(avltree_t *t, avltree_node_t *node);
extern bool avltree_delete_min(avltree_t *t);
extern void avltree_walk(avltree_t *t, avltree_walker_t walker);
extern void avltree_walk(avltree_t *t, avltree_walker_t walker, void *arg);
 
#endif
 
/trunk/kernel/generic/src/proc/task.c
46,6 → 46,7
#include <synch/waitq.h>
#include <arch.h>
#include <panic.h>
#include <adt/avl.h>
#include <adt/btree.h>
#include <adt/list.h>
#include <ipc/ipc.h>
61,12 → 62,12
#define LOADED_PROG_STACK_PAGES_NO 1
#endif
 
/** Spinlock protecting the tasks_btree B+tree. */
/** Spinlock protecting the tasks_tree AVL tree. */
SPINLOCK_INITIALIZE(tasks_lock);
 
/** B+tree of active tasks.
/** AVL tree of active tasks.
*
* The task is guaranteed to exist after it was found in the tasks_btree as
* The task is guaranteed to exist after it was found in the tasks_tree as
* long as:
* @li the tasks_lock is held,
* @li the task's lock is held when task's lock is acquired before releasing
74,7 → 75,7
* @li the task's refcount is greater than 0
*
*/
btree_t tasks_btree;
avltree_t tasks_tree;
 
static task_id_t task_counter = 0;
 
86,9 → 87,25
void task_init(void)
{
TASK = NULL;
btree_create(&tasks_btree);
avltree_create(&tasks_tree);
}
 
/*
* The idea behind this walker is to remember a single task different from TASK.
*/
static bool task_done_walker(avltree_node_t *node, void *arg)
{
task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
task_t **tp = (task_t **) arg;
 
if (t != TASK) {
*tp = t;
return false; /* stop walking */
}
 
return true; /* continue the walk */
}
 
/** Kill all tasks except the current task.
*
*/
102,21 → 119,7
spinlock_lock(&tasks_lock);
t = NULL;
link_t *cur;
for (cur = tasks_btree.leaf_head.next;
cur != &tasks_btree.leaf_head; cur = cur->next) {
btree_node_t *node;
node = list_get_instance(cur, btree_node_t, leaf_link);
unsigned int i;
for (i = 0; i < node->keys; i++) {
if ((task_t *) node->value[i] != TASK) {
t = (task_t *) node->value[i];
break;
}
}
}
avltree_walk(&tasks_tree, task_done_walker, &t);
if (t != NULL) {
task_id_t id = t->taskid;
187,7 → 190,9
 
spinlock_lock(&tasks_lock);
ta->taskid = ++task_counter;
btree_insert(&tasks_btree, (btree_key_t) ta->taskid, (void *) ta, NULL);
avltree_node_initialize(&ta->tasks_tree_node);
ta->tasks_tree_node.key = ta->taskid;
avltree_insert(&tasks_tree, &ta->tasks_tree_node);
spinlock_unlock(&tasks_lock);
interrupts_restore(ipl);
 
204,7 → 209,7
* Remove the task from the task B+tree.
*/
spinlock_lock(&tasks_lock);
btree_remove(&tasks_btree, t->taskid, NULL);
avltree_delete(&tasks_tree, &t->tasks_tree_node);
spinlock_unlock(&tasks_lock);
 
/*
310,9 → 315,13
*/
task_t *task_find_by_id(task_id_t id)
{
btree_node_t *leaf;
avltree_node_t *node;
return (task_t *) btree_search(&tasks_btree, (btree_key_t) id, &leaf);
node = avltree_search(&tasks_tree, (avltree_key_t) id);
 
if (node)
return avltree_get_instance(node, task_t, tasks_tree_node);
return NULL;
}
 
/** Get accounting data of given task.
400,10 → 409,33
return 0;
}
 
static bool task_print_walker(avltree_node_t *node, void *arg)
{
task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
int j;
spinlock_lock(&t->lock);
uint64_t cycles;
char suffix;
order(task_get_accounting(t), &cycles, &suffix);
printf("%-6llu %-10s %-3ld %#10zx %#10zx %9llu%c %7zd %6zd",
t->taskid, t->name, t->context, t, t->as, cycles, suffix,
t->refcount, atomic_get(&t->active_calls));
for (j = 0; j < IPC_MAX_PHONES; j++) {
if (t->phones[j].callee)
printf(" %zd:%#zx", j, t->phones[j].callee);
}
printf("\n");
spinlock_unlock(&t->lock);
return true;
}
 
/** Print task list */
void task_print_list(void)
{
link_t *cur;
ipl_t ipl;
/* Messing with task structures, avoid deadlock */
415,39 → 447,8
printf("------ ---------- --- ---------- ---------- ---------- ------- "
"------ ------>\n");
 
for (cur = tasks_btree.leaf_head.next; cur != &tasks_btree.leaf_head;
cur = cur->next) {
btree_node_t *node;
unsigned int i;
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
task_t *t;
int j;
avltree_walk(&tasks_tree, task_print_walker, NULL);
 
t = (task_t *) node->value[i];
spinlock_lock(&t->lock);
uint64_t cycles;
char suffix;
order(task_get_accounting(t), &cycles, &suffix);
printf("%-6llu %-10s %-3ld %#10zx %#10zx %9llu%c %7zd "
"%6zd", t->taskid, t->name, t->context, t, t->as,
cycles, suffix, t->refcount,
atomic_get(&t->active_calls));
for (j = 0; j < IPC_MAX_PHONES; j++) {
if (t->phones[j].callee)
printf(" %zd:%#zx", j,
t->phones[j].callee);
}
printf("\n");
spinlock_unlock(&t->lock);
}
}
 
spinlock_unlock(&tasks_lock);
interrupts_restore(ipl);
}
/trunk/kernel/generic/src/proc/thread.c
577,7 → 577,7
interrupts_restore(ipl);
}
 
static void thread_walker(avltree_node_t *node)
static bool thread_walker(avltree_node_t *node, void *arg)
{
thread_t *t;
600,6 → 600,8
printf(" %#10zx", t->sleep_queue);
printf("\n");
 
return true;
}
 
/** Print list of threads debug info */
616,7 → 618,7
printf("------ ---------- ---------- -------- ---------- --- --------"
"-- ---------- ---------- ---- ---------\n");
 
avltree_walk(&threads_tree, thread_walker);
avltree_walk(&threads_tree, thread_walker, NULL);
 
spinlock_unlock(&threads_lock);
interrupts_restore(ipl);
/trunk/kernel/generic/src/adt/avl.c
685,24 → 685,44
return true;
}
 
static void _avltree_walk(avltree_node_t *node, avltree_walker_t walker)
/** Walk a subtree of an AVL tree in-order and apply a supplied walker on each
* visited node.
*
* @param node Node representing the root of an AVL subtree to be
* walked.
* @param walker Walker function that will be appliad on each visited
* node.
* @param arg Argument for the walker.
*
* @return Zero if the walk should stop or non-zero otherwise.
*/
static bool _avltree_walk(avltree_node_t *node, avltree_walker_t walker,
void *arg)
{
if (node->lft)
_avltree_walk(node->lft, walker);
walker(node);
if (node->rgt)
_avltree_walk(node->rgt, walker);
if (node->lft) {
if (!_avltree_walk(node->lft, walker, arg))
return false;
}
if (!walker(node, arg))
return false;
if (node->rgt) {
if (!_avltree_walk(node->rgt, walker, arg))
return false;
}
return true;
}
 
/** Walk the AVL tree and apply the walker function on each visited node.
/** Walk the AVL tree in-order and apply the walker function on each visited
* node.
*
* @param t AVL tree to be walked.
* @param walker Walker function that will be called on each visited
* node.
* @param arg Argument for the walker.
*/
void avltree_walk(avltree_t *t, avltree_walker_t walker)
void avltree_walk(avltree_t *t, avltree_walker_t walker, void *arg)
{
_avltree_walk(t->root, walker);
_avltree_walk(t->root, walker, arg);
}
 
/** @}