1 /*---------------------------------------------------------------------------*
2 Project: MEM library
3 File: mem_frameHeap.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/frameHeap.h>
16 #include "heapCommoni.h"
17 #include <stdlib.h>
18
19
20 /* ========================================================================
21 Macro constants
22 ======================================================================== */
23
24 // Minimum alignment value
25 #define MIN_ALIGNMENT 4
26
27
28 /* ========================================================================
29 static functions
30 ======================================================================== */
31
32 /*---------------------------------------------------------------------------*
33 Name: IsValidFrmHeapHandle_
34
35 Description: Checks the signature to determine whether the frame heap is valid.
36
37 Arguments: handle: The heap handle
38
39 Returns: TRUE the heap handle is valid
40 FALSE the heap handle is not valid
41 *---------------------------------------------------------------------------*/
42 static inline BOOL
IsValidFrmHeapHandle_(MEMHeapHandle handle)43 IsValidFrmHeapHandle_( MEMHeapHandle handle )
44 {
45 if ( handle == MEM_HEAP_INVALID_HANDLE )
46 {
47 return FALSE;
48 }
49
50 {
51 MEMiHeapHead* pHeapHd = handle;
52 return pHeapHd->signature == MEMi_FRMHEAP_SIGNATURE;
53 }
54 }
55
56 /*---------------------------------------------------------------------------*
57 Name: GetFrmHeapHeadPtrFromHeapHead_
58
59 Description: Get pointer to frame heap header from pointer to heap header.
60
61 Arguments: pHHead: Pointer to the heap header.
62
63 Returns: Returns the pointer to the frame heap header.
64 *---------------------------------------------------------------------------*/
65 static inline MEMiFrmHeapHead*
GetFrmHeapHeadPtrFromHeapHead_(MEMiHeapHead * pHHead)66 GetFrmHeapHeadPtrFromHeapHead_( MEMiHeapHead* pHHead )
67 {
68 return (MEMiFrmHeapHead*)AddU32ToPtr( pHHead, sizeof(MEMiHeapHead) );
69 }
70
71 /*---------------------------------------------------------------------------*
72 Name: GetHeapHeadPtrFromFrmHeapHead_
73
74 Description: Gets heap header pointer from frame heap header pointer.
75
76 Arguments: pFrmHeapHd: frame heap header pointer.
77
78 Returns: Returns the pointer to the heap header.
79 *---------------------------------------------------------------------------*/
80 static inline MEMiHeapHead*
GetHeapHeadPtrFromFrmHeapHead_(MEMiFrmHeapHead * pFrmHeapHd)81 GetHeapHeadPtrFromFrmHeapHead_( MEMiFrmHeapHead* pFrmHeapHd )
82 {
83 return (MEMiHeapHead*)SubU32ToPtr(pFrmHeapHd, sizeof(MEMiHeapHead));
84 }
85
86 /*---------------------------------------------------------------------------*
87 Name: InitFrameHeap_
88
89 Description: Initializes the frame heap.
90
91 Arguments: startAddress: Starting address of memory used as frame heap.
92 endAddress: Ending address +1 of the memory to be used as the frame heap.
93 optFlag: Option flag.
94
95 Returns: Returns the pointer to the heap header.
96 *---------------------------------------------------------------------------*/
97 static MEMiHeapHead*
InitFrameHeap_(void * startAddress,void * endAddress,u16 optFlag)98 InitFrameHeap_(
99 void* startAddress,
100 void* endAddress,
101 u16 optFlag
102 )
103 {
104 MEMiHeapHead* pHeapHd = (MEMiHeapHead*)startAddress;
105 MEMiFrmHeapHead* pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead_( pHeapHd );
106
107 MEMiInitHeapHead( // Heap common initialization
108 pHeapHd,
109 MEMi_FRMHEAP_SIGNATURE,
110 AddU32ToPtr( pFrmHeapHd, sizeof(MEMiFrmHeapHead) ), // heapStart
111 endAddress, // heapEnd
112 optFlag );
113
114 pFrmHeapHd->headAllocator = pHeapHd->heapStart;
115 pFrmHeapHd->tailAllocator = pHeapHd->heapEnd;
116
117 pFrmHeapHd->pState = NULL; // State saving state location
118
119 return pHeapHd;
120 }
121
122
123 /*---------------------------------------------------------------------------*
124 Name: AllocFromHead_
125
126 Description: Allocates the memory block from the top of the heap.
127 There is an alignment specification.
128
129 Arguments: pHHead: Pointer to the heap header.
130 size : Size of the memory block to be allocated.
131 alignment: Alignment value.
132
133 Returns: Returns the pointer
134 to the allocated memory block if the allocation is successful.
135 If fails, NULL is returned.
136 *---------------------------------------------------------------------------*/
137 static void*
AllocFromHead_(MEMiFrmHeapHead * pFrmHeapHd,u32 size,int alignment)138 AllocFromHead_(
139 MEMiFrmHeapHead* pFrmHeapHd,
140 u32 size,
141 int alignment
142 )
143 {
144 void* newBlock = RoundUpPtr(pFrmHeapHd->headAllocator, alignment);
145 void* endAddress = AddU32ToPtr(newBlock, size);
146
147 if ( GetUIntPtr(endAddress) > GetUIntPtr(pFrmHeapHd->tailAllocator) )
148 {
149 return NULL;
150 }
151
152 FillAllocMemory( // Fill memory
153 GetHeapHeadPtrFromFrmHeapHead_(pFrmHeapHd),
154 pFrmHeapHd->headAllocator,
155 GetOffsetFromPtr(pFrmHeapHd->headAllocator, endAddress));
156
157 pFrmHeapHd->headAllocator = endAddress;
158
159 return newBlock;
160 }
161
162 /*---------------------------------------------------------------------------*
163 Name: AllocFromTail_
164
165 Description: Allocates a memory block from the tail of the heap.
166 There is an alignment specification.
167
168 Arguments: pHHead: Pointer to the heap header.
169 size : Size of the memory block to be allocated.
170 alignment: Alignment value.
171
172 Returns: Returns the pointer
173 to the allocated memory block if the allocation is successful.
174 If fails, NULL is returned.
175 *---------------------------------------------------------------------------*/
176 static void*
AllocFromTail_(MEMiFrmHeapHead * pFrmHeapHd,u32 size,int alignment)177 AllocFromTail_(
178 MEMiFrmHeapHead* pFrmHeapHd,
179 u32 size,
180 int alignment
181 )
182 {
183 void* newBlock = RoundDownPtr(SubU32ToPtr(pFrmHeapHd->tailAllocator, size), alignment);
184
185 if ( GetUIntPtr(newBlock) < GetUIntPtr(pFrmHeapHd->headAllocator) )
186 {
187 return NULL;
188 }
189
190 FillAllocMemory( // Fill memory
191 GetHeapHeadPtrFromFrmHeapHead_(pFrmHeapHd),
192 newBlock,
193 GetOffsetFromPtr(newBlock, pFrmHeapHd->tailAllocator) );
194
195 pFrmHeapHd->tailAllocator = newBlock;
196
197 return newBlock;
198 }
199
200 /*---------------------------------------------------------------------------*
201 Name: FreeHead_
202
203 Description: Free memory blocks allocated from the head of the heap area all at once.
204
205 Arguments: pHeapHd: heap header pointer.
206
207 Returns: None.
208 *---------------------------------------------------------------------------*/
209 static void
FreeHead_(MEMiHeapHead * pHeapHd)210 FreeHead_( MEMiHeapHead* pHeapHd )
211 {
212 MEMiFrmHeapHead* pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead_(pHeapHd);
213
214 FillFreeMemory(
215 pHeapHd,
216 pHeapHd->heapStart,
217 GetOffsetFromPtr(pHeapHd->heapStart, pFrmHeapHd->headAllocator) );
218
219 pFrmHeapHd->headAllocator = pHeapHd->heapStart;
220 pFrmHeapHd->pState = NULL;
221 }
222
223
224 /*---------------------------------------------------------------------------*
225 Name: FreeTail_
226
227 Description: Free the memory blocks allocated from the tail of the heap area all at once.
228
229 Arguments: pHeapHd: heap header pointer.
230
231 Returns: None.
232 *---------------------------------------------------------------------------*/
233 static void
FreeTail_(MEMiHeapHead * pHeapHd)234 FreeTail_( MEMiHeapHead* pHeapHd )
235 {
236 MEMiFrmHeapHead* pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead_(pHeapHd);
237
238 FillFreeMemory(
239 pHeapHd,
240 pFrmHeapHd->tailAllocator,
241 GetOffsetFromPtr(pFrmHeapHd->tailAllocator, pHeapHd->heapEnd) );
242
243 /*
244 In order not to accidentally restore released memory blocks due to recovery of the heap allocation state,
245 reset the tail allocation pointer of the save information.
246 */
247 {
248 MEMiFrmHeapState* pState;
249 for ( pState = pFrmHeapHd->pState; pState; pState = pState->pPrevState )
250 {
251 pState->tailAllocator = pHeapHd->heapEnd;
252 }
253 }
254
255 pFrmHeapHd->tailAllocator = pHeapHd->heapEnd;
256 }
257
258
259 /*---------------------------------------------------------------------------*
260 Name: PrintSize_
261
262 Description: Output size and percentage.
263
264 Arguments: size : Target size.
265 wholeSize: Whole size.
266
267 Returns: None.
268 *---------------------------------------------------------------------------*/
269 #if defined(_DEBUG)
270
271 static void
PrintSize_(u32 size,u32 wholeSize)272 PrintSize_(
273 u32 size,
274 u32 wholeSize
275 )
276 {
277 OSReport("%9d (%6.2f%%)", size, 100.0 * size / wholeSize);
278 }
279
280 // #if defined(_DEBUG)
281 #endif
282
283
284 /* ========================================================================
285 External Functions (Non-Public)
286 ======================================================================== */
287
288 /*---------------------------------------------------------------------------*
289 Name: MEMiGetFreeStartForFrmHeap
290
291 Description: Gets the head address of the free area of the frame heap.
292
293 Arguments: heap : Handle for frame heap
294
295 Returns: Returns the head address of the free area of the frame heap.
296 *---------------------------------------------------------------------------*/
297 void*
MEMiGetFreeStartForFrmHeap(MEMHeapHandle heap)298 MEMiGetFreeStartForFrmHeap( MEMHeapHandle heap )
299 {
300 ASSERT(IsValidFrmHeapHandle_(heap));
301
302 return GetFrmHeapHeadPtrFromHeapHead_(heap)->headAllocator;
303 }
304
305 /*---------------------------------------------------------------------------*
306 Name: MEMiGetFreeEndForFrmHeap
307
308 Description: Gets the end address of the free area of the frame heap.
309
310 Arguments: heap : Handle for frame heap
311
312 Returns: Returns the end address +1 of the free area of the frame heap.
313 *---------------------------------------------------------------------------*/
314 void*
MEMiGetFreeEndForFrmHeap(MEMHeapHandle heap)315 MEMiGetFreeEndForFrmHeap( MEMHeapHandle heap )
316 {
317 ASSERT(IsValidFrmHeapHandle_(heap));
318
319 return GetFrmHeapHeadPtrFromHeapHead_(heap)->tailAllocator;
320 }
321
322
323 /*---------------------------------------------------------------------------*
324 Name: MEMiDumpFrmHeap
325
326 Description: Displays the data inside the frame heap.
327 This function is for debugging.
328
329 Arguments: heap : Handle for frame heap
330
331 Returns: None.
332 *---------------------------------------------------------------------------*/
333 #if defined(_DEBUG)
334
335 void
MEMiDumpFrmHeap(MEMHeapHandle heap)336 MEMiDumpFrmHeap( MEMHeapHandle heap )
337 {
338 ASSERT(IsValidFrmHeapHandle_(heap));
339
340 {
341 MEMiHeapHead *const pHeapHd = heap;
342 MEMiFrmHeapHead *const pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead_( pHeapHd );
343 const u32 heapSize = GetOffsetFromPtr( pHeapHd->heapStart, pHeapHd->heapEnd );
344
345 MEMiDumpHeapHead(pHeapHd);
346
347 OSReport( " head [%p - %p) ", pHeapHd->heapStart, pFrmHeapHd->headAllocator);
348 PrintSize_(GetOffsetFromPtr(pHeapHd->heapStart, pFrmHeapHd->headAllocator), heapSize);
349 OSReport("\n free ");
350 PrintSize_(GetOffsetFromPtr(pFrmHeapHd->headAllocator, pFrmHeapHd->tailAllocator), heapSize);
351 OSReport("\n tail [%p - %p) ", pFrmHeapHd->tailAllocator, pHeapHd->heapEnd);
352 PrintSize_(GetOffsetFromPtr(pFrmHeapHd->tailAllocator, pHeapHd->heapEnd), heapSize);
353 OSReport("\n");
354
355 if ( pFrmHeapHd->pState )
356 {
357 MEMiFrmHeapState* pState;
358
359 OSReport(" state : [tag] [head] [tail]\n");
360
361 for ( pState = pFrmHeapHd->pState; pState; pState = pState->pPrevState )
362 {
363 OSReport(" '%c%c%c%c' : %p %p\n", pState->tagName >>24, (pState->tagName >>16) & 0xFF, (pState->tagName >>8) & 0xFF, pState->tagName & 0xFF,
364 pState->headAllocator, pState->tailAllocator);
365 }
366 }
367
368 OSReport("\n");
369 }
370 }
371
372 // #if defined(_DEBUG)
373 #endif
374
375
376
377 /* ========================================================================
378 External functions (public)
379 ======================================================================== */
380
381 /*---------------------------------------------------------------------------*
382 Name: MEMCreateFrmHeapEx
383
384 Description: Creates a frame heap.
385
386 Arguments: startAddress: Start address of heap area
387 size : Size of heap area
388 optFlag: Option flag.
389 MEM_HEAP_OPT_0_CLEAR -- 0 clear flag at memory allocation
390 MEM_HEAP_OPT_DEBUG_FILL -- the debug fill flag
391
392 Returns: Returns the handle for the created frame heap if the function succeeds.
393 If the function fails, MEM_INVALID_HEAP_HANDLE is returned.
394
395 Memo: Base is not thread save.
396 When you thread save, please try to add the argument specifying the heap attribute,
397 or please suppress the function that sets the attribute.
398 *---------------------------------------------------------------------------*/
399 MEMHeapHandle
MEMCreateFrmHeapEx(void * startAddress,u32 size,u16 optFlag)400 MEMCreateFrmHeapEx(
401 void* startAddress,
402 u32 size,
403 u16 optFlag
404 )
405 {
406 void* endAddress;
407
408 ASSERT(startAddress != NULL);
409
410 endAddress = RoundDownPtr(AddU32ToPtr(startAddress, size), MIN_ALIGNMENT);
411 startAddress = RoundUpPtr(startAddress, MIN_ALIGNMENT);
412
413 if ( GetUIntPtr(startAddress) > GetUIntPtr(endAddress)
414 || GetOffsetFromPtr(startAddress, endAddress) < sizeof(MEMiHeapHead) + sizeof(MEMiFrmHeapHead)
415 )
416 {
417 return MEM_HEAP_INVALID_HANDLE;
418 }
419
420 { // Initialize frame heap
421 MEMiHeapHead* pHHead = InitFrameHeap_( startAddress, endAddress, optFlag );
422 return pHHead; // The pointer to the heap header is used as-is as the handle value.
423 }
424 }
425
426
427 /*---------------------------------------------------------------------------*
428 Name: MEMDestroyFrmHeap
429
430 Description: Destroys the frame heap.
431
432 Arguments: heap : Handle for frame heap
433
434 Returns: Returns a pointer to the region occupied by the destroyed heap.
435 *---------------------------------------------------------------------------*/
436 void*
MEMDestroyFrmHeap(MEMHeapHandle heap)437 MEMDestroyFrmHeap( MEMHeapHandle heap )
438 {
439 ASSERT(IsValidFrmHeapHandle_(heap));
440
441 MEMiFinalizeHeap(heap);
442 return (void*)heap;
443 }
444
445 /*---------------------------------------------------------------------------*
446 Name: MEMAllocFromFrmHeapEx
447
448 Description: Allocates a memory block from the frame heap
449 The memory block alignment can be specified.
450 If a negative alignment value is specified, an empty region is searched for from the back of the heap.
451
452 Arguments: heap : Handle for frame heap
453 size : Size of the memory block to be allocated (in bytes)
454 alignment: Alignment of the memory block to be allocated.
455 The following values can be specified: �}4, �}8, �}16, �}32, �}64, �}128, ...
456
457 Returns: Returns the pointer
458 to the allocated memory block if the allocation is successful.
459 If fails, NULL is returned.
460 *---------------------------------------------------------------------------*/
461 void*
MEMAllocFromFrmHeapEx(MEMHeapHandle heap,u32 size,int alignment)462 MEMAllocFromFrmHeapEx(
463 MEMHeapHandle heap,
464 u32 size,
465 int alignment
466 )
467 {
468 void* memory = NULL;
469 MEMiFrmHeapHead* pFrmHeapHd;
470
471 ASSERT(IsValidFrmHeapHandle_(heap));
472
473 // alignment check
474 ASSERT(alignment % MIN_ALIGNMENT == 0);
475 ASSERT((abs(alignment) & (abs(alignment) - 1)) == 0);
476 ASSERT(MIN_ALIGNMENT <= abs(alignment));
477
478 pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead_(heap);
479
480 if ( size == 0 )
481 {
482 size = 1;
483 }
484
485 size = RoundUp(size, MIN_ALIGNMENT);
486
487 LockHeap( heap );
488
489 if ( alignment >= 0 ) // Allocate from the front of the heap
490 {
491 memory = AllocFromHead_(pFrmHeapHd, size, alignment);
492 }
493 else // Allocate from the end of the heap
494 {
495 memory = AllocFromTail_(pFrmHeapHd, size, -alignment);
496 }
497
498 UnlockHeap( heap );
499
500 return memory;
501 }
502
503 /*---------------------------------------------------------------------------*
504 Name: MEMFreeToFrmHeap
505
506 Description: This function returns the memory block to the frame heap.
507
508 Arguments: heap : Handle for frame heap
509 mode: Method of returning memory block
510
511 Returns: None.
512 *---------------------------------------------------------------------------*/
513 void
MEMFreeToFrmHeap(MEMHeapHandle heap,int mode)514 MEMFreeToFrmHeap(
515 MEMHeapHandle heap,
516 int mode
517 )
518 {
519 ASSERT(IsValidFrmHeapHandle_(heap));
520
521 LockHeap( heap );
522
523 if (mode & MEM_FRMHEAP_FREE_HEAD)
524 {
525 FreeHead_(heap);
526 }
527
528 if (mode & MEM_FRMHEAP_FREE_TAIL)
529 {
530 FreeTail_(heap);
531 }
532
533 UnlockHeap( heap );
534 }
535
536 /*---------------------------------------------------------------------------*
537 Name: MEMGetAllocatableSizeForFrmHeapEx
538
539 Description: Get the maximum allocatable size in the frame heap.
540 The memory block alignment can be specified.
541
542 Arguments: heap : Handle for frame heap
543 alignment: Alignment of the memory block to be allocated.
544 The following values can be specified: �}4, �}8, �}16, �}32, �}64, �}128, ...
545
546 Returns: Returns the maximum allocatable size in the frame heap (in bytes)
547 *---------------------------------------------------------------------------*/
548 u32
MEMGetAllocatableSizeForFrmHeapEx(MEMHeapHandle heap,int alignment)549 MEMGetAllocatableSizeForFrmHeapEx(
550 MEMHeapHandle heap,
551 int alignment
552 )
553 {
554 ASSERT(IsValidFrmHeapHandle_(heap));
555
556 // alignment check
557 ASSERT(alignment % MIN_ALIGNMENT == 0);
558 ASSERT((abs(alignment) & (abs(alignment) - 1)) == 0);
559 ASSERT(MIN_ALIGNMENT <= abs(alignment));
560
561 alignment = abs(alignment); // Convert to a positive value just to be sure
562
563 {
564 u32 retVal;
565 const MEMiFrmHeapHead* pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead_(heap);
566 BOOL enabled = OSDisableInterrupts();
567 const void* block = RoundUpPtr(pFrmHeapHd->headAllocator, alignment);
568
569 if ( GetUIntPtr(block) > GetUIntPtr(pFrmHeapHd->tailAllocator) )
570 {
571 retVal = 0;
572 }
573 else
574 {
575 retVal = GetOffsetFromPtr( block, pFrmHeapHd->tailAllocator );
576 }
577 (void)OSRestoreInterrupts( enabled );
578 return retVal;
579 }
580 }
581
582
583 /*---------------------------------------------------------------------------*
584 Name: MEMRecordStateForFrmHeap
585
586 Description: This function records the current use status of the frame heap.
587 You can return to the recorded memory usage status later.
588 20 bytes are used to record the status.
589
590 Arguments: heap : Handle for frame heap
591 tagName: Tag name given to the status record.
592
593 Returns: Returns TRUE if successful.
594 Returns FALSE if unsuccessful.
595 *---------------------------------------------------------------------------*/
596 BOOL
MEMRecordStateForFrmHeap(MEMHeapHandle heap,u32 tagName)597 MEMRecordStateForFrmHeap(
598 MEMHeapHandle heap,
599 u32 tagName
600 )
601 {
602 BOOL retVal;
603 ASSERT(IsValidFrmHeapHandle_(heap));
604
605 LockHeap( heap );
606 {
607 MEMiFrmHeapHead* pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead_(heap);
608 void* oldHeadAllocator = pFrmHeapHd->headAllocator;
609
610 // Allocate memory for saving information.
611 MEMiFrmHeapState* pState = (MEMiFrmHeapState*)AllocFromHead_(pFrmHeapHd, sizeof(MEMiFrmHeapState), MIN_ALIGNMENT);
612
613 if ( ! pState )
614 {
615 retVal = FALSE;
616 goto ret_;
617 }
618
619 // Store the current status
620 pState->tagName = tagName;
621 pState->headAllocator = oldHeadAllocator;
622 pState->tailAllocator = pFrmHeapHd->tailAllocator;
623 pState->pPrevState = pFrmHeapHd->pState;
624
625 pFrmHeapHd->pState = pState;
626 retVal = TRUE;
627 }
628 ret_:
629 UnlockHeap( heap );
630
631 return retVal;
632 }
633
634 /*---------------------------------------------------------------------------*
635 Name: MEMFreeByStateToFrmHeap
636
637 Description: This function returns the frame heap memory block based on the recorded status.
638 This function uses the specified tag name to restore the memory usage status in effect immediately prior to
639 calling RecordStateForFrmHeap().
640 If 0 is specified for the tag name the status is returned to that in effect
641 right before the last call of RecordStateForFrmHeap().
642
643 When a memory block is returned by specifying a tag name,
644 the recorded information will disappear if RecordStateForFrmHeap()
645 is called later.
646
647 Arguments: heap : Handle for frame heap
648 tagName: Tag name given to the status record.
649
650 Returns: Returns TRUE if successful.
651 Returns FALSE if unsuccessful.
652 *---------------------------------------------------------------------------*/
653 BOOL
MEMFreeByStateToFrmHeap(MEMHeapHandle heap,u32 tagName)654 MEMFreeByStateToFrmHeap(
655 MEMHeapHandle heap,
656 u32 tagName
657 )
658 {
659 BOOL retVal;
660 ASSERT(IsValidFrmHeapHandle_(heap));
661
662 LockHeap( heap );
663 {
664 MEMiFrmHeapHead* pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead_(heap);
665 MEMiFrmHeapState* pState = pFrmHeapHd->pState;
666
667 if ( tagName != 0 ) // The tag name specification exists
668 {
669 for ( ; pState; pState = pState->pPrevState )
670 {
671 if ( pState->tagName == tagName )
672 {
673 break;
674 }
675 }
676 }
677
678 if ( ! pState )
679 {
680 retVal = FALSE;
681 goto ret_;
682 }
683
684 {
685 void* oldHeadAllocator = pFrmHeapHd->headAllocator;
686 void* oldTailAllocator = pFrmHeapHd->tailAllocator;
687
688 pFrmHeapHd->headAllocator = pState->headAllocator;
689 pFrmHeapHd->tailAllocator = pState->tailAllocator;
690 pFrmHeapHd->pState = pState->pPrevState;
691
692 FillFreeMemory( heap,
693 pFrmHeapHd->headAllocator,
694 GetOffsetFromPtr(pFrmHeapHd->headAllocator, oldHeadAllocator) );
695 FillFreeMemory( heap,
696 oldTailAllocator,
697 GetOffsetFromPtr(oldTailAllocator, pFrmHeapHd->tailAllocator) );
698 }
699
700 retVal = TRUE;
701 }
702 ret_:
703 UnlockHeap( heap );
704 return retVal;
705 }
706
707 /*---------------------------------------------------------------------------*
708 Name: MEMAdjustFrmHeap
709
710 Description: This function frees the open region of the frame heap from the
711 heap region and reduces the heap region by that amount.
712 There must not be memory blocks allocated from the back of heap memory.
713
714 Arguments: heap : Handle for frame heap
715
716 Returns: Returns the frame heap size in bytes after reduction if successful.
717 (in bytes).
718 Returns 0 if unsuccessful.
719 *---------------------------------------------------------------------------*/
720 u32
MEMAdjustFrmHeap(MEMHeapHandle heap)721 MEMAdjustFrmHeap( MEMHeapHandle heap )
722 {
723 ASSERT(IsValidFrmHeapHandle_(heap));
724
725 {
726 MEMiHeapHead* pHeapHd = heap;
727 MEMiFrmHeapHead* pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead_( pHeapHd );
728 u32 retVal;
729
730 LockHeap( heap );
731
732 // The function fails if there are any memory blocks allocated from end.
733 if ( 0 < GetOffsetFromPtr( pFrmHeapHd->tailAllocator, pHeapHd->heapEnd ) )
734 {
735 retVal = 0;
736 goto ret_;
737 }
738
739 pFrmHeapHd->tailAllocator = pHeapHd->heapEnd = pFrmHeapHd->headAllocator;
740
741 retVal = GetOffsetFromPtr( heap, pHeapHd->heapEnd );
742 ret_:
743 UnlockHeap( heap );
744 return retVal;
745 }
746 }
747
748 /*---------------------------------------------------------------------------*
749 Name: MEMResizeForMBlockFrmHeap
750
751 Description: This function changes the size of the memory block allocated from the frame heap.
752
753 The memory block to be resized must be the end
754 memory block allocated in the forward direction from the available region of the heap.
755
756 Arguments: heap : Handle for frame heap
757 memBlock: Pointer to the memory block to be resized.
758 newSize: The new size to be allocated (in bytes).
759 If a value less than 4 is specified processing is performed as if 4 was specified.
760
761 Returns: Returns the size of the resized memory block (in bytes) if the function is successful.
762 Returns 0 if the function fails.
763 *---------------------------------------------------------------------------*/
764 u32
MEMResizeForMBlockFrmHeap(MEMHeapHandle heap,void * memBlock,u32 newSize)765 MEMResizeForMBlockFrmHeap(
766 MEMHeapHandle heap,
767 void* memBlock,
768 u32 newSize
769 )
770 {
771 MEMiHeapHead* pHeapHd = NULL;
772 MEMiFrmHeapHead* pFrmHeapHd = NULL;
773
774 ASSERT(IsValidFrmHeapHandle_(heap));
775 ASSERT(memBlock == RoundDownPtr(memBlock, MIN_ALIGNMENT)); // Check if at the minimum alignment boundary.
776
777 pHeapHd = heap;
778 pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead_( pHeapHd );
779
780 ASSERT( ComparePtr(pHeapHd->heapStart, memBlock) <= 0
781 && ComparePtr(pFrmHeapHd->headAllocator, memBlock) > 0 ); // Be sure that memory blocks exist in the forward direction
782 ASSERT( pFrmHeapHd->pState == NULL
783 || ComparePtr(pFrmHeapHd->pState, memBlock) < 0 ); // Be sure that there is no status saved after the memory block
784
785 /*
786 Set up so newSize cannot be 0.
787 If it is somehow 0, it's because the memory block specified by memBlock has ceased to exist.
788 */
789 if ( newSize == 0 )
790 {
791 newSize = 1;
792 }
793 newSize = RoundUp( newSize, MIN_ALIGNMENT );
794
795 LockHeap( heap );
796 {
797 const u32 oldSize = GetOffsetFromPtr( memBlock, pFrmHeapHd->headAllocator );
798 void* endAddress = AddU32ToPtr( memBlock, newSize );
799
800 if ( newSize == oldSize ) // If the block size is not changed
801 {
802 goto ret_;
803 }
804
805 if ( newSize > oldSize ) // During magnification
806 {
807 if ( ComparePtr( endAddress, pFrmHeapHd->tailAllocator ) > 0 ) // If the size is insufficient
808 {
809 newSize = 0;
810 goto ret_;
811 }
812
813 FillAllocMemory( heap, pFrmHeapHd->headAllocator, newSize - oldSize );
814 }
815 else // During reduction
816 {
817 FillFreeMemory( heap, endAddress, oldSize - newSize );
818 }
819
820 pFrmHeapHd->headAllocator = endAddress;
821 }
822 ret_:
823 UnlockHeap( heap );
824 return newSize;
825 }
826
827
828
829
830