summaryrefslogtreecommitdiff
path: root/kern/task.c
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2017-05-31 21:12:41 +0200
committerRichard Braun <rbraun@sceen.net>2017-05-31 21:12:41 +0200
commit60d1eb47786f9b2461067f65f62fde31d34f1089 (patch)
tree578bad3cd9a20dc58ae9539112c92a81d07ff55c /kern/task.c
parentccefd921e76ba4ca7f3d6b54691315c0718b039c (diff)
kern/{task,thread}: add the task_info and thread_trace shell commands
Diffstat (limited to 'kern/task.c')
-rw-r--r--kern/task.c89
1 files changed, 89 insertions, 0 deletions
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 <kern/kmem.h>
#include <kern/list.h>
#include <kern/param.h>
+#include <kern/shell.h>
#include <kern/spinlock.h>
#include <kern/task.h>
#include <kern/thread.h>
@@ -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