MemoryManager: Make some variables atomic and the frame bitmap a LockedValue
This commit is contained in:
parent
f97515bd7e
commit
132963070b
@ -4,6 +4,7 @@
|
||||
#include "arch/MMU.h"
|
||||
#include "memory/KernelVM.h"
|
||||
#include "memory/MemoryMap.h"
|
||||
#include "thread/Spinlock.h"
|
||||
#include <luna/Alignment.h>
|
||||
#include <luna/Bitmap.h>
|
||||
#include <luna/CString.h>
|
||||
@ -16,13 +17,13 @@ extern const u8 end_of_kernel_rodata[1];
|
||||
extern const u8 start_of_kernel_data[1];
|
||||
extern const u8 end_of_kernel_data[1];
|
||||
|
||||
static usize free_mem = 0;
|
||||
static usize used_mem = 0;
|
||||
static usize reserved_mem = 0;
|
||||
static Atomic<usize> free_mem;
|
||||
static Atomic<usize> used_mem;
|
||||
static Atomic<usize> reserved_mem;
|
||||
|
||||
static u64 start_index = 0;
|
||||
static Atomic<u64> start_index;
|
||||
|
||||
static Bitmap g_frame_bitmap;
|
||||
static LockedValue<Bitmap> g_frame_bitmap;
|
||||
|
||||
#define CHECK_PAGE_ALIGNED(address) expect(is_aligned<ARCH_PAGE_SIZE>(address), "Address is not page-aligned")
|
||||
|
||||
@ -55,6 +56,8 @@ namespace MemoryManager
|
||||
MemoryMapIterator iter;
|
||||
MemoryMapEntry entry;
|
||||
|
||||
g_frame_bitmap.init();
|
||||
|
||||
const auto largest_free_entry = iter.largest_free();
|
||||
|
||||
expect(largest_free_entry.is_free(), "We were given a largest free memory region that isn't even free!");
|
||||
@ -74,20 +77,24 @@ namespace MemoryManager
|
||||
expect(frame_bitmap_size < largest_free_entry.size(),
|
||||
"No single memory region is enough to hold the frame bitmap");
|
||||
|
||||
g_frame_bitmap.initialize(frame_bitmap_addr, frame_bitmap_size);
|
||||
|
||||
g_frame_bitmap.clear(true); // Set all pages to used/reserved by default, then clear out the free ones
|
||||
|
||||
iter.rewind();
|
||||
while (iter.next().try_set_value(entry))
|
||||
{
|
||||
const u64 index = entry.address() / ARCH_PAGE_SIZE;
|
||||
const usize pages = entry.size() / ARCH_PAGE_SIZE;
|
||||
if (!entry.is_free()) { reserved_mem += entry.size(); }
|
||||
else
|
||||
auto frame_bitmap = g_frame_bitmap.lock();
|
||||
|
||||
frame_bitmap->initialize(frame_bitmap_addr, frame_bitmap_size);
|
||||
|
||||
frame_bitmap->clear(true); // Set all pages to used/reserved by default, then clear out the free ones
|
||||
|
||||
iter.rewind();
|
||||
while (iter.next().try_set_value(entry))
|
||||
{
|
||||
free_mem += entry.size();
|
||||
g_frame_bitmap.clear_region(index, pages, false);
|
||||
const u64 index = entry.address() / ARCH_PAGE_SIZE;
|
||||
const usize pages = entry.size() / ARCH_PAGE_SIZE;
|
||||
if (!entry.is_free()) { reserved_mem += entry.size(); }
|
||||
else
|
||||
{
|
||||
free_mem += entry.size();
|
||||
frame_bitmap->clear_region(index, pages, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,23 +110,27 @@ namespace MemoryManager
|
||||
|
||||
// NOTE: We force these operations to succeed, because if we can't map the frame bitmap to virtual memory
|
||||
// there's no point in continuing.
|
||||
auto bitmap_pages = g_frame_bitmap.size_in_bytes() / ARCH_PAGE_SIZE;
|
||||
auto bitmap_pages = g_frame_bitmap.lock()->size_in_bytes() / ARCH_PAGE_SIZE;
|
||||
|
||||
auto virtual_bitmap_base =
|
||||
KernelVM::alloc_several_pages(bitmap_pages)
|
||||
.expect_value("Unable to allocate virtual memory for the physical frame bitmap, cannot continue");
|
||||
map_frames_at(virtual_bitmap_base, (u64)g_frame_bitmap.location(), bitmap_pages,
|
||||
MMU::ReadWrite | MMU::NoExecute)
|
||||
|
||||
u64 phys = (u64)g_frame_bitmap.lock()->location();
|
||||
map_frames_at(virtual_bitmap_base, phys, bitmap_pages, MMU::ReadWrite | MMU::NoExecute)
|
||||
.expect_value("Unable to map the physical frame bitmap to virtual memory, cannot continue");
|
||||
|
||||
g_frame_bitmap.initialize((void*)virtual_bitmap_base, g_frame_bitmap.size_in_bytes());
|
||||
auto frame_bitmap = g_frame_bitmap.lock();
|
||||
|
||||
frame_bitmap->initialize((void*)virtual_bitmap_base, frame_bitmap->size_in_bytes());
|
||||
}
|
||||
|
||||
void lock_frame(u64 frame)
|
||||
{
|
||||
const u64 index = frame / ARCH_PAGE_SIZE;
|
||||
if (g_frame_bitmap.get(index)) return;
|
||||
g_frame_bitmap.set(index, true);
|
||||
auto frame_bitmap = g_frame_bitmap.lock();
|
||||
if (frame_bitmap->get(index)) return;
|
||||
frame_bitmap->set(index, true);
|
||||
used_mem += ARCH_PAGE_SIZE;
|
||||
free_mem -= ARCH_PAGE_SIZE;
|
||||
}
|
||||
@ -131,10 +142,11 @@ namespace MemoryManager
|
||||
|
||||
Result<u64> alloc_frame()
|
||||
{
|
||||
for (u64 index = start_index; index < g_frame_bitmap.size(); index++)
|
||||
auto frame_bitmap = g_frame_bitmap.lock();
|
||||
for (u64 index = start_index; index < frame_bitmap->size(); index++)
|
||||
{
|
||||
if (g_frame_bitmap.get(index)) continue;
|
||||
g_frame_bitmap.set(index, true);
|
||||
if (frame_bitmap->get(index)) continue;
|
||||
frame_bitmap->set(index, true);
|
||||
start_index = index + 1;
|
||||
free_mem -= ARCH_PAGE_SIZE;
|
||||
used_mem += ARCH_PAGE_SIZE;
|
||||
@ -147,9 +159,10 @@ namespace MemoryManager
|
||||
Result<void> free_frame(u64 frame)
|
||||
{
|
||||
const u64 index = frame / ARCH_PAGE_SIZE;
|
||||
if (index > g_frame_bitmap.size()) return err(EFAULT);
|
||||
if (!g_frame_bitmap.get(index)) return err(EFAULT);
|
||||
g_frame_bitmap.set(index, false);
|
||||
auto frame_bitmap = g_frame_bitmap.lock();
|
||||
if (index > frame_bitmap->size()) return err(EFAULT);
|
||||
if (!frame_bitmap->get(index)) return err(EFAULT);
|
||||
frame_bitmap->set(index, false);
|
||||
used_mem -= ARCH_PAGE_SIZE;
|
||||
free_mem += ARCH_PAGE_SIZE;
|
||||
if (start_index > index) start_index = index;
|
||||
|
Loading…
Reference in New Issue
Block a user