1 /*---------------------------------------------------------------------------*
2 Project: MEM library
3 File: mem_frameHeap.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 #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: Gets 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 to the allocated memory block if the memory block was successfully allocated.
134
135 If the operation 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 end 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 to the allocated memory block if the memory block was successfully allocated.
173
174 If the operation 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: Deallocates 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: Deallocates the memory blocks allocated from 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 Reset the save data end allocation pointer to avoid restoring deallocated memory blocks resulting from the recovery of the heap allocation status.
245
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 the 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 the 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 information in the frame heap.
327 This function is used for debugging.
328
329 Arguments: heap: Handle for the 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 MEM_INVALID_HEAP_HANDLE is returned if the function fails.
394
395 Memo: This is essentially not thread-safe.
396 To make it thread safe, please try to add the argument specifying the heap attribute or suppress the function that sets the attribute.
397
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 the handle value.
423 }
424 }
425
426
427 /*---------------------------------------------------------------------------*
428 Name: MEMDestroyFrmHeap
429
430 Description: Destroys the frame heap.
431
432 Arguments: heap: Handle for the 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 available region is searched for from the back of the heap.
451
452 Arguments: heap: Handle for the 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: + or - 4, + or - 8, + or - 16, + or - 32, + or - 64, + or - 128, ...
456
457 Returns: Returns the pointer to the allocated memory block if the memory block was successfully allocated.
458
459 If the operation 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 the 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: Gets the maximum allocatable size in the frame heap.
540 The memory block alignment can be specified.
541
542 Arguments: heap: Handle for the frame heap
543 alignment: Alignment of the memory block to be allocated
544 The following values can be specified: + or - 4, + or - 8, + or - 16, + or - 32, + or - 64, + or - 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 the 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 calling RecordStateForFrmHeap().
639
640 If 0 is specified for the tag name the status is returned to that in effect the last time RecordStateForFrmHeap() was called.
641
642
643 When a memory block is returned by specifying a tag name, the information recorded with RecordStateForFrmHeap() which is called later will disappear.
644
645
646
647 Arguments: heap: Handle for the 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 deallocates an available region of the frame heap from the heap region and reduces the heap region by that amount.
711
712 There must not be memory blocks allocated from the back of heap memory.
713
714
715 Arguments: heap: Handle for the frame heap
716
717 Returns: Returns the frame heap size in bytes after reduction if successful.
718
719 Returns 0 if unsuccessful.
720 *---------------------------------------------------------------------------*/
721 u32
MEMAdjustFrmHeap(MEMHeapHandle heap)722 MEMAdjustFrmHeap( MEMHeapHandle heap )
723 {
724 ASSERT(IsValidFrmHeapHandle_(heap));
725
726 {
727 MEMiHeapHead* pHeapHd = heap;
728 MEMiFrmHeapHead* pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead_( pHeapHd );
729 u32 retVal;
730
731 LockHeap( heap );
732
733 // The function fails if there are any memory blocks allocated from the end.
734 if ( 0 < GetOffsetFromPtr( pFrmHeapHd->tailAllocator, pHeapHd->heapEnd ) )
735 {
736 retVal = 0;
737 goto ret_;
738 }
739
740 pFrmHeapHd->tailAllocator = pHeapHd->heapEnd = pFrmHeapHd->headAllocator;
741
742 retVal = GetOffsetFromPtr( heap, pHeapHd->heapEnd );
743 ret_:
744 UnlockHeap( heap );
745 return retVal;
746 }
747 }
748
749 /*---------------------------------------------------------------------------*
750 Name: MEMResizeForMBlockFrmHeap
751
752 Description: This function changes the size of the memory block allocated from the frame heap.
753
754 The memory block to be resized must be the end memory block allocated in the front of the available region of the heap.
755
756
757 Arguments: heap: Handle for the frame heap
758 memBlock: Pointer to the memory block to be resized.
759 newSize: The new size to be allocated (in bytes).
760 If a value less than 4 is specified, processing is performed as if 4 was specified.
761
762 Returns: Returns the size of the resized memory block (in bytes) if the function is successful.
763 Returns 0 if the function fails.
764 *---------------------------------------------------------------------------*/
765 u32
MEMResizeForMBlockFrmHeap(MEMHeapHandle heap,void * memBlock,u32 newSize)766 MEMResizeForMBlockFrmHeap(
767 MEMHeapHandle heap,
768 void* memBlock,
769 u32 newSize
770 )
771 {
772 MEMiHeapHead* pHeapHd = NULL;
773 MEMiFrmHeapHead* pFrmHeapHd = NULL;
774
775 ASSERT(IsValidFrmHeapHandle_(heap));
776 ASSERT(memBlock == RoundDownPtr(memBlock, MIN_ALIGNMENT)); // Check if at the minimum alignment boundary.
777
778 pHeapHd = heap;
779 pFrmHeapHd = GetFrmHeapHeadPtrFromHeapHead_( pHeapHd );
780
781 ASSERT( ComparePtr(pHeapHd->heapStart, memBlock) <= 0
782 && ComparePtr(pFrmHeapHd->headAllocator, memBlock) > 0 ); // Be sure that memory blocks exist at the front
783 ASSERT( pFrmHeapHd->pState == NULL
784 || ComparePtr(pFrmHeapHd->pState, memBlock) < 0 ); // Be sure that there is no status saved after the memory block
785
786 /*
787 Have set up so newSize cannot be 0.
788 This is because if newSize is somehow 0, the memory block specified by memBlock has ceased to exist.
789 */
790 if ( newSize == 0 )
791 {
792 newSize = 1;
793 }
794 newSize = RoundUp( newSize, MIN_ALIGNMENT );
795
796 LockHeap( heap );
797 {
798 const u32 oldSize = GetOffsetFromPtr( memBlock, pFrmHeapHd->headAllocator );
799 void* endAddress = AddU32ToPtr( memBlock, newSize );
800
801 if ( newSize == oldSize ) // If the block size is not changed
802 {
803 goto ret_;
804 }
805
806 if ( newSize > oldSize ) // During magnification
807 {
808 if ( ComparePtr( endAddress, pFrmHeapHd->tailAllocator ) > 0 ) // If the size is insufficient
809 {
810 newSize = 0;
811 goto ret_;
812 }
813
814 FillAllocMemory( heap, pFrmHeapHd->headAllocator, newSize - oldSize );
815 }
816 else // During reduction
817 {
818 FillFreeMemory( heap, endAddress, oldSize - newSize );
819 }
820
821 pFrmHeapHd->headAllocator = endAddress;
822 }
823 ret_:
824 UnlockHeap( heap );
825 return newSize;
826 }
827
828
829
830
831