[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