Attempt to introduce newlib heap implementation

This commit is contained in:
plutoo 2017-10-09 00:41:19 +02:00
parent 85538c9fb3
commit 99bd9c76aa
8 changed files with 51 additions and 132 deletions

View File

@ -24,7 +24,7 @@ VERSION := $(LIBNX_MAJOR).$(LIBNX_MINOR).$(LIBNX_PATCH)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
TARGET := nx TARGET := nx
#BUILD := build #BUILD := build
SOURCES := source/system source/kernel source/services source/heap SOURCES := source/system source/kernel source/services
DATA := data DATA := data
INCLUDES := include INCLUDES := include

View File

@ -12,7 +12,6 @@ extern "C" {
#include <switch/result.h> #include <switch/result.h>
#include <switch/svc.h> #include <switch/svc.h>
#include <switch/ipc.h> #include <switch/ipc.h>
#include <switch/heap.h>
#include <switch/kernel/tmem.h> #include <switch/kernel/tmem.h>
#include <switch/kernel/mutex.h> #include <switch/kernel/mutex.h>

View File

@ -1,2 +0,0 @@
void* heapAllocPages(size_t size);
void* heapAlloc(size_t size);

View File

@ -1,105 +0,0 @@
// 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 INNER_HEAP_SIZE 0x20000
#define OUTER_HEAP_SIZE (0x2000000*4)
void* addr;
Result rc = svcSetHeapSize(&addr, OUTER_HEAP_SIZE);
if (R_SUCCEEDED(rc)) {
heapInit(addr, OUTER_HEAP_SIZE);
}
else {
static u8 g_Heap[INNER_HEAP_SIZE];
heapInit(&g_Heap[0], INNER_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;
}

View File

@ -1,5 +1,6 @@
// Copyright 2017 plutoo // Copyright 2017 plutoo
#include <switch.h> #include <switch.h>
#include <malloc.h>
static void _EntryWrap(Thread* t) { static void _EntryWrap(Thread* t) {
t->entry(t->arg); t->entry(t->arg);
@ -11,7 +12,7 @@ Result threadCreate(
int cpuid) int cpuid)
{ {
Result rc = 0; Result rc = 0;
void* stack = heapAllocPages(stack_sz); void* stack = memalign(0x1000, stack_sz);
if (stack == NULL) { if (stack == NULL) {
rc = MAKERESULT(MODULE_LIBNX, LIBNX_OUTOFMEM); rc = MAKERESULT(MODULE_LIBNX, LIBNX_OUTOFMEM);
@ -47,7 +48,7 @@ Result threadCreate(
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
virtmemFreeMap(stack_mirror, stack_sz); virtmemFreeMap(stack_mirror, stack_sz);
//heapFree(stack); free(stack);
} }
} }
@ -69,7 +70,7 @@ Result threadClose(Thread* t) {
rc = svcUnmapMemory(t->stack_mirror, t->stack_mem, t->stack_sz); rc = svcUnmapMemory(t->stack_mirror, t->stack_mem, t->stack_sz);
virtmemFreeMap(t->stack_mirror, t->stack_sz); virtmemFreeMap(t->stack_mirror, t->stack_sz);
//heapFree(t->stack); free(t->stack_mem);
svcCloseHandle(t->handle); svcCloseHandle(t->handle);
return rc; return rc;

View File

@ -1,5 +1,6 @@
// Copyright 2017 plutoo // Copyright 2017 plutoo
#include <switch.h> #include <switch.h>
#include <malloc.h>
Result tmemCreate(TransferMemory* t, size_t size, Permission perm) Result tmemCreate(TransferMemory* t, size_t size, Permission perm)
{ {
@ -9,7 +10,7 @@ Result tmemCreate(TransferMemory* t, size_t size, Permission perm)
t->Size = size; t->Size = size;
t->Perm = perm; t->Perm = perm;
t->MappedAddr = NULL; t->MappedAddr = NULL;
t->SourceAddr = heapAllocPages(size); t->SourceAddr = memalign(0x1000, size);
if (t->SourceAddr == NULL) { if (t->SourceAddr == NULL) {
rc = MAKERESULT(MODULE_LIBNX, LIBNX_OUTOFMEM); rc = MAKERESULT(MODULE_LIBNX, LIBNX_OUTOFMEM);
@ -77,8 +78,7 @@ Result tmemClose(TransferMemory* t)
Result rc = 0; Result rc = 0;
if (t->SourceAddr != NULL) { if (t->SourceAddr != NULL) {
// todo: Free is currently broken for page-aligned allocs. free(t->SourceAddr);
//heapFree(t->SourceAddr);
} }
if (t->MappedAddr != NULL) { if (t->MappedAddr != NULL) {

View File

@ -1,15 +1,31 @@
#include <switch.h> #include <switch.h>
#include <sys/iosupport.h>
#include <sys/time.h>
#include <sys/lock.h>
#include <sys/reent.h>
#include <string.h>
void __nx_exit(int rc); void __nx_exit(int rc);
void virtmemSetup(); void virtmemSetup();
void heapSetup(); void newlibSetup();
static void _SetupHeap() {
#define INNER_HEAP_SIZE 0x20000
#define OUTER_HEAP_SIZE (0x2000000*4)
char* addr;
Result rc = svcSetHeapSize((void**)&addr, OUTER_HEAP_SIZE);
size_t size = OUTER_HEAP_SIZE;
if (R_FAILED(rc)) {
static char g_Heap[INNER_HEAP_SIZE];
addr = &g_Heap[0];
size = INNER_HEAP_SIZE;
}
// Multilib
extern char* fake_heap_start;
extern char* fake_heap_end;
fake_heap_start = addr;
fake_heap_end = addr + size;
}
void __attribute__((weak)) __appInit(void) void __attribute__((weak)) __appInit(void)
{ {
@ -27,13 +43,10 @@ void __attribute__((weak)) __libnx_init(void)
{ {
// Called by crt0. // Called by crt0.
// Newlib initialization goes here.
void exitImpl(int rc);
__syscalls.exit = exitImpl;
// Libnx initialization goes here. // Libnx initialization goes here.
newlibSetup();
virtmemSetup(); virtmemSetup();
heapSetup(); _SetupHeap();
// Initialize services. // Initialize services.
__appInit(); __appInit();
@ -55,8 +68,3 @@ void __attribute__((weak)) NORETURN __libnx_exit(void)
svcExitProcess(); svcExitProcess();
while(1); while(1);
} }
void NORETURN exitImpl(int rc)
{
__libnx_exit();
}

18
nx/source/system/newlib.c Normal file
View File

@ -0,0 +1,18 @@
#include <switch.h>
#include <sys/iosupport.h>
#include <sys/time.h>
#include <sys/lock.h>
#include <sys/reent.h>
void __attribute__((weak)) NORETURN __libnx_exit(void);
static void NORETURN _ExitImpl(int rc) {
__libnx_exit();
}
void newlibSetup() {
void exitImpl(int rc);
__syscalls.exit = _ExitImpl;
}