Now with a heap! Holy cow!
parent
2a3c4ec827
commit
7ed12065be
|
@ -0,0 +1,51 @@
|
|||
#ifndef __HEAP_H__
|
||||
#define __HEAP_H__
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define HEAP_HEADER_MAGIC 0x8A4DF92E
|
||||
#define HEAP_FOOTER_MAGIC 0x9AFE352B
|
||||
|
||||
#define HEAP_START 0xD0000000
|
||||
#define HEAP_INITIAL_SIZE 0x00400000
|
||||
#define HEAP_MIN_SIZE 0x00400000
|
||||
|
||||
#define HEAP_INDEX_SIZE 0x00020000
|
||||
|
||||
typedef struct {
|
||||
u32 Magic;
|
||||
u8 Hole;
|
||||
u32 Size;
|
||||
} T_HEAP_HEADER;
|
||||
|
||||
typedef struct {
|
||||
u32 Magic;
|
||||
T_HEAP_HEADER *Header;
|
||||
} T_HEAP_FOOTER;
|
||||
|
||||
typedef struct {
|
||||
void **Array;
|
||||
u32 Size;
|
||||
u32 MaxSize;
|
||||
} T_HEAP_INDEX;
|
||||
|
||||
T_HEAP_INDEX heap_index_initialize(void *Address, u32 MaxSize);
|
||||
void heap_index_insert(T_HEAP_INDEX *Index, void *Value);
|
||||
u8 heap_index_smaller(void *A, void *B);
|
||||
|
||||
typedef struct {
|
||||
T_HEAP_INDEX Index;
|
||||
u32 Start;
|
||||
u32 End;
|
||||
u32 Max;
|
||||
} T_HEAP;
|
||||
|
||||
T_HEAP *heap_create(u32 Start, u32 End, u32 Max);
|
||||
void *heap_alloc(T_HEAP *Heap, u32 Size, u8 Aligned);
|
||||
void heap_free(T_HEAP *Heap, void *Address);
|
||||
|
||||
void heap_init_simple(void);
|
||||
void *kmalloc(u32 Size);
|
||||
void kfree(void *Data);
|
||||
|
||||
#endif
|
|
@ -5,5 +5,6 @@
|
|||
|
||||
void paging_init_simple(void);
|
||||
u8 paging_get_physical(u32 Virtual, u32 *Physical);
|
||||
void paging_allocate_page(u32 Virtual);
|
||||
void paging_map_kernel_page(u32 Virtual, u32 Physical);
|
||||
void paging_map_kernel_table(u32 Virtual, u32 Physical);
|
||||
#endif
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,381 @@
|
|||
#include "Tier0/heap.h"
|
||||
#include "Tier0/kstdlib.h"
|
||||
#include "Tier0/kstdio.h"
|
||||
#include "Tier0/physical_alloc.h"
|
||||
#include "Tier0/paging.h"
|
||||
|
||||
T_HEAP *g_heap;
|
||||
|
||||
T_HEAP_INDEX heap_index_initialize(void *Address, u32 MaxSize)
|
||||
{
|
||||
T_HEAP_INDEX Index;
|
||||
Index.Array = (void**)Address;
|
||||
Index.MaxSize = MaxSize;
|
||||
Index.Size = 0;
|
||||
|
||||
kmemset(Address, 0, MaxSize * 4);
|
||||
|
||||
return Index;
|
||||
}
|
||||
|
||||
void heap_index_insert(T_HEAP_INDEX *Index, void *Value)
|
||||
{
|
||||
u32 i = 0;
|
||||
while (i < Index->Size && heap_index_smaller(Index->Array[i], Value))
|
||||
i++;
|
||||
|
||||
if (i == Index->Size)
|
||||
Index->Array[Index->Size++] = Value;
|
||||
else
|
||||
{
|
||||
void *Temporary = Index->Array[i];
|
||||
Index->Array[i] = Value;
|
||||
while (i < Index->Size)
|
||||
{
|
||||
i++;
|
||||
void *Temporary2 = Index->Array[i];
|
||||
Index->Array[i] = Temporary;
|
||||
Temporary = Temporary2;
|
||||
}
|
||||
Index->Size++;
|
||||
}
|
||||
}
|
||||
|
||||
u8 heap_index_smaller(void *A, void *B)
|
||||
{
|
||||
return (((T_HEAP_HEADER *)A)->Size < ((T_HEAP_HEADER *)B)->Size)>0 ?1:0;
|
||||
}
|
||||
|
||||
void *heap_index_get(T_HEAP_INDEX *Index, u32 Position)
|
||||
{
|
||||
return Index->Array[Position];
|
||||
}
|
||||
|
||||
void heap_index_remove(T_HEAP_INDEX *Index, u32 Position)
|
||||
{
|
||||
while (Position < Index->Size)
|
||||
{ Index->Array[Position] = Index->Array[Position + 1];
|
||||
Position++;
|
||||
}
|
||||
Index->Size--;
|
||||
}
|
||||
|
||||
T_HEAP *heap_create(u32 Start, u32 End, u32 Max)
|
||||
{
|
||||
u16 NumSuperPages = (End - Start ) / (1024 * 1024 * 4);
|
||||
if ((End - Start) % (1024 * 1024 * 4) != 0)
|
||||
NumSuperPages++;
|
||||
|
||||
kprintf("[i] Allocating %i superpages (%i MB) for heap.\n",
|
||||
NumSuperPages, (End - Start) / 0x100000);
|
||||
for (int i = 0; i < NumSuperPages; i++)
|
||||
{
|
||||
u32 Physical = physmem_superpage_to_physical(
|
||||
physmem_allocate_superpage()
|
||||
);
|
||||
|
||||
paging_map_kernel_table(Start + i * 1024 * 1024 * 4, Physical);
|
||||
}
|
||||
|
||||
T_HEAP* Heap = (T_HEAP *)Start;
|
||||
Start += sizeof(T_HEAP);
|
||||
|
||||
Heap->Index = heap_index_initialize((void*)Start, HEAP_INDEX_SIZE);
|
||||
Start += HEAP_INDEX_SIZE * sizeof(void*);
|
||||
|
||||
Heap->Start = Start;
|
||||
Heap->End = Start + NumSuperPages * 4 * 1024 * 1024;
|
||||
Heap->Max = Max;
|
||||
|
||||
T_HEAP_HEADER *Hole = (T_HEAP_HEADER *)Start;
|
||||
Hole->Size = End - Start;
|
||||
Hole->Magic = HEAP_HEADER_MAGIC;
|
||||
Hole->Hole = 1;
|
||||
heap_index_insert(&Heap->Index, (void*)Hole);
|
||||
|
||||
return Heap;
|
||||
}
|
||||
|
||||
s32 _heap_find_smallest_hole(T_HEAP *Heap, u32 Size, u8 Aligned)
|
||||
{
|
||||
u32 Iterator = 0;
|
||||
while (Iterator < Heap->Index.Size)
|
||||
{
|
||||
T_HEAP_HEADER *Header = heap_index_get(&Heap->Index, Iterator);
|
||||
if (Aligned > 0)
|
||||
{
|
||||
u32 Location = (u32)Header;
|
||||
u32 Offset = 0;
|
||||
|
||||
if (((Location + sizeof(T_HEAP_HEADER)) & 0xFFFFF000) != 0)
|
||||
Offset = 0x1000 - (Location + sizeof(T_HEAP_HEADER)) % 0x1000;
|
||||
|
||||
u32 HoleSize = (u32)Header->Size - Offset;
|
||||
|
||||
if (HoleSize >= Size)
|
||||
break;
|
||||
}
|
||||
else if (Header->Size >= Size)
|
||||
break;
|
||||
Iterator++;
|
||||
}
|
||||
|
||||
if (Iterator == Heap->Index.Size)
|
||||
return -1;
|
||||
else
|
||||
return Iterator;
|
||||
}
|
||||
|
||||
void _heap_expand(T_HEAP *Heap, u32 Size)
|
||||
{
|
||||
u16 NumSuperPages = Size / 0x400000;
|
||||
if (Size % 0x400000 != 0)
|
||||
NumSuperPages++;
|
||||
|
||||
for (int i = 0; i < NumSuperPages; i++)
|
||||
{
|
||||
u16 SuperPage = physmem_allocate_superpage();
|
||||
u32 Physical = physmem_superpage_to_physical(SuperPage);
|
||||
paging_map_kernel_table(Heap->End + i * 0x400000, Physical);
|
||||
}
|
||||
}
|
||||
|
||||
u32 _heap_contract(T_HEAP *Heap, u32 Size)
|
||||
{
|
||||
if (Size & 0x400000)
|
||||
{
|
||||
Size &= 0x400000;
|
||||
Size += 0x400000;
|
||||
}
|
||||
|
||||
if (Size < HEAP_MIN_SIZE)
|
||||
Size = HEAP_MIN_SIZE;
|
||||
|
||||
u32 OldSize = Heap->End - Heap->Start;
|
||||
u32 NumberToDelete = (OldSize - Size) / 0x400000;
|
||||
|
||||
for (int i = 0; i < NumberToDelete; i++)
|
||||
{
|
||||
u32 Virtual = Heap->End + i * 0x400000;
|
||||
u32 Physical;
|
||||
paging_get_physical(Virtual, &Physical);
|
||||
u16 SuperPage = Physical / 0x400000;
|
||||
physmem_free_superpage(SuperPage);
|
||||
}
|
||||
|
||||
Heap->End -= NumberToDelete * 0x400000;
|
||||
|
||||
return (Heap->End - Heap->Start);
|
||||
}
|
||||
|
||||
void *heap_alloc(T_HEAP *Heap, u32 Size, u8 Aligned)
|
||||
{
|
||||
u32 RealSize = Size + sizeof(T_HEAP_HEADER) + sizeof(T_HEAP_FOOTER);
|
||||
s32 Iterator = _heap_find_smallest_hole(Heap, RealSize, Aligned);
|
||||
|
||||
if (Iterator == -1)
|
||||
{
|
||||
u32 OldSize = Heap->End - Heap->Start;
|
||||
u32 OldEnd = Heap->End;
|
||||
|
||||
_heap_expand(Heap, RealSize);
|
||||
u32 NewSize = Heap->End - Heap->Start;
|
||||
|
||||
Iterator = 0;
|
||||
u32 Last = 0;
|
||||
s32 LastIndex = -1;
|
||||
|
||||
while (Iterator < Heap->Index.Size)
|
||||
{
|
||||
u32 Location = (u32)heap_index_get(&Heap->Index, Iterator);
|
||||
if (Location > Last)
|
||||
{
|
||||
Last = Location;
|
||||
LastIndex = Iterator;
|
||||
}
|
||||
Iterator++;
|
||||
}
|
||||
|
||||
if (LastIndex == -1)
|
||||
{
|
||||
T_HEAP_HEADER *Header = (T_HEAP_HEADER *)OldEnd;
|
||||
Header->Magic = HEAP_HEADER_MAGIC;
|
||||
Header->Size = NewSize - OldSize;
|
||||
Header->Hole = 1;
|
||||
|
||||
T_HEAP_FOOTER *Footer = (T_HEAP_FOOTER *)(OldEnd + Header->Size
|
||||
- sizeof(T_HEAP_FOOTER));
|
||||
Footer->Magic = HEAP_FOOTER_MAGIC;
|
||||
Footer->Header = Header;
|
||||
|
||||
heap_index_insert(&Heap->Index, (void*)Header);
|
||||
}
|
||||
else
|
||||
{
|
||||
T_HEAP_HEADER *Header = (T_HEAP_HEADER *)Last;
|
||||
Header->Size += NewSize - OldSize;
|
||||
|
||||
T_HEAP_FOOTER *Footer = (T_HEAP_FOOTER *)((u32)Header
|
||||
+ Header->Size - sizeof(T_HEAP_FOOTER));
|
||||
Footer->Header = Header;
|
||||
Footer->Magic = HEAP_FOOTER_MAGIC;
|
||||
}
|
||||
|
||||
return heap_alloc(Heap, Size, Aligned);
|
||||
}
|
||||
|
||||
T_HEAP_HEADER *Header = (T_HEAP_HEADER*)heap_index_get(&Heap->Index,
|
||||
Iterator);
|
||||
u32 HoleStart = (u32)Header;
|
||||
u32 HoleSize = Header->Size;
|
||||
|
||||
if (HoleSize - RealSize < sizeof(T_HEAP_HEADER) + sizeof(T_HEAP_FOOTER))
|
||||
{
|
||||
Size += (HoleSize - RealSize);
|
||||
RealSize = HoleSize;
|
||||
}
|
||||
|
||||
if (Aligned && HoleStart & 0xFFFFF000)
|
||||
{
|
||||
u32 NewLocation = HoleStart + 0x1000 - (HoleStart & 0xFFF)
|
||||
- sizeof(T_HEAP_HEADER);
|
||||
Header->Size = 0x1000 - (HoleStart & 0xFFF) - sizeof(T_HEAP_HEADER);
|
||||
Header->Magic = HEAP_HEADER_MAGIC;
|
||||
Header->Hole = 1;
|
||||
|
||||
T_HEAP_FOOTER *Footer = (T_HEAP_FOOTER*)(NewLocation
|
||||
- sizeof(T_HEAP_FOOTER));
|
||||
Footer->Magic = HEAP_FOOTER_MAGIC;
|
||||
Footer->Header = Header;
|
||||
|
||||
HoleStart = NewLocation;
|
||||
HoleSize -= Header->Size;
|
||||
}
|
||||
else
|
||||
heap_index_remove(&Heap->Index, Iterator);
|
||||
|
||||
T_HEAP_HEADER *BlockHeader = (T_HEAP_HEADER *)HoleStart;
|
||||
BlockHeader->Magic = HEAP_HEADER_MAGIC;
|
||||
BlockHeader->Size = RealSize;
|
||||
BlockHeader->Hole = 0;
|
||||
|
||||
|
||||
T_HEAP_FOOTER *BlockFooter = (T_HEAP_FOOTER *)(HoleStart + RealSize
|
||||
- sizeof(T_HEAP_FOOTER));
|
||||
BlockFooter->Magic = HEAP_FOOTER_MAGIC;
|
||||
BlockFooter->Header = BlockHeader;
|
||||
|
||||
if (HoleSize - RealSize > 0)
|
||||
{
|
||||
T_HEAP_HEADER *NewHoleHeader = (T_HEAP_HEADER*)(HoleStart + RealSize);
|
||||
NewHoleHeader->Magic = HEAP_HEADER_MAGIC;
|
||||
NewHoleHeader->Size = HoleSize - RealSize;
|
||||
NewHoleHeader->Hole = 1;
|
||||
|
||||
T_HEAP_FOOTER *NewHoleFooter = (T_HEAP_FOOTER*)((u32)NewHoleHeader
|
||||
+ NewHoleHeader->Size - sizeof(T_HEAP_FOOTER));
|
||||
|
||||
if ((u32)NewHoleFooter < Heap->End)
|
||||
{
|
||||
NewHoleFooter->Magic = HEAP_FOOTER_MAGIC;
|
||||
NewHoleFooter->Header = NewHoleHeader;
|
||||
}
|
||||
|
||||
heap_index_insert(&Heap->Index, (void*)NewHoleHeader);
|
||||
}
|
||||
|
||||
return (void *)((u32)BlockHeader + sizeof(T_HEAP_HEADER));
|
||||
}
|
||||
|
||||
void heap_free(T_HEAP *Heap, void *Data)
|
||||
{
|
||||
if (Data == 0) return;
|
||||
T_HEAP_HEADER *Header = (T_HEAP_HEADER *)((u32)Data
|
||||
- sizeof(T_HEAP_HEADER));
|
||||
T_HEAP_FOOTER *Footer = (T_HEAP_FOOTER *)((u32)Header + Header->Size
|
||||
- sizeof(T_HEAP_FOOTER));
|
||||
|
||||
if (Header->Magic != HEAP_HEADER_MAGIC)
|
||||
return;
|
||||
if (Footer->Magic != HEAP_FOOTER_MAGIC)
|
||||
return;
|
||||
Header->Hole = 1;
|
||||
|
||||
u8 ShouldAdd = 1;
|
||||
|
||||
T_HEAP_FOOTER *FooterLeft = (T_HEAP_FOOTER *)((u32)Data
|
||||
- sizeof(T_HEAP_FOOTER));
|
||||
if (FooterLeft->Magic == HEAP_FOOTER_MAGIC && FooterLeft->Header->Hole)
|
||||
{
|
||||
u32 OurSize = Header->Size;
|
||||
Header = FooterLeft->Header;
|
||||
Footer->Header = Header;
|
||||
Header->Size += OurSize;
|
||||
ShouldAdd = 0;
|
||||
}
|
||||
|
||||
T_HEAP_HEADER *HeaderRight = (T_HEAP_HEADER *)((u32)Footer
|
||||
+ sizeof(T_HEAP_FOOTER));
|
||||
if (HeaderRight->Magic == HEAP_HEADER_MAGIC && HeaderRight->Hole)
|
||||
{
|
||||
Header->Size += HeaderRight->Size;
|
||||
Footer = (T_HEAP_FOOTER *)((u32)HeaderRight + HeaderRight->Size
|
||||
- sizeof(T_HEAP_FOOTER));
|
||||
Footer->Header = Header;
|
||||
|
||||
u32 Iterator = 0;
|
||||
while (Iterator < Heap->Index.Size &&
|
||||
heap_index_get(&Heap->Index, Iterator) != (void *)HeaderRight)
|
||||
Iterator++;
|
||||
|
||||
if (Iterator != -1)
|
||||
heap_index_remove(&Heap->Index, Iterator);
|
||||
}
|
||||
|
||||
if ((u32)Footer + sizeof(T_HEAP_FOOTER) == Heap->End)
|
||||
{
|
||||
u32 OldSize = Heap->End - Heap->Start;
|
||||
u32 NewSize = _heap_contract(Heap, (u32)Header - Heap->Start);
|
||||
|
||||
if (Header->Size > (OldSize - NewSize))
|
||||
{
|
||||
Header->Size -= (OldSize - NewSize);
|
||||
Footer = (T_HEAP_FOOTER *)((u32)Header + Header->Size
|
||||
- sizeof(T_HEAP_FOOTER));
|
||||
Footer->Magic = HEAP_FOOTER_MAGIC;
|
||||
Footer->Header = Header;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 Iterator = 0;
|
||||
while (Iterator < Heap->Index.Size &&
|
||||
heap_index_get(&Heap->Index, Iterator) != (void *)Header)
|
||||
Iterator++;
|
||||
|
||||
if (Iterator < Heap->Index.Size)
|
||||
{
|
||||
heap_index_remove(&Heap->Index, Iterator);
|
||||
ShouldAdd = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ShouldAdd)
|
||||
heap_index_insert(&Heap->Index, (void *)Header);
|
||||
}
|
||||
|
||||
void heap_init_simple(void)
|
||||
{
|
||||
g_heap = heap_create(HEAP_START, HEAP_START + HEAP_INITIAL_SIZE,
|
||||
HEAP_START + 0x0FFFF000);
|
||||
}
|
||||
|
||||
void *kmalloc(u32 Size)
|
||||
{
|
||||
return heap_alloc(g_heap, Size, 0);
|
||||
}
|
||||
|
||||
void kfree(void *Data)
|
||||
{
|
||||
heap_free(g_heap, Data);
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
#include "Tier0/pic.h"
|
||||
#include "Tier0/kbd_layout.h"
|
||||
#include "Tier0/physical_alloc.h"
|
||||
#include "Tier0/heap.h"
|
||||
|
||||
void interrupts_irq_sample(void);
|
||||
|
||||
|
@ -64,13 +65,7 @@ void kmain(void *MultibootHeader, u32 Magic)
|
|||
|
||||
kprintf("[i] Hardware interrupts are now enabled.\n");
|
||||
|
||||
/*while(1)
|
||||
{
|
||||
s8 c = ps2_getc();
|
||||
kprintf("%c", c);
|
||||
}*/
|
||||
|
||||
physmem_dump_map();
|
||||
heap_init_simple();
|
||||
|
||||
LOOPFOREVER;
|
||||
}
|
||||
|
|
|
@ -3,14 +3,9 @@
|
|||
#include "Tier0/kstdio.h"
|
||||
#include "types.h"
|
||||
|
||||
// 10 megabytes is safe guess, I guess.
|
||||
#define PAGING_FREEFORALL_START 0x00F00000
|
||||
|
||||
u32 g_kernel_page_directory[1024] __attribute__ ((aligned (4096)));
|
||||
u32 g_kernel_page_tables[1024][1024] __attribute__ ((aligned (4096)));
|
||||
|
||||
u32 g_paging_current_offset = PAGING_FREEFORALL_START;
|
||||
|
||||
u8 paging_get_physical(u32 Virtual, u32 *Physical)
|
||||
{
|
||||
u16 DirectoryIndex = (Virtual >> 22) & 0x3FF;
|
||||
|
@ -112,20 +107,3 @@ void paging_init_simple(void)
|
|||
"mov %%eax, %%cr0\n" :: "m" (PhysicalDirectory));
|
||||
}
|
||||
|
||||
// This allocates a 4kb page for whatever reason
|
||||
void paging_allocate_page(u32 Virtual)
|
||||
{
|
||||
u32 MaximumAddress = system_get_memory_upper();
|
||||
while (!system_memory_available(g_paging_current_offset, 0x1000))
|
||||
{
|
||||
g_paging_current_offset += 0x1000;
|
||||
if (g_paging_current_offset > MaximumAddress)
|
||||
{
|
||||
kprintf("[e] Fatal error: out of memory!\n");
|
||||
for (;;) {}
|
||||
}
|
||||
}
|
||||
|
||||
paging_map_kernel_page(Virtual, g_paging_current_offset);
|
||||
g_paging_current_offset += 0x1000;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue