Refactor linear heap code (formerly known as GSP heap)

This commit is contained in:
fincs 2014-08-27 23:44:38 +02:00
parent 16544492a2
commit 125398a52f
8 changed files with 68 additions and 39 deletions

View File

@ -161,12 +161,12 @@ int main()
GPU_Init(NULL); GPU_Init(NULL);
u32 gpuCmdSize=0x40000; u32 gpuCmdSize=0x40000;
u32* gpuCmd=(u32*)gfxAllocLinear(gpuCmdSize*4); u32* gpuCmd=(u32*)linearAlloc(gpuCmdSize*4);
GPU_Reset(gxCmdBuf, gpuCmd, gpuCmdSize); GPU_Reset(gxCmdBuf, gpuCmd, gpuCmdSize);
vertArray=(float*)gfxAllocLinear(0x100000); vertArray=(float*)linearAlloc(0x100000);
texData=(u32*)gfxAllocLinear(0x100000); texData=(u32*)linearAlloc(0x100000);
memcpy(texData, test_png_bin, test_png_bin_size); memcpy(texData, test_png_bin, test_png_bin_size);
memcpy(vertArray, mdlData, sizeof(mdlData)); memcpy(vertArray, mdlData, sizeof(mdlData));

View File

@ -8,6 +8,7 @@ extern "C" {
#include <3ds/types.h> #include <3ds/types.h>
#include <3ds/svc.h> #include <3ds/svc.h>
#include <3ds/srv.h> #include <3ds/srv.h>
#include <3ds/linear.h>
#include <3ds/os.h> #include <3ds/os.h>
#include <3ds/gfx.h> #include <3ds/gfx.h>

View File

@ -26,7 +26,6 @@ void gfxSwapBuffersGpu();
//helper stuff //helper stuff
u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height); u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height);
void* gfxAllocLinear(size_t size);
//global variables //global variables
extern u8* gfxTopLeftFramebuffers[2]; extern u8* gfxTopLeftFramebuffers[2];

View File

@ -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);

View File

