summaryrefslogtreecommitdiff
path: root/Source/Kernel/TaskManager/Thread.class.cpp
diff options
context:
space:
mode:
authorAlexis211 <alexis211@gmail.com>2009-08-29 13:39:06 +0200
committerAlexis211 <alexis211@gmail.com>2009-08-29 13:39:06 +0200
commitc92beeedda51487696ce476ee30604f22e7b2270 (patch)
tree29b89d31b0b35792e1ed2bc5861be0439e7e40d9 /Source/Kernel/TaskManager/Thread.class.cpp
parent5deab22107fc38bd2bea19f07889b14c376754e0 (diff)
downloadMelon-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.cpp106
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;
+}