Vhex-kernel/src/kernel/memory/pm_alloc.c

86 lines
1.7 KiB
C

#include <kernel/memory.h>
static struct pm_block_cache_s *block_alloc(void)
{
extern struct memory_info_s pmemory;
uint32_t i;
i = -1;
while (++i < pmemory.blocks)
{
// Check if the block are used
if (pmemory.cache[i].status == USED)
continue;
// Initialize block and return address
pmemory.cache[i].status = USED;
pmemory.cache[i].next = NULL;
return (&pmemory.cache[i]);
}
return (NULL);
}
void *pm_alloc(size_t size)
{
extern struct memory_info_s pmemory;
struct pm_block_cache_s **head;
struct pm_block_cache_s *block;
uint32_t block_entry;
uint32_t nb_blocks;
// Check obvious error.
if (size == 0)
return (NULL);
// Get the number of blocks we need.
nb_blocks = (size + PM_BLOCK_SIZE - 1) / PM_BLOCK_SIZE;
// Find block entry.
block_entry = 0;
head = &pmemory.head;
while (*head != NULL)
{
// Check is it is the last allocated
// object.
if ((*head)->next == NULL)
{
// Check memory space.
if ((*head)->end + 1 + nb_blocks >= pmemory.blocks)
return (NULL);
// Get cache entry.
block_entry = (*head)->end + 1;
head = &(*head)->next;
break;
}
// Calculate the gap between current
// allocated object and the next object.
if (((*head)->next->start) - ((*head)->end + 1) >= nb_blocks)
{
block_entry = (*head)->end + 1;
head = &(*head)->next;
break;
}
// Get next allocated block.
head = &(*head)->next;
}
// Setup new allocated block
block = block_alloc();
if (block == NULL)
return (NULL);
// Initialize new block
block->start = block_entry;
block->end = block_entry + nb_blocks - 1;
// Insert new block.
block->next = *head;
*head = block;
// Generate physical memory address
return ((void*)((block_entry * PM_BLOCK_SIZE) + pmemory.start));
}