smp: proper cleanup on (non-main) thread exit

This commit is contained in:
Edgaru089 2021-11-11 15:44:59 +08:00
parent 240e01d69c
commit 20bc9f4a64
3 changed files with 42 additions and 3 deletions

View File

@ -39,10 +39,11 @@ static inline int minmax(int val, int min, int max) {
static SYSV_ABI void kThreader(int a, int b, int c, int d, int e, int f) { static SYSV_ABI void kThreader(int a, int b, int c, int d, int e, int f) {
io_Printf("kThreader: args[%d,%d,%d,%d,%d,%d]\n", a, b, c, d, e, f); io_Printf("kThreader: args[%d,%d,%d,%d,%d,%d]\n", a, b, c, d, e, f);
for (;;) { for (int i = 0; i < 10; i++) {
smp_thread_Sleep(768);
io_Printf("kThreader: Not sleeping!\n"); io_Printf("kThreader: Not sleeping!\n");
smp_thread_Sleep(768);
} }
io_Printf("kThreader: byebye!\n");
} }

View File

@ -3,6 +3,7 @@
#include "kthread_switch.h" #include "kthread_switch.h"
#include "internal.h" #include "internal.h"
#include "../runtime/panic_assert.h"
#include "../util/tree.h" #include "../util/tree.h"
#include "../interrupt/interrupt.h" #include "../interrupt/interrupt.h"
#include "../driver/irq/pic/rtc/rtc.h" #include "../driver/irq/pic/rtc/rtc.h"
@ -10,6 +11,23 @@
#include "../memory/paging_internal.h" #include "../memory/paging_internal.h"
// defined in assembly
SYSV_ABI void __smp_thread_EntryPoint();
// for __smp_thread_EntryPoint cleanups
// assumes interrupt is disabled
SYSV_ABI NORETURN void __smp_thread_Cleanup() {
__smp_Thread *t = __smp_Current[0];
tree_Delete(__smp_Threads, tree_FindNode(__smp_Threads, t->id));
__smp_Current[0] = 0;
// Now that we're pretending to be a idle thread, this should not return
// thread_Switch() sets the interrupt flag on idle for us
smp_thread_Yield();
Panic("__smp_thread_Cleanup: Yield not switching to another thread");
}
smp_thread_ID smp_thread_Init() { smp_thread_ID smp_thread_Init() {
INTERRUPT_DISABLE; INTERRUPT_DISABLE;
__smp_Threads = tree_Create(sizeof(__smp_Thread)); __smp_Threads = tree_Create(sizeof(__smp_Thread));
@ -51,8 +69,9 @@ smp_thread_ID smp_thread_Start(void *entry, const smp_thread_Arguments *args, un
t->state.cs = GDT_EXEC_SELECTOR; t->state.cs = GDT_EXEC_SELECTOR;
t->state.ss = 0; t->state.ss = 0;
t->state.rip = (uint64_t)entry; t->state.rip = (uint64_t)__smp_thread_EntryPoint;
t->state.rax = (uint64_t)entry;
t->state.rdi = args->a; t->state.rdi = args->a;
t->state.rsi = args->b; t->state.rsi = args->b;
t->state.rdx = args->c; t->state.rdx = args->c;

19
smp/kthread_asm.S Normal file
View File

@ -0,0 +1,19 @@
format elf64
extrn __smp_thread_Cleanup
public __smp_thread_EntryPoint
; sysvx64abi void __smp_thread_EntryPoint(uintptr_t a,b,c,d,e,f)
;
; Calls thread entry point in RAX, and, after it returns,
; removes the current thread from the structure.
section '.text' executable
__smp_thread_EntryPoint:
call rax
; Thread returned; delete the current thread
; The current thread: In __smp_Threads, not in __smp_ThreadsWaiting
cli ; Disable interrupt on thread structure operations
jmp __smp_thread_Cleanup ; This will not return