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