summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexis211 <alexis211@gmail.com>2009-10-16 22:58:05 +0200
committerAlexis211 <alexis211@gmail.com>2009-10-16 22:58:05 +0200
commit54d76800cf8010434065556e12f693b101383d8b (patch)
tree5388f108f5a461fac83f593c19b85533f1a0e468
parent518d722a88a62d81150e54b8ae02be7176171ccf (diff)
parent4d5348a49f54d95c0271c8f9c4ef01c005d6b74b (diff)
downloadMelon-54d76800cf8010434065556e12f693b101383d8b.tar.gz
Melon-54d76800cf8010434065556e12f693b101383d8b.zip
Merge branch 'heap_class'
Conflicts: Source/Kernel/Melon.ke
-rwxr-xr-xSource/Kernel/Melon.kebin613280 -> 609378 bytes
-rw-r--r--Source/Kernel/MemoryManager/Heap.class.cpp20
-rw-r--r--Source/Kernel/MemoryManager/Heap.class.h28
-rw-r--r--Source/Kernel/MemoryManager/PageDirectory.class.cpp2
-rw-r--r--Source/Kernel/MemoryManager/PhysMem.ns.cpp5
-rw-r--r--Source/Kernel/SyscallManager/IDT.ns.cpp4
-rw-r--r--Source/Kernel/TaskManager/Mutex.class.cpp6
-rw-r--r--Source/Kernel/TaskManager/Process.class.cpp18
-rw-r--r--Source/Kernel/TaskManager/Process.class.h3
-rw-r--r--Source/Kernel/TaskManager/Task.ns.cpp52
-rw-r--r--Source/Kernel/TaskManager/Thread.class.cpp3
-rw-r--r--Source/Kernel/TaskManager/Thread.class.h2
12 files changed, 96 insertions, 47 deletions
diff --git a/Source/Kernel/Melon.ke b/Source/Kernel/Melon.ke
index da8d78d..326bd23 100755
--- a/Source/Kernel/Melon.ke
+++ b/Source/Kernel/Melon.ke
Binary files differ
diff --git a/Source/Kernel/MemoryManager/Heap.class.cpp b/Source/Kernel/MemoryManager/Heap.class.cpp
index f5bbe0a..7331cd0 100644
--- a/Source/Kernel/MemoryManager/Heap.class.cpp
+++ b/Source/Kernel/MemoryManager/Heap.class.cpp
@@ -1,7 +1,7 @@
#include "Heap.class.h"
#include <MemoryManager/PageDirectory.class.h>
-Heap::Heap() {
+Heap::Heap() : m_mutex(MUTEX_FALSE) {
m_usable = false;
m_index.data = 0;
m_index.size = 0;
@@ -12,6 +12,8 @@ Heap::~Heap() {
}
void Heap::create(u32int start, u32int size, u32int idxsize, PageDirectory* pagedir, bool user, bool rw) {
+ if (m_usable) return;
+
if (start & 0x0FFF) start = (start & 0xFFFFF000) + 0x1000;
if (size & 0x0FFF) size = (size & 0xFFFFF000) + 0x1000;
m_start = start + idxsize; //m_start is start of real data, start is start of index.
@@ -42,6 +44,8 @@ void Heap::create(u32int start, u32int size, u32int idxsize, PageDirectory* page
m_usable = true;
m_free = (m_end - m_start);
+
+ m_mutex.unlock();
}
void Heap::expand(u32int quantity) {
@@ -113,6 +117,8 @@ void Heap::contract() { //Automatically work out how much we can contract
}
void *Heap::alloc(u32int sz, bool no_expand) {
+ m_mutex.waitLock();
+
u32int newsize = sz + sizeof(heap_header_t) + sizeof(heap_footer_t);
u32int iterator = 0;
while (iterator < m_index.size) {
@@ -120,8 +126,12 @@ void *Heap::alloc(u32int sz, bool no_expand) {
iterator++;
}
if (iterator == m_index.size) { //No hole is big enough
- if (no_expand) return 0;
+ if (no_expand) {
+ m_mutex.unlock();
+ return 0;
+ }
expand((sz & 0xFFFFF000) + 0x1000);
+ m_mutex.unlock();
return alloc(sz, true); //Recurse call
}
@@ -152,6 +162,8 @@ void *Heap::alloc(u32int sz, bool no_expand) {
m_free -= loc->size;
+ m_mutex.unlock();
+
return (void*)((u32int)loc + sizeof(heap_header_t));
}
@@ -162,6 +174,8 @@ void Heap::free(void *ptr) {
heap_footer_t *footer = (heap_footer_t*)((u32int)header + header->size - sizeof(heap_footer_t));
if (header->magic != HEAP_MAGIC or footer->magic != HEAP_MAGIC) return;
+ m_mutex.waitLock();
+
m_free += header->size;
//Unify left
@@ -192,4 +206,6 @@ void Heap::free(void *ptr) {
header->size >= 0x2000 and (m_end - m_start > HEAP_MIN_SIZE)) {
contract();
}
+
+ m_mutex.unlock();
}
diff --git a/Source/Kernel/MemoryManager/Heap.class.h b/Source/Kernel/MemoryManager/Heap.class.h
index a1feaa1..930a589 100644
--- a/Source/Kernel/MemoryManager/Heap.class.h
+++ b/Source/Kernel/MemoryManager/Heap.class.h
@@ -2,6 +2,7 @@
#define DEF_HEAP_CLASS_H
#include <Core/common.wtf.h>
+#include <TaskManager/Mutex.class.h>
//Heap minimum size : 2M
#define HEAP_MIN_SIZE 0x00200000
@@ -33,6 +34,8 @@ class Heap {
heap_index_t m_index;
PageDirectory* m_pagedir;
+ Mutex m_mutex;
+
void insertIntoIndex(heap_header_t *e);
u32int findIndexEntry(heap_header_t *e);
void removeFromIndex(u32int idx);
@@ -41,20 +44,35 @@ class Heap {
void expand(u32int quantity);
void contract(); //Quantity is automatically calculated
-
public:
Heap();
~Heap();
- bool usable() { return m_usable; }
-
void create(u32int start, u32int size, u32int idxsize, PageDirectory* pagedir, bool user, bool rw);
void* alloc(u32int sz, bool no_expand = false);
void free(void* ptr);
- u32int size() { return m_end - m_start; }
- u32int free() { return m_free; }
+ bool usable() {
+ m_mutex.waitLock();
+ bool ret = m_usable;
+ m_mutex.unlock();
+ return ret;
+ }
+
+ u32int size() {
+ m_mutex.waitLock();
+ u32int ret = m_end - m_start;
+ m_mutex.unlock();
+ return ret;
+ }
+
+ u32int free() {
+ m_mutex.waitLock();
+ u32int ret = m_free;
+ m_mutex.unlock();
+ return ret;
+ }
};
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/Mutex.class.cpp b/Source/Kernel/TaskManager/Mutex.class.cpp
index a6c3ba8..8ba274f 100644
--- a/Source/Kernel/TaskManager/Mutex.class.cpp
+++ b/Source/Kernel/TaskManager/Mutex.class.cpp
@@ -13,8 +13,10 @@ bool Mutex::lock() {
}
void Mutex::waitLock() {
- while (atomic_exchange(&m_locked, MUTEX_TRUE) == MUTEX_TRUE)
- Task::currThread()->sleep(10); //Wait 10ms
+ while (atomic_exchange(&m_locked, MUTEX_TRUE) == MUTEX_TRUE) {
+ if (Task::currThread() != 0) Task::currThread()->sleep(10); //Wait 10ms
+ else return;
+ }
}
void Mutex::unlock() {
diff --git a/Source/Kernel/TaskManager/Process.class.cpp b/Source/Kernel/TaskManager/Process.class.cpp
index 2653269..2706986 100644
--- a/Source/Kernel/TaskManager/Process.class.cpp
+++ b/Source/Kernel/TaskManager/Process.class.cpp
@@ -60,11 +60,11 @@ void Process::exit() {
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];
+ for (SimpleList<File*> *iter = m_fileDescriptors; iter != 0; iter = iter->next()) {
+ iter->v()->close(false);
+ delete iter->v();
}
- m_fileDescriptors.clear();
+ delete m_fileDescriptors; //Will recursively delete whole list
m_state = P_FINISHED;
}
@@ -91,17 +91,11 @@ void Process::threadFinishes(Thread* thread, u32int retval) {
}
void Process::registerFileDescriptor(File* fd) {
- m_fileDescriptors.push(fd);
+ m_fileDescriptors = m_fileDescriptors->cons(fd);
}
void Process::unregisterFileDescriptor(File* fd) {
- for (u32int i = 0; i < m_fileDescriptors.size(); i++) {
- if (m_fileDescriptors[i] == fd) {
- m_fileDescriptors[i] = m_fileDescriptors.back();
- m_fileDescriptors.pop();
- break;
- }
- }
+ m_fileDescriptors = m_fileDescriptors->removeOnce(fd);
}
PageDirectory* Process::getPagedir() {
diff --git a/Source/Kernel/TaskManager/Process.class.h b/Source/Kernel/TaskManager/Process.class.h
index 65a5d8b..b975db1 100644
--- a/Source/Kernel/TaskManager/Process.class.h
+++ b/Source/Kernel/TaskManager/Process.class.h
@@ -3,6 +3,7 @@
#include <Library/String.class.h>
#include <Library/Vector.class.h>
+#include <Library/SimpleList.class.h>
#include <MemoryManager/PageDirectory.class.h>
#include <VTManager/VirtualTerminal.proto.h>
@@ -35,7 +36,7 @@ class Process {
VirtualTerminal *m_vt;
Vector<Thread*> m_threads;
- Vector<File*> m_fileDescriptors;
+ SimpleList<File*> *m_fileDescriptors;
public:
static Process* createKernel(String cmdline, VirtualTerminal *vt); //Also creates a Thread for what's curently happening
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 <Library/Vector.class.h>
+#include <MemoryManager/PhysMem.ns.h>
+
+#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<Thread*> *idleThread = 0;
u32int nextpid = 1;
-struct finished_thread_t { //Forms a linked list
- Thread* thread;
- u32int errcode;
-};
-SimpleList<finished_thread_t> *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<Thread*> *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<Thread*> *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<Process*> *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<Thread*>*)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*);