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:
Xnoe 2021-11-10 18:31:00 +00:00
parent 4a271865e0
commit c10c3690a5
Signed by: xnoe
GPG Key ID: 45AC398F44F0DAFE
11 changed files with 242 additions and 93 deletions

View File

@ -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) {

View File

@ -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;
}
}
};
}

View 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
View File

@ -0,0 +1,4 @@
#include "global.h"
namespace Global {
Allocator* allocator;
}

10
src/kernel/global.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef GLOBAL_H
#define GLOBAL_H
#include "memory.h"
namespace Global {
extern Allocator* allocator;
}
#endif

View File

@ -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) {

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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