/*---------------------------------------------------------------------------* Project: MEM library File: frm-1.c Programmers: Makoto Takano Copyright 2005 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. *---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------* Note: Demo using frame heap. 1. The demo creates a frame heap within the expanded heap, once the expanded heap is created. 2. Allocates memory from the front and back of the frame heap, and saves using tags marked 'FRST', 'SCND', or 'THRD' for the state. 3. Again, it allocates memory from the front and back of the frame heap and dumps the statuses. 4. Dumps the statuses while restoring the states with the FreeByStateToFrmHeap function. 5. Frees all memory allocated from the back. 6. Reduces the frame heap's memory capacity using the AdjustFrmHeap function. 7. Returns memory to the parent heap's expanded heap. The amount returned is the amount that the frame heap was reduced by. 8. Destroys the heap and terminates. *---------------------------------------------------------------------------*/ #include #include // Outputs the heap status for non-debug builds. static void ReportFrmHeap( MEMHeapHandle heap ); static void ReportExpHeap( MEMHeapHandle heap ); /*---------------------------------------------------------------------------* Name: SampleFrameHeap Description: The sample of the frame heap. Arguments: heapAddress: The starting address of the memory allocated to the heap. heapSize: The size of the memory allocated to the heap. Returns: None. *---------------------------------------------------------------------------*/ static void SampleFrameHeap( void* heapAddress, u32 heapSize) { void* pExpMBlock; void* pMBlocks[8]; MEMHeapHandle hExpHeap; MEMHeapHandle hFrmHeap; u32 frmHeapSize; // -------------------------------------------------------- // Makes the frame heap inside the expanded heap once the expanded heap is created. // -------------------------------------------------------- { // Creation of the expanded heap hExpHeap = MEMCreateExpHeap( heapAddress, heapSize ); // Creation of a memory block that appropriates the entire allocatable size pExpMBlock = MEMAllocFromExpHeap( hExpHeap, MEMGetAllocatableSizeForExpHeap( hExpHeap ) ); ASSERT( pExpMBlock != NULL ); // Creation of the frame heap hFrmHeap = MEMCreateFrmHeap( pExpMBlock, MEMGetSizeForMBlockExpHeap( pExpMBlock ) ); } // -------------------------------------------------------- // Conduct the memory block allocation, state save, and restoration // -------------------------------------------------------- { // Allocation of the normal memory blocks pMBlocks[0] = MEMAllocFromFrmHeap( hFrmHeap, 100 ); ASSERT( pMBlocks[0] != NULL ); // Allocates from the end of the heap region. The default alignment value is 4. pMBlocks[1] = MEMAllocFromFrmHeapEx( hFrmHeap, 100, -MEM_HEAP_DEFAULT_ALIGNMENT ); ASSERT( pMBlocks[1] != NULL ); // Save the memory block allocation state. The tag is 'FRST'. (void)MEMRecordStateForFrmHeap( hFrmHeap, 'FRST' ); // Allocate from the beginning and end of the memory block. The alignment is 8. pMBlocks[2] = MEMAllocFromFrmHeapEx( hFrmHeap, 200, 8 ); ASSERT( pMBlocks[2] != NULL ); pMBlocks[3] = MEMAllocFromFrmHeapEx( hFrmHeap, 200, -8 ); ASSERT( pMBlocks[3] != NULL ); // Save the memory block allocation state. The tag is 'SCND'. (void)MEMRecordStateForFrmHeap( hFrmHeap, 'SCND' ); // Allocate from the beginning and end of the memory block. The alignment is 16. pMBlocks[4] = MEMAllocFromFrmHeapEx( hFrmHeap, 300, 16 ); ASSERT( pMBlocks[4] != NULL ); pMBlocks[5] = MEMAllocFromFrmHeapEx( hFrmHeap, 300, -16 ); ASSERT( pMBlocks[5] != NULL ); // Save the memory block allocation state. The tag is 'THRD' (void)MEMRecordStateForFrmHeap( hFrmHeap, 'THRD' ); // Allocate from the beginning and end of the memory block. The alignment is 32. pMBlocks[6] = MEMAllocFromFrmHeapEx( hFrmHeap, 300, 32 ); ASSERT( pMBlocks[6] != NULL ); pMBlocks[7] = MEMAllocFromFrmHeapEx( hFrmHeap, 300, -32 ); ASSERT( pMBlocks[7] != NULL ); #ifdef _DEBUG MEMDumpHeap( hFrmHeap ); #else ReportFrmHeap( hFrmHeap ); #endif // Specify a tag and restore the state (void)MEMFreeByStateToFrmHeap( hFrmHeap, 'SCND' ); #ifdef _DEBUG MEMDumpHeap( hFrmHeap ); #else ReportFrmHeap( hFrmHeap ); #endif // Restore the state without specifying a tag (restore to the 'FRST' state) (void)MEMFreeByStateToFrmHeap( hFrmHeap, 0 ); #ifdef _DEBUG MEMDumpHeap( hFrmHeap ); #else ReportFrmHeap( hFrmHeap ); #endif } // -------------------------------------------------------- // Free the memory block allocated from the end of the heap region, then compress the frame heap region. // -------------------------------------------------------- { // Free the memory block allocated from the end of the heap (void)MEMFreeToFrmHeap( hFrmHeap, MEM_FRMHEAP_FREE_TAIL ); // Compress the frame heap frmHeapSize = MEMAdjustFrmHeap( hFrmHeap ); // Compress the memory block of the expanded heap along with the compression of the frame heap (void)MEMResizeForMBlockExpHeap( hExpHeap, pExpMBlock, frmHeapSize ); // Get the heap that holds the memory block, and dump it. // (Frame heap: the contents of hFrmHeap are displayed)) #ifdef _DEBUG MEMDumpHeap( MEMFindContainHeap(pMBlocks[0]) ); // Dump the expanded heap MEMDumpHeap( hExpHeap ); #else if ( MEMIsFrmHeap( MEMFindContainHeap(pMBlocks[0]) ) ) { ReportFrmHeap( MEMFindContainHeap(pMBlocks[0]) ); } ReportExpHeap( hExpHeap ); #endif } // -------------------------------------------------------- // Clean up // -------------------------------------------------------- { // Get rid of the frame heap void* addr = MEMDestroyFrmHeap( hFrmHeap ); MEMFreeToExpHeap( hExpHeap, addr ); // Gets rid of the expanded heap (void)MEMDestroyExpHeap( hExpHeap ); } } /*---------------------------------------------------------------------------* Name: main *---------------------------------------------------------------------------*/ void main( void ) { void *arenaLo, *arenaHi; OSInit(); arenaLo = OSGetArenaLo(); arenaHi = OSGetArenaHi(); SampleFrameHeap( arenaLo, (u32)arenaHi - (u32) arenaLo ); while(1) {} } /* ------------------------------------------------------------------------ * This is the code for outputting the heap state as a sample * during non-debug builds. * Normally, more detailed output can be derived during a debug build by using the MEMDumpHeap function. */ #ifndef _DEBUG static void ReportFrmHeap( MEMHeapHandle heap ) { u32 allocatableSize = MEMGetAllocatableSizeForFrmHeap( heap ); u32 totalSize = (u32)MEMGetHeapTotalUsableSize( heap ); u32 usedSize = totalSize - allocatableSize; OSReport("[OS Foundation Frame Heap]\n"); OSReport(" whole [%p - %p)\n", MEMGetHeapStartAddress( heap ), MEMGetHeapEndAddress( heap ) ); OSReport(" %d / %d bytes (%6.2f%%) used\n", usedSize, totalSize, 100.0 * usedSize / totalSize ); OSReport("\n"); } /* structure that gets information for reports. Used to specify parameters when calling the visitor function. */ typedef struct { u32 size; // data size storage region u32 cnt; // number of memory blocks used } TReportParam; /*---------------------------------------------------------------------------* Name: ReportVisitorFunc Description: A Visitor function for outputting the heap state. Arguments: memBlock: The memory block heap : Handle for expanded heap userParam: call parameter for the visitor function gets the total memory size Returns: None. *---------------------------------------------------------------------------*/ static void ReportVisitorFunc( void* memBlock, MEMHeapHandle heap, u32 userParam ) { #pragma unused( heap ) TReportParam* pParam = (TReportParam*)userParam; u16 allocDir = MEMGetAllocDirForMBlockExpHeap( memBlock ); u16 groupId = MEMGetGroupIDForMBlockExpHeap ( memBlock ); u32 size = MEMGetSizeForMBlockExpHeap ( memBlock ); pParam->size += MEMGetSizeForMBlockExpHeap( memBlock ); pParam->cnt++; OSReport(" %s %08x: %8d %3d\n", allocDir == MEM_EXPHEAP_ALLOC_DIR_REAR ? " rear" : "front", (u32)memBlock, size, groupId ); } /*---------------------------------------------------------------------------* Name: ReportExpHeap Description: Outputs the state of the expanded heap. The MEMDumpHeap will provide detailed output for debug builds. Arguments: heap heap handle Returns: None. *---------------------------------------------------------------------------*/ static void ReportExpHeap( MEMHeapHandle heap ) { TReportParam param = { 0, 0 }; OSReport("[OS Foundation Exp Heap]\n"); OSReport(" whole [%p - %p)\n", MEMGetHeapStartAddress( heap ), MEMGetHeapEndAddress( heap ) ); OSReport(" attr address: size gid\n"); // Header line MEMVisitAllocatedForExpHeap( heap, // The heap handle ReportVisitorFunc, // function visitor (u32)¶m // User parameters ); OSReport("\n"); { u32 usedSize = param.size; u32 usedCnt = param.cnt; OSReport(" %d bytes allocated (U:%d)\n", usedSize, usedCnt); } OSReport("\n"); } #endif