From 4d5348a49f54d95c0271c8f9c4ef01c005d6b74b Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Fri, 16 Oct 2009 17:35:50 +0200 Subject: We now use a temporary stack in task management for : - deleting current thread whe it finishes - doing everything that goes with that --- Source/Kernel/Melon.ke | Bin 612550 -> 610322 bytes .../Kernel/MemoryManager/PageDirectory.class.cpp | 2 +- Source/Kernel/MemoryManager/PhysMem.ns.cpp | 5 +- Source/Kernel/SyscallManager/IDT.ns.cpp | 4 +- Source/Kernel/TaskManager/Process.class.cpp | 2 +- Source/Kernel/TaskManager/Task.ns.cpp | 52 ++++++++++++++------- Source/Kernel/TaskManager/Thread.class.cpp | 3 +- Source/Kernel/TaskManager/Thread.class.h | 2 +- 8 files changed, 44 insertions(+), 26 deletions(-) (limited to 'Source') diff --git a/Source/Kernel/Melon.ke b/Source/Kernel/Melon.ke index 99e1599..3eb5982 100755 Binary files a/Source/Kernel/Melon.ke and b/Source/Kernel/Melon.ke differ diff --git a/Source/Kernel/MemoryManager/PageDirectory.class.cpp b/Source/Kernel/MemoryManager/PageDirectory.class.cpp index 2c8507f..13fbc36 100644 --- a/Source/Kernel/MemoryManager/PageDirectory.class.cpp +++ b/Source/Kernel/MemoryManager/PageDirectory.class.cpp @@ -43,7 +43,6 @@ PageDirectory::PageDirectory(PageDirectory* other) { } PageDirectory::~PageDirectory() { - PageAlloc::free((void*)tablesPhysical); for (int i = 0; i < 768; i++) { //Only free addresses below 0xC0000000, upper is kernel space if (tables[i] != 0) { for (int j = 0; j < 1024; j++) { @@ -52,6 +51,7 @@ PageDirectory::~PageDirectory() { PageAlloc::free((void*)tables[i]); } } + PageAlloc::free((void*)tablesPhysical); } page_t *PageDirectory::getPage(u32int address, bool make) { diff --git a/Source/Kernel/MemoryManager/PhysMem.ns.cpp b/Source/Kernel/MemoryManager/PhysMem.ns.cpp index 1794106..382e8a4 100644 --- a/Source/Kernel/MemoryManager/PhysMem.ns.cpp +++ b/Source/Kernel/MemoryManager/PhysMem.ns.cpp @@ -61,8 +61,9 @@ void freeFrame(page_t *page) { if (page->frame == 0) { return; } else { - if (page->frame >= 0x100) //First 1M are reserved (system) - frames->clearBit(page->frame / 0x1000); + if (page->frame >= 0x100) { //First 1M are reserved (system) + frames->clearBit(page->frame); + } page->frame = 0; } } diff --git a/Source/Kernel/SyscallManager/IDT.ns.cpp b/Source/Kernel/SyscallManager/IDT.ns.cpp index 1a62d88..fcab741 100644 --- a/Source/Kernel/SyscallManager/IDT.ns.cpp +++ b/Source/Kernel/SyscallManager/IDT.ns.cpp @@ -74,9 +74,9 @@ extern "C" void interrupt_handler(registers_t regs) { doSwitch = doSwitch or Task::IRQwakeup(regs.int_no - 32); } if (regs.int_no == 66) { //This syscall signals to kernel that thread ended. - Task::currentThreadExits(regs.eax); + Task::currentThreadExits(regs.eax); //DO NOT COUNT ON COMMING BACK FROM HERE } - if (doSwitch) Task::doSwitch(); //DO NEVER COUNT ON COMMING BACK FROM HERE + if (doSwitch) Task::doSwitch(); //DO NOT COUNT ON COMMING BACK FROM HERE EITHER } namespace IDT { diff --git a/Source/Kernel/TaskManager/Process.class.cpp b/Source/Kernel/TaskManager/Process.class.cpp index 6b07e7a..2706986 100644 --- a/Source/Kernel/TaskManager/Process.class.cpp +++ b/Source/Kernel/TaskManager/Process.class.cpp @@ -64,7 +64,7 @@ void Process::exit() { iter->v()->close(false); delete iter->v(); } - delete m_fileDescriptors; + delete m_fileDescriptors; //Will recursively delete whole list m_state = P_FINISHED; } diff --git a/Source/Kernel/TaskManager/Task.ns.cpp b/Source/Kernel/TaskManager/Task.ns.cpp index 4db05bc..66eca94 100644 --- a/Source/Kernel/TaskManager/Task.ns.cpp +++ b/Source/Kernel/TaskManager/Task.ns.cpp @@ -1,5 +1,9 @@ #include "Task.ns.h" #include +#include + +#define INVALID_TASK_MAGIC 0xBEEFFEED +#define TEMP_STACK_SIZE 128 //This must be big enough so that we can call all we need to call when a task finishes //From Task.wtf.asm extern "C" u32int read_eip(); @@ -16,12 +20,7 @@ SimpleList *idleThread = 0; u32int nextpid = 1; -struct finished_thread_t { //Forms a linked list - Thread* thread; - u32int errcode; -}; -SimpleList *firstFinishedThread = 0; - +u32int temp_stack[TEMP_STACK_SIZE]; //Temporary stack used for finishing current thread Thread* currThread() { return currentThread->v(); @@ -53,20 +52,15 @@ void initialize(String cmdline, VirtualTerminal *vt) { } SimpleList *nextThread() { - //Clean up finished threads - while (firstFinishedThread != 0) { - if (firstFinishedThread->v().thread == currentThread->v()) break; - firstFinishedThread->v().thread->finish(firstFinishedThread->v().errcode); - firstFinishedThread = firstFinishedThread->delThis(); - } - //Find next thread + if ((u32int)currentThread == INVALID_TASK_MAGIC) { + currentThread = threads; //This will happen when we come here just after current thread has finished + } SimpleList *iter = currentThread; while (1) { iter = iter->next(); if (iter == 0) iter = threads; if (iter->v()->runnable() and iter->v() != idleThread->v()) { - if (firstFinishedThread != 0 and firstFinishedThread->v().thread == iter->v()) return idleThread; return iter; } if (iter == currentThread) break; @@ -88,7 +82,8 @@ void doSwitch() { return; } - if ((u32int)currentThread->v() != 0xFFFFFFFF) currentThread->v()->setState(esp, ebp, eip); + //This will happen when we come here just after current thread has finished + if ((u32int)currentThread != INVALID_TASK_MAGIC) currentThread->v()->setState(esp, ebp, eip); currentThread = nextThread(); Thread* t = currentThread->v(); @@ -127,6 +122,8 @@ bool IRQwakeup(u8int irq) { } void allocKernelPageTable(u32int id, page_table_t *table, u32int tablePhys) { + kernelPageDirectory->tables[id] = table; + kernelPageDirectory->tablesPhysical[id] = tablePhys; if (id < 768) return; //this would be a BUG for (SimpleList *iter = processes; iter != 0; iter = iter->next()) { iter->v()->getPagedir()->tables[id] = table; @@ -134,9 +131,28 @@ void allocKernelPageTable(u32int id, page_table_t *table, u32int tablePhys) { } } -void currentThreadExits(u32int errcode) { - finished_thread_t tmp = {currentThread->v(), errcode}; - firstFinishedThread = firstFinishedThread->cons(tmp); +void currThreadExitProceed(u32int errcode) { + currentThread->v()->finish(errcode); + currentThread = (SimpleList*)INVALID_TASK_MAGIC; + doSwitch(); //Normally never come back from here +} + +void currentThreadExits(u32int errcode) { //Call currThreadExitProceed with a working stack (we use temp_stack) + u32int* stack = &temp_stack[TEMP_STACK_SIZE]; + stack--; + *stack = errcode; + stack--; + *stack = 0; + u32int esp = (u32int)(stack), ebp = (u32int)(stack + 1), eip = (u32int)currThreadExitProceed; + + asm volatile(" \ + cli; \ + mov %0, %%ebp; \ + mov %1, %%esp; \ + mov %2, %%ecx; \ + mov %3, %%cr3; \ + jmp *%%ecx;" + : : "r"(ebp), "r"(esp), "r"(eip), "r"(kernelPageDirectory->physicalAddr)); } void registerThread(Thread* t) { diff --git a/Source/Kernel/TaskManager/Thread.class.cpp b/Source/Kernel/TaskManager/Thread.class.cpp index fd5cfd9..fe1d08e 100644 --- a/Source/Kernel/TaskManager/Thread.class.cpp +++ b/Source/Kernel/TaskManager/Thread.class.cpp @@ -34,8 +34,9 @@ Thread::Thread(Process* process, thread_entry_t entry_point, void* data) { Thread::~Thread() { Task::unregisterThread(this); - if (m_isKernel) + if (m_isKernel) { PageAlloc::free((void*)m_kernelStackFrame); + } //Don't unregister thread in process, it has probably already been done } diff --git a/Source/Kernel/TaskManager/Thread.class.h b/Source/Kernel/TaskManager/Thread.class.h index dffc84a..369f62f 100644 --- a/Source/Kernel/TaskManager/Thread.class.h +++ b/Source/Kernel/TaskManager/Thread.class.h @@ -7,7 +7,7 @@ #define T_ZOMBIE 0 #define T_RUNNING 1 #define T_SLEEPING 2 -#define T_IRQWAIT 3 //This can only happen if process->uid == 0 (root) +#define T_IRQWAIT 3 typedef u32int(*thread_entry_t)(void*); -- cgit v1.2.3