paging: heap_alloc: fix allocation of more than 1 page (not without the help of grok)
This commit is contained in:
+32
-10
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Освобождение памяти
|
// Освобождение памяти
|
||||||
|
|||||||
Reference in New Issue
Block a user