1010#include "ctypes.h"
1111#include "stdio.h"
1212#include "stdlib.h"
13+ #include "paging.h"
1314
1415u32 free_mem_addr_guard1 = 0xDEADBEEF ;
1516u32 free_mem_addr = HEAP_START ;
1617u32 free_mem_addr_guard2 = 0xCAFEBABE ;
1718static mem_block_t * free_blocks = NULL ;
19+ u32 heap_current_end = HEAP_START + HEAP_SIZE ;
1820
1921// Инициализация памяти heap
2022void heap_init () {
@@ -24,13 +26,57 @@ void heap_init() {
2426 free_blocks -> next = NULL ;
2527 free_blocks -> is_free = 1 ;
2628
29+ // Обновим текущий конец кучи
30+ heap_current_end = HEAP_START + HEAP_SIZE ;
31+
2732 kprint ("Heap initialized at " );
2833 char buf [32 ] = "" ;
2934 hex_to_ascii (HEAP_START , buf );
3035 kprint (buf );
3136 kprint ("\n" );
3237}
3338
39+ int expand_heap (u32 size ) {
40+ // Выравниваем размер вверх до границы страницы
41+ u32 num_pages = (size + PAGE_SIZE - 1 ) / PAGE_SIZE ;
42+ u32 expand_size = num_pages * PAGE_SIZE ;
43+
44+ printf ("Expanding heap by %d bytes (%d pages)\n" , expand_size , num_pages );
45+
46+ // Мы будем расширять кучу начиная с адреса heap_current_end
47+ u32 virtual_address = heap_current_end ;
48+
49+ for (u32 i = 0 ; i < num_pages ; i ++ ) {
50+ // Запрашиваем физический фрейм
51+ page_t * page = get_page (virtual_address , 1 , kernel_directory );
52+ if (!page ) {
53+ kprint ("Failed to get page for heap expansion!\n" );
54+ return 0 ;
55+ }
56+
57+ // Выделяем фрейм для страницы (с флагами ядра и записи)
58+ alloc_frame (page , 0 , 1 );
59+
60+ // Обновляем виртуальный адрес для следующей страницы
61+ virtual_address += PAGE_SIZE ;
62+ }
63+
64+ // Теперь нам нужно добавить новую область памяти в список свободных блоков
65+ mem_block_t * new_block = (mem_block_t * )heap_current_end ;
66+ new_block -> size = expand_size - sizeof (mem_block_t ); // Учитываем заголовок
67+ new_block -> is_free = 1 ;
68+ new_block -> next = free_blocks ; // Добавляем в начало списка
69+
70+ // Обновляем глобальный список свободных блоков
71+ free_blocks = new_block ;
72+
73+ // Обновляем текущий конец кучи
74+ heap_current_end += expand_size ;
75+
76+ printf ("Heap expanded successfully. New end: %x\n" , heap_current_end );
77+ return 1 ;
78+ }
79+
3480void * kmalloc (u32 size ) {
3581 // Выравниваем размер до границы BLOCK_SIZE
3682 if (size % BLOCK_SIZE != 0 ) {
@@ -47,13 +93,9 @@ void *kmalloc(u32 size) {
4793 // самого блока
4894 if (current -> size > size + sizeof (mem_block_t ) + BLOCK_SIZE ) {
4995 // Можем разделить блок
50- mem_block_t * new_block =
51- (mem_block_t * )((u32 )current + sizeof (mem_block_t ) +
96+ mem_block_t * new_block = (mem_block_t * )((u32 )current + sizeof (mem_block_t ) +
5297 size ); // поинтер на новый блок
53- new_block -> size =
54- current -> size - size -
55- sizeof (
56- mem_block_t ); // размер текущего - выделяемый - размер структуры
98+ new_block -> size = current -> size - size - sizeof (mem_block_t ); // размер текущего - выделяемый - размер структуры
5799 new_block -> is_free = 1 ; // свободен
58100 new_block -> next = current -> next ;
59101
@@ -70,20 +112,68 @@ void *kmalloc(u32 size) {
70112 current = current -> next ;
71113 }
72114
73- kprint ("No free blocks found\n" );
74- return NULL ;
115+ // Если дошли сюда, значит, подходящего блока не найдено -> пробуем расширить кучу
116+ printf ("No free block found for size %d. Trying to expand heap...\n" , size );
117+ if (expand_heap (size )) {
118+ // После расширения кучи пробуем аллоцировать снова (рекурсивно)
119+ return kmalloc (size );
120+ } else {
121+ kprint ("Heap expansion failed!\n" );
122+ return NULL ;
123+ }
75124}
76125
77126void * krealloc (void * ptr , u32 size ) {
78- if (!ptr ) return kmalloc (size ); // если нет указателя то просто аллоцируем память
79- if (size == 0 ) { kfree (ptr ); return NULL ; } // если размер нулевой освобождаем поинтер
127+ if (!ptr )
128+ return kmalloc (size );
129+
130+ if (size == 0 ) {
131+ kfree (ptr );
132+ return NULL ;
133+ }
134+
135+ // Получаем заголовок блока
136+ mem_block_t * block = (mem_block_t * )((u32 )ptr - sizeof (mem_block_t ));
137+
138+ // Если текущий блок достаточно большой
139+ if (block -> size >= size ) {
140+ // Можно ли разделить блок?
141+ if (block -> size - size >= sizeof (mem_block_t ) + BLOCK_SIZE ) {
142+ mem_block_t * new_block = (mem_block_t * )((u32 )block + sizeof (mem_block_t ) + size );
143+ new_block -> size = block -> size - size - sizeof (mem_block_t );
144+ new_block -> is_free = 1 ;
145+ new_block -> next = block -> next ;
146+
147+ block -> size = size ;
148+ block -> next = new_block ;
149+ }
150+ return ptr ;
151+ }
152+
153+ // Пытаемся объединить с последующим свободным блоком
154+ if (block -> next && block -> next -> is_free ) {
155+ u32 total_size = block -> size + sizeof (mem_block_t ) + block -> next -> size ;
156+ if (total_size >= size ) {
157+ block -> size = total_size ;
158+ block -> next = block -> next -> next ;
80159
81- mem_block_t * block = (mem_block_t * )((u32 )ptr - sizeof (mem_block_t )); // создаем блок
82- if (block -> size >= size ) return ptr ; // если текущий блок достаточно большой
160+ // Разделяем блок, если осталось место
161+ if (total_size - size >= sizeof (mem_block_t ) + BLOCK_SIZE ) {
162+ mem_block_t * new_block = (mem_block_t * )((u32 )block + sizeof (mem_block_t ) + size );
163+ new_block -> size = total_size - size - sizeof (mem_block_t );
164+ new_block -> is_free = 1 ;
165+ new_block -> next = block -> next ;
166+ block -> next = new_block ;
167+ block -> size = size ;
168+ }
169+ return ptr ;
170+ }
171+ }
83172
84- void * new_ptr = kmalloc (size ); // новый поинтер
85- if (new_ptr ) { // если все ок то копируем память и освобождаем старый поинтер
86- memory_copy (ptr , new_ptr , block -> size );
173+ // Если не можем расширить, выделяем новый блок и копируем данные
174+ void * new_ptr = kmalloc (size );
175+ if (new_ptr ) {
176+ memcpy (new_ptr , ptr , block -> size );
87177 kfree (ptr );
88178 }
89179 return new_ptr ;
@@ -93,25 +183,64 @@ void kfree(void *ptr) {
93183 if (!ptr )
94184 return ;
95185
96- // получаем указатель на заголовок блока
186+ // Получаем указатель на заголовок блока
97187 mem_block_t * block = (mem_block_t * )((u32 )ptr - sizeof (mem_block_t ));
98188
99- if (block -> is_free ) { // блок уже освобожден
189+ if (block -> is_free ) {
100190 kprint ("Double free detected!\n" );
101191 return ;
102192 }
103193
104194 block -> is_free = 1 ;
105195
106- /* попробуем объединить с соседними свободными блоками*/
196+ // Попробуем объединить с соседними свободными блоками
107197 mem_block_t * current = free_blocks ;
198+ mem_block_t * prev = NULL ;
199+
108200 while (current ) {
109201 if (current -> is_free && current -> next && current -> next -> is_free ) {
110- // соединим текущий блок со следующим
202+ // Объединяем текущий блок со следующим
111203 current -> size += sizeof (mem_block_t ) + current -> next -> size ;
112204 current -> next = current -> next -> next ;
113- free_mem_addr -= current -> size ;
114205 }
206+
207+ // Проверяем, можно ли освободить страницы
208+ if (current -> is_free ) {
209+ u32 block_start = (u32 )current ;
210+ u32 block_end = block_start + sizeof (mem_block_t ) + current -> size ;
211+
212+ // Выравниваем границы блока по границам страниц
213+ u32 start_page = block_start & ~(PAGE_SIZE - 1 );
214+ u32 end_page = (block_end + PAGE_SIZE - 1 ) & ~(PAGE_SIZE - 1 );
215+
216+ // Проверяем, полностью ли свободны страницы в этом блоке
217+ for (u32 page = start_page ; page < end_page ; page += PAGE_SIZE ) {
218+ page_t * page_entry = get_page (page , 0 , kernel_directory );
219+ if (page_entry && page_entry -> present ) {
220+ // Проверяем, нет ли занятых блоков в этой странице
221+ int page_is_free = 1 ;
222+ mem_block_t * check = free_blocks ;
223+ while (check ) {
224+ u32 check_start = (u32 )check ;
225+ u32 check_end = check_start + sizeof (mem_block_t ) + check -> size ;
226+
227+ if (!check -> is_free && check_start < page + PAGE_SIZE && check_end > page ) {
228+ page_is_free = 0 ;
229+ break ;
230+ }
231+ check = check -> next ;
232+ }
233+
234+ if (page_is_free ) {
235+ // Освобождаем фрейм и страницу
236+ free_frame (page_entry );
237+ page_entry -> present = 0 ;
238+ }
239+ }
240+ }
241+ }
242+
243+ prev = current ;
115244 current = current -> next ;
116245 }
117246}
@@ -153,14 +282,44 @@ void kmemdump() {
153282 u32 counter = 0 ;
154283
155284 printf ("Heap: %x - %x (%d bytes)\n" , info .heap_start ,
156- info .heap_start + info .heap_size , info .heap_size );
285+ info .heap_current_end , info .heap_current_end - info .heap_start );
157286 printf ("Block size: %d bytes\n" , info .block_size );
158287 printf ("Total: USED=%d bytes, FREE=%d bytes, in %d blocks\n\n" ,
159288 info .total_used , info .total_free , info .block_count );
160289
290+ // Вывод информации о страницах хипа
291+
292+ int present_pages_count = 0 ;
293+ int not_present_pages_count = 0 ;
294+ for (u32 addr = info .heap_start ; addr < info .heap_current_end ; addr += PAGE_SIZE ) {
295+ page_t * page = get_page (addr , 0 , kernel_directory );
296+ if (page && page -> present ) {
297+ present_pages_count += 1 ;
298+ } else {
299+ not_present_pages_count += 1 ;
300+ }
301+ }
302+
303+ printf ("Heap pages: PRESENT=%d | NOT PRESENT=%d" , present_pages_count , not_present_pages_count );
304+
305+ printf ("\nMemory blocks:\n" );
161306 while (current ) {
162307 printf ("Block %d: %x, Size=%d, %s\n" , counter ++ , (u32 )current ,
163308 current -> size , current -> is_free ? "FREE" : "USED" );
309+
310+ // Дополнительная информация о страницах этого блока
311+ u32 block_start = (u32 )current ;
312+ u32 block_end = block_start + sizeof (mem_block_t ) + current -> size ;
313+ u32 start_page = block_start & ~(PAGE_SIZE - 1 );
314+ u32 end_page = (block_end + PAGE_SIZE - 1 ) & ~(PAGE_SIZE - 1 );
315+
316+ for (u32 page_addr = start_page ; page_addr < end_page ; page_addr += PAGE_SIZE ) {
317+ page_t * page = get_page (page_addr , 0 , kernel_directory );
318+ if (page && page -> present ) {
319+ printf (" Page %x -> Frame %x\n" , page_addr , page -> frame * PAGE_SIZE );
320+ }
321+ }
322+
164323 current = current -> next ;
165324 }
166325}
0 commit comments