From 8773024d1b4e756fe5d3494479247c64c7ad8491 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 8 Oct 2024 09:51:26 +0000 Subject: begin implementing frame allocator --- arch/x86_64/src/memory/frame_allocator.cpp | 70 +++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index b9d26a5..b8f53be 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -2,8 +2,76 @@ namespace teachos::arch::memory { - auto area_frame_allocator::allocate_frame() -> std::optional {} + auto area_frame_allocator::allocate_frame() -> std::optional + { + /* + * 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) + { + frame frame{next_free_frame.frame_number}; + + struct frame current_area_last_frame = { + frame::containing_address(current_area->base_address + current_area->area_length - 1)}; + + if (next_free_frame > current_area_last_frame) + { + // All frames of current area are used, switch to next area + choose_next_area(); + } + else if (frame >= multiboot_start && frame <= kernel_end) + { + // `frame` is used by the kernel or multiboot information structure + next_free_frame = arch::memory::frame{kernel_end.frame_number + 1}; + } + else + { + // Frame is unused, increment `next_free_frame` and return it + next_free_frame.frame_number += 1; + return frame; + } + + // `frame` was not valid, try it again with the updated `next_free_frame` + return allocate_frame(); + } + + // no free frames left + return std::nullopt; + } auto area_frame_allocator::deallocate_frame(frame frame) -> void {} + namespace + { + auto area_frame_allocator::choose_next_area() -> void + { + current_area = std::nullopt; + + // TODO: Fix this loop as soon as you've created an area iterator + for (const auto & area : areas) + { + std::size_t address = area.base_addr + area.length - 1; + if (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 || area.base_addr < current_area->base_address) + { + current_area = area; + } + } + } + + if (current_area) + { + // Update the `next_free_frame` according to the new memory area + frame start_frame = frame::containing_address(current_area->base_address); + if (next_free_frame < start_frame) + { + next_free_frame = start_frame; + } + } + } + + } // namespace } // namespace teachos::arch::memory -- cgit v1.2.3