1 /*---------------------------------------------------------------------------*
2   Project:     MEM library
3   File:        mem_heapCommon.c
4   Programmers: Makoto Takano
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 #include <revolution/mem.h>
16 #include "heapCommoni.h"
17 
18 /* ========================================================================
19     static variables
20    ======================================================================== */
21 
22 /* ------------------------------------------------------------------------
23     list related
24    ------------------------------------------------------------------------ */
25 
26 static MEMList   sRootList;                      // root heap list
27 static BOOL      sRootListInitialized = FALSE;   // if sRootList is initialized, True
28 static OSMutex   sRootMutex;                     // multi-heap management exclusion controls (24B)
29 
30 /* ------------------------------------------------------------------------
31     fill related
32    ------------------------------------------------------------------------ */
33 
34 #if defined(_DEBUG)
35 
36 static u32 sFillVals[ MEM_HEAP_FILL_MAX ] =
37 {
38     0xC3C3C3C3, // Value to fill when creating heap
39     0xF3F3F3F3, // Value to fill when allocating memory block
40     0xD3D3D3D3, // Value to fill when releasing memory block
41 };
42 
43 // #if defined(_DEBUG)
44 #endif
45 
46 
47 /* ========================================================================
48     static functions
49    ======================================================================== */
50 
51 /* ------------------------------------------------------------------------
52     list related
53    ------------------------------------------------------------------------ */
54 
55 /*---------------------------------------------------------------------------*
56   Name:         FindContainHeap_
57 
58   Description:  Recursively searches the heap containing the specified memory block from the list.
59                 block from the list.
60 
61   Arguments:    pList:     pointer to list
62                 memBlock:  pointer to memory block
63 
64   Returns:      If the heap that allocated the specified memory block is found,
65                 returns a pointer to that heap.
66                 Returns NULL, if it is not found.
67  *---------------------------------------------------------------------------*/
68 static MEMiHeapHead*
FindContainHeap_(MEMList * pList,const void * memBlock)69 FindContainHeap_(
70     MEMList*         pList,
71     const void*      memBlock
72 )
73 {
74     MEMiHeapHead* pHeapHd = NULL;
75     while ( NULL != ( pHeapHd = (MEMiHeapHead*)MEMGetNextListObject(pList, pHeapHd) ) )
76     {
77         if ( GetUIntPtr( pHeapHd->heapStart ) <= GetUIntPtr( memBlock )
78              &&  GetUIntPtr( memBlock ) < GetUIntPtr( pHeapHd->heapEnd )
79         )
80         {
81             MEMiHeapHead* pChildHeapHd = FindContainHeap_( &pHeapHd->childList, memBlock );
82             if ( pChildHeapHd )
83             {
84                 return pChildHeapHd;
85             }
86             return pHeapHd;
87         }
88     }
89     return NULL;
90 }
91 
92 
93 /*---------------------------------------------------------------------------*
94   Name:         FindParentHeap_
95 
96   Description:  Searches for the parent heap for the specified heap, under the node indicated in the arguments.
97   Arguments:    pNodeHeap:
98                 pTargetHeap:
99 
100   Returns:      Returns a pointer to the heap's header when the parent heap is found.
101                 Returns NULL if not found.
102  *---------------------------------------------------------------------------*/
103 static MEMiHeapHead*
FindParentHeap_(MEMiHeapHead * pNodeHeap,const MEMiHeapHead * pTargetHeap)104 FindParentHeap_(
105     MEMiHeapHead*       pNodeHeap,
106     const MEMiHeapHead* pTargetHeap
107 )
108 {
109     MEMList*       pList   = &pNodeHeap->childList;
110     MEMiHeapHead*  pHeapHd = NULL;
111 
112     while ( NULL != ( pHeapHd = (MEMiHeapHead*)MEMGetNextListObject(pList, pHeapHd) ) )
113     {
114         if ( pHeapHd == pTargetHeap )
115         {
116             // is a parent heap of the child heap member and target match
117             return pNodeHeap;
118         }
119 
120         // continues the search for children if the target address is included
121         if ( GetUIntPtr( pHeapHd->heapStart ) <= GetUIntPtr( pTargetHeap )
122              &&  GetUIntPtr( pTargetHeap ) < GetUIntPtr( pHeapHd->heapEnd )
123         )
124         {
125             return FindParentHeap_( pHeapHd, pTargetHeap );
126         }
127     }
128     return NULL;
129 }
130 
131 /*---------------------------------------------------------------------------*
132   Name:         FindListContainHeap_
133 
134   Description:  Searches the parent heap that contains the heap, and returns a pointer to the parent heap list.
135                 the nth block header, where n = "idx".
136 
137   Arguments:    pHeapHd:  pointer to the header of search target heap.
138 
139   Returns:      If the parent heap that includes the specified heap is found:
140                 Returns a pointer to the parent heap's child list.
141                 If the parent heap is not found, a pointer to the root list is returned.
142  *---------------------------------------------------------------------------*/
143 static MEMList*
FindListContainHeap_(const MEMiHeapHead * pHeapHd)144 FindListContainHeap_( const MEMiHeapHead* pHeapHd )
145 {
146     MEMList* pList = &sRootList;
147 
148     MEMiHeapHead* pContainHeap = FindContainHeap_( &sRootList, pHeapHd );
149 
150     if ( pContainHeap )
151     {
152         pList = &pContainHeap->childList;
153     }
154 
155     return pList;
156 }
157 
158 
159 /* ========================================================================
160     External Functions (Non-Public)
161    ======================================================================== */
162 
163 /*---------------------------------------------------------------------------*
164   Name:         MEMiInitHeapHead
165 
166   Description:  Initializes heap header.
167 
168   Arguments:    pHeapHd:    Pointer to the heap header.
169                 signature:  signature.
170                 heapStart:  start address of heap memory.
171                 heapEnd:    end address +1 of heap memory.
172                 optFlag:    heap option
173 
174   Returns:      None.
175  *---------------------------------------------------------------------------*/
176 void
MEMiInitHeapHead(MEMiHeapHead * pHeapHd,u32 signature,void * heapStart,void * heapEnd,u16 optFlag)177 MEMiInitHeapHead(
178     MEMiHeapHead*   pHeapHd,
179     u32             signature,
180     void*           heapStart,
181     void*           heapEnd,
182     u16             optFlag
183 )
184 {
185     pHeapHd->signature = signature;
186 
187     pHeapHd->heapStart = heapStart;
188     pHeapHd->heapEnd   = heapEnd;
189 
190     pHeapHd->attribute.val = 0;
191 
192     SetOptForHeap( pHeapHd, optFlag );
193 
194     FillNoUseMemory(
195             pHeapHd,
196             heapStart,
197             GetOffsetFromPtr( heapStart, heapEnd )
198     );
199 
200     MEM_INIT_LIST( &pHeapHd->childList, MEMiHeapHead, link );
201 
202     // performs initialization when the heap list is first created
203     if ( ! sRootListInitialized )
204     {
205         MEM_INIT_LIST( &sRootList, MEMiHeapHead, link );
206         OSInitMutex( &sRootMutex );
207         sRootListInitialized = TRUE;
208     }
209 
210     // Mutex initialization
211     OSInitMutex( &pHeapHd->mutex );
212 
213     // addition to the multi-heap list
214     OSLockMutex( &sRootMutex );
215     MEMAppendListObject( FindListContainHeap_( pHeapHd ), pHeapHd );
216     OSUnlockMutex( &sRootMutex );
217 
218 }
219 
220 /*---------------------------------------------------------------------------*
221   Name:         MEMiFinalizeHeap
222 
223   Description:  Takes care of the heap common.
224 
225   Arguments:    pHeapHd:  Pointer to the heap header.
226 
227   Returns:      None.
228  *---------------------------------------------------------------------------*/
229 void
MEMiFinalizeHeap(MEMiHeapHead * pHeapHd)230 MEMiFinalizeHeap( MEMiHeapHead* pHeapHd )
231 {
232     // deletion from the multi-heap list
233     OSLockMutex( &sRootMutex );
234     MEMRemoveListObject( FindListContainHeap_( pHeapHd ), pHeapHd );
235     OSUnlockMutex( &sRootMutex );
236     pHeapHd->signature = 0;
237 }
238 
239 
240 /*---------------------------------------------------------------------------*
241   Name:         MEMiDumpHeapHead
242 
243   Description:  Displays heap header information.
244 
245   Arguments:    pHeapHd:  Pointer to the heap header.
246 
247   Returns:      None.
248  *---------------------------------------------------------------------------*/
249 void
MEMiDumpHeapHead(MEMiHeapHead * pHeapHd)250 MEMiDumpHeapHead( MEMiHeapHead* pHeapHd )
251 {
252     OSReport("[OS Foundation ");
253 
254     switch ( pHeapHd->signature )
255     {
256     case MEMi_EXPHEAP_SIGNATURE: { OSReport("Exp");   break; }
257     case MEMi_FRMHEAP_SIGNATURE: { OSReport("Frame"); break; }
258     case MEMi_UNTHEAP_SIGNATURE: { OSReport("Unit");  break; }
259     default:
260         ASSERT( FALSE );
261     }
262 
263     OSReport(" Heap]\n");
264 
265     OSReport("    whole [%p - %p)\n", pHeapHd, pHeapHd->heapEnd);
266 }
267 
268 
269 
270 /* ========================================================================
271     External functions (public)
272    ======================================================================== */
273 
274 /*---------------------------------------------------------------------------*
275   Name:         MEMFindContainHeap
276 
277   Description:  Searches for heap containing memory block.
278 
279   Arguments:    memBlock:  memory block to be searched.
280 
281   Returns:      If the heap that includes the specified memory block is found,
282                 returns a handle to that heap.
283                 Returns HEAP_INVALID_HANDLE if not found.
284  *---------------------------------------------------------------------------*/
285 MEMHeapHandle
MEMFindContainHeap(const void * memBlock)286 MEMFindContainHeap( const void* memBlock )
287 {
288     return FindContainHeap_( &sRootList, memBlock );
289 }
290 
291 
292 /*---------------------------------------------------------------------------*
293   Name:         MEMFindParentHeap
294 
295   Description:  Searches for the parent heap.
296 
297   Arguments:    memBlock:  memory block to be searched.
298 
299   Returns:      If the heap that includes the specified memory block is found,
300                 returns a handle to that heap.
301                 Returns HEAP_INVALID_HANDLE if not found.
302  *---------------------------------------------------------------------------*/
303 MEMHeapHandle
MEMFindParentHeap(MEMHeapHandle heap)304 MEMFindParentHeap( MEMHeapHandle heap )
305 {
306     MEMiHeapHead* pHeapHd = NULL;
307 
308     while ( NULL != ( pHeapHd = (MEMiHeapHead*)MEMGetNextListObject(&sRootList, pHeapHd) ) )
309     {
310         if ( pHeapHd == heap )
311         {
312             return MEM_HEAP_INVALID_HANDLE;
313         }
314         // searches for children if the target address is included
315         if ( GetUIntPtr( pHeapHd->heapStart ) <= GetUIntPtr( heap )
316              &&  GetUIntPtr( heap ) < GetUIntPtr( pHeapHd->heapEnd )
317         )
318         {
319             return FindParentHeap_( pHeapHd, heap );
320         }
321     }
322     return MEM_HEAP_INVALID_HANDLE;
323 }
324 
325 
326 #if defined(_DEBUG)
327 
328 /*---------------------------------------------------------------------------*
329   Name:         MEMDumpHeap
330 
331   Description:  Displays the information in the heap.
332                 This function is for debugging.
333 
334   Arguments:    heap :    Handle for frame heap
335 
336   Returns:      None.
337  *---------------------------------------------------------------------------*/
338 
339 void
MEMDumpHeap(MEMHeapHandle heap)340 MEMDumpHeap( MEMHeapHandle heap )
341 {
342     MEMiHeapHead* pHeapHd = heap;
343     switch ( pHeapHd->signature )
344     {
345     case MEMi_EXPHEAP_SIGNATURE:
346         {
347             LockHeap( heap );
348             MEMiDumpExpHeap(heap);
349             UnlockHeap( heap );
350         }
351         break;
352     case MEMi_FRMHEAP_SIGNATURE:
353         {
354             LockHeap( heap );
355             MEMiDumpFrmHeap(heap);
356             UnlockHeap( heap );
357         }
358         break;
359     case MEMi_UNTHEAP_SIGNATURE:
360         {
361             LockHeap( heap );
362             MEMiDumpUnitHeap(heap);
363             UnlockHeap( heap );
364         }
365         break;
366     default:
367         OSReport("[OS Foundation] dump heap : unknown heap. - %p\n", heap);
368     }
369 }
370 
371 
372 /*---------------------------------------------------------------------------*
373   Name:         MEMSetFillValForHeap
374 
375   Description:  Gets the value that is placed in memory when creating the heap and allocating/freeing memory blocks.
376                 Sets the value to be set.
377                 This function is for use in debugging.
378                 Always returns 0 in the final ROM version library.
379 
380   Arguments:    type:  type of value to get
381                 val:   set value
382 
383   Returns:      Returns the previous value that was set in memory when memory block was allocated.
384  *---------------------------------------------------------------------------*/
385 u32
MEMSetFillValForHeap(int type,u32 val)386 MEMSetFillValForHeap(
387     int     type,
388     u32     val
389 )
390 {
391     ASSERT( type < MEM_HEAP_FILL_MAX );
392 
393     {
394         u32 oldVal = sFillVals[type];
395         sFillVals[type] = val;
396         return oldVal;
397     }
398 }
399 
400 
401 /*---------------------------------------------------------------------------*
402   Name:         MEMGetFillValForHeap
403 
404   Description:  Gets the value that is placed in memory when creating the heap and allocating/freeing memory blocks.
405                 Gets the value to be set.
406                 This function is for use in debugging.
407                 Always returns 0 in the final ROM version library.
408 
409   Arguments:    type:  type of value to get
410 
411   Returns:      Returns the value set in the memory of the type specified.
412  *---------------------------------------------------------------------------*/
413 u32
MEMGetFillValForHeap(int type)414 MEMGetFillValForHeap( int type )
415 {
416     ASSERT( type < MEM_HEAP_FILL_MAX );
417 
418     return sFillVals[ type ];
419 }
420 
421 // #if defined(_DEBUG)
422 #endif
423 
424