Now with a heap! Holy cow!

alentours-dev
Sergiusz Bazanski 2011-03-14 17:49:22 +01:00
parent 2a3c4ec827
commit 7ed12065be
7 changed files with 437 additions and 31 deletions

51
include/Tier0/heap.h Normal file
View File

@ -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

View File

@ -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

BIN
src/Tier0/.heap.c.swp Normal file

Binary file not shown.

BIN
src/Tier0/.kmain.c.swp Normal file

Binary file not shown.

381
src/Tier0/heap.c Normal file
View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}