paging: heap_alloc: fix allocation of more than 1 page (not without the help of grok)

This commit is contained in:
2025-03-29 14:04:57 +03:00
parent 2724595592
commit 6f7cbfedbb
+32 -10
View File
@@ -58,7 +58,7 @@ void init_allocator() {
// Выделяем свободную страницу // Выделяем свободную страницу
void* alloc_page() { void* alloc_page() {
printf("alloc_page called\n"); // printf("alloc_page called\n");
int i, j; int i, j;
for (i = 0; i < 512; i++) { for (i = 0; i < 512; i++) {
if (page_bitmap[i] != 0xFF) { if (page_bitmap[i] != 0xFF) {
@@ -354,9 +354,7 @@ void* heap_alloc(uint32_t size) {
// Ищем подходящий свободный блок // Ищем подходящий свободный блок
while (current) { while (current) {
if (current->is_free && current->size >= size) { if (current->is_free && current->size >= size) {
// Нашли блок
if (current->size >= size + sizeof(Block) + 4) { if (current->size >= size + sizeof(Block) + 4) {
// Разделяем блок, если он слишком большой
Block* new_block = (Block*)((uint32_t)current + sizeof(Block) + size); Block* new_block = (Block*)((uint32_t)current + sizeof(Block) + size);
new_block->size = current->size - size - sizeof(Block); new_block->size = current->size - size - sizeof(Block);
new_block->is_free = 1; new_block->is_free = 1;
@@ -366,25 +364,49 @@ void* heap_alloc(uint32_t size) {
current->next = new_block; current->next = new_block;
} }
current->is_free = 0; current->is_free = 0;
return (void*)((uint32_t)current + sizeof(Block)); // Возвращаем адрес после заголовка return (void*)((uint32_t)current + sizeof(Block));
} }
prev = current; prev = current;
current = current->next; current = current->next;
} }
// Нет свободного блока — добавляем новую страницу
// Нет подходящего блока — выделяем нужное количество страниц
uint32_t total_size = size + sizeof(Block); // Размер с заголовком
uint32_t pages_needed = (total_size + 0xFFF) / 0x1000; // Округляем вверх до страниц
uint32_t alloc_size = pages_needed * 0x1000; // Сколько байт выделяем
void* new_page = (void*)((uint32_t)kernel_heap.start + kernel_heap.size); void* new_page = (void*)((uint32_t)kernel_heap.start + kernel_heap.size);
map_kernel_page(new_page, 0x2); for (uint32_t i = 0; i < pages_needed; i++) {
kernel_heap.size += 0x1000; map_kernel_page((void*)((uint32_t)new_page + i * 0x1000), 0x2);
}
kernel_heap.size += alloc_size;
Block* new_block = (Block*)new_page; Block* new_block = (Block*)new_page;
new_block->size = 0x1000 - sizeof(Block); new_block->size = alloc_size - sizeof(Block);
new_block->is_free = 1; new_block->is_free = 1;
new_block->next = (Block*)0; new_block->next = (Block*)0;
if (prev) prev->next = new_block; if (prev) prev->next = new_block;
if (!kernel_heap.first) kernel_heap.first = new_block;
// Рекурсивно вызываем, чтобы выделить из нового блока // Теперь current указывает на новый блок, продолжаем цикл
return heap_alloc(size); current = new_block;
if (current->size >= size) {
if (current->size >= size + sizeof(Block) + 4) {
Block* split_block = (Block*)((uint32_t)current + sizeof(Block) + size);
split_block->size = current->size - size - sizeof(Block);
split_block->is_free = 1;
split_block->next = current->next;
current->size = size;
current->next = split_block;
}
current->is_free = 0;
return (void*)((uint32_t)current + sizeof(Block));
}
// Если что-то пошло не так, возвращаем NULL
return (void*)0;
} }
// Освобождение памяти // Освобождение памяти