diff --git a/samples/custom_default_heap/CMakeLists.txt b/samples/custom_default_heap/CMakeLists.txt new file mode 100644 index 00000000..9202bbf7 --- /dev/null +++ b/samples/custom_default_heap/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.2) +project(custom_default_heap C) +include("${WUT_ROOT}/share/wut.cmake" REQUIRED) + +add_executable(custom_default_heap + main.c) + +target_link_libraries(custom_default_heap + whb + proc_ui + sysapp) + +wut_add_exports(custom_default_heap + exports.def) + +wut_create_rpx(custom_default_heap.rpx + custom_default_heap) + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/custom_default_heap.rpl" + DESTINATION "${CMAKE_INSTALL_PREFIX}") diff --git a/samples/custom_default_heap/exports.def b/samples/custom_default_heap/exports.def new file mode 100644 index 00000000..00f80fa1 --- /dev/null +++ b/samples/custom_default_heap/exports.def @@ -0,0 +1,2 @@ +:TEXT +__preinit_user diff --git a/samples/custom_default_heap/main.c b/samples/custom_default_heap/main.c new file mode 100644 index 00000000..6761752c --- /dev/null +++ b/samples/custom_default_heap/main.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static MEMHeapHandle sCustomHeap = NULL; +static uint32_t sCustomHeapAddr = 0; +static uint32_t sCustomHeapSize = 0; + +static void * +CustomAllocFromDefaultHeap(uint32_t size) +{ + return MEMAllocFromExpHeapEx(sCustomHeap, size, 4); +} + +static void * +CustomAllocFromDefaultHeapEx(uint32_t size, + int32_t alignment) +{ + return MEMAllocFromExpHeapEx(sCustomHeap, size, alignment); +} + +static void +CustomFreeToDefaultHeap(void* ptr) +{ + MEMFreeToExpHeap(sCustomHeap, ptr); +} + +static OSDynLoad_Error +CustomDynLoadAlloc(int32_t size, + int32_t align, + void **outAddr) +{ + if (!outAddr) { + return OS_DYNLOAD_INVALID_ALLOCATOR_PTR; + } + + if (align >= 0 && align < 4) { + align = 4; + } else if (align < 0 && align > -4) { + align = -4; + } + + if (!(*outAddr = MEMAllocFromDefaultHeapEx(size, align))) { + return OS_DYNLOAD_OUT_OF_MEMORY; + } + + return OS_DYNLOAD_OK; +} + +static void +CustomDynLoadFree(void *addr) +{ + MEMFreeToDefaultHeap(addr); +} + +void +__preinit_user(MEMHeapHandle *mem1, + MEMHeapHandle *foreground, + MEMHeapHandle *mem2) +{ + uint32_t addr, size; + + MEMAllocFromDefaultHeap = CustomAllocFromDefaultHeap; + MEMAllocFromDefaultHeapEx = CustomAllocFromDefaultHeapEx; + MEMFreeToDefaultHeap = CustomFreeToDefaultHeap; + + if (OSGetForegroundBucket(NULL, NULL)) { + OSGetMemBound(OS_MEM1, &addr, &size); + *mem1 = MEMCreateFrmHeapEx((void *)addr, size, 0); + + OSGetForegroundBucketFreeArea(&addr, &size); + *foreground = MEMCreateFrmHeapEx((void *)addr, size, 0); + } + + OSGetMemBound(OS_MEM2, &addr, &size); + sCustomHeap = MEMCreateExpHeapEx((void *)addr, size, MEM_HEAP_FLAG_USE_LOCK); + sCustomHeapAddr = addr; + sCustomHeapSize = size; + *mem2 = sCustomHeap; + + OSDynLoad_SetAllocator(CustomDynLoadAlloc, CustomDynLoadFree); + OSDynLoad_SetTLSAllocator(CustomDynLoadAlloc, CustomDynLoadFree); +} + + +void +heapBlockVisitor(void *block, + MEMHeapHandle heap, + void *context) +{ + WHBLogPrintf("Block 0x%08X, size 0x%08X, group 0x%04X, direction %d", + (uint32_t)block, + MEMGetSizeForMBlockExpHeap(block), + MEMGetGroupIDForMBlockExpHeap(block), + MEMGetAllocDirForMBlockExpHeap(block)); +} + +int +main(int argc, char **argv) +{ + WHBProcInit(); + WHBLogConsoleInit(); + WHBLogPrintf("sCustomHeapAddr = 0x%08X", sCustomHeapAddr); + WHBLogPrintf("sCustomHeapSize = 0x%08X", sCustomHeapSize); + + WHBLogPrintf("MEMGetTotalFreeSizeForExpHeap = 0x%08X", MEMGetTotalFreeSizeForExpHeap(sCustomHeap)); + WHBLogPrintf("MEMGetAllocatableSizeForExpHeapEx = 0x%08X", MEMGetAllocatableSizeForExpHeapEx(sCustomHeap, 4)); + + MEMVisitAllocatedForExpHeap(sCustomHeap, heapBlockVisitor, NULL); + + while(WHBProcIsRunning()) { + WHBLogConsoleDraw(); + OSSleepTicks(OSMillisecondsToTicks(100)); + } + + WHBLogConsoleFree(); + WHBProcShutdown(); + return 0; +}