diff --git a/src/kernel/block_allocator.h b/src/kernel/block_allocator.h new file mode 100644 index 0000000..f7a12fb --- /dev/null +++ b/src/kernel/block_allocator.h @@ -0,0 +1,28 @@ +#pragma once +/// \file block_allocator.h +/// Definitions and functions for a generic block allocator + +#include +#include + +class block_allocator +{ +public: + inline block_allocator(uintptr_t start, size_t size) : + m_next_block(start), m_block_size(size) {} + + inline uintptr_t allocate() { + if (m_free.count() > 0) + return m_free.pop(); + else + return __atomic_fetch_add(&m_next_block, m_block_size, __ATOMIC_SEQ_CST); + } + + inline void free(uintptr_t p) { m_free.append(p); } + inline uintptr_t end() const { return m_next_block; } + +private: + uintptr_t m_next_block; + const size_t m_block_size; + util::vector m_free; +}; diff --git a/src/kernel/objects/vm_area.cpp b/src/kernel/objects/vm_area.cpp index 85318fd..51f757a 100644 --- a/src/kernel/objects/vm_area.cpp +++ b/src/kernel/objects/vm_area.cpp @@ -143,9 +143,8 @@ vm_area_open::get_page(uintptr_t offset, uintptr_t &phys) vm_area_guarded::vm_area_guarded(uintptr_t start, size_t buf_pages, size_t size, vm_flags flags) : - m_start {start}, - m_pages {buf_pages}, - m_next {mem::frame_size}, + m_pages {buf_pages + 1}, // Sections are N+1 pages for the leading guard page + m_stacks {start, m_pages*mem::frame_size}, vm_area_open {size, flags} { } @@ -155,31 +154,26 @@ vm_area_guarded::~vm_area_guarded() {} uintptr_t vm_area_guarded::get_section() { - if (m_cache.count() > 0) { - return m_cache.pop(); - } - - uintptr_t addr = m_next; - m_next += (m_pages + 1) * mem::frame_size; - return m_start + addr; + // Account for the leading guard page + return m_stacks.allocate() + mem::frame_size; } void vm_area_guarded::return_section(uintptr_t addr) { - m_cache.append(addr); + // Account for the leading guard page + return m_stacks.free(addr - mem::frame_size); } bool vm_area_guarded::get_page(uintptr_t offset, uintptr_t &phys) { - if (offset > m_next) + if (offset >= m_stacks.end()) return false; - // make sure this isn't in a guard page. (sections are - // m_pages big plus 1 leading guard page, so page 0 is - // invalid) - if ((offset >> 12) % (m_pages+1) == 0) + // make sure this isn't in a guard page. (sections have 1 leading + // guard page, so page 0 is invalid) + if ((offset >> 12) % m_pages == 0) return false; return vm_area_open::get_page(offset, phys); diff --git a/src/kernel/objects/vm_area.h b/src/kernel/objects/vm_area.h index 12f4ee7..926234b 100644 --- a/src/kernel/objects/vm_area.h +++ b/src/kernel/objects/vm_area.h @@ -9,6 +9,7 @@ #include #include +#include "block_allocator.h" #include "objects/kobject.h" class page_tree; @@ -174,10 +175,8 @@ public: virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; private: - util::vector m_cache; - uintptr_t m_start; size_t m_pages; - uintptr_t m_next; + block_allocator m_stacks; }; } // namespace obj