Kernel: FixedWidthAllocator creation can now fail

This commit is contained in:
Bananymous 2023-07-19 18:07:24 +03:00
parent 88e3998664
commit 98cedf155c
2 changed files with 35 additions and 14 deletions

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <BAN/Errors.h>
#include <BAN/UniqPtr.h> #include <BAN/UniqPtr.h>
#include <kernel/Memory/Heap.h> #include <kernel/Memory/Heap.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
@ -28,6 +29,8 @@ namespace Kernel
private: private:
FixedWidthAllocator(PageTable&, uint32_t); FixedWidthAllocator(PageTable&, uint32_t);
BAN::ErrorOr<void> initialize();
bool allocate_page_if_needed(vaddr_t, uint8_t flags); bool allocate_page_if_needed(vaddr_t, uint8_t flags);
struct node struct node

View File

@ -5,10 +5,12 @@ namespace Kernel
BAN::ErrorOr<BAN::UniqPtr<FixedWidthAllocator>> FixedWidthAllocator::create(PageTable& page_table, uint32_t allocation_size) BAN::ErrorOr<BAN::UniqPtr<FixedWidthAllocator>> FixedWidthAllocator::create(PageTable& page_table, uint32_t allocation_size)
{ {
auto* allocator = new FixedWidthAllocator(page_table, allocation_size); auto* allocator_ptr = new FixedWidthAllocator(page_table, allocation_size);
if (allocator == nullptr) if (allocator_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
return BAN::UniqPtr<FixedWidthAllocator>::adopt(allocator); auto allocator = BAN::UniqPtr<FixedWidthAllocator>::adopt(allocator_ptr);
TRY(allocator->initialize());
return allocator;
} }
FixedWidthAllocator::FixedWidthAllocator(PageTable& page_table, uint32_t allocation_size) FixedWidthAllocator::FixedWidthAllocator(PageTable& page_table, uint32_t allocation_size)
@ -16,12 +18,21 @@ namespace Kernel
, m_allocation_size(BAN::Math::max(allocation_size, m_min_allocation_size)) , m_allocation_size(BAN::Math::max(allocation_size, m_min_allocation_size))
{ {
ASSERT(BAN::Math::is_power_of_two(allocation_size)); ASSERT(BAN::Math::is_power_of_two(allocation_size));
}
BAN::ErrorOr<void> FixedWidthAllocator::initialize()
{
m_nodes_page = (vaddr_t)kmalloc(PAGE_SIZE); m_nodes_page = (vaddr_t)kmalloc(PAGE_SIZE);
ASSERT(m_nodes_page); if (!m_nodes_page)
return BAN::Error::from_errno(ENOMEM);
m_allocated_pages = (vaddr_t)kmalloc(PAGE_SIZE); m_allocated_pages = (vaddr_t)kmalloc(PAGE_SIZE);
ASSERT(m_allocated_pages); if (!m_allocated_pages)
{
kfree((void*)m_nodes_page);
m_nodes_page = 0;
return BAN::Error::from_errno(ENOMEM);
}
memset((void*)m_nodes_page, 0, PAGE_SIZE); memset((void*)m_nodes_page, 0, PAGE_SIZE);
memset((void*)m_allocated_pages, 0, PAGE_SIZE); memset((void*)m_allocated_pages, 0, PAGE_SIZE);
@ -37,23 +48,30 @@ namespace Kernel
m_free_list = node_table; m_free_list = node_table;
m_used_list = nullptr; m_used_list = nullptr;
return {};
} }
FixedWidthAllocator::~FixedWidthAllocator() FixedWidthAllocator::~FixedWidthAllocator()
{ {
for (uint32_t page_index = 0; page_index < PAGE_SIZE / sizeof(vaddr_t); page_index++) if (m_nodes_page && m_allocated_pages)
{ {
vaddr_t page_vaddr = ((vaddr_t*)m_allocated_pages)[page_index]; for (uint32_t page_index = 0; page_index < PAGE_SIZE / sizeof(vaddr_t); page_index++)
if (page_vaddr == 0) {
continue; vaddr_t page_vaddr = ((vaddr_t*)m_allocated_pages)[page_index];
if (page_vaddr == 0)
continue;
ASSERT(!m_page_table.is_page_free(page_vaddr)); ASSERT(!m_page_table.is_page_free(page_vaddr));
Heap::get().release_page(m_page_table.physical_address_of(page_vaddr)); Heap::get().release_page(m_page_table.physical_address_of(page_vaddr));
m_page_table.unmap_page(page_vaddr); m_page_table.unmap_page(page_vaddr);
}
} }
kfree((void*)m_nodes_page); if (m_nodes_page)
kfree((void*)m_allocated_pages); kfree((void*)m_nodes_page);
if (m_allocated_pages)
kfree((void*)m_allocated_pages);
} }
paddr_t FixedWidthAllocator::allocate() paddr_t FixedWidthAllocator::allocate()