diff --git a/smp/internal.c b/smp/internal.c index 854f075..7209b8e 100644 --- a/smp/internal.c +++ b/smp/internal.c @@ -12,3 +12,4 @@ smp_thread_ID __smp_Idallo; tree_Tree *__smp_Threads; tree_Tree *__smp_ThreadsWaiting; +tree_Tree *__smp_StackPool; diff --git a/smp/internal.h b/smp/internal.h index 6aa07d2..0b9faed 100644 --- a/smp/internal.h +++ b/smp/internal.h @@ -22,6 +22,7 @@ typedef struct { // Last-saved thread state after preemptive context switch smp_thread_State state; + uint64_t stackframe; // stack frame, lowest (begin) addr } __smp_Thread; // variables defined in internal.c @@ -48,3 +49,6 @@ extern smp_thread_ID __smp_Idallo; extern tree_Tree *__smp_Threads; // [priority] -> struct __smp_Thread* extern tree_Tree *__smp_ThreadsWaiting; + +// unused thread stack pages for use; 4K in size +extern tree_Tree *__smp_StackPool; diff --git a/smp/kthread.c b/smp/kthread.c index f965e26..30fe57d 100644 --- a/smp/kthread.c +++ b/smp/kthread.c @@ -21,6 +21,9 @@ SYSV_ABI NORETURN void __smp_thread_Cleanup() { tree_Delete(__smp_Threads, tree_FindNode(__smp_Threads, t->id)); __smp_Current[0] = 0; + // Push the freed stack frame into the pool + tree_Insert(__smp_StackPool, t->stackframe, NULL); + // 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(); @@ -32,6 +35,7 @@ smp_thread_ID smp_thread_Init() { INTERRUPT_DISABLE; __smp_Threads = tree_Create(sizeof(__smp_Thread)); __smp_ThreadsWaiting = tree_Create(sizeof(void *)); + __smp_StackPool = tree_Create(0); __smp_Now = 1; smp_thread_ID id = ++__smp_Idallo; @@ -79,10 +83,17 @@ smp_thread_ID smp_thread_Start(void *entry, const smp_thread_Arguments *args, un t->state.r8 = args->e; t->state.r9 = args->f; - // allocate a new 4K stack - uint64_t newstack = memory_AllocateKernelMapping(4096, 4096); - paging_map_PageAllocated(newstack, 1, MAP_PROT_READ | MAP_PROT_WRITE); - t->state.rsp = newstack + 4096; + tree_Node *spare = tree_FirstNode(__smp_StackPool); + if (spare) { + // use the existing stack from the pool + t->state.rsp = t->stackframe = spare->key + 4096; + tree_Delete(__smp_StackPool, spare); + } else { + // allocate a new 4K stack + uint64_t newstack = memory_AllocateKernelMapping(4096, 4096); + paging_map_PageAllocated(newstack, 1, MAP_PROT_READ | MAP_PROT_WRITE); + t->state.rsp = t->stackframe = newstack + 4096; + } // insert the thread into the waiting queue *((void **)tree_Insert(__smp_ThreadsWaiting, t->lastTick + t->nice, 0)) = t;