@ -17,25 +17,7 @@ bool enable3d;
Handle gspEvent, gspSharedMemHandle; Handle gspEvent, gspSharedMemHandle;
u8* gspHeap;
u32* gxCmdBuf; 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) void gfxSet3D(bool enable)
{ {
@ -90,9 +72,6 @@ void gfxInit()
GSPGPU_RegisterInterruptRelayQueue(NULL, gspEvent, 0x1, &gspSharedMemHandle, &gfxThreadID); GSPGPU_RegisterInterruptRelayQueue(NULL, gspEvent, 0x1, &gspSharedMemHandle, &gfxThreadID);
svcMapMemoryBlock(gspSharedMemHandle, (u32)gfxSharedMemory, 0x3, 0x10000000); svcMapMemoryBlock(gspSharedMemHandle, (u32)gfxSharedMemory, 0x3, 0x10000000);
//map GSP heap
svcControlMemory((u32*)&gspHeap, 0x0, 0x0, __gsp_heap_size, 0x10003, 0x3);
// default gspHeap configuration : // default gspHeap configuration :
// topleft1 0x00000000-0x00046500 // topleft1 0x00000000-0x00046500
// topleft2 0x00046500-0x0008CA00 // topleft2 0x00046500-0x0008CA00
@ -102,12 +81,12 @@ void gfxInit()
// topright1 0x000FD200-0x00143700 // topright1 0x000FD200-0x00143700
// topright2 0x00143700-0x00189C00 // topright2 0x00143700-0x00189C00
gfxTopLeftFramebuffers[0]=gfxAllocLinear(0x46500); gfxTopLeftFramebuffers[0]=linearAlloc(0x46500);
gfxTopLeftFramebuffers[1]=gfxAllocLinear(0x46500); gfxTopLeftFramebuffers[1]=linearAlloc(0x46500);
gfxBottomFramebuffers[0]=gfxAllocLinear(0x38400); gfxBottomFramebuffers[0]=linearAlloc(0x38400);
gfxBottomFramebuffers[1]=gfxAllocLinear(0x38400); gfxBottomFramebuffers[1]=linearAlloc(0x38400);
gfxTopRightFramebuffers[0]=gfxAllocLinear(0x46500); gfxTopRightFramebuffers[0]=linearAlloc(0x46500);
gfxTopRightFramebuffers[1]=gfxAllocLinear(0x46500); gfxTopRightFramebuffers[1]=linearAlloc(0x46500);
enable3d=false; enable3d=false;
//initialize framebuffer info structures //initialize framebuffer info structures
@ -129,8 +108,13 @@ void gfxExit()
// Exit event handler // Exit event handler
gspExitEventHandler(); gspExitEventHandler();
//free GSP heap // Free framebuffers (let's pretend linearFree is actually implemented...)
svcControlMemory((u32*)&gspHeap, (u32)gspHeap, 0x0, __gsp_heap_size, MEMOP_FREE, 0x0); linearFree(gfxTopRightFramebuffers[1]);
linearFree(gfxTopRightFramebuffers[0]);
linearFree(gfxBottomFramebuffers[1]);
linearFree(gfxBottomFramebuffers[0]);
linearFree(gfxTopLeftFramebuffers[1]);
linearFree(gfxTopLeftFramebuffers[0]);
//unmap GSP shared mem //unmap GSP shared mem
svcUnmapMemoryBlock(gspSharedMemHandle, 0x10002000); svcUnmapMemoryBlock(gspSharedMemHandle, 0x10002000);

View File

@ -6,10 +6,11 @@
int __system_argc; int __system_argc;
char** __system_argv; char** __system_argv;
void (*__system_retAddr)(void); void (*__system_retAddr)(void);
u32 __linear_heap;
// Data from _prm structure // Data from _prm structure
extern void* __service_ptr; // used to detect if we're run from a homebrew launcher 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; extern const char* __system_arglist;
// newlib definitions we need // newlib definitions we need
@ -27,7 +28,10 @@ void __attribute__((noreturn)) __ctru_exit(int rc)
// TODO: APT exit goes here // 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); svcControlMemory(&heapBase, heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0);
// Jump to the loader if it provided a callback // Jump to the loader if it provided a callback
@ -48,6 +52,9 @@ void initSystem(void (*retAddr)(void))
heapBase = 0x08000000; heapBase = 0x08000000;
svcControlMemory(&heapBase, heapBase, 0x0, __heap_size, MEMOP_ALLOC, 0x3); 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 // Set up newlib heap
fake_heap_start = (char*)heapBase; fake_heap_start = (char*)heapBase;
fake_heap_end = fake_heap_start + __heap_size; fake_heap_end = fake_heap_start + __heap_size;

32
libctru/source/linear.c Normal file
View File

@ -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
}

View File

@ -358,7 +358,7 @@ Result GSPGPU_SubmitGxCommand(u32* sharedGspCmdBuf, u32 gxCommand[0x8], Handle*
svcClearEvent(gspEvent); svcClearEvent(gspEvent);
u32 cmdBufHeader; 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 commandIndex=cmdBufHeader&0xFF;
u8 totalCommands=(cmdBufHeader>>8)&0xFF; u8 totalCommands=(cmdBufHeader>>8)&0xFF;
@ -370,17 +370,17 @@ Result GSPGPU_SubmitGxCommand(u32* sharedGspCmdBuf, u32 gxCommand[0x8], Handle*
memcpy(dst, gxCommand, 0x20); memcpy(dst, gxCommand, 0x20);
u32 mcrVal=0x0; 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++; totalCommands++;
cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|(((u32)totalCommands)<<8); cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|(((u32)totalCommands)<<8);
while(1) while(1)
{ {
u32 strexResult; 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; 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; totalCommands=((cmdBufHeader&0xFF00)>>8)+1;
cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|((totalCommands<<8)&0xFF00); cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|((totalCommands<<8)&0xFF00);
} }