aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/memory/allocator
diff options
context:
space:
mode:
authorFabian Imhof <fabian.imhof@ost.ch>2024-10-27 13:29:01 +0000
committerFabian Imhof <fabian.imhof@ost.ch>2024-10-27 13:29:01 +0000
commit181f35d20e315947fa3463d6774ca164c6a4bc0d (patch)
tree5ca45fbb92d3ae781296feda29dbed996d605199 /arch/x86_64/src/memory/allocator
parent1518177efac38961a36db0bc40152d00c38e6281 (diff)
parentbecb1ce0abdaf4e6ad08bb6db7c706dd13a1294b (diff)
downloadkernel-181f35d20e315947fa3463d6774ca164c6a4bc0d.tar.xz
kernel-181f35d20e315947fa3463d6774ca164c6a4bc0d.zip
Merge branch 'feat_memory_manager' of ssh://gitlab.ost.ch:45022/teachos/kernel into feat_memory_manager
Diffstat (limited to 'arch/x86_64/src/memory/allocator')
-rw-r--r--arch/x86_64/src/memory/allocator/area_frame_allocator.cpp95
1 files changed, 43 insertions, 52 deletions
diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp
index 05b828c..6ed4f28 100644
--- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp
+++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp
@@ -2,13 +2,16 @@
#include "arch/exception_handling/assert.hpp"
+#include <algorithm>
+#include <array>
+#include <ranges>
+
namespace teachos::arch::memory::allocator
{
area_frame_allocator::area_frame_allocator(multiboot::memory_information mem_info)
: next_free_frame(0)
, current_area(std::nullopt)
- , area_begin(mem_info.memory_areas)
- , area_end(mem_info.memory_areas + mem_info.area_count)
+ , memory_areas(mem_info.memory_areas, mem_info.area_count)
, kernel_start(physical_frame::containing_address(mem_info.kernel_start))
, kernel_end(physical_frame::containing_address(mem_info.kernel_end))
, multiboot_start(physical_frame::containing_address(mem_info.multiboot_start))
@@ -20,26 +23,21 @@ namespace teachos::arch::memory::allocator
auto area_frame_allocator::choose_next_area() -> void
{
current_area = std::nullopt;
+ auto next_area_with_free_frames = memory_areas | std::views::filter([this](multiboot::memory_area const & area) {
+ auto address = area.base_address + area.area_length - 1;
+ return physical_frame::containing_address(address) >= next_free_frame;
+ });
- for (multiboot::memory_area_iterator it = begin(); it != end(); ++it)
- {
- multiboot::memory_area & area = *it;
+ auto lowest_area_with_free_frames =
+ std::ranges::min_element(next_area_with_free_frames, [](multiboot::memory_area a, multiboot::memory_area b) {
+ return a.base_address < b.base_address;
+ });
- std::size_t address = area.base_address + area.area_length - 1;
- if (physical_frame::containing_address(address) >= next_free_frame)
- {
- // The `next_free_frame` address is smaller than the last address of the current area
- if (!current_area.has_value() || area.base_address < current_area.value().base_address)
- {
- current_area.emplace(area);
- }
- }
- }
-
- if (current_area.has_value())
+ if (lowest_area_with_free_frames != next_area_with_free_frames.end())
{
+ current_area = *lowest_area_with_free_frames;
// Update the `next_free_frame` according to the new memory area
- physical_frame start_frame = physical_frame::containing_address(current_area->base_address);
+ auto start_frame = physical_frame::containing_address(current_area.value().base_address);
if (next_free_frame < start_frame)
{
next_free_frame = start_frame;
@@ -53,41 +51,38 @@ namespace teachos::arch::memory::allocator
* Only try to allocate memory if current_area is not null, because
* the current_area is null if there is no more available memory.
*/
- if (current_area.has_value())
+ if (!current_area.has_value())
{
- physical_frame physical_frame{next_free_frame.frame_number};
+ return std::nullopt;
+ }
- struct physical_frame current_area_last_frame = {
- physical_frame::containing_address(current_area->base_address + current_area->area_length - 1)};
+ auto address = current_area.value().base_address + current_area.value().area_length - 1;
+ physical_frame current_area_last_frame = physical_frame::containing_address(address);
- if (next_free_frame > current_area_last_frame)
- {
- // All frames of current area are used, switch to next area
- choose_next_area();
- }
- else if (physical_frame >= kernel_start && physical_frame <= kernel_end)
- {
- // `physical_frame` is used by the kernel
- next_free_frame = allocator::physical_frame{kernel_end.frame_number + 1};
- }
- else if (physical_frame >= multiboot_start && physical_frame <= multiboot_end)
- {
- // `physical_frame` is used by the multiboot information structure
- next_free_frame = allocator::physical_frame{multiboot_end.frame_number + 1};
- }
- else
- {
- // Frame is unused, increment `next_free_frame` and return it
- next_free_frame.frame_number += 1;
- return physical_frame;
- }
-
- // `physical_frame` was not valid, try it again with the updated `next_free_frame`
- return allocate_frame();
+ if (next_free_frame > current_area_last_frame)
+ {
+ // All frames of current area are used, switch to next area.
+ choose_next_area();
+ }
+ else if (next_free_frame >= kernel_start && next_free_frame <= kernel_end)
+ {
+ // `physical_frame` is used by the kernel or multiboot information structure.
+ next_free_frame = allocator::physical_frame{kernel_end.frame_number + 1};
+ }
+ else if (next_free_frame >= multiboot_start && next_free_frame <= multiboot_end)
+ {
+ // `physical_frame` is used by the kernel or multiboot information structure.
+ next_free_frame = allocator::physical_frame{multiboot_end.frame_number + 1};
+ }
+ else
+ {
+ // Frame is unused, increment `next_free_frame` and return it.
+ next_free_frame.frame_number += 1;
+ return next_free_frame;
}
- // no free frames left
- return std::nullopt;
+ // `physical_frame` was not valid, try it again with the updated `next_free_frame`.
+ return allocate_frame();
}
auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void
@@ -95,8 +90,4 @@ namespace teachos::arch::memory::allocator
exception_handling::assert(false && physical_frame.frame_number == 0,
"[deallocate_frame] Not implemented Exception");
}
-
- auto area_frame_allocator::begin() -> multiboot::memory_area_iterator { return area_begin; }
-
- auto area_frame_allocator::end() -> multiboot::memory_area_iterator { return area_end; }
} // namespace teachos::arch::memory::allocator