/*---------------------------------------------------------------------------* Project: MEM library File: exp-1.c Programmers: Takano Makoto 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: a demo for using the expansion heap 1. An expansion heap is created using statically allocated memory. 2. Memory is allocated from both the front and rear of the heap. 3. The group ID is changed to 1 and more memory is allocated. 4. The visitor function is used to get the size of the allocated memory taken from the heap's rear. 5. Using the function visitor, all of the memory for group ID 1 is released, and the size of the released memory is calculated. 6. Destroys the expansion heap. *---------------------------------------------------------------------------*/ #include #include // Outputs the heap status for non-debug builds. static void ReportExpHeap( MEMHeapHandle heap ); #define HEAP_BUF_ELEMENT_NUM (4096 / sizeof(u32)) static u32 sHeapBuf[ HEAP_BUF_ELEMENT_NUM ]; /* The structure that holds the group ID and the total size. Used to specify parameters when calling the visitor function. */ typedef struct { u16 groupID; // Group ID specification u16 padding; // Not used u32 size; // Data size storage region } TGroupParam; /*---------------------------------------------------------------------------* Name: GetTailSizeVisitorFunc Description: A Visitor function that gets total size of the allocated memory from the end of the heap. Arguments: memBlock: the memory block heap: expansion heap handle userParam: call parameter for the visitor function Gets the total memory size. Returns: None. *---------------------------------------------------------------------------*/ static void GetTailSizeVisitorFunc( void* memBlock, MEMHeapHandle heap, u32 userParam ) { #pragma unused( heap ) // Performs process for memory allocated from the rear of the heap. if ( MEMGetAllocDirForMBlockExpHeap(memBlock) == MEM_EXPHEAP_ALLOC_MODE_NEAR ) { *(u32*)userParam += MEMGetSizeForMBlockExpHeap(memBlock); } } /*---------------------------------------------------------------------------* Name: FreeGroupVisitorFunc Description: Visitor function that specifies a group to release the heap. Arguments: memBlock: The memory block heap: Handle for expanded heap userParam: call parameter for the visitor function pointer to the TGroupParam format data Returns: None. *---------------------------------------------------------------------------*/ static void FreeGroupVisitorFunc( void* memBlock, MEMHeapHandle heap, u32 userParam ) { TGroupParam* pGrpParam = (TGroupParam*)userParam; // Performs process for memory whose group ID is the same as the argument ID. if ( MEMGetGroupIDForMBlockExpHeap(memBlock) == pGrpParam->groupID ) { // Adds the size pGrpParam->size += MEMGetSizeForMBlockExpHeap(memBlock); // Releases the heap MEMFreeToExpHeap( heap, memBlock ); } } /*---------------------------------------------------------------------------* Name: SampleExpHeap Description: The sample of the expanded 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 SampleExpHeap( void* heapAddress, u32 heapSize ) { void* pMBlocks[4]; // Creation of the expanded heap MEMHeapHandle hExpHeap = MEMCreateExpHeap( heapAddress, heapSize ); // Normal allocation of the memory blocks pMBlocks[0] = MEMAllocFromExpHeap( hExpHeap, 100 ); ASSERT( pMBlocks[0] != NULL ); // Allocates from the end of the heap region. The default alignment value is 4. pMBlocks[2] = MEMAllocFromExpHeapEx( hExpHeap, 100, -MEM_HEAP_DEFAULT_ALIGNMENT ); ASSERT( pMBlocks[2] != NULL ); // Changes the group ID to 1. group ID is 0 when the heap is created. (void)MEMSetGroupIDForExpHeap( hExpHeap, 1 ); // Allocates the memory blocks. The alignment is 16. pMBlocks[1] = MEMAllocFromExpHeapEx( hExpHeap, 200, 16 ); ASSERT( pMBlocks[1] != NULL ); // Allocates from the end of the heap region. The alignment is 16. pMBlocks[3] = MEMAllocFromExpHeapEx( hExpHeap, 200, -16 ); ASSERT( pMBlocks[3] != NULL ); // Dump output of heap data #ifdef _DEBUG // MEMDumpHeap is only valid in debug builds. MEMDumpHeap( hExpHeap ); #else ReportExpHeap( hExpHeap ); #endif // Expansion of the memory block from 200 to 300 if ( MEMResizeForMBlockExpHeap( hExpHeap, pMBlocks[1], 300 ) == 0 ) { // Reallocates if there is a failure in memory block resizing. void* tmp; tmp = MEMAllocFromExpHeapEx( hExpHeap, 300, 16 ); ASSERT( tmp != NULL ); memcpy( tmp, pMBlocks[1], 200 ); MEMFreeToExpHeap( hExpHeap, pMBlocks[1] ); pMBlocks[1] = tmp; } // Gets the total size of the memory block allocated from the rear of the expansion heap. { u32 size = 0; MEMVisitAllocatedForExpHeap( hExpHeap, // The heap handle GetTailSizeVisitorFunc, // visitor function (u32)&size ); // Region for getting the memory size OSReport("size of allocated from rear = %ld\n", size ); } // Releases the memory whose group ID is 1. { TGroupParam grpParam; grpParam.groupID = 1; grpParam.size = 0; // Processes FreeGroupVisitorFunc for all allocated regions. MEMVisitAllocatedForExpHeap( hExpHeap, // The heap handle FreeGroupVisitorFunc, // visitor function (u32)&grpParam ); // User parameters OSReport("[free exp heap] group 1 size %ld\n", grpParam.size ); } // Dump output of heap data #ifdef _DEBUG // MEMDumpHeap is only valid in debug builds. MEMDumpHeap( hExpHeap ); #else ReportExpHeap( hExpHeap ); #endif // Destroy the expanded heap (void)MEMDestroyExpHeap( hExpHeap ); } /*---------------------------------------------------------------------------* Name: main *---------------------------------------------------------------------------*/ void main( void ) { OSInit(); SampleExpHeap( sHeapBuf, sizeof sHeapBuf ); while(1) {} } /* ------------------------------------------------------------------------ * This is the code for outputting the heap state as a sample for non-debug build. * * Normally, more detailed output can be derived during a debug build by using the MEMDumpHeap function. */ #ifndef _DEBUG /* 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, // visitor function (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