mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
Attempt to introduce newlib heap implementation
This commit is contained in:
parent
85538c9fb3
commit
99bd9c76aa
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
void* heapAllocPages(size_t size);
|
|
||||||
void* heapAlloc(size_t size);
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
||||||
|
@ -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) {
|
||||||
|
@ -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
18
nx/source/system/newlib.c
Normal 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;
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user