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

[tyndur-devel] [PATCH 2/4] kernel/libc: Multithreading-Syscalls



From: Patrick Pokatilo <shyxormz@xxxxxxxxxx>

+ kernel/libc: Native tyndur-Thread-API hinzugefügt

Signed-off-by: Patrick Pokatilo <shyxormz@xxxxxxxxxx>
Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 src/include/syscallno.h                  |    6 ++-
 src/include/types.h                      |    1 +
 src/kernel2/include/syscall.h            |   10 +++
 src/kernel2/include/tasks.h              |    6 ++
 src/kernel2/src/syscall.c                |    4 +
 src/kernel2/src/syscalls/pm.c            |   74 ++++++++++++++++++++
 src/kernel2/src/tasks/thread.c           |   25 ++++++-
 src/modules/include/syscall.h            |    3 +
 src/modules/include/unistd.h             |    3 +
 src/modules/lib/posix/getpid.c           |   10 +++-
 src/modules/lib/syscalls/create_thread.c |  110 ++++++++++++++++++++++++++++++
 11 files changed, 246 insertions(+), 6 deletions(-)
 create mode 100644 src/modules/lib/syscalls/create_thread.c

diff --git a/src/include/syscallno.h b/src/include/syscallno.h
index ec43668..12779e0 100644
--- a/src/include/syscallno.h
+++ b/src/include/syscallno.h
@@ -68,6 +68,10 @@
 
 #define SYSCALL_PM_WAIT_FOR_RPC 17
 
+#define SYSCALL_PM_GET_TID 119
+#define SYSCALL_PM_CREATE_THREAD 120
+#define SYSCALL_PM_EXIT_THREAD 121
+
 #define SYSCALL_GET_TICK_COUNT 40
 
 #define SYSCALL_FORTY_TWO 42
@@ -112,6 +116,6 @@
 #define SYSCALL_LIO_SRV_NODE_REMOVE                 118
 
 //ACHTUNG: Muss eine Zahl groesser als die Groesste Syscall-Nummer sein
-#define SYSCALL_MAX 119
+#define SYSCALL_MAX 122
 
 #endif
diff --git a/src/include/types.h b/src/include/types.h
index 22bf560..0352b09 100644
--- a/src/include/types.h
+++ b/src/include/types.h
@@ -39,6 +39,7 @@ typedef void * vaddr_t;
 typedef int pid_t;
 typedef unsigned int uid_t;
 typedef unsigned int gid_t;
+typedef unsigned int tid_t;
 
 #endif
 
diff --git a/src/kernel2/include/syscall.h b/src/kernel2/include/syscall.h
index 2eb93b0..c49051a 100644
--- a/src/kernel2/include/syscall.h
+++ b/src/kernel2/include/syscall.h
@@ -125,6 +125,16 @@ void syscall_pm_exit_process(void);
 void* syscall_pm_enumerate_tasks(void);
 
 
