peredOS/kernel/heap.c

83 lines
3.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "heap.h"
#include "vmm.h"
#include "pmm.h"
#include "../drivers/serial.h"
static heap_chunk_t* heap_start_chunk = NULL;
void kheap_init(void) {
kprint_serial("HEAP: Initializing Kernel Heap...\n");
// 1. Выделяем одну физ. страницу под старт кучи
void* phys_page = pmm_alloc_page();
// 2. Мапим её на виртуальный адрес HEAP_START
// Нам нужны флаги Present (1) + Write (2) = 3
vmm_map_page((uint32_t)phys_page, HEAP_START, 3);
// 3. Создаем базовый блок на всю эту страницу
heap_start_chunk = (heap_chunk_t*)HEAP_START;
heap_start_chunk->size = PAGE_SIZE - sizeof(heap_chunk_t);
heap_start_chunk->is_free = 1;
heap_start_chunk->next = NULL;
kprint_serial("HEAP: Kernel Heap initialized successfully at 0x00400000!\n");
}
void* kmalloc(size_t size) {
if (size == 0) return NULL;
// Выравниваем размер по 4 байта для стабильности на x86
size = (size + 3) & ~3;
heap_chunk_t* current = heap_start_chunk;
// Ищем подходящий свободный блок (First Fit)
while (current != NULL) {
if (current->is_free && current->size >= size) {
// Если блок сильно больше, чем надо, дробим его
// sizeof(heap_chunk_t) + 4 байта минимально на остаток
if (current->size >= size + sizeof(heap_chunk_t) + 4) {
heap_chunk_t* new_chunk = (heap_chunk_t*)((uint32_t)current + sizeof(heap_chunk_t) + size);
new_chunk->size = current->size - size - sizeof(heap_chunk_t);
new_chunk->is_free = 1;
new_chunk->next = current->next;
current->size = size;
current->next = new_chunk;
}
current->is_free = 0;
// Возвращаем указатель на память СРАЗУ ЗА заголовком
return (void*)((uint32_t)current + sizeof(heap_chunk_t));
}
current = current->next;
}
// По-хорошему, если памяти не хватило, нужно выделить еще страницу из PMM
// и расширить кучу. Но для первого теста выкинем панику.
kprint_serial("HEAP ERROR: OUT OF KERNEL HEAP MEMORY!\n");
return NULL;
}
void kfree(void* ptr) {
if (ptr == NULL) return;
// Смещаемся назад, чтобы получить доступ к заголовку блока
heap_chunk_t* chunk = (heap_chunk_t*)((uint32_t)ptr - sizeof(heap_chunk_t));
chunk->is_free = 1;
// Склеиваем последовательные свободные блоки (Coalescing), чтобы не было фрагментации
heap_chunk_t* current = heap_start_chunk;
while (current != NULL) {
if (current->is_free && current->next && current->next->is_free) {
current->size += sizeof(heap_chunk_t) + current->next->size;
current->next = current->next->next;
// Не шагаем вперед, проверяем текущий блок еще раз с новым next
continue;
}
current = current->next;
}
}