Bitmap: Introduce a new method 'find' and use it in MM and KernelVM
All checks were successful
continuous-integration/drone/push Build is passing
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:
parent
31ee97b7de
commit
4287ec6cb0
7
.vscode/c_cpp_properties.json
vendored
7
.vscode/c_cpp_properties.json
vendored
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
1
kernel/debug.cmake
Normal file
@ -0,0 +1 @@
|
||||
target_compile_definitions(moon PRIVATE LOCKED_VALUE_DEBUG)
|
@ -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)
|
||||
|
@ -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 {};
|
||||
}
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user