From 125398a52f6d0968b4a085878ae840f47940c900 Mon Sep 17 00:00:00 2001 From: fincs Date: Wed, 27 Aug 2014 23:44:38 +0200 Subject: [PATCH] Refactor linear heap code (formerly known as GSP heap) --- examples/gpu/source/main.c | 6 ++--- libctru/include/3ds.h | 1 + libctru/include/3ds/gfx.h | 1 - libctru/include/3ds/linear.h | 6 +++++ libctru/source/gfx.c | 42 +++++++++++------------------------ libctru/source/initSystem.c | 11 +++++++-- libctru/source/linear.c | 32 ++++++++++++++++++++++++++ libctru/source/services/gsp.c | 8 +++---- 8 files changed, 68 insertions(+), 39 deletions(-) create mode 100644 libctru/include/3ds/linear.h create mode 100644 libctru/source/linear.c diff --git a/examples/gpu/source/main.c b/examples/gpu/source/main.c index 40c46e0..97d0ff4 100644 --- a/examples/gpu/source/main.c +++ b/examples/gpu/source/main.c @@ -161,12 +161,12 @@ int main() GPU_Init(NULL); u32 gpuCmdSize=0x40000; - u32* gpuCmd=(u32*)gfxAllocLinear(gpuCmdSize*4); + u32* gpuCmd=(u32*)linearAlloc(gpuCmdSize*4); GPU_Reset(gxCmdBuf, gpuCmd, gpuCmdSize); - vertArray=(float*)gfxAllocLinear(0x100000); - texData=(u32*)gfxAllocLinear(0x100000); + vertArray=(float*)linearAlloc(0x100000); + texData=(u32*)linearAlloc(0x100000); memcpy(texData, test_png_bin, test_png_bin_size); memcpy(vertArray, mdlData, sizeof(mdlData)); diff --git a/libctru/include/3ds.h b/libctru/include/3ds.h index 6628e69..f2a9367 100644 --- a/libctru/include/3ds.h +++ b/libctru/include/3ds.h @@ -8,6 +8,7 @@ extern "C" { #include <3ds/types.h> #include <3ds/svc.h> #include <3ds/srv.h> +#include <3ds/linear.h> #include <3ds/os.h> #include <3ds/gfx.h> diff --git a/libctru/include/3ds/gfx.h b/libctru/include/3ds/gfx.h index 27923a9..a0533c6 100644 --- a/libctru/include/3ds/gfx.h +++ b/libctru/include/3ds/gfx.h @@ -26,7 +26,6 @@ void gfxSwapBuffersGpu(); //helper stuff u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height); -void* gfxAllocLinear(size_t size); //global variables extern u8* gfxTopLeftFramebuffers[2]; diff --git a/libctru/include/3ds/linear.h b/libctru/include/3ds/linear.h new file mode 100644 index 0000000..f42a8b9 --- /dev/null +++ b/libctru/include/3ds/linear.h @@ -0,0 +1,6 @@ +#pragma once + +// Functions for allocating/deallocating memory from linear heap +void* linearAlloc(size_t size); +void* linearRealloc(void* mem, size_t size); +void linearFree(void* mem); diff --git a/libctru/source/gfx.c b/libctru/source/gfx.c index 0f7596b..8c8b79b 100644 --- a/libctru/source/gfx.c +++ b/libctru/source/gfx.c @@ -17,25 +17,7 @@ bool enable3d; Handle gspEvent, gspSharedMemHandle; -u8* gspHeap; u32* gxCmdBuf; -extern u32 __gsp_heap_size; - -// TODO: this function is not thread-safe and you cannot 'free' this memory. -void* gfxAllocLinear(size_t size) -{ - static size_t currentOffset = 0; - size_t free = __gsp_heap_size - currentOffset; - - if(free >= size) - { - currentOffset += size; - return (void*) &gspHeap[currentOffset - size]; - } - - return NULL; -} - void gfxSet3D(bool enable) { @@ -90,9 +72,6 @@ void gfxInit() GSPGPU_RegisterInterruptRelayQueue(NULL, gspEvent, 0x1, &gspSharedMemHandle, &gfxThreadID); svcMapMemoryBlock(gspSharedMemHandle, (u32)gfxSharedMemory, 0x3, 0x10000000); - //map GSP heap - svcControlMemory((u32*)&gspHeap, 0x0, 0x0, __gsp_heap_size, 0x10003, 0x3); - // default gspHeap configuration : // topleft1 0x00000000-0x00046500 // topleft2 0x00046500-0x0008CA00 @@ -102,12 +81,12 @@ void gfxInit() // topright1 0x000FD200-0x00143700 // topright2 0x00143700-0x00189C00 - gfxTopLeftFramebuffers[0]=gfxAllocLinear(0x46500); - gfxTopLeftFramebuffers[1]=gfxAllocLinear(0x46500); - gfxBottomFramebuffers[0]=gfxAllocLinear(0x38400); - gfxBottomFramebuffers[1]=gfxAllocLinear(0x38400); - gfxTopRightFramebuffers[0]=gfxAllocLinear(0x46500); - gfxTopRightFramebuffers[1]=gfxAllocLinear(0x46500); + gfxTopLeftFramebuffers[0]=linearAlloc(0x46500); + gfxTopLeftFramebuffers[1]=linearAlloc(0x46500); + gfxBottomFramebuffers[0]=linearAlloc(0x38400); + gfxBottomFramebuffers[1]=linearAlloc(0x38400); + gfxTopRightFramebuffers[0]=linearAlloc(0x46500); + gfxTopRightFramebuffers[1]=linearAlloc(0x46500); enable3d=false; //initialize framebuffer info structures @@ -129,8 +108,13 @@ void gfxExit() // Exit event handler gspExitEventHandler(); - //free GSP heap - svcControlMemory((u32*)&gspHeap, (u32)gspHeap, 0x0, __gsp_heap_size, MEMOP_FREE, 0x0); + // Free framebuffers (let's pretend linearFree is actually implemented...) + linearFree(gfxTopRightFramebuffers[1]); + linearFree(gfxTopRightFramebuffers[0]); + linearFree(gfxBottomFramebuffers[1]); + linearFree(gfxBottomFramebuffers[0]); + linearFree(gfxTopLeftFramebuffers[1]); + linearFree(gfxTopLeftFramebuffers[0]); //unmap GSP shared mem svcUnmapMemoryBlock(gspSharedMemHandle, 0x10002000); diff --git a/libctru/source/initSystem.c b/libctru/source/initSystem.c index b1ad146..0179a7d 100644 --- a/libctru/source/initSystem.c +++ b/libctru/source/initSystem.c @@ -6,10 +6,11 @@ int __system_argc; char** __system_argv; void (*__system_retAddr)(void); +u32 __linear_heap; // Data from _prm structure extern void* __service_ptr; // used to detect if we're run from a homebrew launcher -extern u32 __heap_size; +extern u32 __heap_size, __linear_heap_size; extern const char* __system_arglist; // newlib definitions we need @@ -27,7 +28,10 @@ void __attribute__((noreturn)) __ctru_exit(int rc) // TODO: APT exit goes here - // Unmap the heap + // Unmap the linear heap + svcControlMemory(&__linear_heap, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0); + + // Unmap the application heap svcControlMemory(&heapBase, heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0); // Jump to the loader if it provided a callback @@ -48,6 +52,9 @@ void initSystem(void (*retAddr)(void)) heapBase = 0x08000000; svcControlMemory(&heapBase, heapBase, 0x0, __heap_size, MEMOP_ALLOC, 0x3); + // Allocate the linear heap + svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, 0x3); + // Set up newlib heap fake_heap_start = (char*)heapBase; fake_heap_end = fake_heap_start + __heap_size; diff --git a/libctru/source/linear.c b/libctru/source/linear.c new file mode 100644 index 0000000..ba78f40 --- /dev/null +++ b/libctru/source/linear.c @@ -0,0 +1,32 @@ +#include <3ds.h> + +extern u32 __linear_heap, __linear_heap_size; + +// TODO: this allocator sucks! It is not thread-safe and you cannot 'free' this memory. +void* linearAlloc(size_t size) +{ + static size_t currentOffset = 0; + size_t free = __linear_heap_size - currentOffset; + + // Enforce 8-byte alignment + size = (size + 7) &~ 7; + + void* mem = NULL; + if (free >= size) + { + mem = (void*)(__linear_heap + currentOffset); + currentOffset += size; + } + + return mem; +} + +void* linearRealloc(void* mem, size_t size) +{ + return NULL; // TODO +} + +void linearFree(void* mem) +{ + // TODO +} diff --git a/libctru/source/services/gsp.c b/libctru/source/services/gsp.c index d92d7ea..f0f72d3 100644 --- a/libctru/source/services/gsp.c +++ b/libctru/source/services/gsp.c @@ -358,7 +358,7 @@ Result GSPGPU_SubmitGxCommand(u32* sharedGspCmdBuf, u32 gxCommand[0x8], Handle* svcClearEvent(gspEvent); u32 cmdBufHeader; - __asm__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf)); + __asm__ __volatile__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf)); u8 commandIndex=cmdBufHeader&0xFF; u8 totalCommands=(cmdBufHeader>>8)&0xFF; @@ -370,17 +370,17 @@ Result GSPGPU_SubmitGxCommand(u32* sharedGspCmdBuf, u32 gxCommand[0x8], Handle* memcpy(dst, gxCommand, 0x20); u32 mcrVal=0x0; - __asm__ ("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (mcrVal)); //Data Synchronization Barrier Register + __asm__ __volatile__ ("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (mcrVal)); //Data Synchronization Barrier Register totalCommands++; cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|(((u32)totalCommands)<<8); while(1) { u32 strexResult; - __asm__ ("strex %[result], %[val], [%[adr]]" : [result] "=&r" (strexResult) : [adr] "r" (sharedGspCmdBuf), [val] "r" (cmdBufHeader)); + __asm__ __volatile__ ("strex %[result], %[val], [%[adr]]" : [result] "=&r" (strexResult) : [adr] "r" (sharedGspCmdBuf), [val] "r" (cmdBufHeader)); if(!strexResult)break; - __asm__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf)); + __asm__ __volatile__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf)); totalCommands=((cmdBufHeader&0xFF00)>>8)+1; cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|((totalCommands<<8)&0xFF00); }