summaryrefslogtreecommitdiff
path: root/Source/Kernel/TaskManager
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Kernel/TaskManager')
-rw-r--r--Source/Kernel/TaskManager/Mutex.class.cpp28
-rw-r--r--Source/Kernel/TaskManager/Mutex.class.h21
-rw-r--r--Source/Kernel/TaskManager/Process.class.cpp68
-rw-r--r--Source/Kernel/TaskManager/Process.class.h30
-rw-r--r--Source/Kernel/TaskManager/Task.ns.cpp8
-rw-r--r--Source/Kernel/TaskManager/Task.ns.h2
-rw-r--r--Source/Kernel/TaskManager/Task.wtf.asm9
-rw-r--r--Source/Kernel/TaskManager/Thread.class.cpp109
-rw-r--r--Source/Kernel/TaskManager/Thread.class.h14
9 files changed, 203 insertions, 86 deletions
diff --git a/Source/Kernel/TaskManager/Mutex.class.cpp b/Source/Kernel/TaskManager/Mutex.class.cpp
deleted file mode 100644
index 8ba274f..0000000
--- a/Source/Kernel/TaskManager/Mutex.class.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "Mutex.class.h"
-#include <TaskManager/Task.ns.h>
-
-extern "C" u32int atomic_exchange(u32int* ptr, u32int newval);
-
-Mutex::Mutex(u32int locked) {
- m_locked = locked;
-}
-
-bool Mutex::lock() {
- if (atomic_exchange(&m_locked, MUTEX_TRUE) == MUTEX_TRUE) return false; //The lock was already locked
- return true;
-}
-
-void Mutex::waitLock() {
- while (atomic_exchange(&m_locked, MUTEX_TRUE) == MUTEX_TRUE) {
- if (Task::currThread() != 0) Task::currThread()->sleep(10); //Wait 10ms
- else return;
- }
-}
-
-void Mutex::unlock() {
- m_locked = MUTEX_FALSE;
-}
-
-bool Mutex::locked() {
- return m_locked;
-}
diff --git a/Source/Kernel/TaskManager/Mutex.class.h b/Source/Kernel/TaskManager/Mutex.class.h
deleted file mode 100644
index 5545559..0000000
--- a/Source/Kernel/TaskManager/Mutex.class.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef DEF_MUTEX_CLASS_H
-#define DEF_MUTEX_CLASS_H
-
-#include <Core/common.wtf.h>
-
-#define MUTEX_FALSE 0
-#define MUTEX_TRUE 1
-
-class Mutex {
- private:
- u32int m_locked;
-
- public:
- Mutex(u32int locked = MUTEX_FALSE);
- bool lock(); //Locks the mutex if it is not locked. Returns true if mutex could be locked, false if already locked
- void waitLock(); //Locks the mutex, waiting for it to be unlocked before if necessary
- void unlock();
- bool locked();
-};
-
-#endif
diff --git a/Source/Kernel/TaskManager/Process.class.cpp b/Source/Kernel/TaskManager/Process.class.cpp
index cf8f00a..a2bbfb4 100644
--- a/Source/Kernel/TaskManager/Process.class.cpp
+++ b/Source/Kernel/TaskManager/Process.class.cpp
@@ -2,12 +2,26 @@
#include <TaskManager/Task.ns.h>
#include <MemoryManager/PhysMem.ns.h>
#include <VFS/File.class.h>
+#include <Linker/Binary.proto.h>
+#include <Process.iface.h>
namespace Mem {
extern Heap kheap;
}
-Process::Process() { //Private constructor, does nothing
+call_t Process::m_callTable[] = {
+ CALL0(PRIF_EXIT, &Process::exitSC),
+ CALL1(PRIF_ALLOCPAGE, &Process::allocPageSC),
+ CALL1(PRIF_FREEPAGE, &Process::freePageSC),
+ CALL0(0, 0)
+};
+
+u32int Process::scall(u8int wat, u32int a, u32int b, u32int c, u32int d) {
+ if (wat == PRIF_SGETCPR) return Task::currProcess()->resId();
+ return (u32int) - 1;
+}
+
+Process::Process() : Ressource(PRIF_OBJTYPE, m_callTable) { //Private constructor, does nothing
}
Process* Process::createKernel(String cmdline, VirtualTerminal *vt) {
@@ -35,13 +49,31 @@ Process* Process::createKernel(String cmdline, VirtualTerminal *vt) {
return p;
}
-Process::Process(String cmdline, u32int uid) {
+Process* Process::run(String filename, FSNode* cwd, u32int uid) {
+ File file(filename, FM_READ, cwd);
+ if (!file.valid()) return 0;
+ Binary* b = Binary::load(file);
+ if (b == 0) return 0;
+ Process* p = new Process(filename, uid);
+ thread_entry_t e = b->toProcess(p);
+ delete b;
+ if (e != 0) {
+ new Thread(p, e, 0);
+ return p;
+ } else {
+ delete p;
+ return 0;
+ }
+}
+
+Process::Process(String cmdline, u32int uid) : Ressource(PRIF_OBJTYPE, m_callTable) {
m_pid = Task::nextPid();
m_cmdline = cmdline;
m_retval = 0;
- m_state = P_RUNNING;
+ m_state = P_STARTING;
m_uid = uid;
m_vt = Task::currProcess()->getVirtualTerminal();
+ m_fileDescriptors = 0;
//Create page directory and user heap
m_pagedir = new PageDirectory(kernelPageDirectory);
m_pagedir->switchTo();
@@ -56,6 +88,10 @@ Process::~Process() {
delete m_userHeap;
}
+void Process::start() {
+ if (m_state == P_STARTING) m_state = P_RUNNING;
+}
+
void Process::exit() {
for (u32int i = 0; i < m_threads.size(); i++) {
delete m_threads[i];
@@ -65,7 +101,7 @@ void Process::exit() {
iter->v()->close(false);
delete iter->v();
}
- delete m_fileDescriptors; //Will recursively delete whole list
+ if (m_fileDescriptors != 0) delete m_fileDescriptors; //Will recursively delete whole list
m_state = P_FINISHED;
}
@@ -76,7 +112,7 @@ void Process::registerThread(Thread* t) {
void Process::threadFinishes(Thread* thread, u32int retval) {
// If it is the main thread of the process, or if it pagefaulted
- if (thread == m_threads[0] or retval == E_PAGEFAULT) {
+ if (thread == m_threads[0] or retval == E_PAGEFAULT or retval == E_EXIT) {
exit();
} else {
//Simply unregister thread
@@ -110,3 +146,25 @@ VirtualTerminal* Process::getVirtualTerminal() {
void Process::setVirtualTerminal(VirtualTerminal* vt) {
m_vt = vt;
}
+
+u32int Process::exitSC() {
+ if (Task::currProcess() != this) return 1;
+ Task::currentThreadExits(E_EXIT);
+ return 0;
+}
+
+u32int Process::allocPageSC(u32int pos) {
+ if (Task::currProcess() != this) return 1;
+ if ((pos & 0x00000FFF) != 0) pos = (pos & 0xFFFFF000) + 0x1000;
+ if (pos >= 0xC0000000) return 1;
+ m_pagedir->allocFrame(pos, true, true);
+ return 0;
+}
+
+u32int Process::freePageSC(u32int pos) {
+ if (Task::currProcess() != this) return 1;
+ if ((pos & 0x00000FFF) != 0) pos = (pos & 0xFFFFF000) + 0x1000;
+ if (pos >= 0xC0000000) return 1;
+ m_pagedir->freeFrame(pos);
+ return 0;
+}
diff --git a/Source/Kernel/TaskManager/Process.class.h b/Source/Kernel/TaskManager/Process.class.h
index ac9614e..89efd0c 100644
--- a/Source/Kernel/TaskManager/Process.class.h
+++ b/Source/Kernel/TaskManager/Process.class.h
@@ -1,19 +1,23 @@
#ifndef DEF_PROCESS_CLASS_H
#define DEF_PROCESS_CLASS_H
-#include <Library/String.class.h>
-#include <Library/Vector.class.h>
-#include <Library/SimpleList.class.h>
+#include <String.class.h>
+#include <Vector.class.h>
+#include <SimpleList.class.h>
#include <MemoryManager/PageDirectory.class.h>
-#include <MemoryManager/Heap.class.h>
+#include <Heap.class.h>
#include <VTManager/VirtualTerminal.proto.h>
+#include <VFS/File.class.h>
+
+#include <SyscallManager/Ressource.class.h>
#define P_ZOMBIE 0
#define P_RUNNING 1
-#define P_FINISHED 2
+#define P_STARTING 2
+#define P_FINISHED 3
#define E_PAGEFAULT 0x0FFFFF00
-#define E_ABORTED 0x0FFFFF01
+#define E_EXIT 0x0FFFFF01
#define E_UNHANDLED_EXCEPTION 0x0FFFFF02
#define STACKSIZE 4096 //Could change
@@ -24,7 +28,7 @@
class Thread;
class File;
-class Process {
+class Process : public Ressource {
friend class Thread;
private:
@@ -42,14 +46,23 @@ class Process {
Vector<Thread*> m_threads;
SimpleList<File*> *m_fileDescriptors;
+
+ //System calls
+ static call_t m_callTable[];
+ u32int exitSC();
+ u32int allocPageSC(u32int);
public:
+ static u32int scall(u8int, u32int, u32int, u32int, u32int);
+
static Process* createKernel(String cmdline, VirtualTerminal *vt); //Also creates a Thread for what's curently happening
+ static Process* run(String filename, FSNode* cwd, u32int uid);
Process(String cmdline, u32int uid);
~Process();
Heap& heap() { return *m_userHeap; }
+ void start(); //Starts thread execution - sets m_state to P_RUNNING if == P_STARTING
void exit(); //Exits properly process by killing all threads and deleting file descriptors
void registerThread(Thread* t); //Called when a thread starts
void threadFinishes(Thread* thread, u32int retval); //Called when a thread finishes
@@ -61,7 +74,8 @@ class Process {
VirtualTerminal* getVirtualTerminal();
void setVirtualTerminal(VirtualTerminal* vt);
-
+ u32int getState() { return m_state; }
+ u32int freePageSC(u32int);
};
#endif
diff --git a/Source/Kernel/TaskManager/Task.ns.cpp b/Source/Kernel/TaskManager/Task.ns.cpp
index a34f14f..aef07f3 100644
--- a/Source/Kernel/TaskManager/Task.ns.cpp
+++ b/Source/Kernel/TaskManager/Task.ns.cpp
@@ -1,5 +1,4 @@
#include "Task.ns.h"
-#include <Library/Vector.class.h>
#include <MemoryManager/PhysMem.ns.h>
#define INVALID_TASK_MAGIC 0xBEEFFEED
@@ -94,8 +93,11 @@ void doSwitch() {
eip = t->getEip();
cr3 = currentProcess->getPagedir()->physicalAddr;
+ asm volatile("cli");
+
+ t->setKernelStack();
+
asm volatile(" \
- cli; \
mov %0, %%ebp; \
mov %1, %%esp; \
mov %2, %%ecx; \
@@ -138,6 +140,7 @@ void currThreadExitProceed(u32int errcode) {
}
void currentThreadExits(u32int errcode) { //Call currThreadExitProceed with a working stack (we use temp_stack)
+ asm volatile("cli");
u32int* stack = &temp_stack[TEMP_STACK_SIZE];
stack--;
*stack = errcode;
@@ -146,7 +149,6 @@ void currentThreadExits(u32int errcode) { //Call currThreadExitProceed with a wo
u32int esp = (u32int)(stack), ebp = (u32int)(stack + 1), eip = (u32int)currThreadExitProceed;
asm volatile(" \
- cli; \
mov %0, %%ebp; \
mov %1, %%esp; \
mov %2, %%ecx; \
diff --git a/Source/Kernel/TaskManager/Task.ns.h b/Source/Kernel/TaskManager/Task.ns.h
index c7c3d23..056e4c0 100644
--- a/Source/Kernel/TaskManager/Task.ns.h
+++ b/Source/Kernel/TaskManager/Task.ns.h
@@ -3,7 +3,7 @@
#include <TaskManager/Thread.class.h>
#include <VTManager/VirtualTerminal.proto.h>
-#include <Library/SimpleList.class.h>
+#include <SimpleList.class.h>
namespace Task {
Thread* currThread();
diff --git a/Source/Kernel/TaskManager/Task.wtf.asm b/Source/Kernel/TaskManager/Task.wtf.asm
index 77db18e..9f27bec 100644
--- a/Source/Kernel/TaskManager/Task.wtf.asm
+++ b/Source/Kernel/TaskManager/Task.wtf.asm
@@ -9,13 +9,6 @@ idle_task:
hlt
jmp idle_task
-[GLOBAL atomic_exchange]
-atomic_exchange:
- mov ecx, [esp+4] ; Get lock address
- mov eax, [esp+8] ; Get new value
- xchg eax, [ecx] ; Old value goes in eax
- ret
-
[GLOBAL copy_page_physical]
copy_page_physical:
push ebx ; According to __cdecl, we must preserve the contents of EBX.
@@ -47,3 +40,5 @@ copy_page_physical:
popf ; Pop EFLAGS back.
pop ebx ; Get the original value of EBX back.
ret
+
+
diff --git a/Source/Kernel/TaskManager/Thread.class.cpp b/Source/Kernel/TaskManager/Thread.class.cpp
index 6d62474..21ef954 100644
--- a/Source/Kernel/TaskManager/Thread.class.cpp
+++ b/Source/Kernel/TaskManager/Thread.class.cpp
@@ -2,17 +2,71 @@
#include <TaskManager/Task.ns.h>
#include <MemoryManager/PageAlloc.ns.h>
#include <DeviceManager/Time.ns.h>
+#include <MemoryManager/GDT.ns.h>
+
+#include <Thread.iface.h>
+
+call_t Thread::m_callTable[] = {
+ CALL1(THIF_SLEEP, &Thread::sleepSC),
+ CALL1(THIF_FINISH, &Thread::finishSC),
+ CALL0(0, 0)
+};
+
+u32int Thread::scall(u8int wat, u32int a, u32int b, u32int c, u32int d) {
+ if (wat == THIF_SGETCTH) return Task::currThread()->resId();
+ return (u32int) - 1;
+}
void runThread(Thread* thread, void* data, thread_entry_t entry_point) {
- asm volatile("sti");
- u32int ret = entry_point(data); //Run !
- asm volatile("mov %0, %%eax; int $66;" : : "r"(ret)); //Syscall for thread ending
+ if (thread->m_isKernel) {
+ asm volatile("sti");
+ u32int ret = entry_point(data); //Run !
+ asm volatile("mov %0, %%eax; int $66;" : : "r"(ret)); //Syscall for thread ending
+ } else {
+ //Setup values on user stack
+ u32int *stack = (u32int*)((u32int)thread->m_userStack.addr + thread->m_userStack.size);
+ stack--;
+ *stack = (u32int)data;
+ stack--;
+ *stack = 0;
+ u32int esp = (u32int)stack, eip = (u32int)entry_point;
+ //Setup a false structure for returning from an interrupt :
+ //- update data segments to 0x23 = user data segment with RPL=3
+ //- mov esp in ebx and eip in ecx
+ //- push value for ss : 0x23 (user data seg rpl3)
+ //- push value for esp
+ //- push flags
+ //- update flags, set IF = 1 (interrupts flag)
+ //- push value for cs : 0x1B = user code segment with RPL=3
+ //- push eip
+ //- return from fake interrupt
+ asm volatile(" \
+ mov $0x23, %%ax; \
+ mov %%ax, %%ds; \
+ mov %%ax, %%es; \
+ mov %%ax, %%fs; \
+ mov %%ax, %%gs; \
+ \
+ mov %0, %%ebx; \
+ mov %1, %%ecx; \
+ pushl $0x23; \
+ pushl %%ebx; \
+ pushf; \
+ pop %%eax; \
+ or $0x200, %%eax; \
+ push %%eax; \
+ pushl $0x1B; \
+ push %%ecx; \
+ iret; \
+ " : : "r"(esp), "r"(eip));
+ }
}
-Thread::Thread() { //Private constructor, does nothing
+Thread::Thread() : Ressource(THIF_OBJTYPE, m_callTable) { //Private constructor, does nothing
+ m_xchgspace = 0;
}
-Thread::Thread(thread_entry_t entry_point, void* data, bool iskernel) {
+Thread::Thread(thread_entry_t entry_point, void* data, bool iskernel) : Ressource(THIF_OBJTYPE, m_callTable) {
if (iskernel) {
setup(Task::getKernelProcess(), entry_point, data, true);
} else {
@@ -20,22 +74,28 @@ Thread::Thread(thread_entry_t entry_point, void* data, bool iskernel) {
}
}
-Thread::Thread(Process* process, thread_entry_t entry_point, void* data) {
+Thread::Thread(Process* process, thread_entry_t entry_point, void* data) : Ressource(THIF_OBJTYPE, m_callTable) {
setup(process, entry_point, data, false);
}
Thread::~Thread() {
Task::unregisterThread(this);
- Mem::kfree(m_kernelStack.addr);
- if (!m_isKernel) m_process->heap().free(m_userStack.addr);
+ Mem::free(m_kernelStack.addr);
+ m_process->getPagedir()->switchTo();
+ if (m_userStack.addr != 0) {
+ m_process->heap().free(m_userStack.addr);
+ }
+ if (m_xchgspace != 0) {
+ m_process->heap().free(m_xchgspace);
+ }
//Don't unregister thread in process, it has probably already been done
}
void Thread::setup(Process* process, thread_entry_t entry_point, void* data, bool isKernel) {
- DEBUG("new Thread :: setup");
+ m_xchgspace = 0;
m_isKernel = isKernel;
m_process = process;
- m_kernelStack.addr = Mem::kalloc(STACKSIZE);
+ m_kernelStack.addr = Mem::alloc(STACKSIZE);
m_kernelStack.size = STACKSIZE;
if (m_isKernel) {
@@ -111,11 +171,11 @@ void Thread::handleException(registers_t regs, int no) {
*(m_process->m_vt) << "At:" << (u32int)faddr;
*(m_process->m_vt) << "\nThread finishing.\n";
- finish(E_PAGEFAULT);
+ Task::currentThreadExits(E_PAGEFAULT); //Calling this will setup a new stack
return;
}
*(m_process->m_vt) << "\nThread finishing.\n";
- finish(E_UNHANDLED_EXCEPTION);
+ Task::currentThreadExits(E_UNHANDLED_EXCEPTION);
}
void Thread::setState(u32int esp, u32int ebp, u32int eip) {
@@ -124,12 +184,22 @@ void Thread::setState(u32int esp, u32int ebp, u32int eip) {
m_eip = eip;
}
+void Thread::setKernelStack() {
+ GDT::tss_entry.esp0 = (u32int)(m_kernelStack.addr) + m_kernelStack.size;
+}
+
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::mkXchgSpace(u32int sz) {
+ if (m_xchgspace != 0) m_process->heap().free(m_xchgspace);
+ m_xchgspace = m_process->heap().alloc(sz);
+ return m_xchgspace;
+}
+
void Thread::sleep(u32int msecs) {
m_state = T_SLEEPING;
waitfor.m_time = Time::time() + msecs;
@@ -145,6 +215,7 @@ void Thread::waitIRQ(u8int irq) {
}
bool Thread::runnable() {
+ if (m_process->getState() != P_RUNNING) return false;
if (m_state == T_RUNNING) return true;
if (m_state == T_SLEEPING and Time::time() >= waitfor.m_time) {
m_state = T_RUNNING;
@@ -152,3 +223,17 @@ bool Thread::runnable() {
}
return false;
}
+
+u32int Thread::sleepSC(u32int msecs) {
+ if (this != Task::currThread()) return 1;
+ sleep(msecs);
+ return 0;
+}
+
+u32int Thread::finishSC(u32int errcode) {
+ if (this != Task::currThread()) return 1;
+ Task::currentThreadExits(errcode);
+ return 0;
+}
+
+
diff --git a/Source/Kernel/TaskManager/Thread.class.h b/Source/Kernel/TaskManager/Thread.class.h
index 9c8fa26..35a9fd6 100644
--- a/Source/Kernel/TaskManager/Thread.class.h
+++ b/Source/Kernel/TaskManager/Thread.class.h
@@ -11,7 +11,7 @@
typedef u32int(*thread_entry_t)(void*);
-class Thread {
+class Thread : public Ressource {
friend class Process; //This might be useful
friend void runThread(Thread*, void*, thread_entry_t);
@@ -22,6 +22,8 @@ class Thread {
u32int m_esp, m_ebp, m_eip;
u8int m_state; //Is one of T_* defined above
+ void* m_xchgspace;
+
union { //What the thread might be waiting for
u32int m_time;
u8int m_irq; //An IRQ number
@@ -35,7 +37,14 @@ class Thread {
void setup(Process* process, thread_entry_t entry_point, void* data, bool isKernel);
+ //Syscalls
+ static call_t m_callTable[];
+ u32int sleepSC(u32int msecs);
+ u32int finishSC(u32int errcode);
+
public:
+ static u32int scall(u8int, u32int, u32int, u32int, u32int);
+
Thread(thread_entry_t entry_point, void* data, bool iskernel = false); //Assumes process is current process, or is kprocess if isk
Thread(Process* process, thread_entry_t entry_point, void* data);
~Thread();
@@ -43,11 +52,14 @@ class Thread {
void handleException(registers_t regs, int no);
void setState(u32int esp, u32int ebp, u32int eip);
+ void setKernelStack();
u32int getEsp();
u32int getEbp();
u32int getEip();
Process* getProcess();
+ void* mkXchgSpace(u32int sz);
+
void sleep(u32int msecs);
void waitIRQ(u8int irq);
bool runnable(); //Called by scheduler