From 086c5439f27d803ea84445f81f7a0006681dc585 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 16 Jan 2026 13:41:46 +0100 Subject: kapi/memory: move buffered allocator --- .../include/arch/memory/buffered_allocator.hpp | 138 --------------------- arch/x86_64/kapi/memory.cpp | 12 +- kapi/include/kapi/memory/buffered_allocator.hpp | 138 +++++++++++++++++++++ 3 files changed, 144 insertions(+), 144 deletions(-) delete mode 100644 arch/x86_64/include/arch/memory/buffered_allocator.hpp create mode 100644 kapi/include/kapi/memory/buffered_allocator.hpp diff --git a/arch/x86_64/include/arch/memory/buffered_allocator.hpp b/arch/x86_64/include/arch/memory/buffered_allocator.hpp deleted file mode 100644 index 87ebbf6..0000000 --- a/arch/x86_64/include/arch/memory/buffered_allocator.hpp +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef TEACHOS_X86_64_BUFFERED_ALLOCATOR_HPP -#define TEACHOS_X86_64_BUFFERED_ALLOCATOR_HPP - -#include "kapi/memory.hpp" -#include "kapi/system.hpp" - -#include -#include -#include -#include -#include - -namespace arch::memory -{ - - template - struct buffered_allocator : kapi::memory::frame_allocator - { - explicit buffered_allocator(frame_allocator * underlying) - : m_underlying{underlying} - , m_free{BufferSize} - { - auto from_underlying = m_underlying->allocate_many(BufferSize); - if (!from_underlying) - { - kapi::system::panic("[x86_64:MEM] Not enough frames available from underlying allocator."); - } - auto [first_frame, count] = *from_underlying; - std::ranges::generate_n(m_pool.begin(), count, [first_frame]() mutable { return first_frame++; }); - } - - buffered_allocator(buffered_allocator const &) = delete; - buffered_allocator(buffered_allocator && other) noexcept = delete; - - ~buffered_allocator() override - { - std::ranges::for_each(m_pool, [this](auto const & maybe_frame) { - if (maybe_frame) - { - m_underlying->release_many({*maybe_frame, 1}); - } - }); - } - - auto operator=(buffered_allocator const &) = delete; - auto operator=(buffered_allocator &&) = delete; - - auto allocate_many(std::size_t count = 1) noexcept - -> std::optional> override - { - if (count > m_free) - { - return m_underlying->allocate_many(count); - } - - auto start_of_set = std::ranges::find_if(m_pool, [](auto const & candidate) { return candidate.has_value(); }); - if (start_of_set == m_pool.end()) - { - return m_underlying->allocate_many(count); - } - - if (std::distance(start_of_set, m_pool.end()) < static_cast(count)) - { - return m_underlying->allocate_many(count); - } - - auto number_of_consecutive_frames = 1uz; - for (auto current = std::next(start_of_set); current != m_pool.end() && number_of_consecutive_frames < count; - ++current) - { - if (*current && *start_of_set && **current == (**start_of_set) + 1) - { - ++number_of_consecutive_frames; - continue; - } - number_of_consecutive_frames = 0; - start_of_set = current; - } - - if (std::distance(start_of_set, m_pool.end()) >= static_cast(count)) - { - auto result = std::make_pair(**start_of_set, count); - m_free -= count; - std::ranges::for_each(start_of_set, start_of_set + count, [](auto & frame) { frame.reset(); }); - sort_pool(); - return result; - } - return m_underlying->allocate_many(count); - } - - auto release_many(std::pair frame_set) -> void override - { - if (m_free == BufferSize) - { - return m_underlying->release_many(frame_set); - } - - auto [first_frame, count] = frame_set; - auto start_of_set = std::ranges::find_if(m_pool, [](auto const & candidate) { return !candidate.has_value(); }); - - for (auto current = start_of_set; current != m_pool.end() && count; ++current) - { - *current = first_frame++; - ++m_free; - --count; - } - sort_pool(); - - if (count) - { - m_underlying->release_many({first_frame, count}); - } - } - - private: - auto sort_pool() -> void - { - std::ranges::sort(m_pool, [](auto lhs, auto rhs) -> bool { - if (lhs && rhs) - { - return *lhs < *rhs; - } - if (!lhs) - { - return false; - } - return true; - }); - } - - frame_allocator * m_underlying; - std::size_t m_free; - std::array, BufferSize> m_pool{}; - }; - -} // namespace arch::memory - -#endif \ No newline at end of file diff --git a/arch/x86_64/kapi/memory.cpp b/arch/x86_64/kapi/memory.cpp index e366ee1..b71fa17 100644 --- a/arch/x86_64/kapi/memory.cpp +++ b/arch/x86_64/kapi/memory.cpp @@ -1,12 +1,12 @@ #include "kapi/memory.hpp" #include "kapi/boot.hpp" +#include "kapi/memory/buffered_allocator.hpp" #include "kapi/system.hpp" #include "arch/boot/boot.hpp" #include "arch/boot/ld.hpp" #include "arch/cpu/registers.hpp" -#include "arch/memory/buffered_allocator.hpp" #include "arch/memory/kernel_mapper.hpp" #include "arch/memory/mmu.hpp" #include "arch/memory/page_table.hpp" @@ -151,7 +151,7 @@ namespace kapi::memory } auto constinit region_based_allocator = std::optional{}; - auto constinit buffered_allocator = std::optional>{}; + auto constinit allocation_buffer = std::optional>{}; auto constinit recursive_page_mapper = std::optional{}; } // namespace @@ -170,12 +170,12 @@ namespace kapi::memory enable_cpu_protections(); region_based_allocator.emplace(collect_memory_information()); - buffered_allocator.emplace(&*region_based_allocator); - recursive_page_mapper.emplace(*buffered_allocator); + allocation_buffer.emplace(&*region_based_allocator); + recursive_page_mapper.emplace(*allocation_buffer); kstd::println("[x86_64:MEM] Preparing new paging hierarchy."); - auto new_pml4_frame = inject_faux_pml4(*buffered_allocator, *recursive_page_mapper); + auto new_pml4_frame = inject_faux_pml4(*allocation_buffer, *recursive_page_mapper); remap_kernel(*recursive_page_mapper); remap_vga_text_mode_buffer(*recursive_page_mapper); @@ -187,7 +187,7 @@ namespace kapi::memory cr3.frame(new_pml4_frame); arch::cpu::cr3::write(cr3); - set_frame_allocator(*buffered_allocator); + set_frame_allocator(*allocation_buffer); set_page_mapper(*recursive_page_mapper); } diff --git a/kapi/include/kapi/memory/buffered_allocator.hpp b/kapi/include/kapi/memory/buffered_allocator.hpp new file mode 100644 index 0000000..49137c6 --- /dev/null +++ b/kapi/include/kapi/memory/buffered_allocator.hpp @@ -0,0 +1,138 @@ +#ifndef TEACHOS_KAPI_BUFFERED_ALLOCATOR_HPP +#define TEACHOS_KAPI_BUFFERED_ALLOCATOR_HPP + +#include "kapi/memory.hpp" +#include "kapi/system.hpp" + +#include +#include +#include +#include +#include + +namespace kapi::memory +{ + + template + struct buffered_allocator : frame_allocator + { + explicit buffered_allocator(frame_allocator * underlying) + : m_underlying{underlying} + , m_free{BufferSize} + { + auto from_underlying = m_underlying->allocate_many(BufferSize); + if (!from_underlying) + { + kapi::system::panic("[OS] Not enough frames available from underlying allocator."); + } + auto [first_frame, count] = *from_underlying; + std::ranges::generate_n(m_pool.begin(), count, [first_frame]() mutable { return first_frame++; }); + } + + buffered_allocator(buffered_allocator const &) = delete; + buffered_allocator(buffered_allocator && other) noexcept = delete; + + ~buffered_allocator() override + { + std::ranges::for_each(m_pool, [this](auto const & maybe_frame) { + if (maybe_frame) + { + m_underlying->release_many({*maybe_frame, 1}); + } + }); + } + + auto operator=(buffered_allocator const &) = delete; + auto operator=(buffered_allocator &&) = delete; + + auto allocate_many(std::size_t count = 1) noexcept + -> std::optional> override + { + if (count > m_free) + { + return m_underlying->allocate_many(count); + } + + auto start_of_set = std::ranges::find_if(m_pool, [](auto const & candidate) { return candidate.has_value(); }); + if (start_of_set == m_pool.end()) + { + return m_underlying->allocate_many(count); + } + + if (std::distance(start_of_set, m_pool.end()) < static_cast(count)) + { + return m_underlying->allocate_many(count); + } + + auto number_of_consecutive_frames = 1uz; + for (auto current = std::next(start_of_set); current != m_pool.end() && number_of_consecutive_frames < count; + ++current) + { + if (*current && *start_of_set && **current == (**start_of_set) + 1) + { + ++number_of_consecutive_frames; + continue; + } + number_of_consecutive_frames = 0; + start_of_set = current; + } + + if (std::distance(start_of_set, m_pool.end()) >= static_cast(count)) + { + auto result = std::make_pair(**start_of_set, count); + m_free -= count; + std::ranges::for_each(start_of_set, start_of_set + count, [](auto & frame) { frame.reset(); }); + sort_pool(); + return result; + } + return m_underlying->allocate_many(count); + } + + auto release_many(std::pair frame_set) -> void override + { + if (m_free == BufferSize) + { + return m_underlying->release_many(frame_set); + } + + auto [first_frame, count] = frame_set; + auto start_of_set = std::ranges::find_if(m_pool, [](auto const & candidate) { return !candidate.has_value(); }); + + for (auto current = start_of_set; current != m_pool.end() && count; ++current) + { + *current = first_frame++; + ++m_free; + --count; + } + sort_pool(); + + if (count) + { + m_underlying->release_many({first_frame, count}); + } + } + + private: + auto sort_pool() -> void + { + std::ranges::sort(m_pool, [](auto lhs, auto rhs) -> bool { + if (lhs && rhs) + { + return *lhs < *rhs; + } + if (!lhs) + { + return false; + } + return true; + }); + } + + frame_allocator * m_underlying; + std::size_t m_free; + std::array, BufferSize> m_pool{}; + }; + +} // namespace kapi::memory + +#endif \ No newline at end of file -- cgit v1.2.3