[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH] kernel2: Syscall SYSCALL_PM_ENUMERATE_TASKS



+ kernel2: Syscall SYSCALL_PM_ENUMERATE_TASKS (Speicherbedarf und
  aktuelles eip bleiben momentan leer)

Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 src/kernel2/include/syscall.h |    4 ++
 src/kernel2/src/syscall.c     |    3 ++
 src/kernel2/src/syscalls/pm.c |   77 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 84 insertions(+), 0 deletions(-)

diff --git a/src/kernel2/include/syscall.h b/src/kernel2/include/syscall.h
index 6637ffd..b7ebfc9 100644
--- a/src/kernel2/include/syscall.h
+++ b/src/kernel2/include/syscall.h
@@ -116,6 +116,10 @@ pid_t syscall_pm_create_process(vaddr_t start, uid_t uid,
 /// Aktuellen Prozess beenden
 void syscall_pm_exit_process(void);
 
+/// Alle Prozesse auflisten
+void* syscall_pm_enumerate_tasks(void);
+
+
 /// Speicher an einen anderen Prozess uebergeben
 void syscall_init_child_page(pid_t pid, vaddr_t src, vaddr_t dest,
     size_t size);
diff --git a/src/kernel2/src/syscall.c b/src/kernel2/src/syscall.c
index 58c82de..fcb9f66 100644
--- a/src/kernel2/src/syscall.c
+++ b/src/kernel2/src/syscall.c
@@ -71,6 +71,9 @@ void syscall_init()
     syscall_register(SYSCALL_PM_INIT_PAGE, &syscall_init_child_page, 4);
     syscall_register(SYSCALL_PM_EXIT_PROCESS, &syscall_pm_exit_process, 0);
 
+    syscall_register(SYSCALL_PM_ENUMERATE_TASKS,
+        &syscall_pm_enumerate_tasks, 0);
+
     syscall_register(SYSCALL_SET_RPC_HANDLER, &syscall_set_rpc_handler, 1);
 #if CONFIG_ARCH == ARCH_I386
     syscall_register(SYSCALL_FASTRPC, &syscall_fastrpc, 5);
diff --git a/src/kernel2/src/syscalls/pm.c b/src/kernel2/src/syscalls/pm.c
index b4f5cf7..750d3dc 100644
--- a/src/kernel2/src/syscalls/pm.c
+++ b/src/kernel2/src/syscalls/pm.c
@@ -38,6 +38,7 @@
 #include <string.h>
 
 #include "syscall.h"
+#include "syscall_structs.h"
 #include "tasks.h"
 #include "cpu.h"
 
@@ -234,3 +235,79 @@ void syscall_pm_wait_for_rpc(void)
     syscall_pm_sleep();
     thread->status = PM_STATUS_WAIT_FOR_RPC;
 }
+
+/**
+ * Alle Prozesse auflisten
+ *
+ * @return Gibt einen Pointer auf neu allozierte Seiten zurueck, die
+ * Informationen ueber alle laufenden Tasks enthalten. Der Pointer zeigt dabei
+ * auf Daten vom Typ task_info_t.
+ */
+void* syscall_pm_enumerate_tasks(void)
+{
+    // Erst werden die Tasks gezaehlt, und die Groesse der
+    // Informationen mit den Kommandozeilen wird errechnet.
+    size_t task_count = 0;
+    size_t result_size = sizeof(task_info_t);
+    pm_process_t* task;
+    unsigned int i;
+
+    for (i = 0; (task = list_get_element_at(process_list, i)); i++) {
+        task_count++;
+        result_size += sizeof(task_info_task_t) + strlen(task->cmdline) + 1;
+    }
+
+    // Anzahl der Seiten berechnen, die die Informationen benoetigen.
+    size_t result_page_count = PAGE_ALIGN_ROUND_UP(result_size) / PAGE_SIZE;
+
+    // Jetzt wird eine freie Stelle im Adressraum des Prozesses
+    // gesucht, wo die Task-Infos hingemappt werden koennen
+    // FIXME Die Seiten muessen nicht physisch zusammenhaengend sein
+    task_info_t* task_info = mmc_automap(&mmc_current_context(),
+        pmm_alloc(result_page_count), result_page_count, MM_USER_START,
+        MM_USER_END, PTE_P | PTE_W | PTE_U);
+
+    // Der Groessen-Eintrag ist nur da, damit der Task die Pages
+    // freigeben koennte.
+    task_info->info_size = result_size;
+    task_info->task_count = task_count;
+
+    // Dieser Pointer zeigt direkt hinter das Array mit den
+    // Task-Informationen. Dort werden die Kommandozeilen
+    // hintereinander gespeichert, und aus den Task-Strukturen wird auf
+    // sie verwiesen.
+    char* cmdlines = (char*) task_info->tasks;
+    cmdlines += task_count * sizeof(task_info_task_t);
+
+    // Jetzt werden die Infos eingefuellt.
+    for (i = 0; (task = list_get_element_at(process_list, i)); i++) {
+        task_info->tasks[i].pid = task->pid;
+        task_info->tasks[i].status = task->status;
+
+        // TODO Ergibt strenggenommen keinen Sinn, evtl. ersten Thread?
+        task_info->tasks[i].eip = 0;
+
+        // Wenn der Task keinen Eltern-Task hat muessen wir aufpassen,
+        // damit wir keinen Pagefault produzieren.
+        if (task->parent == NULL) {
+            task_info->tasks[i].parent_pid = 0;
+        } else {
+            task_info->tasks[i].parent_pid = task->parent->pid;
+        }
+
+        // Die Kommandozeile inklusive Nullbyte kopieren
+        size_t cmdline_size = strlen(task->cmdline) + 1;
+        memcpy(cmdlines, task->cmdline, cmdline_size);
+
+        // Den Pointer fuer die Kommandozeile setzen
+        task_info->tasks[i].cmdline = cmdlines;
+
+        // Den Zielpointer fuer die naechste Kommandozeile direkt
+        // hinter die aktuelle setzen.
+        cmdlines += cmdline_size;
+
+        task_info->tasks[i].memory_used = 0; // TODO
+    }
+
+    return task_info;
+}
-- 
1.6.0.2