From 60d1eb47786f9b2461067f65f62fde31d34f1089 Mon Sep 17 00:00:00 2001 From: Richard Braun Date: Wed, 31 May 2017 21:12:41 +0200 Subject: kern/{task,thread}: add the task_info and thread_trace shell commands --- kern/task.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) (limited to 'kern/task.c') diff --git a/kern/task.c b/kern/task.c index 7f1c53d2..66b43bff 100644 --- a/kern/task.c +++ b/kern/task.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -56,20 +57,61 @@ static struct spinlock task_list_lock; static void task_init(struct task *task, const char *name, struct vm_map *map) { + task->nr_refs = 1; spinlock_init(&task->lock); list_init(&task->threads); task->map = map; strlcpy(task->name, name, sizeof(task->name)); } +static void +task_shell_info(int argc, char *argv[]) +{ + struct task *task; + int error; + + if (argc == 1) { + task_info(NULL); + return; + } else { + task = task_lookup(argv[1]); + + if (task == NULL) { + error = ERROR_INVAL; + goto error; + } + + task_info(task); + task_unref(task); + } + + return; + +error: + printf("task: info: %s\n", error_str(error)); +} + +static struct shell_cmd task_shell_cmds[] = { + SHELL_CMD_INITIALIZER("task_info", task_shell_info, + "task_info", "print all tasks and threads"), +}; + void __init task_setup(void) { + unsigned int i; + int error; + kmem_cache_init(&task_cache, "task", sizeof(struct task), 0, NULL, 0); list_init(&task_list); spinlock_init(&task_list_lock); task_init(kernel_task, "x15", kernel_map); list_insert_head(&task_list, &kernel_task->node); + + for (i = 0; i < ARRAY_SIZE(task_shell_cmds); i++) { + error = shell_cmd_register(&task_shell_cmds[i]); + error_check(error, __func__); + } } int @@ -107,6 +149,31 @@ error_task: return error; } +struct task * +task_lookup(const char *name) +{ + struct task *task; + + spinlock_lock(&task_list_lock); + + list_for_each_entry(&task_list, task, node) { + spinlock_lock(&task->lock); + + if (strcmp(task->name, name) == 0) { + task_ref(task); + spinlock_unlock(&task->lock); + spinlock_unlock(&task_list_lock); + return task; + } + + spinlock_unlock(&task->lock); + } + + spinlock_unlock(&task_list_lock); + + return NULL; +} + void task_add_thread(struct task *task, struct thread *thread) { @@ -123,6 +190,26 @@ task_remove_thread(struct task *task, struct thread *thread) spinlock_unlock(&task->lock); } +struct thread * +task_lookup_thread(struct task *task, const char *name) +{ + struct thread *thread; + + spinlock_lock(&task->lock); + + list_for_each_entry(&task->threads, thread, task_node) { + if (strcmp(thread->name, name) == 0) { + thread_ref(thread); + spinlock_unlock(&task->lock); + return thread; + } + } + + spinlock_unlock(&task->lock); + + return NULL; +} + void task_info(struct task *task) { @@ -149,6 +236,8 @@ task_info(struct task *task) * can be used to debug in the middle of most critical sections. * Threads are only destroyed after being removed from their task * so holding the task lock is enough to guarantee existence. + * + * TODO Handle tasks and threads names modifications. */ list_for_each_entry(&task->threads, thread, task_node) { printf(TASK_INFO_ADDR_FMT " %c %8s:" TASK_INFO_ADDR_FMT -- cgit v1.2.3