summaryrefslogtreecommitdiff
path: root/Source/Kernel/TaskManager
diff options
context:
space:
mode:
authorAlexis211 <alexis211@gmail.com>2009-10-09 16:29:05 +0200
committerAlexis211 <alexis211@gmail.com>2009-10-09 16:29:05 +0200
commitb9a988061e8220c5ef2406f5cd2221bf3f1b435d (patch)
tree7d523347e555a7555740d7b0ceffbeb35c32d1e6 /Source/Kernel/TaskManager
parent92abedffec913fe7337117403c5e07185356c81b (diff)
downloadMelon-b9a988061e8220c5ef2406f5cd2221bf3f1b435d.tar.gz
Melon-b9a988061e8220c5ef2406f5cd2221bf3f1b435d.zip
Exiting from a thread now works without hanging everything.
Diffstat (limited to 'Source/Kernel/TaskManager')
-rw-r--r--Source/Kernel/TaskManager/Process.class.cpp9
-rw-r--r--Source/Kernel/TaskManager/Task.ns.cpp31
-rw-r--r--Source/Kernel/TaskManager/Task.ns.h2
-rw-r--r--Source/Kernel/TaskManager/Thread.class.cpp3
4 files changed, 39 insertions, 6 deletions
diff --git a/Source/Kernel/TaskManager/Process.class.cpp b/Source/Kernel/TaskManager/Process.class.cpp
index 5a707cd..236d13a 100644
--- a/Source/Kernel/TaskManager/Process.class.cpp
+++ b/Source/Kernel/TaskManager/Process.class.cpp
@@ -56,10 +56,10 @@ u32int Process::stackAlloc() {
}
void Process::exit() {
- while (!m_threads.empty()) {
- delete m_threads.back();
- m_threads.pop();
+ for (u32int i = 0; i < m_threads.size(); i++) {
+ delete m_threads[i];
}
+ m_threads.clear();
for (u32int i = 0; i < m_fileDescriptors.size(); i++) {
m_fileDescriptors[i]->close(false);
delete m_fileDescriptors[i];
@@ -74,7 +74,6 @@ void Process::registerThread(Thread* t) {
}
void Process::threadFinishes(Thread* thread, u32int retval) {
- delete thread;
// If it is the main thread of the process, or if it pagefaulted
if (thread == m_threads[0] or retval == E_PAGEFAULT) {
exit();
@@ -84,8 +83,10 @@ void Process::threadFinishes(Thread* thread, u32int retval) {
if (m_threads[i] == thread) {
m_threads[i] = m_threads.back();
m_threads.pop();
+ break;
}
}
+ delete thread;
}
}
diff --git a/Source/Kernel/TaskManager/Task.ns.cpp b/Source/Kernel/TaskManager/Task.ns.cpp
index b430f24..a32c8c0 100644
--- a/Source/Kernel/TaskManager/Task.ns.cpp
+++ b/Source/Kernel/TaskManager/Task.ns.cpp
@@ -10,6 +10,12 @@ namespace Task {
Vector <Process*> processes; //TODO : use a linked list instead
Vector <Thread*> threads;
+struct finished_thread_t { //Forms a linked list
+ Thread* thread;
+ u32int errcode;
+ finished_thread_t *next;
+} *firstFinishedThread = 0;
+
Thread* currentThread = NULL;
Process* currentProcess = NULL;
Thread* idleThread = NULL;
@@ -29,11 +35,28 @@ void initialize(String cmdline, VirtualTerminal *vt) {
}
Thread* nextThread() {
+ //Clean up finished threads
+ while (firstFinishedThread != 0) {
+ DEBUG_HEX((u32int)firstFinishedThread);
+ if (firstFinishedThread->thread == currentThread) break;
+ firstFinishedThread->thread->finish(firstFinishedThread->errcode);
+ finished_thread_t* t = firstFinishedThread;
+ firstFinishedThread = t->next;
+ delete t;
+ }
+ for (u32int i = 0; i < threads.size(); i++) {
+ if (threads[i] == currentThread) {
+ currentThreadId = i;
+ }
+ }
+
+ //Find next thread
u32int nid = currentThreadId;
while (1) {
nid++;
if (nid >= threads.size()) nid = 0;
if (threads[nid]->runnable() and threads[nid] != idleThread) {
+ if (firstFinishedThread != 0 and firstFinishedThread->thread == threads[nid]) return idleThread;
currentThreadId = nid;
return threads[nid];
}
@@ -104,6 +127,14 @@ Process* getKernelProcess() {
return processes[0];
}
+void currentThreadExits(u32int errcode) {
+ finished_thread_t *t = new finished_thread_t;
+ t->thread = currentThread;
+ t->errcode = errcode;
+ t->next = firstFinishedThread;
+ firstFinishedThread = t;
+}
+
void registerThread(Thread* t) {
unregisterThread(t); //...//
threads.push(t);
diff --git a/Source/Kernel/TaskManager/Task.ns.h b/Source/Kernel/TaskManager/Task.ns.h
index 634d103..a41eaf7 100644
--- a/Source/Kernel/TaskManager/Task.ns.h
+++ b/Source/Kernel/TaskManager/Task.ns.h
@@ -17,6 +17,8 @@ namespace Task {
void allocKernelPageTable(u32int id, page_table_t *table, u32int tablePhys);
Process* getKernelProcess(); //Returns first registered process
+ void currentThreadExits(u32int errcode); //Syscall called when a thread finishes
+
//These are used by the constructors/destructors of Thread and Process
void registerThread(Thread* t);
void unregisterThread(Thread* t);
diff --git a/Source/Kernel/TaskManager/Thread.class.cpp b/Source/Kernel/TaskManager/Thread.class.cpp
index 43884d7..93a2cd3 100644
--- a/Source/Kernel/TaskManager/Thread.class.cpp
+++ b/Source/Kernel/TaskManager/Thread.class.cpp
@@ -33,10 +33,9 @@ Thread::Thread(Process* process, thread_entry_t entry_point, void* data) {
}
Thread::~Thread() {
- if (Task::currentThread == this) Task::currentThread = (Thread*)0xFFFFFFFF; //Signal that current thread is invalid
+ Task::unregisterThread(this);
if (m_isKernel)
PageAlloc::free((void*)m_kernelStackFrame);
- Task::unregisterThread(this);
//Don't unregister thread in process, it has probably already been done
}