summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordzwdz2022-08-20 00:00:52 +0200
committerdzwdz2022-08-20 00:00:52 +0200
commit2a16c1f6f9118e7127d532421ae19b959b3f1d87 (patch)
treea1b5134cc4a460e38e02e4bb2103a7c06d255198
parent040bb34290c9a4305e13637e002060411e5a8385 (diff)
user/libc: don't access the old stack from the new thread at all
-rw-r--r--src/user/app/tests/kernel/threads.c12
-rw-r--r--src/user/lib/thread.S46
-rw-r--r--src/user/lib/thread.c11
-rw-r--r--src/user/lib/thread.h9
4 files changed, 57 insertions, 21 deletions
diff --git a/src/user/app/tests/kernel/threads.c b/src/user/app/tests/kernel/threads.c
index 2964883..cb7111d 100644
--- a/src/user/app/tests/kernel/threads.c
+++ b/src/user/app/tests/kernel/threads.c
@@ -18,7 +18,6 @@ static void test_basic_thread(void) {
test(global_n == 10);
}
-
handle_t global_h;
static void shared_handle(void *sem) {
handle_t ends[2];
@@ -39,7 +38,18 @@ static void test_shared_handle(void) {
test(!strcmp("Hello!", buf));
}
+static void many_thread(void *arg) {
+ *(uint64_t*)arg += 10;
+}
+static void test_many_threads(void) {
+ uint64_t n = 0;
+ for (int i = 0; i < 10; i++) thread_create(0, many_thread, &n);
+ for (int i = 0; i < 10; i++) _syscall_await();
+ test(n == 100);
+}
+
void r_k_threads(void) {
run_test(test_basic_thread);
run_test(test_shared_handle);
+ run_test(test_many_threads);
}
diff --git a/src/user/lib/thread.S b/src/user/lib/thread.S
index 3cd3500..1a27c30 100644
--- a/src/user/lib/thread.S
+++ b/src/user/lib/thread.S
@@ -1,8 +1,40 @@
+#define ASM_FILE 1
+#include <camellia/syscalls.h>
+#include <camellia/flags.h>
+
.section .text
-.global chstack
-.type chstack, @function
-// _Noreturn void chstack(void *arg, void (*fn)(void*), void *esp);
-chstack:
- mov %rdx, %rsp
- call *%rsi
- jmp 0 // "exit"
+.global thread_creates
+.type thread_creates, @function
+// void thread_creates(int flags, void (*fn)(void*), void *arg, void *stack);
+thread_creates:
+ push %r12
+ push %r13
+ push %r14
+
+ /* save fn, arg, stack */
+ mov %rsi, %r12
+ mov %rdx, %r13
+ mov %rcx, %r14
+
+ mov %rdi, %rsi
+ or $(FORK_SHAREMEM | FORK_SHAREHANDLE), %rsi
+ mov $_SYSCALL_FORK, %rdi
+ xor %rdx, %rdx
+ syscall
+
+ test %rax, %rax
+ jz 1f
+ /* in parent, return normally */
+ pop %r14
+ pop %r13
+ pop %r12
+ ret
+1: /* in child */
+ mov %r14, %rsp
+ mov %r13, %rdi
+ call *%r12
+
+ mov $_SYSCALL_EXIT, %rdi
+ xor %rsi, %rsi
+ syscall
+ hlt /* if all else fails... */
diff --git a/src/user/lib/thread.c b/src/user/lib/thread.c
deleted file mode 100644
index f7353ad..0000000
--- a/src/user/lib/thread.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <camellia/flags.h>
-#include <camellia/syscalls.h>
-#include <stdlib.h>
-#include <user/lib/thread.h>
-
-void thread_create(int flags, void (*fn)(void*), void *arg) {
- if (!_syscall_fork(flags | FORK_SHAREMEM | FORK_SHAREHANDLE, NULL)) {
- void *stack = malloc(4096);
- chstack(arg, fn, stack + 4096);
- }
-}
diff --git a/src/user/lib/thread.h b/src/user/lib/thread.h
index 0d7376a..5a5ddc0 100644
--- a/src/user/lib/thread.h
+++ b/src/user/lib/thread.h
@@ -1,4 +1,9 @@
#pragma once
+#include <stdlib.h>
-void thread_create(int flags, void (*fn)(void*), void *arg);
-_Noreturn void chstack(void *arg, void (*fn)(void*), void *esp);
+void thread_creates(int flags, void (*fn)(void*), void *arg, void *stack);
+
+static inline void thread_create(int flags, void (*fn)(void*), void *arg) {
+ /* error checking is for WIMPS. */
+ thread_creates(flags, fn, arg, malloc(4096) + 4096);
+}