libnx/nx/source/heap/heap.c

96 lines
2.0 KiB
C

// Copyright 2017 plutoo
// Worst heap ever xD
#include <switch.h>
typedef struct HeapHeader HeapHeader;
typedef enum {
USED = 0x55534544,
FREE = 0x46524545
} HeapState;
struct HeapHeader {
size_t State;
size_t Size;
HeapHeader* Next;
HeapHeader* Prev;
};
static HeapHeader g_LastFree;
void heapInit(void* base, size_t size) {
HeapHeader* hdr = (HeapHeader*) base;
hdr->Next = &g_LastFree;
hdr->Prev = &g_LastFree;
hdr->Size = size - sizeof(HeapHeader);
hdr->State = FREE;
g_LastFree.Next = hdr;
g_LastFree.Prev = hdr;
}
void heapSetup() {
// Called by crt0.
#define HEAP_SIZE 0x1000000
static u8 g_Heap[HEAP_SIZE];
heapInit(&g_Heap[0], HEAP_SIZE);
}
void* heapAllocPages(size_t size) {
void* ptr = heapAlloc(size + 0x1000);
if (ptr != NULL) {
ptr = (void*) ((((uintptr_t) ptr) + 0xFFF) &~ 0xFFF);
}
return ptr;
}
void* heapAlloc(size_t size) {
size = (size + 15) &~ 15;
HeapHeader* hdr = &g_LastFree;
while ((hdr = hdr->Next) != &g_LastFree) {
if (hdr->Size >= size) {
size_t rem = hdr->Size - size;
if (rem < sizeof(HeapHeader)) {
size = hdr->Size;
rem = 0;
}
hdr->State = USED;
hdr->Size = size;
hdr->Prev->Next = hdr->Next;
hdr->Next->Prev = hdr->Prev;
if (rem != 0) {
HeapHeader* rem_hdr = (HeapHeader*) (((uintptr_t)(hdr + 1)) + size);
rem_hdr->State = FREE;
rem_hdr->Size = rem - sizeof(HeapHeader);
rem_hdr->Next = g_LastFree.Next;
rem_hdr->Prev = &g_LastFree;
g_LastFree.Next = rem_hdr;
}
return (void*) (((uintptr_t) hdr) + sizeof(HeapHeader));
}
}
return NULL;
}
void heapFree(void* ptr) {
HeapHeader* hdr = (HeapHeader*) (((uintptr_t) ptr) - sizeof(HeapHeader));
hdr->State = FREE;
hdr->Next = g_LastFree.Next;
g_LastFree.Next = hdr;
hdr->Prev = &g_LastFree;
}