aboutsummaryrefslogtreecommitdiff
path: root/kernel/src/memory
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-03-13 22:28:50 +0100
committerFelix Morgner <felix.morgner@ost.ch>2026-03-13 23:51:38 +0100
commite284d574ed9237a215d994861cc502452fec11ce (patch)
tree716c9929ef4c0df2b89ab0166c615271aec2374c /kernel/src/memory
parent7ba274d0838e5cd4e48e85f81557bbb837ed4349 (diff)
downloadteachos-e284d574ed9237a215d994861cc502452fec11ce.tar.xz
teachos-e284d574ed9237a215d994861cc502452fec11ce.zip
kernel/memory: implement basic bitmap allocator
Diffstat (limited to 'kernel/src/memory')
-rw-r--r--kernel/src/memory/bitmap_allocator.cpp100
1 files changed, 100 insertions, 0 deletions
diff --git a/kernel/src/memory/bitmap_allocator.cpp b/kernel/src/memory/bitmap_allocator.cpp
new file mode 100644
index 0000000..c010f77
--- /dev/null
+++ b/kernel/src/memory/bitmap_allocator.cpp
@@ -0,0 +1,100 @@
+#include "kernel/memory/bitmap_allocator.hpp"
+
+#include "kapi/memory.hpp"
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+#include <span>
+#include <utility>
+
+namespace kernel::memory
+{
+
+ bitmap_frame_allocator::bitmap_frame_allocator(std::span<std::uint64_t> storage, std::size_t frame_count) noexcept
+ : m_bitmap{storage}
+ , m_frame_count{frame_count}
+ , m_last_index{}
+ {
+ std::ranges::fill(m_bitmap, ~0uz);
+ }
+
+ auto bitmap_frame_allocator::allocate_many(std::size_t count) noexcept
+ -> std::optional<std::pair<kapi::memory::frame, std::size_t>>
+ {
+ if (count == 0)
+ {
+ return std::nullopt;
+ }
+
+ auto free_count = 0uz;
+ auto first_free = 0uz;
+
+ for (auto i = 0uz; i < m_frame_count; ++i)
+ {
+ auto const current = (m_last_index + i) % m_frame_count;
+ if (!test(current))
+ {
+ if (free_count == 0)
+ {
+ first_free = current;
+ }
+
+ ++free_count;
+
+ if (free_count == count)
+ {
+ for (auto j = 0uz; j < count; ++j)
+ {
+ set(first_free + j);
+ }
+ m_last_index = first_free + count;
+ return std::make_pair(kapi::memory::frame{first_free}, count);
+ }
+ }
+ else
+ {
+ free_count = 0;
+ }
+ }
+
+ return std::nullopt;
+ }
+
+ auto bitmap_frame_allocator::release_many(std::pair<kapi::memory::frame, std::size_t> frame_set) -> void
+ {
+ auto const [start, count] = frame_set;
+ for (auto i = 0uz; i < count; ++i)
+ {
+ clear(start.number() + i);
+ }
+ }
+
+ auto bitmap_frame_allocator::mark_used(kapi::memory::frame frame) -> void
+ {
+ set(frame.number());
+ }
+
+ auto bitmap_frame_allocator::test(std::size_t index) const noexcept -> bool
+ {
+ auto entry_entry = index / 64;
+ auto entry_offset = index % 64;
+ return (m_bitmap[entry_entry] & (1uz << entry_offset));
+ }
+
+ auto bitmap_frame_allocator::set(std::size_t index) noexcept -> void
+ {
+ auto entry_entry = index / 64;
+ auto entry_offset = index % 64;
+ m_bitmap[entry_entry] |= (1uz << entry_offset);
+ }
+
+ auto bitmap_frame_allocator::clear(std::size_t index) noexcept -> void
+ {
+ auto entry_entry = index / 64;
+ auto entry_offset = index % 64;
+ m_bitmap[entry_entry] &= ~(1uz << entry_offset);
+ }
+
+} // namespace kernel::memory \ No newline at end of file