Bitmap: Introduce a new method 'find' and use it in MM and KernelVM
All checks were successful
continuous-integration/drone/push Build is passing

This method looks for the first bit with a value, optionally from a starting index, and returns its index.
This should be (haven't benchmarked) way faster than the manual way,
AKA what MM and KernelVM were doing.

This is due to this method using bit and byte manipulation tricks instead of just calling get() until getting the desired result :)
This commit is contained in:
apio 2023-01-09 17:59:52 +01:00
parent 31ee97b7de
commit 4287ec6cb0
Signed by: apio
GPG Key ID: B8A7D06E42258954
8 changed files with 101 additions and 28 deletions

View File

@ -2,7 +2,7 @@
"configurations": [
{
"name": "Luna",
"compilerPath": "${workspaceFolder}/toolchain/x86-64-luna/bin/x86_64-luna-gcc",
"compilerPath": "${workspaceFolder}/toolchain/x86_64-luna/bin/x86_64-luna-gcc",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "gcc-x64",
@ -10,9 +10,10 @@
"includePath": [
"${default}",
"${workspaceFolder}/base/usr/include",
"${workspaceFolder}/libc/include"
"${workspaceFolder}/libc/include",
"${workspaceFolder}/luna/include"
]
}
],
"version": 4
}
}

View File

@ -72,6 +72,7 @@ endif()
if(MOON_DEBUG_SYMBOLS)
message(STATUS "Building Moon with debug symbols")
target_compile_options(moon PRIVATE -ggdb)
include(debug.cmake)
endif()
target_link_options(moon PRIVATE -lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mcmodel=kernel)

1
kernel/debug.cmake Normal file
View File

@ -0,0 +1 @@
target_compile_definitions(moon PRIVATE LOCKED_VALUE_DEBUG)

View File

@ -29,15 +29,16 @@ namespace KernelVM
Result<u64> alloc_one_page()
{
auto kernelvm_bitmap = g_kernelvm_bitmap.lock();
for (u64 index = 0; index < kernelvm_bitmap->size(); index++)
{
if (kernelvm_bitmap->get(index)) continue;
kernelvm_bitmap->set(index, true);
g_used_vm += ARCH_PAGE_SIZE;
return KERNEL_VM_RANGE_START + (index * ARCH_PAGE_SIZE);
}
return err(ENOMEM);
const auto maybe_index = kernelvm_bitmap->find(false);
if (!maybe_index.has_value()) return err(ENOMEM);
const usize index = maybe_index.value();
kernelvm_bitmap->set(index, true);
g_used_vm += ARCH_PAGE_SIZE;
return KERNEL_VM_RANGE_START + (index * ARCH_PAGE_SIZE);
}
bool find_several_pages_impl(usize count, u64& start_index)

View File

@ -120,46 +120,57 @@ namespace MemoryManager
frame_bitmap->initialize((void*)virtual_bitmap_base, frame_bitmap->size_in_bytes());
}
void lock_frame(u64 frame)
void do_lock_frame(u64 index, Bitmap& bitmap)
{
const u64 index = frame / ARCH_PAGE_SIZE;
auto frame_bitmap = g_frame_bitmap.lock();
if (frame_bitmap->get(index)) return;
frame_bitmap->set(index, true);
if (bitmap.get(index)) return;
bitmap.set(index, true);
used_mem += ARCH_PAGE_SIZE;
free_mem -= ARCH_PAGE_SIZE;
}
void lock_frame(u64 frame)
{
const u64 index = frame / ARCH_PAGE_SIZE;
auto frame_bitmap = g_frame_bitmap.lock();
do_lock_frame(index, *frame_bitmap);
}
void lock_frames(u64 frames, usize count)
{
for (usize index = 0; index < count; index++) { lock_frame(frames + (index * ARCH_PAGE_SIZE)); }
auto frame_bitmap = g_frame_bitmap.lock();
const u64 frame_index = frames / ARCH_PAGE_SIZE;
for (usize index = 0; index < count; index++) { do_lock_frame(frame_index + index, *frame_bitmap); }
}
Result<u64> alloc_frame()
{
auto frame_bitmap = g_frame_bitmap.lock();
for (u64 index = start_index; index < frame_bitmap->size(); index++)
{
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;
return index * ARCH_PAGE_SIZE;
}
return err(ENOMEM);
const auto maybe_index = frame_bitmap->find(false, start_index);
if (!maybe_index.has_value()) return err(ENOMEM);
const usize index = maybe_index.value();
start_index = index + 1;
do_lock_frame(index, *frame_bitmap);
return index * ARCH_PAGE_SIZE;
}
Result<void> free_frame(u64 frame)
{
const u64 index = frame / ARCH_PAGE_SIZE;
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;
return {};
}

View File

@ -1,4 +1,6 @@
#pragma once
#include "Log.h"
#include "arch/CPU.h"
#include <luna/Atomic.h>
#include <luna/Option.h>
@ -73,11 +75,25 @@ template <typename T> class LockedValue
{
}
#ifndef LOCKED_VALUE_DEBUG
LockedValueGuard lock()
{
m_lock.lock();
return { *this };
}
#else
LockedValueGuard lock()
{
if (m_lock.try_lock()) { return { *this }; }
kwarnln("Spinning on a locked LockedValue. This might lead to a deadlock...");
CPU::print_stack_trace();
m_lock.lock();
return { *this };
}
#endif
Option<LockedValueGuard> try_lock()
{

View File

@ -1,4 +1,5 @@
#pragma once
#include <luna/Option.h>
#include <luna/Types.h>
class Bitmap
@ -34,11 +35,13 @@ class Bitmap
return m_location;
}
Option<usize> find(bool value, usize begin = 0) const;
void clear(bool value);
void clear_region(usize start, usize bits, bool value);
private:
u8 value_byte(bool b)
u8 value_byte(bool b) const
{
return b ? 0xff : 0;
}

View File

@ -86,3 +86,42 @@ void Bitmap::clear_region(usize start, usize bits, bool value)
start++;
}
}
Option<usize> Bitmap::find(bool value, usize begin) const
{
expect(initialized(), "Bitmap was never initialized");
usize size = this->size();
expect(begin < size, "Start index out of range");
while (begin % 8)
{
if (get(begin) == value) return begin;
begin++;
}
if (begin == size) return {};
usize i = begin / 8;
u8 byte_that_does_not_contain_value = value_byte(!value);
while (i < m_size_in_bytes)
{
if (m_location[i] == byte_that_does_not_contain_value)
{
i++;
continue;
}
usize index = i * 8;
for (usize j = 0; j < 8; j++, index++)
{
if (get(index) == value) return index;
}
// Once we've located a byte that contains the value, we should succeed in finding it.
unreachable();
}
return {};
}