+/// Thread erstellen
+tid_t syscall_pm_create_thread(vaddr_t start, void *arg);
+
+/// ID des aktuellen Threads abfragen
+tid_t syscall_pm_get_tid(void);
+
+/// Thread beenden
+void syscall_pm_exit_thread(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/include/tasks.h b/src/kernel2/include/tasks.h
index 1b719d7..f31b4b6 100644
--- a/src/kernel2/include/tasks.h
+++ b/src/kernel2/include/tasks.h
@@ -140,6 +140,12 @@ typedef struct {
 
     /// Gesetzt, wenn der Thread ein VM86-Thread mit allem Drum und Dran ist
     bool vm86;
+
+    /// Eindeutige Threadnummer
+    tid_t tid;
+
+    /// Gesetzt, wenn der Thread beim Beenden den gesamten Prozess beendet
+    bool is_main_thread;
 } pm_thread_t;
 
 typedef void (*pm_process_destroy_handler)(pm_process_t* process, void* prv);
diff --git a/src/kernel2/src/syscall.c b/src/kernel2/src/syscall.c
index 1871739..bd41275 100644
--- a/src/kernel2/src/syscall.c
+++ b/src/kernel2/src/syscall.c
@@ -76,6 +76,10 @@ void syscall_init()
     syscall_register(SYSCALL_PM_ENUMERATE_TASKS,
         &syscall_pm_enumerate_tasks, 0);
 
+    syscall_register(SYSCALL_PM_CREATE_THREAD, &syscall_pm_create_thread, 2);
+    syscall_register(SYSCALL_PM_GET_TID, &syscall_pm_get_tid, 0);
+    syscall_register(SYSCALL_PM_EXIT_THREAD, &syscall_pm_exit_thread, 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 948b577..6ab13d2 100644
--- a/src/kernel2/src/syscalls/pm.c
+++ b/src/kernel2/src/syscalls/pm.c
@@ -351,3 +351,77 @@ void* syscall_pm_enumerate_tasks(void)
 
     return task_info;
 }
+
+/**
+ * TID des aktuellen Threads ausfindig machen
+ *
+ * @return TID des aktuellen Threads
+ */
+tid_t syscall_pm_get_tid()
+{
+    int i = 0;
+
+    pm_thread_t *thread;
+
+    while ((thread = list_get_element_at(current_process->threads, i))) {
+        if (thread->status == PM_STATUS_RUNNING) {
+            return thread->tid;
+        }
+    }
+
+    return -1;
+}
+
+/**
+ * Neuen Thread in einem Prozess erstellen. Der neue Task wird blockiert, bis
+ * er vom Ersteller entblockt wird.
+ *
+ * @param start Start-Adresse
+ * @param arg Argument für den Thread
+ *
+ * @return TID des neuen Tasks
+ */
+tid_t syscall_pm_create_thread(vaddr_t start, void *arg)
+{
+    pm_thread_t *thread;
+
+    thread = pm_thread_create(current_process, start);
+    if (thread == NULL) {
+        return -1;
+    }
+
+    while (pm_thread_block(thread) == false);
+
+    interrupt_stack_frame_t *isf = (interrupt_stack_frame_t *)thread->user_isf;
+
+    *((void **)(isf->esp)) = arg;
+
+    isf->esp -= sizeof(void *);
+
+    while (pm_thread_unblock(thread) == true);
+
+    return thread->tid;
+}
+
+void syscall_pm_exit_thread(void)
+{
+    pm_thread_t *thread;
+    tid_t tid;
+    int i = 0;
+
+    tid = syscall_pm_get_tid();
+
+    if (tid == -1) {
+        // TODO Kann das wirklich passieren?
+        return;
+    }
+
+    while ((thread = list_get_element_at(current_process->threads, i))) {
+        if (thread->tid == tid) {
+            pm_scheduler_push(thread);
+            pm_thread_block(thread);
+            pm_thread_destroy(thread);
+            break;
+        }
+    }
+}
diff --git a/src/kernel2/src/tasks/thread.c b/src/kernel2/src/tasks/thread.c
index 639d2c9..961fe31 100644
--- a/src/kernel2/src/tasks/thread.c
+++ b/src/kernel2/src/tasks/thread.c
@@ -44,6 +44,18 @@
 #include "lock.h"
 #include "cpu.h"
 
+static tid_t next_tid = 1;
+
+static tid_t generate_tid(void)
+{
+    static lock_t tid_lock = LOCK_UNLOCKED;
+    lock(&tid_lock);
+    tid_t tid = next_tid++;
+    unlock(&tid_lock);
+
+    return tid;
+}
+
 /**
  * Neuen Thread erstellen
  *
@@ -60,6 +72,11 @@ pm_thread_t* pm_thread_create(pm_process_t* process, vaddr_t entry)
     if (thread == NULL) {
         return NULL;
     }
+
+    thread->is_main_thread = (process != current_process);
+
+    // Dem Thread eine ID zuordnen
+    thread->tid = generate_tid();
     
     // Ein Pointer auf den Prozess im Thread hinterlegen
     thread->process = process;
@@ -139,6 +156,8 @@ pm_thread_t* pm_thread_create(pm_process_t* process, vaddr_t entry)
  */
 void pm_thread_destroy(pm_thread_t* thread)
 {
+    // TODO Andere Threads beenden, falls thread->is_main_thread
+
     // Zuerst muss der Thread angehalten werden
     while (pm_thread_block(thread) == false);
     
@@ -232,12 +251,10 @@ bool pm_thread_unblock(pm_thread_t* thread)
 
     // Der Thread wird nur entsperrt, wenn er auch wirklich blockiert ist
     if (thread->status == PM_STATUS_BLOCKED) {
-        lock(&thread->lock);
-        unlock(&thread->lock);
-        return true;
+        thread->status = PM_STATUS_READY;
+        result = true;
     }
 
     unlock(&thread->lock);
     return result;
 }
-
diff --git a/src/modules/include/syscall.h b/src/modules/include/syscall.h
index d89449d..0679631 100644
--- a/src/modules/include/syscall.h
+++ b/src/modules/include/syscall.h
@@ -104,6 +104,9 @@ void syscall_timer(uint32_t timer_id, uint32_t usec);
 
 void syscall_debug_stacktrace(pid_t pid);
 
+tid_t create_thread(uint32_t start, void *arg);
+void exit_thread(void);
+tid_t get_tid(void);
 
 // LIO2
 
diff --git a/src/modules/include/unistd.h b/src/modules/include/unistd.h
index d101135..95e9f18 100644
--- a/src/modules/include/unistd.h
+++ b/src/modules/include/unistd.h
@@ -62,6 +62,9 @@ pid_t getpid(void);
 /// PID des Elternprozesses auslesen
 pid_t getppid(void);
 
+/// TID des aktuellen Threads auslesen
+tid_t gettid(void);
+
 /// Hardlink erstellen
 int link(const char* oldpath, const char* newpath);
 
diff --git a/src/modules/lib/posix/getpid.c b/src/modules/lib/posix/getpid.c
index 1ab55de..40faded 100644
--- a/src/modules/lib/posix/getpid.c
+++ b/src/modules/lib/posix/getpid.c
@@ -50,4 +50,12 @@ pid_t getppid()
     return get_parent_pid(0);
 }
 
