1 /*---------------------------------------------------------------------------*
2   Project:     MEM library
3   File:        exp-1.c
4   Programmers: Takano Makoto
5 
6   Copyright 2005 Nintendo. All rights reserved.
7 
8   These coded instructions, statements, and computer programs contain
9   proprietary information of Nintendo of America Inc. and/or Nintendo
10   Company Ltd., and are protected by Federal copyright law.  They may
11   not be disclosed to third parties or copied or duplicated in any form,
12   in whole or in part, without the prior written consent of Nintendo.
13  *---------------------------------------------------------------------------*/
14 
15 /*---------------------------------------------------------------------------*
16   Note:         a demo for using the expansion heap
17 
18         1. An expansion heap is created using statically allocated memory.
19         2. Memory is allocated from both the front and rear of the heap.
20         3. The group ID is changed to 1 and more memory is allocated.
21         4. The visitor function is used to get the size of the allocated memory taken from the heap's rear.
22         5. Using the function visitor, all of the memory for group ID 1 is released, and the size of the released memory is calculated.
23 
24         6. Destroys the expansion heap.
25  *---------------------------------------------------------------------------*/
26 
27 #include <revolution/mem.h>
28 #include <string.h>
29 
30 // Outputs the heap status for non-debug builds.
31 static void     ReportExpHeap( MEMHeapHandle  heap );
32 
33 #define HEAP_BUF_ELEMENT_NUM    (4096 / sizeof(u32))
34 
35 static u32 sHeapBuf[ HEAP_BUF_ELEMENT_NUM ];
36 
37 /*
38     The structure that holds the group ID and the total size.
39     Used to specify parameters when calling the visitor function.
40  */
41 typedef struct
42 {
43     u16     groupID;    // Group ID specification
44     u16     padding;    // Not used
45     u32     size;       // Data size storage region
46 } TGroupParam;
47 
48 
49 /*---------------------------------------------------------------------------*
50   Name:         GetTailSizeVisitorFunc
51 
52   Description:  A Visitor function that gets total size of the allocated memory from the end of the heap.
53 
54 
55   Arguments:    memBlock:	the memory block
56                 heap: 		expansion heap handle
57                 userParam: 	call parameter for the visitor function
58                             Gets the total memory size.
59 
60   Returns:      None.
61  *---------------------------------------------------------------------------*/
62 static void
GetTailSizeVisitorFunc(void * memBlock,MEMHeapHandle heap,u32 userParam)63 GetTailSizeVisitorFunc(
64     void*               memBlock,
65     MEMHeapHandle       heap,
66     u32                 userParam
67 )
68 {
69 #pragma unused( heap )
70     // Performs process for memory allocated from the rear of the heap.
71     if ( MEMGetAllocDirForMBlockExpHeap(memBlock) == MEM_EXPHEAP_ALLOC_MODE_NEAR )
72     {
73         *(u32*)userParam += MEMGetSizeForMBlockExpHeap(memBlock);
74     }
75 }
76 
77 
78 /*---------------------------------------------------------------------------*
79   Name:         FreeGroupVisitorFunc
80 
81   Description:  Visitor function that specifies a group to release the heap.
82 
83   Arguments:    memBlock:   	The memory block
84                 heap: 		Handle for expanded heap
85                 userParam: 	call parameter for the visitor function
86                             pointer to the TGroupParam format data
87 
88   Returns:      None.
89  *---------------------------------------------------------------------------*/
90 static void
FreeGroupVisitorFunc(void * memBlock,MEMHeapHandle heap,u32 userParam)91 FreeGroupVisitorFunc(
92     void*             memBlock,
93     MEMHeapHandle     heap,
94     u32               userParam
95 )
96 {
97     TGroupParam* pGrpParam = (TGroupParam*)userParam;
98 
99     // Performs process for memory whose group ID is the same as the argument ID.
100     if ( MEMGetGroupIDForMBlockExpHeap(memBlock) == pGrpParam->groupID )
101     {
102         // Adds the size
103         pGrpParam->size += MEMGetSizeForMBlockExpHeap(memBlock);
104         // Releases the heap
105         MEMFreeToExpHeap( heap, memBlock );
106     }
107 }
108 
109 
110 
111 /*---------------------------------------------------------------------------*
112   Name:         SampleExpHeap
113 
114   Description:  The sample of the expanded heap.
115 
116   Arguments:    heapAddress: 	The starting address of the memory allocated to the heap.
117                 heapSize: 	The size of the memory allocated to the heap.
118 
119   Returns:      None.
120  *---------------------------------------------------------------------------*/
121 static void
SampleExpHeap(void * heapAddress,u32 heapSize)122 SampleExpHeap(
123     void*   heapAddress,
124     u32     heapSize
125 )
126 {
127     void* pMBlocks[4];
128 
129     // Creation of the expanded heap
130     MEMHeapHandle hExpHeap = MEMCreateExpHeap( heapAddress, heapSize );
131 
132     // Normal allocation of the memory blocks
133     pMBlocks[0] = MEMAllocFromExpHeap( hExpHeap, 100 );
134     ASSERT( pMBlocks[0] != NULL );
135 
136     // Allocates from the end of the heap region. The default alignment value is 4.
137     pMBlocks[2] = MEMAllocFromExpHeapEx( hExpHeap, 100, -MEM_HEAP_DEFAULT_ALIGNMENT );
138     ASSERT( pMBlocks[2] != NULL );
139 
140     // Changes the group ID to 1. group ID is 0 when the heap is created.
141     (void)MEMSetGroupIDForExpHeap( hExpHeap, 1 );
142 
143     // Allocates the memory blocks. The alignment is 16.
144     pMBlocks[1] = MEMAllocFromExpHeapEx( hExpHeap, 200, 16 );
145     ASSERT( pMBlocks[1] != NULL );
146 
147     // Allocates from the end of the heap region. The alignment is 16.
148     pMBlocks[3] = MEMAllocFromExpHeapEx( hExpHeap, 200, -16 );
149     ASSERT( pMBlocks[3] != NULL );
150 
151     // Dump output of heap data
152 #ifdef _DEBUG       // MEMDumpHeap is only valid in debug builds.
153     MEMDumpHeap( hExpHeap );
154 #else
155     ReportExpHeap( hExpHeap );
156 #endif
157     // Expansion of the memory block from 200 to 300
158     if ( MEMResizeForMBlockExpHeap( hExpHeap, pMBlocks[1], 300 ) == 0 )
159     {
160         // Reallocates if there is a failure in memory block resizing.
161         void* tmp;
162         tmp = MEMAllocFromExpHeapEx( hExpHeap, 300, 16 );
163         ASSERT( tmp != NULL );
164         memcpy( tmp, pMBlocks[1], 200 );
165         MEMFreeToExpHeap( hExpHeap, pMBlocks[1] );
166         pMBlocks[1] = tmp;
167     }
168 
169     // Gets the total size of the memory block allocated from the rear of the expansion heap.
170     {
171         u32 size = 0;
172 
173         MEMVisitAllocatedForExpHeap(
174             hExpHeap,               // The heap handle
175             GetTailSizeVisitorFunc, // visitor function
176             (u32)&size );           // Region for getting the memory size
177         OSReport("size of allocated from rear = %ld\n", size );
178     }
179 
180     // Releases the memory whose group ID is 1.
181     {
182         TGroupParam grpParam;
183         grpParam.groupID = 1;
184         grpParam.size    = 0;
185 
186         // Processes FreeGroupVisitorFunc for all allocated regions.
187         MEMVisitAllocatedForExpHeap(
188             hExpHeap,               // The heap handle
189             FreeGroupVisitorFunc,   // visitor function
190             (u32)&grpParam );       // User parameters
191 
192         OSReport("[free exp heap] group 1 size %ld\n", grpParam.size );
193     }
194 
195     // Dump output of heap data
196 #ifdef _DEBUG       // MEMDumpHeap is only valid in debug builds.
197     MEMDumpHeap( hExpHeap );
198 #else
199     ReportExpHeap( hExpHeap );
200 #endif
201 
202     // Destroy the expanded heap
203     (void)MEMDestroyExpHeap( hExpHeap );
204 }
205 
206 
207 
208 /*---------------------------------------------------------------------------*
209   Name:         main
210  *---------------------------------------------------------------------------*/
211 void
main(void)212 main( void )
213 {
214     OSInit();
215 
216     SampleExpHeap( sHeapBuf, sizeof sHeapBuf );
217 
218     while(1) {}
219 }
220 
221 
222 
223 
224 
225 /* ------------------------------------------------------------------------
226  * This is the code for outputting the heap state as a sample for non-debug build.
227  *
228  * Normally, more detailed output can be derived during a debug build by using the MEMDumpHeap function.
229  */
230 #ifndef _DEBUG
231 
232 /*
233     Structure that gets information for reports.
234     Used to specify parameters when calling the visitor function.
235  */
236 typedef struct
237 {
238     u32     size;       // Data size storage region
239     u32     cnt;        // Number of memory blocks used
240 } TReportParam;
241 
242 
243 /*---------------------------------------------------------------------------*
244   Name:         ReportVisitorFunc
245 
246   Description:  A Visitor function for outputting the heap state.
247 
248   Arguments:    memBlock:   	The memory block
249                 heap: 		Handle for expanded heap
250                 userParam: 	call parameter for the visitor function
251                             Gets the total memory size.
252 
253   Returns:      None.
254  *---------------------------------------------------------------------------*/
255 static void
ReportVisitorFunc(void * memBlock,MEMHeapHandle heap,u32 userParam)256 ReportVisitorFunc(
257     void*           memBlock,
258     MEMHeapHandle   heap,
259     u32             userParam
260 )
261 {
262 #pragma unused( heap )
263     TReportParam* pParam   = (TReportParam*)userParam;
264     u16           allocDir = MEMGetAllocDirForMBlockExpHeap( memBlock );
265     u16           groupId  = MEMGetGroupIDForMBlockExpHeap ( memBlock );
266     u32           size     = MEMGetSizeForMBlockExpHeap    ( memBlock );
267 
268     pParam->size += MEMGetSizeForMBlockExpHeap( memBlock );
269     pParam->cnt++;
270 
271     OSReport("    %s %08x: %8d  %3d\n",
272         allocDir == MEM_EXPHEAP_ALLOC_DIR_REAR ? " rear" : "front",
273         (u32)memBlock,
274         size,
275         groupId
276     );
277 }
278 
279 /*---------------------------------------------------------------------------*
280   Name:         ReportExpHeap
281 
282   Description:  Outputs the state of the expanded heap.
283                 The MEMDumpHeap will provide detailed output for debug builds.
284 
285   Arguments:    heap:    heap handle
286 
287   Returns:      None.
288  *---------------------------------------------------------------------------*/
289 static void
ReportExpHeap(MEMHeapHandle heap)290 ReportExpHeap( MEMHeapHandle  heap )
291 {
292     TReportParam param = { 0, 0 };
293 
294     OSReport("[OS Foundation Exp Heap]\n");
295 
296     OSReport("    whole [%p - %p)\n", MEMGetHeapStartAddress( heap ), MEMGetHeapEndAddress( heap ) );
297     OSReport("     attr  address:   size    gid\n");   // Header line
298 
299     MEMVisitAllocatedForExpHeap(
300         heap,                       // The heap handle
301         ReportVisitorFunc,          // visitor function
302         (u32)&param                 // User parameters
303     );
304 
305     OSReport("\n");
306 
307     {
308         u32 usedSize  = param.size;
309         u32 usedCnt   = param.cnt;
310 
311         OSReport("    %d bytes allocated (U:%d)\n",
312                            usedSize, usedCnt);
313     }
314     OSReport("\n");
315 }
316 
317 #endif
318 
319