A huge amount of changes and additions. Added xnoe::Maybe, fixed xnoe::linkedlist and xnoe::linkedlistelem, fixed bug in Allocator::deallocate, update Process::allocate, implement Process::deallocate, fix operator delete, add Global namespace and Global::allocator, update new, delete, new\[\] and delete\[\], add AllocTracker, etc. Allocations now work how I want them to :D
This commit is contained in:
parent
4a271865e0
commit
c10c3690a5
@ -12,8 +12,8 @@ namespace xnoe {
|
||||
xnoe::linkedlist<xnoe::tuple<key, value>>* table;
|
||||
|
||||
public:
|
||||
hashtable(Allocator* allocator) {
|
||||
this->table = new(allocator) xnoe::linkedlist<xnoe::tuple<key, value>>[4096];
|
||||
hashtable() {
|
||||
this->table = new xnoe::linkedlist<xnoe::tuple<key, value>>[4096];
|
||||
}
|
||||
|
||||
void set(key k, value v) {
|
||||
|
@ -7,33 +7,53 @@ namespace xnoe {
|
||||
template<typename T>
|
||||
struct linkedlistelem {
|
||||
T elem;
|
||||
linkedlistelem<T>* previous;
|
||||
linkedlistelem<T>* prev;
|
||||
linkedlistelem<T>* next;
|
||||
|
||||
linkedlistelem(T t) {
|
||||
this->elem = t;
|
||||
this->previous = 0;
|
||||
this->prev = 0;
|
||||
this->next = 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct linkedlist {
|
||||
linkedlistelem<T>* start;
|
||||
linkedlistelem<T>* end;
|
||||
xnoe::linkedlistelem<T>* start;
|
||||
xnoe::linkedlistelem<T>* end;
|
||||
|
||||
void append(linkedlistelem<T>* t) {
|
||||
this->end->next = t;
|
||||
t->prev = this->end;
|
||||
t->next = 0;
|
||||
this->end = t;
|
||||
void append(T t) {
|
||||
xnoe::linkedlistelem<T>* llelem = new xnoe::linkedlistelem<T>(t);
|
||||
append(llelem);
|
||||
}
|
||||
|
||||
void prepend(linkedlistelem<T>* t) {
|
||||
this->start->previous = t;
|
||||
t->next = this->start;
|
||||
t->prev = 0;
|
||||
this->start = t;
|
||||
void append(xnoe::linkedlistelem<T>* llelem) {
|
||||
if (this->start && this->end) {
|
||||
this->end->next = llelem;
|
||||
llelem->prev = this->end;
|
||||
llelem->next = 0;
|
||||
this->end = llelem;
|
||||
} else {
|
||||
this->start = llelem;
|
||||
this->end = llelem;
|
||||
}
|
||||
}
|
||||
|
||||
void prepend(T t) {
|
||||
xnoe::linkedlistelem<T>* llelem = new xnoe::linkedlistelem<T>(t);
|
||||
prepend(llelem);
|
||||
}
|
||||
|
||||
void prepend(xnoe::linkedlistelem<T>* llelem) {
|
||||
if (this->start && this->end) {
|
||||
this->start->prev = llelem;
|
||||
llelem->next = this->start;
|
||||
llelem->prev = 0;
|
||||
this->end = llelem;
|
||||
} else {
|
||||
this->start = llelem;
|
||||
this->end = llelem;
|
||||
}
|
||||
}
|
||||
|
||||
void insert(linkedlist<T>* ll, uint32_t index) {
|
||||
@ -44,14 +64,36 @@ namespace xnoe {
|
||||
current->next = ll->start;
|
||||
}
|
||||
|
||||
void remove(Allocator* allocator, uint32_t index) {
|
||||
/*void remove(uint32_t index) {
|
||||
linkedlistelem<T>* current = this->start;
|
||||
for (int i=0; i<index; i++, current = current->next);
|
||||
|
||||
current->prev->next = current->next;
|
||||
current->next->prev = current->prev;
|
||||
|
||||
delete(allocator, current);
|
||||
delete current;
|
||||
}*/
|
||||
|
||||
void remove(linkedlistelem<T>* elem) {
|
||||
linkedlistelem<T>* current = start;
|
||||
while (current) {
|
||||
if (current == elem) {
|
||||
if (current->prev)
|
||||
current->prev->next = current->next;
|
||||
|
||||
if (current->next)
|
||||
current->next->prev = current->prev;
|
||||
|
||||
if (current == start)
|
||||
start = 0;
|
||||
|
||||
if (current = end)
|
||||
end = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
31
src/kernel/datatypes/maybe.h
Normal file
31
src/kernel/datatypes/maybe.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef MAYBE_H
|
||||
#define MAYBE_H
|
||||
|
||||
namespace xnoe {
|
||||
template<typename T>
|
||||
class Maybe {
|
||||
private:
|
||||
T t;
|
||||
bool ok;
|
||||
|
||||
public:
|
||||
Maybe() {
|
||||
this->ok = false;
|
||||
}
|
||||
|
||||
Maybe(T t) {
|
||||
this->ok = true;
|
||||
this->t = t;
|
||||
}
|
||||
|
||||
T get() {
|
||||
return t;
|
||||
}
|
||||
|
||||
bool is_ok() {
|
||||
return ok;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
4
src/kernel/global.cpp
Normal file
4
src/kernel/global.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
#include "global.h"
|
||||
namespace Global {
|
||||
Allocator* allocator;
|
||||
}
|
10
src/kernel/global.h
Normal file
10
src/kernel/global.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef GLOBAL_H
|
||||
#define GLOBAL_H
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
namespace Global {
|
||||
extern Allocator* allocator;
|
||||
}
|
||||
|
||||
#endif
|
@ -23,6 +23,7 @@ __attribute__((interrupt)) void page_fault(interrupt_frame* frame, uint32_t err_
|
||||
uint32_t problem_address;
|
||||
asm("mov %%cr2, %0" : "=a" (problem_address) :);
|
||||
printf("Page Fault at %x\n", problem_address);
|
||||
asm("hlt");
|
||||
}
|
||||
|
||||
__attribute__((interrupt)) void ignore_interrupt(interrupt_frame* frame) {
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "allocate.h"
|
||||
#include "memory.h"
|
||||
#include "process.h"
|
||||
#include "global.h"
|
||||
#include "datatypes/hashtable.h"
|
||||
|
||||
int main() {
|
||||
@ -24,41 +25,32 @@ int main() {
|
||||
PageMap virt_pm(0xc0620000);
|
||||
|
||||
Allocator kernel_allocator = Allocator(&kernel_pd, &phys_pm, &virt_pm, 0xd0000000);
|
||||
Global::allocator = &kernel_allocator;
|
||||
|
||||
xnoe::hashtable<void*, uint32_t>* kproc_hashtable = new (&kernel_allocator) xnoe::hashtable<void*, uint32_t>(&kernel_allocator);
|
||||
|
||||
Process kernel_process = Process(0, kproc_hashtable, &kernel_pd, &phys_pm, &virt_pm, 0xd0000000);
|
||||
|
||||
uint32_t* test = new(&kernel_process)uint32_t;
|
||||
uint32_t* test2 = new(&kernel_process)uint32_t;
|
||||
uint32_t* test3 = new(&kernel_process)uint32_t[1024];
|
||||
|
||||
*test = 0xdead;
|
||||
*test2 = 0xbeef;
|
||||
Process kernel_process = Process(0, &kernel_pd, &phys_pm, &virt_pm, 0xd0000000);
|
||||
Global::allocator = &kernel_process;
|
||||
|
||||
init_idt();
|
||||
|
||||
printf("Hello, World!\n\nWe are running XnoeOS Code in C now, Protected Mode has been achieved (as well as Virtual Memory / Paging!!!) and everything is working super nicely!\n\nHow wonderful!\n\nNow I just need to hope my print function works properly too~~\n");
|
||||
printf("Hello, World!\n\nWe are running XnoeOS Code in C++ now, Protected Mode has been achieved (as well as Virtual Memory / Paging!!!) and everything is working super nicely!\n\nHow wonderful!\n\nNow I just need to hope my print function works properly too~~\n");
|
||||
|
||||
printf("KERNEL OK!\n");
|
||||
|
||||
printf("Test :%x\nTest 2:%x\nTest 3:%x\n", test, test2, test3);
|
||||
printf("Test value :%x\nTest 2 value:%x\n", *test, *test2);
|
||||
|
||||
init_keyboard();
|
||||
|
||||
enable_idt();
|
||||
init_atapio();
|
||||
|
||||
uint8_t sector[512];
|
||||
uint8_t* filebuffer = new uint8_t[0x3000];
|
||||
|
||||
read_sector(0, sector);
|
||||
|
||||
uint8_t* filebuffer = new(&kernel_process)uint8_t[0x3000];
|
||||
char* buffer = 0;
|
||||
|
||||
while (1) {
|
||||
if (buffer)
|
||||
delete[] buffer;
|
||||
buffer = new char[128];
|
||||
printf("Buffer allocations: %d\n", kernel_process.count_allocations(buffer));
|
||||
printf(">>> ");
|
||||
char buffer[128];
|
||||
for (int i=0; i<128; i++)
|
||||
buffer[i] = 0;
|
||||
readline(128, buffer);
|
||||
|
@ -149,11 +149,13 @@ void PageDirectory::map(uint32_t phys, uint32_t virt) {
|
||||
};
|
||||
|
||||
page_tables[split->pd_index].map_table(split->pt_index, phys >> 12);
|
||||
asm volatile ("invlpg (%0)" : : "r" (virt) : "memory");
|
||||
}
|
||||
|
||||
void PageDirectory::unmap(uint32_t virt) {
|
||||
split_addr* split = (split_addr*)&virt;
|
||||
page_tables[split->pd_index].unmap_table(split->pt_index);
|
||||
asm volatile ("invlpg (%0)" : : "r" (virt) : "memory");
|
||||
}
|
||||
|
||||
uint32_t PageDirectory::virtual_to_physical(uint32_t virt) {
|
||||
@ -196,21 +198,5 @@ void Allocator::deallocate(uint32_t virt_addr) {
|
||||
PD->unmap(virt_addr);
|
||||
|
||||
phys->mark_available(phys_addr);
|
||||
virt->mark_unavailable(virt_addr);
|
||||
}
|
||||
|
||||
void* operator new (uint32_t size, Allocator* allocator) {
|
||||
return allocator->allocate(size);
|
||||
}
|
||||
|
||||
void operator delete (void* ptr, Allocator* allocator) {
|
||||
allocator->deallocate((uint32_t)ptr);
|
||||
}
|
||||
|
||||
void* operator new[] (uint32_t size, Allocator* allocator) {
|
||||
return allocator->allocate(size);
|
||||
}
|
||||
|
||||
void operator delete[] (void* ptr, Allocator* allocator) {
|
||||
allocator->deallocate((uint32_t)ptr);
|
||||
virt->mark_available(virt_addr);
|
||||
}
|
@ -80,10 +80,4 @@ public:
|
||||
virtual void deallocate(uint32_t virt_addr);
|
||||
};
|
||||
|
||||
void* operator new (uint32_t size, Allocator* allocator);
|
||||
void operator delete (void* ptr, Allocator* allocator);
|
||||
|
||||
void* operator new[] (uint32_t size, Allocator* allocator);
|
||||
void operator delete[] (void* ptr, Allocator* allocator);
|
||||
|
||||
#endif
|
@ -1,44 +1,111 @@
|
||||
#include "process.h"
|
||||
|
||||
Process::Process(uint32_t PID, xnoe::hashtable<void*, uint32_t>* table, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base)
|
||||
AllocTracker::AllocTracker(void* base, uint32_t size, uint32_t count) : page_base(base), page_size(size), alloc_count(count) {}
|
||||
|
||||
xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*> Process::get_alloc_tracker(uint32_t address) {
|
||||
xnoe::linkedlistelem<AllocTracker>* current = this->allocations.start;
|
||||
while (current) {
|
||||
if (current->elem.page_base < address && (current->elem.page_base + 4096 * current->elem.page_size) > address) {
|
||||
return xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*>(current);
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*>();
|
||||
}
|
||||
|
||||
Process::Process(uint32_t PID, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base)
|
||||
: Allocator(page_directory, phys, virt, virt_alloc_base) {
|
||||
this->PID = PID;
|
||||
this->allocmap = table;
|
||||
this->page_remaining = 0;
|
||||
this->last_page_pointer = virt_alloc_base;
|
||||
}
|
||||
|
||||
void* Process::allocate(uint32_t size) {
|
||||
uint32_t elem_size = sizeof(xnoe::linkedlistelem<xnoe::tuple<uint32_t, uint32_t>>);
|
||||
printf("Elem size: %d\n", elem_size);
|
||||
uint32_t actualsize = size + elem_size;
|
||||
|
||||
void* ptr = 0;
|
||||
|
||||
if (this->page_remaining > actualsize) {
|
||||
ptr = last_page_pointer + (4096 - page_remaining);
|
||||
page_remaining -= actualsize;
|
||||
printf("Non-allocating return\nptr: %x\nremaining: %d\n", ptr, page_remaining);
|
||||
} else if (actualsize % 4096 == 0) {
|
||||
ptr = Allocator::allocate(actualsize);
|
||||
page_remaining = 0;
|
||||
printf("Whole allocating return\nptr: %x\n", ptr);
|
||||
void* ptr;
|
||||
// Determine if there's enough space to just allocate what's been requested
|
||||
if (size < this->page_remaining) {
|
||||
xnoe::linkedlistelem<AllocTracker>* alloctracker = this->allocations.end;
|
||||
alloctracker->elem.alloc_count += 1;
|
||||
ptr = this->last_page_pointer + (4096 - this->page_remaining);
|
||||
this->page_remaining -= size;
|
||||
} else {
|
||||
uint32_t remaining = 4096 - (actualsize % 4096);
|
||||
uint32_t fpindex = actualsize >> 12;
|
||||
uint32_t elem_size = sizeof(xnoe::linkedlistelem<AllocTracker>);
|
||||
size += elem_size;
|
||||
|
||||
void* alloc_base = Allocator::allocate(actualsize);
|
||||
ptr = last_page_pointer + (4096 - page_remaining);
|
||||
last_page_pointer = alloc_base + (fpindex<<12);
|
||||
page_remaining = remaining;
|
||||
printf("Partially allocating return\nptr: %x\nremaining: %d\n", ptr, page_remaining);
|
||||
// Determine how many pages we'll allocate, and the remainder;
|
||||
uint32_t pages = size / 4096;
|
||||
uint32_t remainder = 4096 - (size % 4096);
|
||||
|
||||
ptr = Allocator::allocate(size);
|
||||
|
||||
// Update local values
|
||||
this->last_page_pointer = ptr + pages * 4096;
|
||||
this->page_remaining = remainder;
|
||||
|
||||
// Create allocations entry
|
||||
xnoe::linkedlistelem<AllocTracker>* elem = (xnoe::linkedlistelem<AllocTracker>*)ptr;
|
||||
elem->next = 0;
|
||||
elem->prev = 0;
|
||||
elem->elem = AllocTracker(ptr, pages + 1, 1);
|
||||
this->allocations.append(elem);
|
||||
|
||||
ptr += elem_size;
|
||||
}
|
||||
|
||||
*(xnoe::linkedlistelem<xnoe::tuple<uint32_t, uint32_t>>*)ptr = xnoe::linkedlistelem<xnoe::tuple<uint32_t, uint32_t>>(xnoe::tuple<uint32_t, uint32_t>((uint32_t)ptr, actualsize));
|
||||
|
||||
return ptr + elem_size;
|
||||
printf("ptr: %x\nPage Remaining: %d\n", this->last_page_pointer, this->page_remaining, ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void Process::deallocate(uint32_t virt_addr) {
|
||||
xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*> alloc_tracker = this->get_alloc_tracker(virt_addr);
|
||||
if (alloc_tracker.is_ok()) {
|
||||
AllocTracker* ac = &alloc_tracker.get()->elem;
|
||||
ac->alloc_count -= 1;
|
||||
if (ac->alloc_count == 0) {
|
||||
void* base = ac->page_base;
|
||||
uint32_t count = ac->page_size;
|
||||
|
||||
this->allocations.remove(alloc_tracker.get());
|
||||
|
||||
for (int i=0; i<count; i++)
|
||||
Allocator::deallocate(base + (4096 * i));
|
||||
|
||||
this->page_remaining = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Process::count_allocations(uint32_t address) {
|
||||
xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*> alloc_tracker = this->get_alloc_tracker(address);
|
||||
|
||||
if (alloc_tracker.is_ok())
|
||||
return alloc_tracker.get()->elem.alloc_count;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
Allocator* Global::allocator;
|
||||
|
||||
Kernel::Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base)
|
||||
: Process(0, page_directory, phys, virt, virt_alloc_base)
|
||||
{}
|
||||
|
||||
void* operator new (uint32_t size) {
|
||||
return Global::allocator->allocate(size);
|
||||
}
|
||||
|
||||
void operator delete (void* ptr) {
|
||||
Global::allocator->deallocate((uint32_t)ptr);
|
||||
}
|
||||
|
||||
void operator delete (void* ptr, unsigned int size) {
|
||||
Global::allocator->deallocate((uint32_t)ptr);
|
||||
}
|
||||
|
||||
void* operator new[] (uint32_t size) {
|
||||
return Global::allocator->allocate(size);
|
||||
}
|
||||
|
||||
void operator delete[] (void* ptr) {
|
||||
Global::allocator->deallocate((uint32_t)ptr);
|
||||
}
|
@ -5,7 +5,17 @@
|
||||
#include "memory.h"
|
||||
#include "datatypes/linkedlist.h"
|
||||
#include "datatypes/hashtable.h"
|
||||
#include "datatypes/maybe.h"
|
||||
#include "screenstuff.h"
|
||||
#include "global.h"
|
||||
|
||||
struct AllocTracker {
|
||||
void* page_base;
|
||||
uint32_t page_size;
|
||||
uint32_t alloc_count;
|
||||
|
||||
AllocTracker(void* base, uint32_t size, uint32_t count);
|
||||
};
|
||||
|
||||
class Process : public Allocator {
|
||||
private:
|
||||
@ -14,20 +24,32 @@ private:
|
||||
uint32_t last_page_pointer;
|
||||
uint32_t page_remaining;
|
||||
|
||||
// List of tuples tracking allocation base addresses and lengths.
|
||||
xnoe::linkedlist<xnoe::tuple<uint32_t, uint32_t>> allocations;
|
||||
// Maps pointers to the position in the linked list.
|
||||
xnoe::hashtable<void*, uint32_t>* allocmap;
|
||||
// List of pages this process has allocated
|
||||
xnoe::linkedlist<AllocTracker> allocations;
|
||||
|
||||
xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*> get_alloc_tracker(uint32_t address);
|
||||
|
||||
public:
|
||||
Process(uint32_t PID, xnoe::hashtable<void*, uint32_t>* table, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base);
|
||||
Process(uint32_t PID, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base);
|
||||
|
||||
void* allocate(uint32_t size) override;
|
||||
void deallocate(uint32_t virt_addr) override;
|
||||
|
||||
uint32_t count_allocations(uint32_t address);
|
||||
};
|
||||
|
||||
class Kernel : private Process {
|
||||
class Kernel : public Process {
|
||||
public:
|
||||
static Allocator* global_allocator;
|
||||
|
||||
Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base);
|
||||
};
|
||||
|
||||
void* operator new (uint32_t size);
|
||||
void operator delete (void* ptr);
|
||||
void operator delete (void* ptr, unsigned int size);
|
||||
|
||||
void* operator new[] (uint32_t size);
|
||||
void operator delete[] (void* ptr);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user