1 /*---------------------------------------------------------------------------*
2   Project:     MEM library
3   File:        frm-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:         Frame heap use demo.
17 
18         1. The demo creates a frame heap within the expanded heap, once the expanded heap is created.
19         2. Allocates memory from the front and back of the frame heap, and saves using tags marked 'FRST', 'SCND', or 'THRD' for the state.
20 
21         3. Again, it allocates memory from the front and back of the frame heap and dumps the statuses.
22         4. Dumps the statuses while restoring the states with the FreeByStateToFrmHeap function.
23         5. Frees all memory allocated from the back.
24         6. Reduces the frame heap's memory capacity using the AdjustFrmHeap function.
25         7. Returns memory to the parent heap's expanded heap. The amount returned is the amount that the frame heap was reduced by.
26         8. Destroys the heap and terminates.
27  *---------------------------------------------------------------------------*/
28 
29 #include <revolution.h>
30 #include <revolution/mem.h>
31 
32 // Outputs the heap status for non-debug builds.
33 static void     ReportFrmHeap( MEMHeapHandle  heap );
34 static void     ReportExpHeap( MEMHeapHandle  heap );
35 
36 /*---------------------------------------------------------------------------*
37   Name:         SampleFrameHeap
38 
39   Description:  The sample of the frame heap.
40 
41   Arguments:    heapAddress:  The starting address of the memory allocated to the heap.
42                 heapSize:     The size of the memory allocated to the heap.
43 
44   Returns:      None.
45  *---------------------------------------------------------------------------*/
46 static void
SampleFrameHeap(void * heapAddress,u32 heapSize)47 SampleFrameHeap(
48     void*   heapAddress,
49     u32     heapSize)
50 {
51     void*               pExpMBlock;
52     void*               pMBlocks[8];
53     MEMHeapHandle       hExpHeap;
54     MEMHeapHandle       hFrmHeap;
55     u32                 frmHeapSize;
56 
57     // --------------------------------------------------------
58     // First create the expanded heap and then create the frame heap inside it.
59     // --------------------------------------------------------
60     {
61         // Creation of the expanded heap
62         hExpHeap = MEMCreateExpHeap( heapAddress, heapSize );
63 
64         // Creation of a memory block that appropriates the entire allocatable size
65         pExpMBlock = MEMAllocFromExpHeap(
66                         hExpHeap,
67                         MEMGetAllocatableSizeForExpHeap( hExpHeap ) );
68         ASSERT( pExpMBlock != NULL );
69 
70         // Creation of the frame heap
71         hFrmHeap = MEMCreateFrmHeap(
72                         pExpMBlock,
73                         MEMGetSizeForMBlockExpHeap( pExpMBlock ) );
74     }
75 
76     // --------------------------------------------------------
77     //  Conduct the memory block allocation, state save, and restoration
78     // --------------------------------------------------------
79     {
80         // Normal allocation of the memory blocks
81         pMBlocks[0] = MEMAllocFromFrmHeap( hFrmHeap, 100 );
82         ASSERT( pMBlocks[0] != NULL );
83 
84         // Allocates from the end of the heap region. The default alignment value is 4.
85         pMBlocks[1] = MEMAllocFromFrmHeapEx( hFrmHeap, 100, -MEM_HEAP_DEFAULT_ALIGNMENT );
86         ASSERT( pMBlocks[1] != NULL );
87 
88         // Save the memory block allocation state. The tag is 'FRST'.
89         (void)MEMRecordStateForFrmHeap( hFrmHeap, 'FRST' );
90 
91         // Allocate from the beginning and end of the memory block. The alignment is 8.
92         pMBlocks[2] = MEMAllocFromFrmHeapEx( hFrmHeap, 200,  8 );
93         ASSERT( pMBlocks[2] != NULL );
94         pMBlocks[3] = MEMAllocFromFrmHeapEx( hFrmHeap, 200, -8 );
95         ASSERT( pMBlocks[3] != NULL );
96 
97         // Save the memory block allocation state. The tag is 'SCND'.
98         (void)MEMRecordStateForFrmHeap( hFrmHeap, 'SCND' );
99 
100         // Allocate from the beginning and end of the memory block. The alignment is 16.
101         pMBlocks[4] = MEMAllocFromFrmHeapEx( hFrmHeap, 300,  16 );
102         ASSERT( pMBlocks[4] != NULL );
103         pMBlocks[5] = MEMAllocFromFrmHeapEx( hFrmHeap, 300, -16 );
104         ASSERT( pMBlocks[5] != NULL );
105 
106         // Save the memory block allocation state. The tag is 'THRD'
107         (void)MEMRecordStateForFrmHeap( hFrmHeap, 'THRD' );
108 
109         // Allocate from the beginning and end of the memory block. The alignment is 32.
110         pMBlocks[6] = MEMAllocFromFrmHeapEx( hFrmHeap, 300,  32 );
111         ASSERT( pMBlocks[6] != NULL );
112         pMBlocks[7] = MEMAllocFromFrmHeapEx( hFrmHeap, 300, -32 );
113         ASSERT( pMBlocks[7] != NULL );
114 
115 #ifdef _DEBUG
116         MEMDumpHeap( hFrmHeap );
117 #else
118         ReportFrmHeap( hFrmHeap );
119 #endif
120         // Specify a tag and restore the state
121         (void)MEMFreeByStateToFrmHeap( hFrmHeap, 'SCND' );
122 
123 #ifdef _DEBUG
124         MEMDumpHeap( hFrmHeap );
125 #else
126         ReportFrmHeap( hFrmHeap );
127 #endif
128 
129         // Restore the state without specifying a tag (restore to the 'FRST' state)
130         (void)MEMFreeByStateToFrmHeap( hFrmHeap, 0 );
131 
132 #ifdef _DEBUG
133         MEMDumpHeap( hFrmHeap );
134 #else
135         ReportFrmHeap( hFrmHeap );
136 #endif
137     }
138 
139     // --------------------------------------------------------
140     // Free the memory block allocated from the end of the heap region, then reduce the frame heap region.
141     // --------------------------------------------------------
142     {
143         // Free the memory block allocated from the end of the heap
144         (void)MEMFreeToFrmHeap( hFrmHeap, MEM_FRMHEAP_FREE_TAIL );
145 
146         // Reduce the frame heap
147         frmHeapSize = MEMAdjustFrmHeap( hFrmHeap );
148 
149         // Reduce the memory block of the expanded heap along with the reduction of the frame heap
150         (void)MEMResizeForMBlockExpHeap( hExpHeap, pExpMBlock, frmHeapSize );
151 
152         // Get the heap that holds the memory block, and dump it.
153         // (Frame heap: the contents of hFrmHeap are displayed))
154 #ifdef _DEBUG
155         MEMDumpHeap( MEMFindContainHeap(pMBlocks[0]) );
156         // Dump the expanded heap
157         MEMDumpHeap( hExpHeap );
158 #else
159         if ( MEMIsFrmHeap( MEMFindContainHeap(pMBlocks[0]) ) )
160         {
161             ReportFrmHeap( MEMFindContainHeap(pMBlocks[0]) );
162         }
163         ReportExpHeap( hExpHeap );
164 #endif
165     }
166 
167     // --------------------------------------------------------
168     //   Clean up
169     // --------------------------------------------------------
170     {
171         // Destroy the frame heap
172         void* addr = MEMDestroyFrmHeap( hFrmHeap );
173         MEMFreeToExpHeap( hExpHeap, addr );
174 
175         // Destroy the expanded heap
176         (void)MEMDestroyExpHeap( hExpHeap );
177     }
178 }
179 
180 
181 /*---------------------------------------------------------------------------*
182   Name:         main
183  *---------------------------------------------------------------------------*/
184 void
main(void)185 main( void )
186 {
187     void *arenaLo, *arenaHi;
188 
189     OSInit();
190     arenaLo = OSGetArenaLo();
191     arenaHi = OSGetArenaHi();
192 
193     SampleFrameHeap( arenaLo, (u32)arenaHi - (u32) arenaLo );
194 
195     while(1) {}
196 }
197 
198 
199 
200 
201 
202 /* ------------------------------------------------------------------------
203  * This is the code for outputting the heap state as a sample for non-debug build.
204  *
205  * Normally, more detailed output can be derived during a debug build by using the MEMDumpHeap function.
206  */
207 #ifndef _DEBUG
208 static void
ReportFrmHeap(MEMHeapHandle heap)209 ReportFrmHeap( MEMHeapHandle  heap )
210 {
211     u32 allocatableSize = MEMGetAllocatableSizeForFrmHeap( heap );
212     u32 totalSize       = (u32)MEMGetHeapTotalUsableSize( heap );
213     u32 usedSize        = totalSize - allocatableSize;
214 
215     OSReport("[OS Foundation Frame Heap]\n");
216     OSReport("    whole [%p - %p)\n", MEMGetHeapStartAddress( heap ), MEMGetHeapEndAddress( heap ) );
217 
218     OSReport("    %d / %d bytes (%6.2f%%) used\n", usedSize, totalSize, 100.0 * usedSize / totalSize );
219     OSReport("\n");
220 }
221 
222 
223 /*
224     Structure that gets information for reports.
225     Used to specify parameters when calling the visitor function.
226  */
227 typedef struct
228 {
229     u32     size;       // Data size storage region
230     u32     cnt;        // Number of memory blocks used
231 } TReportParam;
232 
233 
234 /*---------------------------------------------------------------------------*
235   Name:         ReportVisitorFunc
236 
237   Description:  A Visitor function for outputting the heap state.
238 
239   Arguments:    memBlock:   The memory block
240                 heap: Handle for expanded heap
241                 userParam: call parameter for the visitor function
242                             Gets the total memory size.
243 
244   Returns:      None.
245  *---------------------------------------------------------------------------*/
246 static void
ReportVisitorFunc(void * memBlock,MEMHeapHandle heap,u32 userParam)247 ReportVisitorFunc(
248     void*           memBlock,
249     MEMHeapHandle   heap,
250     u32             userParam
251 )
252 {
253 #pragma unused( heap )
254     TReportParam* pParam   = (TReportParam*)userParam;
255     u16           allocDir = MEMGetAllocDirForMBlockExpHeap( memBlock );
256     u16           groupId  = MEMGetGroupIDForMBlockExpHeap ( memBlock );
257     u32           size     = MEMGetSizeForMBlockExpHeap    ( memBlock );
258 
259     pParam->size += MEMGetSizeForMBlockExpHeap( memBlock );
260     pParam->cnt++;
261 
262     OSReport("    %s %08x: %8d  %3d\n",
263         allocDir == MEM_EXPHEAP_ALLOC_DIR_REAR ? " rear" : "front",
264         (u32)memBlock,
265         size,
266         groupId
267     );
268 }
269 
270 /*---------------------------------------------------------------------------*
271   Name:         ReportExpHeap
272 
273   Description:  Outputs the state of the expanded heap.
274                 The MEMDumpHeap will provide detailed output for debug builds.
275 
276   Arguments:    heap    heap handle
277 
278   Returns:      None.
279  *---------------------------------------------------------------------------*/
280 static void
ReportExpHeap(MEMHeapHandle heap)281 ReportExpHeap( MEMHeapHandle  heap )
282 {
283     TReportParam param = { 0, 0 };
284 
285     OSReport("[OS Foundation Exp Heap]\n");
286 
287     OSReport("    whole [%p - %p)\n", MEMGetHeapStartAddress( heap ), MEMGetHeapEndAddress( heap ) );
288     OSReport("    attr  address:   size    gid\n");   // Header line
289 
290     MEMVisitAllocatedForExpHeap(
291         heap,                       // The heap handle
292         ReportVisitorFunc,          // visitor function
293         (u32)&param                 // User parameters
294     );
295 
296     OSReport("\n");
297 
298     {
299         u32 usedSize  = param.size;
300         u32 usedCnt   = param.cnt;
301 
302         OSReport("    %d bytes allocated (U:%d)\n",
303                            usedSize, usedCnt);
304     }
305     OSReport("\n");
306 }
307 
308 #endif
309