diff options
author | Alexis211 <alexis211@gmail.com> | 2009-08-29 13:39:06 +0200 |
---|---|---|
committer | Alexis211 <alexis211@gmail.com> | 2009-08-29 13:39:06 +0200 |
commit | c92beeedda51487696ce476ee30604f22e7b2270 (patch) | |
tree | 29b89d31b0b35792e1ed2bc5861be0439e7e40d9 /Source/Kernel/TaskManager/Thread.class.cpp | |
parent | 5deab22107fc38bd2bea19f07889b14c376754e0 (diff) | |
download | Melon-c92beeedda51487696ce476ee30604f22e7b2270.tar.gz Melon-c92beeedda51487696ce476ee30604f22e7b2270.zip |
The Melon kernel now has support for simple multitasking
Diffstat (limited to 'Source/Kernel/TaskManager/Thread.class.cpp')
-rw-r--r-- | Source/Kernel/TaskManager/Thread.class.cpp | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/Source/Kernel/TaskManager/Thread.class.cpp b/Source/Kernel/TaskManager/Thread.class.cpp new file mode 100644 index 0000000..cc2f569 --- /dev/null +++ b/Source/Kernel/TaskManager/Thread.class.cpp @@ -0,0 +1,106 @@ +#include "Thread.class.h" +#include <TaskManager/Task.ns.h> +#include <MemoryManager/PageAlloc.ns.h> +#include <DeviceManager/Time.ns.h> + +void runThread(Thread* thread, u32int (*entry_point)()) { + asm volatile("sti"); + thread->run(entry_point); +} + +Thread::Thread() { //Private constructor, does nothing +} + +Thread::Thread(u32int (*entry_point)(), bool iskernel) { + if (iskernel) { + m_isKernel = true; + u32int tmp; + m_kernelStackFrame = (u32int)PageAlloc::alloc(&tmp); + m_process = Task::getKernelProcess(); + setup(entry_point, m_kernelStackFrame + STACKSIZE); + } else { + m_isKernel = false; + m_process = Task::currentProcess; + setup(entry_point, m_process->stackAlloc() + STACKSIZE); + } +} + +Thread::Thread(Process* process, u32int (*entry_point)()) { + m_isKernel = false; + m_process = process; + setup(entry_point, m_process->stackAlloc() + STACKSIZE); +} + +Thread::~Thread() { + if (m_isKernel) + PageAlloc::free((void*)m_kernelStackFrame); + Task::unregisterThread(this); + //Don't unregister thread in process, it has probably already been done +} + +void Thread::setup(u32int (*entry_point)(), u32int esp) { + //Pass function parameters for runThread() + u32int *stack = (u32int*)esp; + stack--; + *stack = (u32int)entry_point; //Push entry point (function parameter) + stack--; + *stack = (u32int)this; //Push object pointer + stack--; + *stack = 0; //Null return address + m_esp = (u32int)stack; + m_ebp = m_esp + 8; + m_eip = (u32int)runThread; + + m_state = T_RUNNING; + m_process->registerThread(this); + Task::registerThread(this); +} + +void Thread::finish(u32int errcode) { + //Needs not set m_state to a finished state, either : + // - thread is unregistered from process and everywhere + // - errcode is an exception or this is main thread, process exits + m_process->threadFinishes(this, errcode); +} + +void Thread::run(u32int (*entry_point)()) { + u32int ret = entry_point(); //Run ! + finish(ret); +} + +void Thread::setState(u32int esp, u32int ebp, u32int eip) { + m_esp = esp; + m_ebp = ebp; + m_eip = eip; +} + +u32int Thread::getEsp() { return m_esp; } +u32int Thread::getEbp() { return m_ebp; } +u32int Thread::getEip() { return m_eip; } + +Process* Thread::getProcess() { return m_process; } + +void Thread::sleep(u32int msecs) { + m_state = T_SLEEPING; + waitfor.m_time = Time::time() + msecs; + + Task::triggerSwitch(); +} + +void Thread::waitIRQ(u8int irq) { + if (m_process->m_uid != 0) return; + + m_state = T_IRQWAIT; + waitfor.m_irq = irq; + + Task::triggerSwitch(); +} + +bool Thread::runnable() { + if (m_state == T_RUNNING) return true; + if (m_state == T_SLEEPING and Time::time() >= waitfor.m_time) { + m_state = T_RUNNING; + return true; + } + return false; +} |