Kernel: We add FixedWidthAllocators on demand
On SYS_ALLOC we will add a new FixedWidthAllocator if the old ones are already full or we don't have one with proper size. This allows arbitary number of allocations as long as you have enough memory available :) Next I will be writing a general allocator for allocations larger than 4096 bytes which should make SYS_ALLOC syscall complete :)
This commit is contained in:
parent
05046d6e93
commit
b0ec0f1a1a
|
@ -21,6 +21,9 @@ namespace Kernel
|
||||||
|
|
||||||
uint32_t allocation_size() const { return m_allocation_size; }
|
uint32_t allocation_size() const { return m_allocation_size; }
|
||||||
|
|
||||||
|
uint32_t allocations() const { return m_allocations; }
|
||||||
|
uint32_t max_allocations() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct node
|
struct node
|
||||||
{
|
{
|
||||||
|
@ -44,7 +47,7 @@ namespace Kernel
|
||||||
node* m_free_list { nullptr };
|
node* m_free_list { nullptr };
|
||||||
node* m_used_list { nullptr };
|
node* m_used_list { nullptr };
|
||||||
|
|
||||||
uint32_t m_allocated { 0 };
|
uint32_t m_allocations { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -94,7 +94,7 @@ namespace Kernel
|
||||||
BAN::String m_working_directory;
|
BAN::String m_working_directory;
|
||||||
BAN::Vector<Thread*> m_threads;
|
BAN::Vector<Thread*> m_threads;
|
||||||
|
|
||||||
BAN::Vector<FixedWidthAllocator> m_fixed_width_allocators;
|
BAN::LinkedList<FixedWidthAllocator> m_fixed_width_allocators;
|
||||||
|
|
||||||
MMU* m_mmu { nullptr };
|
MMU* m_mmu { nullptr };
|
||||||
TTY* m_tty { nullptr };
|
TTY* m_tty { nullptr };
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace Kernel
|
||||||
, m_allocated_pages(other.m_allocated_pages)
|
, m_allocated_pages(other.m_allocated_pages)
|
||||||
, m_free_list(other.m_free_list)
|
, m_free_list(other.m_free_list)
|
||||||
, m_used_list(other.m_used_list)
|
, m_used_list(other.m_used_list)
|
||||||
, m_allocated(other.m_allocated)
|
, m_allocations(other.m_allocations)
|
||||||
{
|
{
|
||||||
other.m_process = nullptr;
|
other.m_process = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -81,9 +81,8 @@ namespace Kernel
|
||||||
|
|
||||||
paddr_t FixedWidthAllocator::allocate()
|
paddr_t FixedWidthAllocator::allocate()
|
||||||
{
|
{
|
||||||
// FIXME: We should get allocate more memory if we run out of
|
if (m_free_list == nullptr)
|
||||||
// nodes in free list.
|
return 0;
|
||||||
ASSERT(m_free_list);
|
|
||||||
|
|
||||||
node* node = m_free_list;
|
node* node = m_free_list;
|
||||||
|
|
||||||
|
@ -101,7 +100,7 @@ namespace Kernel
|
||||||
m_used_list->prev = node;
|
m_used_list->prev = node;
|
||||||
m_used_list = node;
|
m_used_list = node;
|
||||||
|
|
||||||
m_allocated++;
|
m_allocations++;
|
||||||
allocate_page_for_node_if_needed(node);
|
allocate_page_for_node_if_needed(node);
|
||||||
return address_of_node(node);
|
return address_of_node(node);
|
||||||
}
|
}
|
||||||
|
@ -110,12 +109,13 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
if (address % m_allocation_size)
|
if (address % m_allocation_size)
|
||||||
return false;
|
return false;
|
||||||
|
if (m_allocations == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
node* node = node_from_address(address);
|
node* node = node_from_address(address);
|
||||||
if (node == nullptr)
|
if (node == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
if (!node->allocated)
|
if (!node->allocated)
|
||||||
{
|
{
|
||||||
dwarnln("deallocate called on unallocated address");
|
dwarnln("deallocate called on unallocated address");
|
||||||
|
@ -123,6 +123,8 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
node->allocated = false;
|
node->allocated = false;
|
||||||
|
|
||||||
|
if (node == m_used_list)
|
||||||
|
m_used_list = node->next;
|
||||||
if (node->prev)
|
if (node->prev)
|
||||||
node->prev->next = node->next;
|
node->prev->next = node->next;
|
||||||
if (node->next)
|
if (node->next)
|
||||||
|
@ -135,10 +137,15 @@ namespace Kernel
|
||||||
m_free_list->prev = node;
|
m_free_list->prev = node;
|
||||||
m_free_list = node;
|
m_free_list = node;
|
||||||
|
|
||||||
m_allocated--;
|
m_allocations--;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t FixedWidthAllocator::max_allocations() const
|
||||||
|
{
|
||||||
|
return PAGE_SIZE / sizeof(node);
|
||||||
|
}
|
||||||
|
|
||||||
vaddr_t FixedWidthAllocator::address_of_node(const node* node) const
|
vaddr_t FixedWidthAllocator::address_of_node(const node* node) const
|
||||||
{
|
{
|
||||||
uint32_t index = node - (struct node*)m_nodes_page;
|
uint32_t index = node - (struct node*)m_nodes_page;
|
||||||
|
|
|
@ -105,11 +105,6 @@ namespace Kernel
|
||||||
|
|
||||||
delete elf;
|
delete elf;
|
||||||
|
|
||||||
MUST(process->m_fixed_width_allocators.emplace_back(process, 64));
|
|
||||||
MUST(process->m_fixed_width_allocators.emplace_back(process, 256));
|
|
||||||
MUST(process->m_fixed_width_allocators.emplace_back(process, 1024));
|
|
||||||
MUST(process->m_fixed_width_allocators.emplace_back(process, 4096));
|
|
||||||
|
|
||||||
register_process(process);
|
register_process(process);
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
@ -378,19 +373,55 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr uint16_t next_power_of_two(uint16_t value)
|
||||||
|
{
|
||||||
|
value--;
|
||||||
|
value |= value >> 1;
|
||||||
|
value |= value >> 2;
|
||||||
|
value |= value >> 4;
|
||||||
|
value |= value >> 8;
|
||||||
|
return value + 1;
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void*> Process::allocate(size_t bytes)
|
BAN::ErrorOr<void*> Process::allocate(size_t bytes)
|
||||||
{
|
{
|
||||||
|
if (bytes <= PAGE_SIZE)
|
||||||
|
{
|
||||||
|
// Do fixed width allocation
|
||||||
|
size_t allocation_size = next_power_of_two(bytes);
|
||||||
|
ASSERT(bytes <= allocation_size);
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
for (auto& allocator : m_fixed_width_allocators)
|
for (auto& allocator : m_fixed_width_allocators)
|
||||||
if (bytes <= allocator.allocation_size())
|
if (allocator.allocation_size() == allocation_size && allocator.allocations() < allocator.max_allocations())
|
||||||
return (void*)allocator.allocate();
|
return (void*)allocator.allocate();
|
||||||
|
|
||||||
|
MUST(m_fixed_width_allocators.emplace_back(this, allocation_size));
|
||||||
|
return (void*)m_fixed_width_allocators.back().allocate();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: Do general allocation
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Process::free(void* ptr)
|
void Process::free(void* ptr)
|
||||||
{
|
{
|
||||||
for (auto& allocator : m_fixed_width_allocators)
|
LockGuard _(m_lock);
|
||||||
if (allocator.deallocate((vaddr_t)ptr))
|
|
||||||
|
for (auto it = m_fixed_width_allocators.begin(); it != m_fixed_width_allocators.end(); it++)
|
||||||
|
{
|
||||||
|
if (it->deallocate((vaddr_t)ptr))
|
||||||
|
{
|
||||||
|
// TODO: This might be too much. Maybe we should only
|
||||||
|
// remove allocators when we have low memory... ?
|
||||||
|
if (it->allocations() == 0)
|
||||||
|
m_fixed_width_allocators.remove(it);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
dwarnln("free called on pointer that was not allocated");
|
dwarnln("free called on pointer that was not allocated");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,34 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define N 512
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i <= 10; i++)
|
||||||
{
|
{
|
||||||
int* ptrs[10];
|
int** ptrs = malloc(N * sizeof(int*));
|
||||||
for (int j = 0; j < 10; j++)
|
if (ptrs == NULL)
|
||||||
{
|
{
|
||||||
ptrs[j] = malloc(10);
|
perror("malloc");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for (int j = 0; j < N; j++)
|
||||||
|
{
|
||||||
|
ptrs[j] = malloc(sizeof(int));
|
||||||
if (ptrs[j] == NULL)
|
if (ptrs[j] == NULL)
|
||||||
{
|
{
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
*ptrs[j] = j;
|
*ptrs[j] = j;
|
||||||
putc('0' + *ptrs[j], stdout);
|
putchar('0' + *ptrs[j] % 10);
|
||||||
}
|
}
|
||||||
for (int j = 0; j < 10; j++)
|
putchar('\n');
|
||||||
|
|
||||||
|
for (int j = 0; j < N; j++)
|
||||||
free(ptrs[j]);
|
free(ptrs[j]);
|
||||||
putc('\n', stdout);
|
free(ptrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue