diff --git a/src/kernel/datatypes/hashtable.h b/src/kernel/datatypes/hashtable.h index 387a56e..a466abb 100644 --- a/src/kernel/datatypes/hashtable.h +++ b/src/kernel/datatypes/hashtable.h @@ -12,8 +12,8 @@ namespace xnoe { xnoe::linkedlist>* table; public: - hashtable(Allocator* allocator) { - this->table = new(allocator) xnoe::linkedlist>[4096]; + hashtable() { + this->table = new xnoe::linkedlist>[4096]; } void set(key k, value v) { diff --git a/src/kernel/datatypes/linkedlist.h b/src/kernel/datatypes/linkedlist.h index c1e3e5f..6710a62 100644 --- a/src/kernel/datatypes/linkedlist.h +++ b/src/kernel/datatypes/linkedlist.h @@ -7,33 +7,53 @@ namespace xnoe { template struct linkedlistelem { T elem; - linkedlistelem* previous; + linkedlistelem* prev; linkedlistelem* next; linkedlistelem(T t) { this->elem = t; - this->previous = 0; + this->prev = 0; this->next = 0; } }; template struct linkedlist { - linkedlistelem* start; - linkedlistelem* end; + xnoe::linkedlistelem* start; + xnoe::linkedlistelem* end; - void append(linkedlistelem* t) { - this->end->next = t; - t->prev = this->end; - t->next = 0; - this->end = t; + void append(T t) { + xnoe::linkedlistelem* llelem = new xnoe::linkedlistelem(t); + append(llelem); } - void prepend(linkedlistelem* t) { - this->start->previous = t; - t->next = this->start; - t->prev = 0; - this->start = t; + void append(xnoe::linkedlistelem* 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* llelem = new xnoe::linkedlistelem(t); + prepend(llelem); + } + + void prepend(xnoe::linkedlistelem* 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* 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* current = this->start; for (int i=0; inext); current->prev->next = current->next; current->next->prev = current->prev; - delete(allocator, current); + delete current; + }*/ + + void remove(linkedlistelem* elem) { + linkedlistelem* 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; + } } }; } diff --git a/src/kernel/datatypes/maybe.h b/src/kernel/datatypes/maybe.h new file mode 100644 index 0000000..5ec2a2d --- /dev/null +++ b/src/kernel/datatypes/maybe.h @@ -0,0 +1,31 @@ +#ifndef MAYBE_H +#define MAYBE_H + +namespace xnoe { + template + 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 \ No newline at end of file diff --git a/src/kernel/global.cpp b/src/kernel/global.cpp new file mode 100644 index 0000000..eee0233 --- /dev/null +++ b/src/kernel/global.cpp @@ -0,0 +1,4 @@ +#include "global.h" +namespace Global { + Allocator* allocator; +} \ No newline at end of file diff --git a/src/kernel/global.h b/src/kernel/global.h new file mode 100644 index 0000000..f1f6a45 --- /dev/null +++ b/src/kernel/global.h @@ -0,0 +1,10 @@ +#ifndef GLOBAL_H +#define GLOBAL_H + +#include "memory.h" + +namespace Global { + extern Allocator* allocator; +} + +#endif \ No newline at end of file diff --git a/src/kernel/idt.cpp b/src/kernel/idt.cpp index 064aeb1..73cbcfe 100644 --- a/src/kernel/idt.cpp +++ b/src/kernel/idt.cpp @@ -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) { diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp index 35dcaab..67d9dcc 100644 --- a/src/kernel/kernel.cpp +++ b/src/kernel/kernel.cpp @@ -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* kproc_hashtable = new (&kernel_allocator) xnoe::hashtable(&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); diff --git a/src/kernel/memory.cpp b/src/kernel/memory.cpp index b57de9d..a271d62 100644 --- a/src/kernel/memory.cpp +++ b/src/kernel/memory.cpp @@ -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); } \ No newline at end of file diff --git a/src/kernel/memory.h b/src/kernel/memory.h index 2bee9fa..33d8fc2 100644 --- a/src/kernel/memory.h +++ b/src/kernel/memory.h @@ -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 \ No newline at end of file diff --git a/src/kernel/process.cpp b/src/kernel/process.cpp index c469313..ddac59d 100644 --- a/src/kernel/process.cpp +++ b/src/kernel/process.cpp @@ -1,44 +1,111 @@ #include "process.h" -Process::Process(uint32_t PID, xnoe::hashtable* 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*> Process::get_alloc_tracker(uint32_t address) { + xnoe::linkedlistelem* 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*>(current); + } + current = current->next; + } + + return xnoe::Maybe*>(); +} + +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>); - 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 = 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); + 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* elem = (xnoe::linkedlistelem*)ptr; + elem->next = 0; + elem->prev = 0; + elem->elem = AllocTracker(ptr, pages + 1, 1); + this->allocations.append(elem); + + ptr += elem_size; } - - *(xnoe::linkedlistelem>*)ptr = xnoe::linkedlistelem>(xnoe::tuple((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*> 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; ipage_remaining = 0; + } + } +} + +uint32_t Process::count_allocations(uint32_t address) { + xnoe::Maybe*> 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); } \ No newline at end of file diff --git a/src/kernel/process.h b/src/kernel/process.h index 6478d3f..f4b6450 100644 --- a/src/kernel/process.h +++ b/src/kernel/process.h @@ -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> allocations; - // Maps pointers to the position in the linked list. - xnoe::hashtable* allocmap; + // List of pages this process has allocated + xnoe::linkedlist allocations; + + xnoe::Maybe*> get_alloc_tracker(uint32_t address); public: - Process(uint32_t PID, xnoe::hashtable* 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 \ No newline at end of file