-
+/**
+ * ID des aktuellen Threads auslesen
+ *
+ * @return Thread-ID
+ */
+tid_t gettid()
+{
+    return get_tid();
+}
diff --git a/src/modules/lib/syscalls/create_thread.c b/src/modules/lib/syscalls/create_thread.c
new file mode 100644
index 0000000..5789df5
--- /dev/null
+++ b/src/modules/lib/syscalls/create_thread.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012 The tyndur Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the tyndur Project
+ * by Patrick Pokatilo.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include "syscall.h"
+
+/**
+ * ID des aktuellen Threads abfragen.
+ *
+ * @return ID
+ */
+tid_t get_tid(void)
+{
+    tid_t pid;
+
+    asm(
+        "mov %1, %%eax;"
+        "int $0x30;"
+        : "=a" (pid) : "i" (SYSCALL_PM_GET_TID));
+
+    return pid;
+}
+
+/**
+ * Neuen Prozess erstellen. Dieser ist solange blockiert, bis er mit
+ * unblock_task erloest wird. Waerend dieser Zeit kann der Elternprozess Mit
+ * Hilfe von init_child_page Einzelne Seiten in den Adressraum des neuen
+ * Prozesses mappen.
+ *
+ * @param initial_eip Der Einsprungspunkt an dem der Prozess seine Arbeit
+ *                      beginnen soll.
+ * @param uid Die Benutzernummer unter der der Neue Prozess laufen soll (FIXME:
+ *              Sollte vom Elternprozess geerbt werden)
+ * @param args Pointer auf die Kommandozeilen-Parameter
+ * @param parent Prozessnummer des Elternprozesses, dem der neue Task
+ *          untergeordenet werden soll, oder 0 fuer den aktuellen Prozess.
+ *
+ * @return Prozessnummer
+ */
+typedef struct
+{
+    void *(*func)(void *);
+    void *arg;
+} ct_parameter_t;
+
+void *ct_start(ct_parameter_t *p)
+{
+    void *result = p->func(p->arg);
+
+    free(p);
+
+    exit_thread();
+
+    return result;
+}
+
+tid_t create_thread(uint32_t start, void *arg)
+{
+    tid_t tid;
+
+    ct_parameter_t *ct_arg = malloc(sizeof(ct_parameter_t));
+
+    ct_arg->func = (void *(*)(void *))start;
+    ct_arg->arg = arg;
+
+    asm(
+        "pushl %3;"
+        "pushl %2;"
+        "mov %1, %%eax;"
+        "int $0x30;"
+        "add $0x08, %%esp;"
+        : "=a" (tid)
+        : "i" (SYSCALL_PM_CREATE_THREAD), "r" (ct_start), "r" (ct_arg));
+
+    return tid;
+}
+
+void exit_thread(void)
+{
+    asm(
+        "mov %0, %%eax;"
+        "int $0x30;"
+        : : "i" (SYSCALL_PM_EXIT_THREAD));
+}
-- 
1.7.7