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