mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
96 lines
2.0 KiB
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;
|
|
}
|
|
|