summaryrefslogtreecommitdiff
path: root/kern/task.c
diff options
context:
space:
mode:
Diffstat (limited to 'kern/task.c')
-rw-r--r--kern/task.c111
1 files changed, 108 insertions, 3 deletions
diff --git a/kern/task.c b/kern/task.c
index 7f1c53d2..ab82ad83 100644
--- a/kern/task.c
+++ b/kern/task.c
@@ -23,7 +23,8 @@
#include <kern/init.h>
#include <kern/kmem.h>
#include <kern/list.h>
-#include <kern/param.h>
+#include <kern/macros.h>
+#include <kern/shell.h>
#include <kern/spinlock.h>
#include <kern/task.h>
#include <kern/thread.h>
@@ -56,13 +57,64 @@ 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));
}
-void __init
+#ifdef X15_SHELL
+
+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 [<task_name>]",
+ "display tasks and threads"),
+};
+
+static int __init
+task_setup_shell(void)
+{
+ SHELL_REGISTER_CMDS(task_shell_cmds);
+ return 0;
+}
+
+INIT_OP_DEFINE(task_setup_shell,
+ INIT_OP_DEP(printf_setup, true),
+ INIT_OP_DEP(shell_setup, true),
+ INIT_OP_DEP(task_setup, true),
+ INIT_OP_DEP(thread_setup, true));
+
+#endif /* X15_SHELL */
+
+static int __init
task_setup(void)
{
kmem_cache_init(&task_cache, "task", sizeof(struct task), 0, NULL, 0);
@@ -70,8 +122,14 @@ task_setup(void)
spinlock_init(&task_list_lock);
task_init(kernel_task, "x15", kernel_map);
list_insert_head(&task_list, &kernel_task->node);
+ return 0;
}
+INIT_OP_DEFINE(task_setup,
+ INIT_OP_DEP(kmem_setup, true),
+ INIT_OP_DEP(spinlock_setup, true),
+ INIT_OP_DEP(vm_map_setup, true));
+
int
task_create(struct task **taskp, const char *name)
{
@@ -107,6 +165,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 +206,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)
{
@@ -132,7 +235,7 @@ task_info(struct task *task)
spinlock_lock(&task_list_lock);
list_for_each_entry(&task_list, task, node) {
- printf("task: %s\n", task->name);
+ task_info(task);
}
spinlock_unlock(&task_list_lock);
@@ -149,6 +252,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