1 /*---------------------------------------------------------------------------*
2 Project: MEM library
3 File: mem_expHeap.c
4 Programmers: Makoto Takano
5
6 Copyright (C)2005-2006 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 #include <revolution/mem/expHeap.h>
15 #include "heapCommoni.h"
16 #include <stdlib.h>
17
18
19 /* ========================================================================
20 Macro Constants
21 ======================================================================== */
22
23 // signature for free memory block
24 #define MBLOCK_FREE_SIGNATURE ('FR')
25
26 // signature for the memory block being used
27 #define MBLOCK_USED_SIGNATURE ('UD')
28
29 // maximum value for the group ID
30 #define MAX_GROUPID 0xff
31
32 // default value for the group ID
33 #define DEFAULT_GROUPID 0
34
35 // minimum value for alignment
36 #define MIN_ALIGNMENT 4
37
38 // default memory allocation mode
39 #define DEFAULT_ALLOC_MODE MEM_EXPHEAP_ALLOC_MODE_FIRST
40
41 // minimum size to register as a free block (size not including header)
42 #define MIN_FREE_BLOCK_SIZE 4
43 // #define MIN_FREE_BLOCK_SIZE 16
44
45 /* ========================================================================
46 Structure definitions
47 ======================================================================== */
48
49 typedef struct MemRegion MemRegion;
50
51 struct MemRegion
52 {
53 void* start;
54 void* end;
55 };
56
57 /* ========================================================================
58 Macro Functions
59 ======================================================================== */
60
61 #if defined(_DEBUG)
62
63 // for warning output when checking the heap
64 #define HEAP_WARNING(exp, ...) \
65 (void) ((exp) && (OSReport(__VA_ARGS__), 0))
66
67 // #if defined(_DEBUG)
68 #endif
69
70
71 /* ========================================================================
72 static functions
73 ======================================================================== */
74
75 /* ------------------------------------------------------------------------
76 pointer operations
77 ------------------------------------------------------------------------ */
78
79 /*---------------------------------------------------------------------------*
80 Name: MaxPtr_
81
82 Description: Get the larger address for two pointers
83
84 Arguments: a, b Pointers to be compared
85
86 Returns: a If the a address is larger
87 b If the b address is larger
88 *---------------------------------------------------------------------------*/
89 static inline void*
MaxPtr_(void * a,void * b)90 MaxPtr_( void* a, void* b )
91 {
92 return GetUIntPtr(a) > GetUIntPtr(b) ? a: b;
93 }
94
95 /*---------------------------------------------------------------------------*
96 Name: IsValidExpHeapHandle_
97
98 Description: Checks the signature to determine whether the expansion heap handle is valid.
99
100 Arguments: handle: the heap handle
101
102 Returns: TRUE The heap handle is valid
103 FALSE The heap handle is not valid
104 *---------------------------------------------------------------------------*/
105 static inline BOOL
IsValidExpHeapHandle_(MEMHeapHandle handle)106 IsValidExpHeapHandle_( MEMHeapHandle handle )
107 {
108 if ( handle == MEM_HEAP_INVALID_HANDLE )
109 {
110 return FALSE;
111 }
112
113 {
114 MEMiHeapHead* pHeapHd = handle;
115 return pHeapHd->signature == MEMi_EXPHEAP_SIGNATURE;
116 }
117 }
118
119 /*---------------------------------------------------------------------------*
120 Name: GetExpHeapHeadPtrFromHeapHead_
121
122 Description: Gets the pointer to the expanded heap header from the pointer to the heap header.
123
124 Arguments: pHHead: pointer to the heap header
125
126 Returns: Returns the pointer to the expanded heap header.
127 *---------------------------------------------------------------------------*/
128 static inline MEMiExpHeapHead*
GetExpHeapHeadPtrFromHeapHead_(MEMiHeapHead * pHHead)129 GetExpHeapHeadPtrFromHeapHead_( MEMiHeapHead* pHHead )
130 {
131 return (MEMiExpHeapHead*)AddU32ToPtr( pHHead, sizeof(MEMiHeapHead) );
132 }
133
134 /*---------------------------------------------------------------------------*
135 Name: GetHeapHeadPtrFromExpHeapHead_
136
137 Description: Gets the pointer to the heap header from the pointer to the expanded heap header.
138
139 Arguments: pEHHead: pointer to the expanded heap header
140
141 Returns: Returns the pointer to the heap header.
142 *---------------------------------------------------------------------------*/
143 static inline MEMiHeapHead*
GetHeapHeadPtrFromExpHeapHead_(MEMiExpHeapHead * pEHHead)144 GetHeapHeadPtrFromExpHeapHead_( MEMiExpHeapHead* pEHHead )
145 {
146 return (MEMiHeapHead*)SubU32ToPtr( pEHHead, sizeof(MEMiHeapHead) );
147 }
148
149 /*---------------------------------------------------------------------------*
150 Name: GetExpHeapHeadPtrFromHandle_
151
152 Description: Gets the pointer to the expanded heap header from the expanded heap handle.
153
154 Arguments: heap: expanded heap handle
155
156 Returns: Returns the pointer to the expanded heap header.
157 *---------------------------------------------------------------------------*/
158 static inline MEMiExpHeapHead*
GetExpHeapHeadPtrFromHandle_(MEMHeapHandle heap)159 GetExpHeapHeadPtrFromHandle_( MEMHeapHandle heap )
160 {
161 return (MEMiExpHeapHead*)GetExpHeapHeadPtrFromHeapHead_( heap );
162 }
163
164 /*---------------------------------------------------------------------------*
165 Name: GetMemPtrForMBlock_
166
167 Description: Gets a pointer to a memory block from a pointer to a MEMiExpHeapMBlockHead structure.
168
169
170 Arguments: pMBlkHd: pointer to the MEMiExpHeapMBlockHead structure
171
172 Returns: Returns the pointer to the memory block.
173 *---------------------------------------------------------------------------*/
174 static inline void*
GetMemPtrForMBlock_(MEMiExpHeapMBlockHead * pMBlkHd)175 GetMemPtrForMBlock_( MEMiExpHeapMBlockHead* pMBlkHd )
176 {
177 return AddU32ToPtr( pMBlkHd, sizeof(MEMiExpHeapMBlockHead) );
178 }
179
180 static inline const void*
GetMemCPtrForMBlock_(const MEMiExpHeapMBlockHead * pMBlkHd)181 GetMemCPtrForMBlock_( const MEMiExpHeapMBlockHead* pMBlkHd )
182 {
183 return AddU32ToCPtr( pMBlkHd, sizeof(MEMiExpHeapMBlockHead) );
184 }
185
186 /*---------------------------------------------------------------------------*
187 Name: GetMBlockHeadPtr_
188
189 Description: Gets a pointer to a MEMiExpHeapMBlockHead structure from a pointer to a memory block.
190
191 Gets the pointer to the memory block.
192
193 Arguments: memBlock: pointer to the memory block
194
195 Returns: Returns a pointer to a MEMiExpHeapMBlockHead structure.
196 *---------------------------------------------------------------------------*/
197 static inline MEMiExpHeapMBlockHead*
GetMBlockHeadPtr_(void * memBlock)198 GetMBlockHeadPtr_( void* memBlock )
199 {
200 return (MEMiExpHeapMBlockHead*)SubU32ToPtr(memBlock, sizeof(MEMiExpHeapMBlockHead));
201 }
202
203 static inline const MEMiExpHeapMBlockHead*
GetMBlockHeadCPtr_(const void * memBlock)204 GetMBlockHeadCPtr_( const void* memBlock )
205 {
206 return (const MEMiExpHeapMBlockHead*)SubU32ToCPtr(memBlock, sizeof(MEMiExpHeapMBlockHead));
207 }
208
209 /*---------------------------------------------------------------------------*
210 Name: GetMBlockEndAddr_
211
212 Description: Gets the terminal memory address from a memory block pointer.
213
214
215 Arguments: pMBHead: pointer to the MEMiExpHeapMBlockHead structure
216
217 Returns: Returns the terminal address of the memory block.
218 *---------------------------------------------------------------------------*/
219 static inline void*
GetMBlockEndAddr_(MEMiExpHeapMBlockHead * pMBHead)220 GetMBlockEndAddr_( MEMiExpHeapMBlockHead* pMBHead )
221 {
222 return AddU32ToPtr( GetMemPtrForMBlock_(pMBHead), pMBHead->blockSize );
223 }
224
225 /* ------------------------------------------------------------------------
226 MEMiExpHeapMBlockHead Structure Access Functions
227 ------------------------------------------------------------------------ */
228
229 /*---------------------------------------------------------------------------*
230 Name: GetAlignmentForMBlock_
231
232 Description: Gets the alignment value for the MEMiExpHeapMBlockHead structure.
233
234 Arguments: pMBlkHd: pointer to the MEMiExpHeapMBlockHead structure
235
236 Returns: Returns the alignment value for the MEMiExpHeapMBlockHead structure.
237 *---------------------------------------------------------------------------*/
238 static inline u16
GetAlignmentForMBlock_(const MEMiExpHeapMBlockHead * pMBlkHd)239 GetAlignmentForMBlock_( const MEMiExpHeapMBlockHead* pMBlkHd )
240 {
241 return pMBlkHd->attribute.fields.alignment;
242 }
243
244 /*---------------------------------------------------------------------------*
245 Name: SetAlignmentForMBlock_
246
247 Description: Sets the alignment value for the MEMiExpHeapMBlockHead structure.
248
249 Arguments: pMBlkHd: pointer to the MEMiExpHeapMBlockHead structure
250 alignment: alignment value to be set
251
252 Returns: None.
253 *---------------------------------------------------------------------------*/
254 static inline void
SetAlignmentForMBlock_(MEMiExpHeapMBlockHead * pMBlkHd,u16 alignment)255 SetAlignmentForMBlock_(
256 MEMiExpHeapMBlockHead* pMBlkHd,
257 u16 alignment
258 )
259 {
260 pMBlkHd->attribute.fields.alignment = alignment;
261 }
262
263
264 /*---------------------------------------------------------------------------*
265 Name: GetGroupIDForMBlock_
266
267 Description: Gets the group ID for the MEMiExpHeapMBlockHead structure
268
269 Arguments: pMBlkHd: pointer to the MEMiExpHeapMBlockHead structure
270
271 Returns: Returns the group ID value.
272 *---------------------------------------------------------------------------*/
273 static inline u16
GetGroupIDForMBlock_(const MEMiExpHeapMBlockHead * pMBHead)274 GetGroupIDForMBlock_( const MEMiExpHeapMBlockHead* pMBHead )
275 {
276 return pMBHead->attribute.fields.groupID;
277 }
278
279 /*---------------------------------------------------------------------------*
280 Name: SetGroupIDForMBlock_
281
282 Description: Sets the group ID for the MEMiExpHeapMBlockHead structure.
283
284 Arguments: pMBlkHd: pointer to the MEMiExpHeapMBlockHead structure
285 id: The group ID to be set
286
287 Returns: None.
288 *---------------------------------------------------------------------------*/
289 static inline void
SetGroupIDForMBlock_(MEMiExpHeapMBlockHead * pMBHead,u16 id)290 SetGroupIDForMBlock_(
291 MEMiExpHeapMBlockHead* pMBHead,
292 u16 id
293 )
294 {
295 pMBHead->attribute.fields.groupID = (u8)id;
296 }
297
298
299 /*---------------------------------------------------------------------------*
300 Name: GetAllocDirForMBlock_
301
302 Description: Gets the memory allocation direction for the MEMiExpHeapMBlockHead structure
303
304 Arguments: pMBlkHd: pointer to the MEMiExpHeapMBlockHead structure
305
306 Returns: Returns the direction for memory allocation.
307 *---------------------------------------------------------------------------*/
308 static inline u16
GetAllocDirForMBlock_(const MEMiExpHeapMBlockHead * pMBHead)309 GetAllocDirForMBlock_( const MEMiExpHeapMBlockHead* pMBHead )
310 {
311 return pMBHead->attribute.fields.allocDir;
312 }
313
314
315 /*---------------------------------------------------------------------------*
316 Name: SetAllocDirForMBlock_
317
318 Description: Sets the memory allocation direction for the MEMiExpHeapMBlockHead structure.
319
320 Arguments: pMBlkHd: pointer to the MEMiExpHeapMBlockHead structure
321 mode: The memory allocation direction to be set
322
323 Returns: None.
324 *---------------------------------------------------------------------------*/
325 static inline void
SetAllocDirForMBlock_(MEMiExpHeapMBlockHead * pMBHead,u16 mode)326 SetAllocDirForMBlock_(
327 MEMiExpHeapMBlockHead* pMBHead,
328 u16 mode
329 )
330 {
331 pMBHead->attribute.fields.allocDir = mode;
332 }
333
334
335 /* ------------------------------------------------------------------------
336 MEMiExpHeapHead Structure Access Functions
337 ------------------------------------------------------------------------ */
338
339 /*---------------------------------------------------------------------------*
340 Name: GetAllocMode_
341
342 Description: Gets the memory allocation mode for the expanded heap.
343
344 Arguments: pEHHead: pointer to the expanded heap header
345
346 Returns: Returns the memory allocation mode for the expanded heap.
347 *---------------------------------------------------------------------------*/
348 static inline u16
GetAllocMode_(MEMiExpHeapHead * pEHHead)349 GetAllocMode_( MEMiExpHeapHead* pEHHead )
350 {
351 return pEHHead->feature.fields.allocMode;
352 }
353
354 /*---------------------------------------------------------------------------*
355 Name: SetAllocMode_
356
357 Description: Sets the memory allocation mode for the expanded heap.
358
359 Arguments: pEHHead: pointer to the expanded heap header
360 mode: memory allocation mode
361
362 Returns: None.
363 *---------------------------------------------------------------------------*/
364 static inline void
SetAllocMode_(MEMiExpHeapHead * pEHHead,u16 mode)365 SetAllocMode_(
366 MEMiExpHeapHead* pEHHead,
367 u16 mode
368 )
369 {
370 pEHHead->feature.fields.allocMode = mode;
371 }
372
373
374 /*---------------------------------------------------------------------------*
375 Name: GetRegionOfMBlock_
376
377 Description: Generates the region data from the MEMiExpHeapMBlockHead structure.
378
379 Arguments: region Pointer to the region information to be generated
380 block Pointer to the memory block header
381
382 Returns: None.
383 *---------------------------------------------------------------------------*/
384 static void
GetRegionOfMBlock_(MemRegion * region,MEMiExpHeapMBlockHead * block)385 GetRegionOfMBlock_(
386 MemRegion* region,
387 MEMiExpHeapMBlockHead* block
388 )
389 {
390 region->start = SubU32ToPtr( block, GetAlignmentForMBlock_(block) );
391 region->end = GetMBlockEndAddr_(block);
392 }
393
394
395 /* ------------------------------------------------------------------------
396 memory block list operations
397 ------------------------------------------------------------------------ */
398
399 /*---------------------------------------------------------------------------*
400 Name: RemoveMBlock_
401
402 Description: Deletes the specified memory block from the memory block list.
403
404 Arguments: list Pointer to the block list
405 block Pointer to the memory block to be deleted
406
407 Returns: Pointer to the prior memory block
408 *---------------------------------------------------------------------------*/
409 static MEMiExpHeapMBlockHead*
RemoveMBlock_(MEMiExpMBlockList * list,MEMiExpHeapMBlockHead * block)410 RemoveMBlock_(
411 MEMiExpMBlockList* list,
412 MEMiExpHeapMBlockHead* block
413 )
414 {
415 MEMiExpHeapMBlockHead *const prev = block->pMBHeadPrev;
416 MEMiExpHeapMBlockHead *const next = block->pMBHeadNext;
417
418 // previous reference link
419 if ( prev )
420 {
421 prev->pMBHeadNext = next;
422 }
423 else
424 {
425 list->head = next;
426 }
427
428 // next reference link
429 if ( next )
430 {
431 next->pMBHeadPrev = prev;
432 }
433 else
434 {
435 list->tail = prev;
436 }
437
438 return prev;
439 }
440
441 /*---------------------------------------------------------------------------*
442 Name: InsertMBlock_
443
444 Description: Inserts a memory block into a memory block list.
445
446 Arguments: list Pointer to the memory block list
447 target Pointer to the memory block to be inserted
448 prev Pointer to the block where the memory block will be inserted
449
450 Returns: Pointer to target
451 *---------------------------------------------------------------------------*/
452 static MEMiExpHeapMBlockHead*
InsertMBlock_(MEMiExpMBlockList * list,MEMiExpHeapMBlockHead * target,MEMiExpHeapMBlockHead * prev)453 InsertMBlock_(
454 MEMiExpMBlockList* list,
455 MEMiExpHeapMBlockHead* target,
456 MEMiExpHeapMBlockHead* prev
457 )
458 {
459 MEMiExpHeapMBlockHead* next;
460
461 // previous reference link
462 target->pMBHeadPrev = prev;
463 if ( prev )
464 {
465 next = prev->pMBHeadNext;
466 prev->pMBHeadNext = target;
467 }
468 else
469 {
470 next = list->head;
471 list->head = target;
472 }
473
474 // next reference link
475 target->pMBHeadNext = next;
476 if ( next )
477 {
478 next->pMBHeadPrev = target;
479 }
480 else
481 {
482 list->tail = target;
483 }
484
485 return target;
486 }
487
488 /*---------------------------------------------------------------------------*
489 Name: AppendMBlock_
490
491 Description: Adds a memory block to the end of the list.
492
493 Arguments: link: list to be added to
494 block: memory block to add
495
496 Returns: None.
497 *---------------------------------------------------------------------------*/
498 static inline void
AppendMBlock_(MEMiExpMBlockList * list,MEMiExpHeapMBlockHead * block)499 AppendMBlock_(
500 MEMiExpMBlockList* list,
501 MEMiExpHeapMBlockHead* block
502 )
503 {
504 (void)InsertMBlock_( list, block, list->tail );
505 }
506
507 /*---------------------------------------------------------------------------*
508 Name: InitMBlock_
509
510 Description: Initializes a memory block.
511
512 Arguments: pRegion: pointer to the structure representing the region used for the memory block
513 signature: memory block signature
514
515 Returns: Returns the pointer to the initialized memory block.
516 *---------------------------------------------------------------------------*/
517 static MEMiExpHeapMBlockHead*
InitMBlock_(MemRegion * pRegion,u16 signature)518 InitMBlock_(
519 MemRegion* pRegion,
520 u16 signature
521 )
522 {
523 MEMiExpHeapMBlockHead* block = (MEMiExpHeapMBlockHead*)pRegion->start;
524
525 block->signature = signature; /* Embed the signature */
526 block->attribute.val = 0; /* Clear the attribute parameters */
527
528 // Set the size from the memory block's starting position to the next region as blockSize
529 block->blockSize = GetOffsetFromPtr( GetMemPtrForMBlock_(block), pRegion->end );
530
531 block->pMBHeadPrev = NULL;
532 block->pMBHeadNext = NULL;
533
534 return block;
535 }
536
537 /*---------------------------------------------------------------------------*
538 Name: InitFreeMBlock_
539
540 Description: Initializes the memory block for use as a free block.
541
542 Arguments: pRegion: pointer to the structure representing the region used for the memory block
543
544 Returns: Returns the pointer to the initialized memory block.
545 *---------------------------------------------------------------------------*/
546 static inline MEMiExpHeapMBlockHead*
InitFreeMBlock_(MemRegion * pRegion)547 InitFreeMBlock_( MemRegion* pRegion )
548 {
549 return InitMBlock_( pRegion, MBLOCK_FREE_SIGNATURE );
550 }
551
552 /*---------------------------------------------------------------------------*
553 Name: InitExpHeap_
554
555 Description: Initializes the expanded heap.
556
557 Arguments: startAddress: memory start address for the expanded heap
558 endAddress: terminal address for the memory for the expanded heap incremented by one
559 optFlag: option flag
560
561 Returns: Returns the pointer to the heap header.
562 *---------------------------------------------------------------------------*/
563 static MEMiHeapHead*
InitExpHeap_(void * startAddress,void * endAddress,u16 optFlag)564 InitExpHeap_(
565 void* startAddress,
566 void* endAddress,
567 u16 optFlag
568 )
569 {
570 MEMiHeapHead* pHeapHd = (MEMiHeapHead*)startAddress;
571 MEMiExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_( pHeapHd );
572
573 MEMiInitHeapHead( // common heap initializations
574 pHeapHd,
575 MEMi_EXPHEAP_SIGNATURE,
576 AddU32ToPtr( pExpHeapHd, sizeof(MEMiExpHeapHead) ), // heapStart
577 endAddress, // heapEnd
578 optFlag );
579
580 pExpHeapHd->groupID = DEFAULT_GROUPID; // Group ID
581 pExpHeapHd->feature.val = 0;
582 SetAllocMode_( pExpHeapHd, DEFAULT_ALLOC_MODE );
583
584 // create a free block
585 {
586 MEMiExpHeapMBlockHead* pMBHead;
587 MemRegion region;
588
589 region.start = pHeapHd->heapStart;
590 region.end = pHeapHd->heapEnd;
591 pMBHead = InitFreeMBlock_( ®ion );
592
593 // block list
594 pExpHeapHd->mbFreeList.head = pMBHead;
595 pExpHeapHd->mbFreeList.tail = pMBHead;
596 pExpHeapHd->mbUsedList.head = NULL;
597 pExpHeapHd->mbUsedList.tail = NULL;
598
599 return pHeapHd;
600 }
601 }
602
603 /*---------------------------------------------------------------------------*
604 Name: AllocUsedBlockFromFreeBlock_
605
606 Description: Allocates a new memory block from free blocks.
607
608 Arguments: pEHHead: Pointer to the expanded heap header.
609 pMBHeadFree: Pointer to the free block header.
610 mblock: Address for the memory block to be allocated.
611 size: Size of the memory block to be allocated.
612 direction: Allocation direction.
613
614 Returns: Returns a pointer to the start of the allocated memory block.
615 *---------------------------------------------------------------------------*/
616 static void*
AllocUsedBlockFromFreeBlock_(MEMiExpHeapHead * pEHHead,MEMiExpHeapMBlockHead * pMBHeadFree,void * mblock,u32 size,u16 direction)617 AllocUsedBlockFromFreeBlock_(
618 MEMiExpHeapHead* pEHHead,
619 MEMiExpHeapMBlockHead* pMBHeadFree,
620 void* mblock,
621 u32 size,
622 u16 direction
623 )
624 {
625 MemRegion freeRgnT;
626 MemRegion freeRgnB;
627 MEMiExpHeapMBlockHead* pMBHeadFreePrev;
628
629 GetRegionOfMBlock_( &freeRgnT, pMBHeadFree );
630 freeRgnB.end = freeRgnT.end;
631 freeRgnB.start = AddU32ToPtr( mblock, size );
632 freeRgnT.end = SubU32ToPtr( mblock, sizeof(MEMiExpHeapMBlockHead) );
633
634 pMBHeadFreePrev = RemoveMBlock_( &pEHHead->mbFreeList, pMBHeadFree ); // delete the free block for the time being
635
636 // when there is no space for creating a free block
637 if ( ( GetOffsetFromPtr(freeRgnT.start, freeRgnT.end) < sizeof(MEMiExpHeapMBlockHead) + MIN_FREE_BLOCK_SIZE ) ||
638 ( direction == MEM_EXPHEAP_ALLOC_DIR_FRONT && !pEHHead->feature.fields.useMarginOfAlign ) )
639 {
640 freeRgnT.end = freeRgnT.start; // include the alignment value for the block being used
641 }
642 else
643 {
644 pMBHeadFreePrev = InsertMBlock_( &pEHHead->mbFreeList, InitFreeMBlock_(&freeRgnT), pMBHeadFreePrev );
645 }
646
647 // when there is no space for creating a free block
648 if ( ( GetOffsetFromPtr(freeRgnB.start, freeRgnB.end) < sizeof(MEMiExpHeapMBlockHead) + MIN_FREE_BLOCK_SIZE ) ||
649 ( direction == MEM_EXPHEAP_ALLOC_DIR_REAR && !pEHHead->feature.fields.useMarginOfAlign ) )
650 {
651 freeRgnB.start= freeRgnB.end; // include the block being used
652 }
653 else
654 {
655 (void)InsertMBlock_( &pEHHead->mbFreeList, InitFreeMBlock_(&freeRgnB), pMBHeadFreePrev );
656 }
657
658 // fill the memory for debugging
659 FillAllocMemory(
660 GetHeapHeadPtrFromExpHeapHead_(pEHHead),
661 freeRgnT.end,
662 GetOffsetFromPtr(freeRgnT.end, freeRgnB.start)
663 );
664
665 // create a new block
666 {
667 MEMiExpHeapMBlockHead* pMBHeadNewUsed;
668 MemRegion region;
669
670 region.start = SubU32ToPtr( mblock, sizeof(MEMiExpHeapMBlockHead) );
671 region.end = freeRgnB.start;
672
673 pMBHeadNewUsed = InitMBlock_(®ion, MBLOCK_USED_SIGNATURE );
674 SetAllocDirForMBlock_( pMBHeadNewUsed, direction );
675 SetAlignmentForMBlock_( pMBHeadNewUsed, (u16)GetOffsetFromPtr(freeRgnT.end, pMBHeadNewUsed) );
676 SetGroupIDForMBlock_( pMBHeadNewUsed, pEHHead->groupID );
677 AppendMBlock_( &pEHHead->mbUsedList, pMBHeadNewUsed );
678 }
679
680 return mblock;
681 }
682
683 /*---------------------------------------------------------------------------*
684 Name: AllocFromHead_
685
686 Description: Allocates the memory block from the start of the heap.
687
688 Arguments: pHeapHd: pointer to the heap header
689 size: size of the memory block to be allocated
690 alignment: alignment value
691
692 Returns: Returns a pointer to the allocated memory block if it was successfully allocated.
693
694 If the operation fails, NULL is returned.
695 *---------------------------------------------------------------------------*/
696 static void*
AllocFromHead_(MEMiHeapHead * pHeapHd,u32 size,int alignment)697 AllocFromHead_(
698 MEMiHeapHead* pHeapHd,
699 u32 size,
700 int alignment
701 )
702 {
703 MEMiExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_(pHeapHd);
704
705 // Allocate the first one found?
706 const BOOL bAllocFirst = GetAllocMode_(pExpHeapHd) == MEM_EXPHEAP_ALLOC_MODE_FIRST;
707
708 MEMiExpHeapMBlockHead* pMBlkHd = NULL;
709 MEMiExpHeapMBlockHead* pMBlkHdFound = NULL;
710 u32 foundSize = 0xffffffff;
711 void* foundMBlock = NULL;
712
713 // search for free block
714 for ( pMBlkHd = pExpHeapHd->mbFreeList.head; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadNext )
715 {
716 void *const mblock = GetMemPtrForMBlock_(pMBlkHd);
717 void *const reqMBlock = RoundUpPtr( mblock, alignment );
718 const u32 offset = GetOffsetFromPtr( mblock, reqMBlock ); // generated offset
719
720 if ( pMBlkHd->blockSize >= size + offset &&
721 foundSize > pMBlkHd->blockSize )
722 {
723 pMBlkHdFound = pMBlkHd;
724 foundSize = pMBlkHd->blockSize;
725 foundMBlock = reqMBlock;
726
727 if ( bAllocFirst || foundSize == size )
728 {
729 break;
730 }
731 }
732 }
733
734 if ( ! pMBlkHdFound ) // no blocks matching the conditions were found
735 {
736 return NULL;
737 }
738
739 return AllocUsedBlockFromFreeBlock_( // allocate a region from the free block that was found
740 pExpHeapHd,
741 pMBlkHdFound,
742 foundMBlock,
743 size,
744 MEM_EXPHEAP_ALLOC_DIR_FRONT
745 );
746 }
747
748 /*---------------------------------------------------------------------------*
749 Name: AllocFromTail_
750
751 Description: Allocates a memory block from the end of the heap.
752
753 Arguments: pHeapHd: pointer to the heap header
754 size: size of the memory block to be allocated
755 alignment: alignment value
756
757 Returns: Returns a pointer to the allocated memory block if it was successfully allocated.
758
759 If the operation fails, NULL is returned.
760 *---------------------------------------------------------------------------*/
761 static void*
AllocFromTail_(MEMiHeapHead * pHeapHd,u32 size,int alignment)762 AllocFromTail_(
763 MEMiHeapHead* pHeapHd,
764 u32 size,
765 int alignment
766 )
767 {
768 MEMiExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_(pHeapHd);
769
770 // Allocate the first one found?
771 const BOOL bAllocFirst = GetAllocMode_(pExpHeapHd) == MEM_EXPHEAP_ALLOC_MODE_FIRST;
772
773 MEMiExpHeapMBlockHead* pMBlkHd = NULL;
774 MEMiExpHeapMBlockHead* pMBlkHdFound = NULL;
775 u32 foundSize = 0xffffffff;
776 void* foundMBlock = NULL;
777
778 // search for free block
779 for ( pMBlkHd = pExpHeapHd->mbFreeList.tail; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadPrev )
780 {
781 void *const mblock = GetMemPtrForMBlock_(pMBlkHd);
782 void *const mblockEnd = AddU32ToPtr( mblock, pMBlkHd->blockSize );
783 void *const reqMBlock = RoundDownPtr( SubU32ToPtr(mblockEnd, size), alignment ); // aligned address
784
785 if ( ComparePtr( reqMBlock, mblock ) >= 0
786 && foundSize > pMBlkHd->blockSize )
787 {
788 pMBlkHdFound = pMBlkHd;
789 foundSize = pMBlkHd->blockSize;
790 foundMBlock = reqMBlock;
791
792 if ( bAllocFirst || foundSize == size )
793 {
794 break;
795 }
796 }
797 }
798
799 if ( ! pMBlkHdFound ) // no blocks matching the conditions were found
800 {
801 return NULL;
802 }
803
804 return AllocUsedBlockFromFreeBlock_( // allocate a region from the free block that was found
805 pExpHeapHd,
806 pMBlkHdFound,
807 foundMBlock,
808 size,
809 MEM_EXPHEAP_ALLOC_DIR_REAR
810 );
811 }
812
813 /*---------------------------------------------------------------------------*
814 Name: RecycleRegion_
815
816 Description: Incorporates an empty region into a free memory block.
817 If it is adjacent to a free block, the free block is expanded.
818 If it is not adjacent to a free block nor large enough to be used as a free block, the size of this empty region will be set as the alignment value for the used block adjacent to the end of it.
819
820
821 If there is no used block adjacent to the end of the empty region, the function fails.
822
823
824 Arguments: pEHHead: pointer to the expanded heap header
825 pRegion: pointer to the empty region
826
827 Returns: Returns TRUE if the function is successful.
828 Returns FALSE if it fails.
829 *---------------------------------------------------------------------------*/
830 static BOOL
RecycleRegion_(MEMiExpHeapHead * pEHHead,const MemRegion * pRegion)831 RecycleRegion_(
832 MEMiExpHeapHead* pEHHead,
833 const MemRegion* pRegion
834 )
835 {
836 MEMiExpHeapMBlockHead* pBlkPrFree = NULL; // immediately preceding free block
837 MemRegion freeRgn = *pRegion;
838
839 // search for free area next to the specified one
840 {
841 MEMiExpHeapMBlockHead* pBlk;
842
843 for ( pBlk = pEHHead->mbFreeList.head; pBlk; pBlk = pBlk->pMBHeadNext )
844 {
845 if ( pBlk < pRegion->start )
846 {
847 pBlkPrFree = pBlk;
848 continue;
849 }
850
851 if ( pBlk == pRegion->end ) // Is the block adjacent to the end?
852 {
853 // combine the available regions
854 freeRgn.end = GetMBlockEndAddr_(pBlk);
855 (void)RemoveMBlock_( &pEHHead->mbFreeList, pBlk );
856
857 // pad the header with NoUse
858 FillNoUseMemory( GetHeapHeadPtrFromExpHeapHead_(pEHHead), pBlk, sizeof(MEMiExpHeapMBlockHead) );
859 }
860 break;
861 }
862 }
863
864 // Is the immediately preceding free block adjacent to the front?
865 if ( pBlkPrFree && GetMBlockEndAddr_(pBlkPrFree) == pRegion->start )
866 {
867 // combine the available regions
868 freeRgn.start = pBlkPrFree;
869 pBlkPrFree = RemoveMBlock_(&pEHHead->mbFreeList, pBlkPrFree);
870 }
871
872 if ( GetOffsetFromPtr(freeRgn.start, freeRgn.end) < sizeof(MEMiExpHeapMBlockHead) ) // size is not suitable for use as a block
873 {
874 return FALSE; // Control reaches this point if an attempt is made to shrink a small block using ResizeForMBlockExpHeap() and if there are no free blocks behind it.
875 //
876 }
877
878 // fill the memory for debugging
879 FillFreeMemory( GetHeapHeadPtrFromExpHeapHead_(pEHHead), pRegion->start, GetOffsetFromPtr(pRegion->start, pRegion->end) );
880
881 (void)InsertMBlock_(
882 &pEHHead->mbFreeList,
883 InitFreeMBlock_(&freeRgn), // create the free block
884 pBlkPrFree
885 );
886
887 return TRUE;
888 }
889
890
891
892
893
894 /* ========================================================================
895 Functions to Check Operations
896 ======================================================================== */
897 #if defined(_DEBUG)
898
899 /*---------------------------------------------------------------------------*
900 Name: CheckMBlock_
901
902 Description: Checks whether the header contents for the memory block are valid.
903
904 Arguments: pMBHead: pointer to the header for the memory block to be checked
905 pHeapHd: pointer to the expanded heap header
906 signature: memory block signature
907 heapType: memory block type (used or free)
908 flag: flag
909
910 Returns: Returns TRUE if the contents of the memory block header are valid, and FALSE otherwise.
911
912 *---------------------------------------------------------------------------*/
913 static BOOL
CheckMBlock_(const MEMiExpHeapMBlockHead * pMBHead,MEMiHeapHead * pHeapHd,u16 signature,const char * heapType,u32 flag)914 CheckMBlock_(
915 const MEMiExpHeapMBlockHead* pMBHead,
916 MEMiHeapHead* pHeapHd,
917 u16 signature,
918 const char* heapType,
919 u32 flag
920 )
921 {
922 const BOOL bPrint = ( 0 != (flag & MEM_HEAP_ERROR_PRINT) );
923 const void *const memBlock = GetMemCPtrForMBlock_(pMBHead);
924
925 if ( pHeapHd )
926 {
927 if ( GetUIntPtr(pMBHead) < GetUIntPtr(pHeapHd->heapStart)
928 || GetUIntPtr(memBlock) > GetUIntPtr(pHeapHd->heapEnd)
929 )
930 {
931 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Bad %s memory block address. - address %08X, heap area [%08X - %08X)\n",
932 heapType, memBlock, pHeapHd->heapStart, pHeapHd->heapEnd);
933 return FALSE;
934 }
935 }
936 else
937 {
938 if ( GetUIntPtr(pMBHead) < 0x80000000 )
939 {
940 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Bad %s memory block address. - address %08X\n",
941 heapType, memBlock);
942 return FALSE;
943 }
944 }
945
946 if ( pMBHead->signature != signature ) // Is the signature different?
947 {
948 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Bad %s memory block signature. - address %08X, signature %04X\n",
949 heapType, memBlock, pMBHead->signature);
950 return FALSE;
951 }
952
953 if ( pMBHead->blockSize >= 0x08000000 ) // Too large? (128 MB or greater)
954 {
955 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Too large %s memory block. - address %08X, block size %08X\n",
956 heapType, memBlock, pMBHead->blockSize);
957 return FALSE;
958 }
959
960 if ( pHeapHd )
961 {
962 if ( GetUIntPtr(memBlock) + pMBHead->blockSize > GetUIntPtr(pHeapHd->heapEnd) )
963 {
964 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " wrong size %s memory block. - address %08X, block size %08X\n",
965 heapType, memBlock, pMBHead->blockSize);
966 return FALSE;
967 }
968 }
969
970 return TRUE;
971 }
972
973
974 /*---------------------------------------------------------------------------*
975 Name: CheckUsedMBlock_
976
977 Description: Checks whether the header contents for the memory block being used are valid.
978
979 Arguments: pMBHead: pointer to the header for the memory block to be checked
980 pHeapHd: pointer to the expanded heap header
981 flag: flag
982
983 Returns: Returns TRUE if the contents of the memory block header are valid, and FALSE otherwise.
984
985 *---------------------------------------------------------------------------*/
986 static inline BOOL
CheckUsedMBlock_(const MEMiExpHeapMBlockHead * pMBHead,MEMiHeapHead * pHeapHd,u32 flag)987 CheckUsedMBlock_(
988 const MEMiExpHeapMBlockHead* pMBHead,
989 MEMiHeapHead* pHeapHd,
990 u32 flag
991 )
992 {
993 if ( pHeapHd )
994 {
995 MEMiExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_(pHeapHd);
996 MEMiExpHeapMBlockHead* pMBlkHd = NULL;
997 for ( pMBlkHd = pExpHeapHd->mbUsedList.head; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadNext )
998 {
999 if ( pMBHead == pMBlkHd )
1000 {
1001 break;
1002 }
1003 }
1004 if ( pMBlkHd == NULL )
1005 {
1006 return FALSE;
1007 }
1008 }
1009 return CheckMBlock_( pMBHead, pHeapHd, MBLOCK_USED_SIGNATURE, "used", flag );
1010 }
1011
1012 /*---------------------------------------------------------------------------*
1013 Name: CheckFreeMBlock_
1014
1015 Description: Checks whether the header contents for the free memory block are valid.
1016
1017 Arguments: pMBHead: pointer to the header for the memory block to be checked
1018 pHeapHd: pointer to the expanded heap header
1019 flag: flag
1020
1021 Returns: Returns TRUE if the contents of the memory block header are valid, and FALSE otherwise.
1022
1023 *---------------------------------------------------------------------------*/
1024 static inline BOOL
CheckFreeMBlock_(const MEMiExpHeapMBlockHead * pMBHead,MEMiHeapHead * pHeapHd,u32 flag)1025 CheckFreeMBlock_(
1026 const MEMiExpHeapMBlockHead* pMBHead,
1027 MEMiHeapHead* pHeapHd,
1028 u32 flag
1029 )
1030 {
1031 return CheckMBlock_( pMBHead, pHeapHd, MBLOCK_FREE_SIGNATURE, "free", flag );
1032 }
1033
1034
1035 /*---------------------------------------------------------------------------*
1036 Name: CheckMBlockPrevPtr_
1037
1038 Description: Checks whether the link to the previous memory block is correct.
1039
1040 Arguments: pMBHead: pointer to the header for the memory block to be checked
1041 pMBHeadPrev: pointer to the header for the memory block prior to the one being checked
1042 flag: flag
1043
1044 Returns: Returns TRUE if the link to the previous memory block is correct and FALSE otherwise.
1045
1046 *---------------------------------------------------------------------------*/
1047 static BOOL
CheckMBlockPrevPtr_(const MEMiExpHeapMBlockHead * pMBHead,const MEMiExpHeapMBlockHead * pMBHeadPrev,u32 flag)1048 CheckMBlockPrevPtr_(
1049 const MEMiExpHeapMBlockHead* pMBHead,
1050 const MEMiExpHeapMBlockHead* pMBHeadPrev,
1051 u32 flag
1052 )
1053 {
1054 const BOOL bPrint = ( 0 != (flag & MEM_HEAP_ERROR_PRINT) );
1055
1056 if ( pMBHead->pMBHeadPrev != pMBHeadPrev )
1057 {
1058 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Wrong link memory block. - address %08X, previous address %08X != %08X\n",
1059 GetMemCPtrForMBlock_(pMBHead), pMBHead->pMBHeadPrev, pMBHeadPrev);
1060 return FALSE;
1061 }
1062
1063 return TRUE;
1064 }
1065
1066
1067 /*---------------------------------------------------------------------------*
1068 Name: CheckMBlockNextPtr_
1069
1070 Description: Checks whether the link to the next memory block is correct.
1071
1072 Arguments: pMBHead: pointer to the header for the memory block to be checked
1073 pMBHeadNext: pointer to the header for the memory block after the one being checked
1074 flag: flag
1075
1076 Returns: Returns TRUE if the link to the next memory block is correct and FALSE otherwise.
1077
1078 *---------------------------------------------------------------------------*/
1079 static BOOL
CheckMBlockNextPtr_(const MEMiExpHeapMBlockHead * pMBHead,const MEMiExpHeapMBlockHead * pMBHeadNext,u32 flag)1080 CheckMBlockNextPtr_(
1081 const MEMiExpHeapMBlockHead* pMBHead,
1082 const MEMiExpHeapMBlockHead* pMBHeadNext,
1083 u32 flag
1084 )
1085 {
1086 const BOOL bPrint = ( 0 != (flag & MEM_HEAP_ERROR_PRINT) );
1087
1088 if (pMBHead->pMBHeadNext != pMBHeadNext)
1089 {
1090 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Wrong link memory block. - address %08X, next address %08X != %08X\n",
1091 GetMemCPtrForMBlock_(pMBHead), pMBHead->pMBHeadNext, pMBHeadNext);
1092 return FALSE;
1093 }
1094
1095 return TRUE;
1096 }
1097
1098
1099 /*---------------------------------------------------------------------------*
1100 Name: CheckMBlockLinkTail_
1101
1102 Description: Checks whether the memory block pointer is at the start or end of the memory block list.
1103
1104 Arguments: pMBHead: pointer to the header for the memory block to be checked
1105 pMBHeadTail: pointer to the memory block at the start or end of the memory block list
1106 headType: string indicating the start or end
1107 flag: flag
1108
1109 Returns: Returns TRUE if the memory block pointer is at the start or end of the memory block list, and FALSE otherwise.
1110
1111 *---------------------------------------------------------------------------*/
1112 static BOOL
CheckMBlockLinkTail_(const MEMiExpHeapMBlockHead * pMBHead,const MEMiExpHeapMBlockHead * pMBHeadTail,const char * heapType,u32 flag)1113 CheckMBlockLinkTail_(
1114 const MEMiExpHeapMBlockHead* pMBHead,
1115 const MEMiExpHeapMBlockHead* pMBHeadTail,
1116 const char* heapType,
1117 u32 flag
1118 )
1119 {
1120 const BOOL bPrint = 0 != (flag & MEM_HEAP_ERROR_PRINT);
1121
1122 if ( pMBHead != pMBHeadTail )
1123 {
1124 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Wrong memory brock list %s pointer. - address %08X, %s address %08X != %08X\n",
1125 heapType, GetMemCPtrForMBlock_(pMBHead), heapType, pMBHead, pMBHeadTail);
1126 return FALSE;
1127 }
1128
1129 return TRUE;
1130 }
1131
1132
1133 /*---------------------------------------------------------------------------*
1134 Name: IsValidUsedMBlock_
1135
1136 Description: Checks whether the memory block being used is appropriate.
1137
1138 Arguments: memBlock: memory block to be checked
1139 heap: handle for the expanded heap containing the memory block
1140 If NULL is specified, no check is run to see if the memory block is included in the heap.
1141
1142
1143 Returns: Returns TRUE if there is no problem with the specified memory block.
1144 Returns FALSE if there is a problem.
1145 *---------------------------------------------------------------------------*/
1146 static BOOL
IsValidUsedMBlock_(const void * memBlock,MEMHeapHandle heap)1147 IsValidUsedMBlock_(
1148 const void* memBlock,
1149 MEMHeapHandle heap
1150 )
1151 {
1152 MEMiHeapHead* pHeapHd = heap;
1153 BOOL ret;
1154
1155 if ( ! memBlock)
1156 {
1157 return FALSE;
1158 }
1159
1160 if ( heap ) { LockHeap( heap ); }
1161
1162 ret = CheckUsedMBlock_(GetMBlockHeadCPtr_(memBlock), pHeapHd, 0);
1163
1164 if ( heap ) { UnlockHeap( heap ); }
1165
1166 return ret;
1167 }
1168
1169 // #if defined(_DEBUG)
1170 #endif
1171
1172
1173
1174 /* ========================================================================
1175 external functions (non-public)
1176 ======================================================================== */
1177
1178 /*---------------------------------------------------------------------------*
1179 Name: MEMiDumpExpHeap
1180
1181 Description: Shows internal expanded heap information.
1182 This function is used for debugging.
1183
1184 Arguments: heap: Handle for the expanded heap.
1185
1186 Returns: None.
1187 *---------------------------------------------------------------------------*/
1188 #if defined(_DEBUG)
1189
1190 void
MEMiDumpExpHeap(MEMHeapHandle heap)1191 MEMiDumpExpHeap( MEMHeapHandle heap )
1192 {
1193 ASSERT(IsValidExpHeapHandle_(heap));
1194
1195 {
1196 u32 usedSize = 0;
1197 u32 usedCnt = 0;
1198 u32 freeSize = 0;
1199 u32 freeCnt = 0;
1200
1201 MEMiHeapHead* pHeapHd = heap;
1202 MEMiExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHandle_(pHeapHd);
1203
1204 MEMiDumpHeapHead(pHeapHd);
1205
1206 OSReport(" attr address: size gid aln prev_ptr next_ptr\n"); // header line
1207
1208 // ---------------- UsedBlock dump ----------------
1209 OSReport(" (Used Blocks)\n" );
1210
1211 if ( pExpHeapHd->mbUsedList.head == NULL )
1212 {
1213 OSReport(" NONE\n");
1214 }
1215 else
1216 {
1217 MEMiExpHeapMBlockHead* pMBHead;
1218
1219 for ( pMBHead = pExpHeapHd->mbUsedList.head; pMBHead; pMBHead = pMBHead->pMBHeadNext )
1220 {
1221 if ( pMBHead->signature != MBLOCK_USED_SIGNATURE )
1222 {
1223 OSReport(" xxxxx %08x: -------- --- --- (-------- --------)\nabort\n", pMBHead);
1224 break;
1225 }
1226
1227 OSReport(" %s %08x: %8d %3d %3d (%08x %08x)\n",
1228 GetAllocDirForMBlock_(pMBHead) == MEM_EXPHEAP_ALLOC_DIR_REAR ? " rear" : "front",
1229 GetMemPtrForMBlock_(pMBHead),
1230 pMBHead->blockSize,
1231 GetGroupIDForMBlock_( pMBHead ),
1232 GetAlignmentForMBlock_( pMBHead ),
1233 pMBHead->pMBHeadPrev ? GetMemPtrForMBlock_(pMBHead->pMBHeadPrev): NULL,
1234 pMBHead->pMBHeadNext ? GetMemPtrForMBlock_(pMBHead->pMBHeadNext): NULL
1235 );
1236
1237 // ---- amount used
1238 usedSize += sizeof(MEMiExpHeapMBlockHead) + pMBHead->blockSize + GetAlignmentForMBlock_(pMBHead);
1239
1240 usedCnt ++;
1241 }
1242 }
1243
1244 // ---------------- FreeBlock dump ----------------
1245 OSReport(" (Free Blocks)\n" );
1246
1247 if ( pExpHeapHd->mbFreeList.head == NULL )
1248 {
1249 OSReport(" NONE\n" );
1250 }
1251 else
1252 {
1253 MEMiExpHeapMBlockHead* pMBHead;
1254
1255 for ( pMBHead = pExpHeapHd->mbFreeList.head; pMBHead; pMBHead = pMBHead->pMBHeadNext )
1256 {
1257 if ( pMBHead->signature != MBLOCK_FREE_SIGNATURE )
1258 {
1259 OSReport(" xxxxx %08x: -------- --- --- (-------- --------)\nabort\n", pMBHead);
1260 break;
1261 }
1262
1263 OSReport(" %s %08x: %8d %3d %3d (%08x %08x)\n",
1264 " free",
1265 GetMemPtrForMBlock_(pMBHead),
1266 pMBHead->blockSize,
1267 GetGroupIDForMBlock_( pMBHead ),
1268 GetAlignmentForMBlock_( pMBHead ),
1269 pMBHead->pMBHeadPrev ? GetMemPtrForMBlock_(pMBHead->pMBHeadPrev): NULL,
1270 pMBHead->pMBHeadNext ? GetMemPtrForMBlock_(pMBHead->pMBHeadNext): NULL
1271 );
1272
1273 freeCnt ++;
1274 }
1275 }
1276
1277 OSReport("\n");
1278
1279 {
1280 u32 heapSize = GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd); // heap size (data region size)
1281 OSReport(" %d / %d bytes (%6.2f%%) used (U:%d F:%d)\n",
1282 usedSize, heapSize, 100.0 * usedSize / heapSize, usedCnt, freeCnt);
1283 }
1284
1285 OSReport("\n");
1286 }
1287 }
1288
1289 // #if defined(_DEBUG)
1290 #endif
1291
1292
1293
1294 /* ========================================================================
1295 external functions (public)
1296 ======================================================================== */
1297
1298 /*---------------------------------------------------------------------------*
1299 Name: MEMCreateExpHeapEx
1300
1301 Description: Creates an expanded heap.
1302
1303 Arguments: startAddress: Start address of heap area
1304 size: Size of heap area
1305 optFlag: Option flag
1306
1307 Returns: If the function succeeds, a handle for the created expanded heap is returned.
1308 If the function fails, MEM_HEAP_INVALID_HANDLE is returned.
1309 *---------------------------------------------------------------------------*/
1310 MEMHeapHandle
MEMCreateExpHeapEx(void * startAddress,u32 size,u16 optFlag)1311 MEMCreateExpHeapEx(
1312 void* startAddress,
1313 u32 size,
1314 u16 optFlag
1315 )
1316 {
1317 void* endAddress;
1318
1319 ASSERT(startAddress != NULL);
1320
1321 endAddress = RoundDownPtr(AddU32ToPtr(startAddress, size), MIN_ALIGNMENT);
1322 startAddress = RoundUpPtr(startAddress, MIN_ALIGNMENT);
1323
1324 if ( GetUIntPtr(startAddress) > GetUIntPtr(endAddress)
1325 || GetOffsetFromPtr(startAddress, endAddress) <
1326 sizeof(MEMiHeapHead) + sizeof(MEMiExpHeapHead) + sizeof(MEMiExpHeapMBlockHead) + MIN_ALIGNMENT
1327 )
1328 {
1329 return MEM_HEAP_INVALID_HANDLE;
1330 }
1331
1332 { // initialization of the expanded heap
1333 MEMiHeapHead* pHeapHd = InitExpHeap_( startAddress, endAddress, optFlag );
1334 return pHeapHd; // the pointer to the heap header is used as the handle value
1335 }
1336 }
1337
1338 /*---------------------------------------------------------------------------*
1339 Name: MEMDestroyExpHeap
1340
1341 Description: Destroys the expanded heap.
1342
1343 Arguments: heap: Handle for the expanded heap.
1344
1345 Returns: Returns a pointer to the region occupied by the destroyed heap.
1346 *---------------------------------------------------------------------------*/
1347 void*
MEMDestroyExpHeap(MEMHeapHandle heap)1348 MEMDestroyExpHeap( MEMHeapHandle heap )
1349 {
1350 ASSERT( IsValidExpHeapHandle_(heap) );
1351
1352 MEMiFinalizeHeap( heap );
1353 return (void*)heap;
1354 }
1355
1356 /*---------------------------------------------------------------------------*
1357 Name: MEMAllocFromExpHeapEx
1358
1359 Description: Allocates a memory block from the expanded heap.
1360 The memory block alignment can be specified.
1361 If a negative alignment value is specified, an available region is searched for from the back of the heap.
1362
1363 Arguments: heap: Handle for the expanded heap.
1364 size: Size of the memory block to be allocated (in bytes)
1365 alignment: Alignment of the memory block to be allocated
1366 The following values can be specified: + or - 4, + or - 8, + or - 16, + or - 32, + or - 64, + or - 128, ...
1367
1368 Returns: Returns a pointer to the allocated memory block if it was successfully allocated.
1369
1370 If the operation fails, NULL is returned.
1371 *---------------------------------------------------------------------------*/
1372 void*
MEMAllocFromExpHeapEx(MEMHeapHandle heap,u32 size,int alignment)1373 MEMAllocFromExpHeapEx(
1374 MEMHeapHandle heap,
1375 u32 size,
1376 int alignment
1377 )
1378 {
1379 void* memory = NULL;
1380
1381 ASSERT( IsValidExpHeapHandle_(heap) );
1382
1383 // check alignment
1384 ASSERT(alignment % MIN_ALIGNMENT == 0);
1385 ASSERT((abs(alignment) & (abs(alignment) - 1)) == 0);
1386 ASSERT(MIN_ALIGNMENT <= abs(alignment));
1387 ASSERT( (-128 <= alignment) && (alignment <= 128 ) );
1388
1389 if ( size == 0 )
1390 {
1391 size = 1;
1392 }
1393
1394 size = RoundUp( size, MIN_ALIGNMENT ); // size actually allocated
1395
1396 LockHeap( heap );
1397
1398 if ( alignment >= 0 ) // allocate from the front
1399 {
1400 memory = AllocFromHead_( heap, size, alignment );
1401 }
1402 else // allocate from the back
1403 {
1404 memory = AllocFromTail_( heap, size, -alignment );
1405 }
1406
1407 UnlockHeap( heap );
1408
1409 return memory;
1410 }
1411
1412 /*---------------------------------------------------------------------------*
1413 Name: MEMResizeForMBlockExpHeap
1414
1415 Description: Changes the size of the memory block allocated from the expanded heap.
1416
1417 Arguments: heap: Handle for the expanded heap.
1418 memBlock: Pointer to the memory block to be resized
1419 size: New size to be allocated (in bytes)
1420
1421 Returns: Returns the size of the resized memory block (in bytes), if the function is successful.
1422 Returns 0 if the function fails.
1423 *---------------------------------------------------------------------------*/
1424 u32
MEMResizeForMBlockExpHeap(MEMHeapHandle heap,void * memBlock,u32 size)1425 MEMResizeForMBlockExpHeap(
1426 MEMHeapHandle heap,
1427 void* memBlock,
1428 u32 size
1429 )
1430 {
1431 MEMiExpHeapHead *pEHHead;
1432 MEMiExpHeapMBlockHead *pMBHead;
1433
1434 ASSERT(IsValidExpHeapHandle_(heap));
1435 ASSERT(memBlock != NULL);
1436
1437 pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1438 pMBHead = GetMBlockHeadPtr_(memBlock);
1439
1440 size = RoundUp( size, MIN_ALIGNMENT );
1441 if ( size == pMBHead->blockSize ) // when the block size is not changed
1442 {
1443 return size;
1444 }
1445
1446 LockHeap( heap );
1447
1448 ASSERT(IsValidUsedMBlock_(memBlock, heap));
1449
1450 // for expanding the new area
1451 if ( size > pMBHead->blockSize )
1452 {
1453 void* crUsedEnd = GetMBlockEndAddr_(pMBHead); // end address for the used block
1454 MEMiExpHeapMBlockHead* block;
1455
1456 // search for the next free block
1457 for ( block = pEHHead->mbFreeList.head; block; block = block->pMBHeadNext )
1458 {
1459 if ( block == crUsedEnd )
1460 {
1461 break;
1462 }
1463 }
1464
1465 // there is no next free block or the size is inadequate
1466 if ( ! block || size > pMBHead->blockSize + sizeof(MEMiExpHeapMBlockHead) + block->blockSize)
1467 {
1468 UnlockHeap( heap );
1469 return 0;
1470 }
1471
1472 {
1473 MemRegion rgnNewFree;
1474 void *oldFreeStart;
1475 MEMiExpHeapMBlockHead *nextBlockPrev;
1476
1477 // get the free block region, and temporarily remove the free block
1478 GetRegionOfMBlock_( &rgnNewFree, block );
1479 nextBlockPrev = RemoveMBlock_( &pEHHead->mbFreeList, block );
1480
1481 oldFreeStart = rgnNewFree.start;
1482 rgnNewFree.start = AddU32ToPtr( memBlock, size ); // region position to be newly freed
1483
1484 // when the remainder is smaller than the memory block size
1485 if ( GetOffsetFromPtr(rgnNewFree.start, rgnNewFree.end) < sizeof(MEMiExpHeapMBlockHead) )
1486 {
1487 rgnNewFree.start = rgnNewFree.end; // absorbed into the used block
1488 }
1489
1490 pMBHead->blockSize = GetOffsetFromPtr(memBlock, rgnNewFree.start); // change the target block size
1491
1492 // when the remainder is equal to or larger than the memory block size
1493 if ( GetOffsetFromPtr(rgnNewFree.start, rgnNewFree.end) >= sizeof(MEMiExpHeapMBlockHead) )
1494 {
1495 (void)InsertMBlock_(&pEHHead->mbFreeList, InitFreeMBlock_(&rgnNewFree), nextBlockPrev); // create a new free block
1496 }
1497
1498 FillAllocMemory( // expanded portion fill
1499 heap,
1500 oldFreeStart,
1501 GetOffsetFromPtr(oldFreeStart, rgnNewFree.start));
1502 }
1503 }
1504 // when the new area is reduced
1505 else
1506 {
1507 MemRegion rgnNewFree;
1508 const u32 oldBlockSize = pMBHead->blockSize;
1509
1510 rgnNewFree.start = AddU32ToPtr(memBlock, size); // region position to be newly freed
1511 rgnNewFree.end = GetMBlockEndAddr_(pMBHead); // end address for the used block
1512
1513 pMBHead->blockSize = size; // change the target block size
1514
1515 if ( ! RecycleRegion_(pEHHead, &rgnNewFree) ) // try to return to the free list
1516 {
1517 pMBHead->blockSize = oldBlockSize; // restore to original form if failed
1518 }
1519 }
1520
1521 UnlockHeap( heap );
1522
1523 return pMBHead->blockSize;
1524 }
1525
1526 /*---------------------------------------------------------------------------*
1527 Name: MEMFreeToExpHeap
1528
1529 Description: Returns the memory block to the expanded heap.
1530
1531 Arguments: heap: Handle for the expanded heap.
1532 memBlock: Pointer to the memory block to be returned
1533
1534 Returns: None.
1535 *---------------------------------------------------------------------------*/
1536 void
MEMFreeToExpHeap(MEMHeapHandle heap,void * memBlock)1537 MEMFreeToExpHeap(
1538 MEMHeapHandle heap,
1539 void* memBlock
1540 )
1541 {
1542 ASSERT(IsValidExpHeapHandle_(heap));
1543 if ( memBlock == NULL )
1544 {
1545 return;
1546 }
1547
1548 LockHeap( heap );
1549 {
1550 MEMiHeapHead *pHeapHd = heap;
1551 MEMiExpHeapHead *pExpHeapHd = GetExpHeapHeadPtrFromHandle_( pHeapHd );
1552 MEMiExpHeapMBlockHead *pMBHead = GetMBlockHeadPtr_( memBlock );
1553 MemRegion region;
1554
1555 ASSERT(IsValidUsedMBlock_(memBlock, heap));
1556
1557 // Is it included in this heap?
1558 ASSERT( pHeapHd->heapStart <= memBlock && memBlock < pHeapHd->heapEnd );
1559
1560 GetRegionOfMBlock_( ®ion, pMBHead );
1561 (void)RemoveMBlock_( &pExpHeapHd->mbUsedList, pMBHead ); // remove from the list being used
1562 (void)RecycleRegion_( pExpHeapHd, ®ion ); // add the specified size from the specified address to the free region
1563 }
1564 UnlockHeap( heap );
1565 }
1566
1567 /*---------------------------------------------------------------------------*
1568 Name: MEMGetTotalFreeSizeForExpHeap
1569
1570 Description: Gets the total size of the available regions of the expanded heap.
1571
1572 Arguments: heap: Handle for the expanded heap.
1573
1574 Returns: Returns the total size of the available regions in the expanded heap (in bytes).
1575 *---------------------------------------------------------------------------*/
1576 u32
MEMGetTotalFreeSizeForExpHeap(MEMHeapHandle heap)1577 MEMGetTotalFreeSizeForExpHeap( MEMHeapHandle heap )
1578 {
1579 u32 sumSize = 0;
1580
1581 ASSERT(IsValidExpHeapHandle_(heap));
1582
1583 LockHeap( heap );
1584
1585 {
1586 MEMiExpHeapHead *pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1587 MEMiExpHeapMBlockHead *pMBHead;
1588
1589 for ( pMBHead = pEHHead->mbFreeList.head; pMBHead; pMBHead = pMBHead->pMBHeadNext )
1590 {
1591 sumSize += pMBHead->blockSize;
1592 }
1593 }
1594
1595 UnlockHeap( heap );
1596 return sumSize;
1597 }
1598
1599 /*---------------------------------------------------------------------------*
1600 Name: MEMGetAllocatableSizeForExpHeapEx
1601
1602 Description: Gets a memory block of the maximum allocatable size from the expanded heap.
1603 The memory block alignment can be specified.
1604
1605 Arguments: heap: Handle for the expanded heap.
1606 alignment: Alignment of the memory block to be allocated
1607 The following values can be specified: + or - 4, + or - 8, + or - 16, + or - 32, + or - 64, + or - 128, ...
1608
1609 Returns: Returns the maximum allocatable size from the expanded heap (in bytes).
1610 *---------------------------------------------------------------------------*/
1611 u32
MEMGetAllocatableSizeForExpHeapEx(MEMHeapHandle heap,int alignment)1612 MEMGetAllocatableSizeForExpHeapEx(
1613 MEMHeapHandle heap,
1614 int alignment
1615 )
1616 {
1617 ASSERT(IsValidExpHeapHandle_(heap));
1618
1619 // check alignment
1620 ASSERT(alignment % MIN_ALIGNMENT == 0);
1621 ASSERT((abs(alignment) & (abs(alignment) - 1)) == 0);
1622 ASSERT(MIN_ALIGNMENT <= abs(alignment));
1623
1624 alignment = abs(alignment); // convert to a positive value just to be sure
1625
1626 LockHeap( heap );
1627
1628 {
1629 MEMiExpHeapHead *pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1630 MEMiExpHeapMBlockHead *pMBlkHd;
1631 u32 maxSize = 0;
1632 u32 offsetMin = 0xFFFFFFFF;
1633
1634 for ( pMBlkHd = pEHHead->mbFreeList.head; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadNext )
1635 {
1636 // memory block position giving consideration to the alignment
1637 void* baseAddress = RoundUpPtr(GetMemPtrForMBlock_(pMBlkHd), alignment);
1638
1639 if ( GetUIntPtr(baseAddress) < GetUIntPtr(GetMBlockEndAddr_(pMBlkHd)) )
1640 {
1641 const u32 blockSize = GetOffsetFromPtr(baseAddress, GetMBlockEndAddr_(pMBlkHd));
1642 // empty area due to the alignment
1643 const u32 offset = GetOffsetFromPtr(GetMemPtrForMBlock_(pMBlkHd), baseAddress);
1644
1645 /*
1646 when the size is large, or if the size is the same but the wasted space is smaller, the memory block is updated
1647
1648 */
1649 if ( maxSize < blockSize
1650 || (maxSize == blockSize && offsetMin > offset)
1651 )
1652 {
1653 maxSize = blockSize;
1654 offsetMin= offset;
1655 }
1656 }
1657 }
1658
1659 UnlockHeap( heap );
1660
1661 return maxSize;
1662 }
1663 }
1664
1665
1666 /*---------------------------------------------------------------------------*
1667 Name: MEMiIsEmptyExpHeap
1668
1669 Description: Checks whether the allocated block exists in the expanded heap.
1670
1671 Arguments: heap: Handle for the expanded heap.
1672
1673 Returns: TRUE if it does not exist and FALSE otherwise.
1674
1675 *---------------------------------------------------------------------------*/
1676 BOOL
MEMiIsEmptyExpHeap(MEMHeapHandle heap)1677 MEMiIsEmptyExpHeap( MEMHeapHandle heap )
1678 {
1679 MEMiExpHeapHead *pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_( heap );
1680 BOOL ret;
1681
1682 LockHeap( heap );
1683
1684 ret = (pExpHeapHd->mbFreeList.head == NULL);
1685
1686 UnlockHeap( heap );
1687
1688 return ret;
1689 }
1690
1691 /*---------------------------------------------------------------------------*
1692 Name: MEMSetAllocModeForExpHeap
1693
1694 Description: Sets the memory allocation mode for the expanded heap.
1695
1696 Arguments: heap: Handle for the expanded heap.
1697 mode: Memory allocation mode.
1698
1699 Returns: Returns the memory allocation mode for the previous expanded heap.
1700 *---------------------------------------------------------------------------*/
1701 u16
MEMSetAllocModeForExpHeap(MEMHeapHandle heap,u16 mode)1702 MEMSetAllocModeForExpHeap(
1703 MEMHeapHandle heap,
1704 u16 mode
1705 )
1706 {
1707 BOOL enabled;
1708 u16 beforeMode;
1709
1710 ASSERT(IsValidExpHeapHandle_(heap));
1711
1712 enabled = OSDisableInterrupts();
1713 {
1714 MEMiExpHeapHead *const pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1715 beforeMode = GetAllocMode_(pEHHead);
1716 SetAllocMode_(pEHHead, mode);
1717 }
1718 (void)OSRestoreInterrupts( enabled );
1719
1720 return beforeMode;
1721 }
1722
1723 /*---------------------------------------------------------------------------*
1724 Name: MEMGetAllocModeForExpHeap
1725
1726 Description: Gets the memory allocation mode for the expanded heap.
1727
1728 Arguments: heap: Handle for the expanded heap.
1729
1730 Returns: Returns the memory allocation mode for the expanded heap.
1731 *---------------------------------------------------------------------------*/
1732 u16
MEMGetAllocModeForExpHeap(MEMHeapHandle heap)1733 MEMGetAllocModeForExpHeap( MEMHeapHandle heap )
1734 {
1735 ASSERT(IsValidExpHeapHandle_(heap));
1736 return GetAllocMode_(GetExpHeapHeadPtrFromHandle_(heap));
1737 }
1738
1739
1740 /*---------------------------------------------------------------------------*
1741 Name: MEMUseMarginOfAlignmentForExpHeap
1742
1743 Description: Configures whether regions should be reused in the gaps that occur during alignment.
1744
1745 Set to FALSE by default.
1746
1747 If this is set to TRUE, it is possible to use small memory regions effectively. However, there is a risk that a large number of free blocks will be created and performance could degrade when memory is allocated.
1748
1749
1750
1751
1752 Arguments: heap: Expanded heap handle
1753 reuse: If TRUE, reuse regions that are generated during alignment.
1754 If FALSE, do not reuse.
1755
1756 Returns: Returns the value of the previous setting.
1757 *---------------------------------------------------------------------------*/
1758 BOOL
MEMUseMarginOfAlignmentForExpHeap(MEMHeapHandle heap,BOOL reuse)1759 MEMUseMarginOfAlignmentForExpHeap( MEMHeapHandle heap, BOOL reuse )
1760 {
1761 MEMiExpHeapHead *const pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1762 BOOL before;
1763
1764 ASSERT( IsValidExpHeapHandle_(heap) );
1765
1766 before = pEHHead->feature.fields.useMarginOfAlign;
1767 pEHHead->feature.fields.useMarginOfAlign = reuse;
1768
1769 return before;
1770 }
1771
1772
1773 /*---------------------------------------------------------------------------*
1774 Name: MEMSetGroupIDForExpHeap
1775
1776 Description: Sets the group ID for the expanded heap.
1777
1778 Arguments: heap: Handle for the expanded heap.
1779 groupID: Group ID value to be set.
1780
1781 Returns: Returns the previous group ID value.
1782 *---------------------------------------------------------------------------*/
1783 u16
MEMSetGroupIDForExpHeap(MEMHeapHandle heap,u16 groupID)1784 MEMSetGroupIDForExpHeap(
1785 MEMHeapHandle heap,
1786 u16 groupID
1787 )
1788 {
1789 u16 beforeGroupID;
1790 BOOL enabled;
1791
1792 ASSERT( IsValidExpHeapHandle_(heap) );
1793 ASSERT( groupID <= MAX_GROUPID );
1794
1795 enabled = OSDisableInterrupts();
1796 {
1797 MEMiExpHeapHead* pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1798 beforeGroupID = pEHHead->groupID;
1799 pEHHead->groupID = groupID;
1800
1801 }
1802 (void)OSRestoreInterrupts( enabled );
1803
1804 return beforeGroupID;
1805 }
1806
1807 /*---------------------------------------------------------------------------*
1808 Name: MEMGetGroupIDForExpHeap
1809
1810 Description: Gets the group ID for the expanded heap.
1811
1812 Arguments: heap: Handle for the expanded heap.
1813
1814 Returns: Returns the group ID value.
1815 *---------------------------------------------------------------------------*/
1816 u16
MEMGetGroupIDForExpHeap(MEMHeapHandle heap)1817 MEMGetGroupIDForExpHeap( MEMHeapHandle heap )
1818 {
1819 ASSERT(IsValidExpHeapHandle_(heap));
1820
1821 return GetExpHeapHeadPtrFromHandle_(heap)->groupID;
1822 }
1823
1824 /*---------------------------------------------------------------------------*
1825 Name: MEMVisitAllocatedForExpHeap
1826
1827 Description: Causes the function specified by the user to be called for all the memory blocks allocated from the expanded heap.
1828
1829 The order of the memory blocks called by the visitor function is the order in which they were allocated.
1830
1831 The visitor type HeapVisitor is defined as below.
1832
1833 typedef void (*HeapVisitor)(
1834 void* memBlock,
1835 MEMHeapHandle heap,
1836 u32 userParam);
1837
1838 memBlock: pointer to the memory block
1839 heap: heap that includes the memory block
1840 userParam: user parameter
1841
1842 Arguments: heap: Handle for the expanded heap.
1843 visitor: Function called for each memory block
1844 userParam: User-specified parameter passed to the visitor function
1845
1846 Returns: None.
1847 *---------------------------------------------------------------------------*/
1848 void
MEMVisitAllocatedForExpHeap(MEMHeapHandle heap,MEMHeapVisitor visitor,u32 userParam)1849 MEMVisitAllocatedForExpHeap(
1850 MEMHeapHandle heap,
1851 MEMHeapVisitor visitor,
1852 u32 userParam
1853 )
1854 {
1855 ASSERT(IsValidExpHeapHandle_(heap));
1856 ASSERT(visitor != NULL);
1857
1858 LockHeap( heap );
1859 {
1860 MEMiExpHeapMBlockHead* pMBHead = GetExpHeapHeadPtrFromHandle_(heap)->mbUsedList.head;
1861
1862 while ( pMBHead )
1863 {
1864 MEMiExpHeapMBlockHead* pMBHeadNext = pMBHead->pMBHeadNext;
1865 (*visitor)(GetMemPtrForMBlock_(pMBHead), heap, userParam);
1866 pMBHead = pMBHeadNext;
1867 }
1868 }
1869 UnlockHeap( heap );
1870 }
1871
1872 /*---------------------------------------------------------------------------*
1873 Name: MEMGetSizeForMBlockExpHeap
1874
1875 Description: Gets the size of the memory block that was allocated from the expanded heap.
1876
1877 Arguments: memBlock: pointer to the memory block for getting the size
1878
1879 Returns: Returns the size of the specified memory block (in bytes).
1880 *---------------------------------------------------------------------------*/
1881 u32
MEMGetSizeForMBlockExpHeap(const void * memBlock)1882 MEMGetSizeForMBlockExpHeap( const void* memBlock )
1883 {
1884 ASSERT(IsValidUsedMBlock_(memBlock, NULL));
1885
1886 return GetMBlockHeadCPtr_( memBlock )->blockSize;
1887 }
1888
1889 /*---------------------------------------------------------------------------*
1890 Name: MEMGetGroupIDForMBlockExpHeap
1891
1892 Description: Gets the group ID for the memory block allocated from the expanded heap.
1893
1894 Arguments: memBlock: pointer to the memory block for getting the group ID
1895
1896 Returns: Returns the group ID for the specified memory block.
1897 *---------------------------------------------------------------------------*/
1898 u16
MEMGetGroupIDForMBlockExpHeap(const void * memBlock)1899 MEMGetGroupIDForMBlockExpHeap( const void* memBlock )
1900 {
1901 ASSERT(IsValidUsedMBlock_(memBlock, NULL));
1902
1903 return GetGroupIDForMBlock_( GetMBlockHeadCPtr_(memBlock) );
1904 }
1905
1906 /*---------------------------------------------------------------------------*
1907 Name: MEMGetAllocDirForMBlockExpHeap
1908
1909 Description: Gets the allocation direction for the memory block allocated from the expanded heap.
1910
1911 Arguments: memBlock: pointer to the memory block
1912
1913 Returns: Returns the allocation direction for the specified memory block.
1914 *---------------------------------------------------------------------------*/
1915 u16
MEMGetAllocDirForMBlockExpHeap(const void * memBlock)1916 MEMGetAllocDirForMBlockExpHeap( const void* memBlock )
1917 {
1918 ASSERT(IsValidUsedMBlock_( memBlock, NULL ));
1919
1920 return GetAllocDirForMBlock_( GetMBlockHeadCPtr_(memBlock) );
1921 }
1922
1923
1924 /*---------------------------------------------------------------------------*
1925 Name: MEMAdjustExpHeap
1926
1927 Description: Deallocates the expanded heap's available region and reduces the memory region that is available for use by the expanded heap.
1928 There must not be memory blocks allocated from the back of heap memory.
1929
1930 Arguments: heap: Handle for the expanded heap.
1931
1932 Returns: Returns the overall expanded heap size after reduction if successful.
1933 (Including the header portion.)
1934 Returns 0 if unsuccessful.
1935
1936 *---------------------------------------------------------------------------*/
1937 u32
MEMAdjustExpHeap(MEMHeapHandle heap)1938 MEMAdjustExpHeap( MEMHeapHandle heap )
1939 {
1940 ASSERT( IsValidExpHeapHandle_(heap) );
1941
1942 {
1943 MEMiHeapHead *pHeapHd = heap;
1944 MEMiExpHeapHead *pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_( heap );
1945 MEMiExpHeapMBlockHead *pMBlkHd;
1946 u32 retVal;
1947
1948 LockHeap( heap );
1949
1950 pMBlkHd = pExpHeapHd->mbFreeList.tail;
1951
1952 // Fail if there are no available regions
1953 if ( pMBlkHd == NULL )
1954 {
1955 retVal = 0;
1956 goto ret_;
1957 }
1958
1959 {
1960 void * const pMBlk = GetMemPtrForMBlock_( pMBlkHd );
1961 void * const pMBlkEnd = AddU32ToPtr( pMBlk, pMBlkHd->blockSize );
1962 u32 blockSize;
1963
1964 // Fail if there exist any memory blocks allocated from the end
1965 if ( pMBlkEnd != MEMGetHeapEndAddress( heap ) )
1966 {
1967 retVal = 0;
1968 goto ret_;
1969 }
1970
1971 // Delete deallocated free block from the free list
1972 (void)RemoveMBlock_( &pExpHeapHd->mbFreeList, pMBlkHd );
1973
1974 blockSize = pMBlkHd->blockSize + sizeof( MEMiExpHeapMBlockHead );
1975 pHeapHd->heapEnd = SubU32ToPtr( pHeapHd->heapEnd, blockSize );
1976
1977 retVal = GetOffsetFromPtr( pHeapHd, pHeapHd->heapEnd );
1978 }
1979 ret_:
1980 UnlockHeap( heap );
1981
1982 return retVal;
1983 }
1984 }
1985
1986
1987 #if defined(_DEBUG)
1988
1989 /*---------------------------------------------------------------------------*
1990 Name: MEMCheckExpHeap
1991
1992 Description: Checks whether the expanded heap has been destroyed.
1993
1994 Arguments: heap: Handle for the expanded heap.
1995 optFlag: Flag.
1996
1997 Returns: Returns TRUE if the heap is normal.
1998 Returns FALSE if the heap has an error.
1999 *---------------------------------------------------------------------------*/
2000 BOOL
MEMCheckExpHeap(MEMHeapHandle heap,u32 optFlag)2001 MEMCheckExpHeap(
2002 MEMHeapHandle heap,
2003 u32 optFlag
2004 )
2005 {
2006 const BOOL bPrint = 0 != (optFlag & MEM_HEAP_ERROR_PRINT);
2007 u32 totalBytes = 0;
2008 BOOL retVal;
2009
2010 if ( ! IsValidExpHeapHandle_(heap) )
2011 {
2012 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Invalid heap handle. - %08X\n", heap);
2013 return FALSE;
2014 }
2015
2016 LockHeap( heap );
2017 {
2018 MEMiHeapHead *const pHeapHd = heap;
2019 MEMiExpHeapHead *const pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_(pHeapHd);
2020 MEMiExpHeapMBlockHead* pMBHead = NULL;
2021 MEMiExpHeapMBlockHead* pMBHeadPrev = NULL;
2022
2023 // used block
2024 for ( pMBHead = pExpHeapHd->mbUsedList.head; pMBHead; pMBHeadPrev = pMBHead, pMBHead = pMBHead->pMBHeadNext )
2025 {
2026 if ( ! CheckUsedMBlock_(pMBHead, pHeapHd, optFlag)
2027 || ! CheckMBlockPrevPtr_(pMBHead, pMBHeadPrev, optFlag) // Is the pointer to the previous block the same as the pointer to the memory block in the previous loop?
2028 )
2029 {
2030 retVal = FALSE;
2031 goto ret_;
2032 }
2033
2034 // calculate size occupied
2035 totalBytes += sizeof(MEMiExpHeapMBlockHead) + pMBHead->blockSize + GetAlignmentForMBlock_(pMBHead);
2036 }
2037
2038 if ( ! CheckMBlockLinkTail_(pMBHeadPrev, pExpHeapHd->mbUsedList.tail, "tail", optFlag)) // Is the last block indicating the pointer to the final block?
2039 {
2040 retVal = FALSE;
2041 goto ret_;
2042 }
2043
2044 // free block
2045 pMBHead = NULL;
2046 pMBHeadPrev = NULL;
2047 for ( pMBHead = pExpHeapHd->mbFreeList.head; pMBHead; pMBHeadPrev = pMBHead, pMBHead = pMBHead->pMBHeadNext )
2048 {
2049 if ( ! CheckFreeMBlock_(pMBHead, pHeapHd, optFlag)
2050 || ! CheckMBlockPrevPtr_(pMBHead, pMBHeadPrev, optFlag) // Is the pointer to the previous block the same as the pointer to the memory block in the previous loop?
2051 )
2052 {
2053 retVal = FALSE;
2054 goto ret_;
2055 }
2056
2057 // calculate size occupied
2058 totalBytes += sizeof(MEMiExpHeapMBlockHead) + pMBHead->blockSize;
2059 }
2060
2061 if ( ! CheckMBlockLinkTail_(pMBHeadPrev, pExpHeapHd->mbFreeList.tail, "tail", optFlag) ) // Is the last block indicating the pointer to the final block?
2062 {
2063 retVal = FALSE;
2064 goto ret_;
2065 }
2066
2067 // Display all results.
2068 if ( totalBytes != GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd) )
2069 {
2070 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Incorrect total memory block size. - heap size %08X, sum size %08X\n",
2071 GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd), totalBytes);
2072 retVal = FALSE;
2073 goto ret_;
2074 }
2075 retVal = TRUE;
2076 }
2077 ret_:
2078 UnlockHeap( heap );
2079 return retVal;
2080 }
2081
2082
2083 /*---------------------------------------------------------------------------*
2084 Name: MEMCheckForMBlockExpHeap
2085
2086 Description: This function checks if the memory block of the expanded heap was destroyed.
2087
2088 Arguments: memBlock: Pointer to the memory block to be checked.
2089 heap: Handle for the expanded heap.
2090 optFlag: Flag.
2091
2092 Returns: Returns TRUE if the memory block is valid.
2093 Returns FALSE if the memory block has an error.
2094 *---------------------------------------------------------------------------*/
2095 BOOL
MEMCheckForMBlockExpHeap(const void * memBlock,MEMHeapHandle heap,u32 optFlag)2096 MEMCheckForMBlockExpHeap(
2097 const void* memBlock,
2098 MEMHeapHandle heap,
2099 u32 optFlag
2100 )
2101 {
2102 const MEMiExpHeapMBlockHead* pMBHead = NULL;
2103 MEMiHeapHead *const pHeapHd = heap;
2104
2105 if ( ! memBlock )
2106 {
2107 return FALSE;
2108 }
2109
2110 pMBHead = GetMBlockHeadCPtr_( memBlock );
2111
2112 if ( ! CheckUsedMBlock_( pMBHead, pHeapHd, optFlag ) )
2113 {
2114 return FALSE;
2115 }
2116
2117 if ( pMBHead->pMBHeadPrev )
2118 {
2119 if ( ! CheckUsedMBlock_(pMBHead->pMBHeadPrev, pHeapHd, optFlag) // check of signature and size of previous block
2120 || ! CheckMBlockNextPtr_(pMBHead->pMBHeadPrev, pMBHead, optFlag) // Is the previous block's pointer to the next block indicating the current block?
2121 )
2122 {
2123 return FALSE;
2124 }
2125 }
2126 else
2127 {
2128 if ( pHeapHd )
2129 {
2130 // When prev is NULL, the head pointer of the list should indicate the current (block).
2131 if ( ! CheckMBlockLinkTail_(pMBHead, GetExpHeapHeadPtrFromHeapHead_(pHeapHd)->mbUsedList.head, "head", optFlag) )
2132 {
2133 return FALSE;
2134 }
2135 }
2136 }
2137
2138 if ( pMBHead->pMBHeadNext )
2139 {
2140 if ( ! CheckUsedMBlock_(pMBHead->pMBHeadNext, pHeapHd, optFlag) // check of signature and size of next block
2141 || ! CheckMBlockPrevPtr_(pMBHead->pMBHeadNext, pMBHead, optFlag) // Is the next block's pointer to the previous block indicating the current block?
2142 )
2143 {
2144 return FALSE;
2145 }
2146 }
2147 else
2148 {
2149 if ( pHeapHd )
2150 {
2151 // When next is NULL, the tail pointer of the list should indicate the current (block).
2152 if ( ! CheckMBlockLinkTail_(pMBHead, GetExpHeapHeadPtrFromHeapHead_(pHeapHd)->mbUsedList.tail, "tail", optFlag) )
2153 {
2154 return FALSE;
2155 }
2156 }
2157 }
2158
2159 return TRUE;
2160 }
2161
2162 // #if defined(_DEBUG)
2163 #endif
2164
2165
2166