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 // Free memory block signature
24 #define MBLOCK_FREE_SIGNATURE ('FR')
25
26 // Signature for the memory block being used
27 #define MBLOCK_USED_SIGNATURE ('UD')
28
29 // Maximum group ID value
30 #define MAX_GROUPID 0xff
31
32 // Default value for the group ID
33 #define DEFAULT_GROUPID 0
34
35 // Minimum alignment value
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 for registration as a free block (exclusive of 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 outputting warnings 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: Gets the larger of two pointers' addresses.
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 the pointer to the memory block
168 from the pointer to the NNSiFndExpHeapMBlockHead structure.
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 the pointer to the NNSiFndExpHeapMBlockHead structure
190 from the pointer to the memory block.
191 from the pointer to the NNSiFndExpHeapMBlockHead structure.
192
193 Arguments: memBlock: Pointer to the memory block.
194
195 Returns: Returns the pointer to the 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 pointer to the NNSiFndExpHeapMBlockHead structure
213 gets the end address of the memory block.
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 Function
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 value 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 Function
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 data 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 Operation
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: a 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 the 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 at which the memory block will be inserted
449
450 Returns: a pointer to the 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: The list to add
494 block: The 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 the 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; /* embeds the signature*/
526 block->attribute.val = 0; /* clears the attribute parameters*/
527
528 // sets 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: The memory end address for the expanded heap is 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( // Heap common initialization
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 // Creates 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 the 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 top 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 ); // Deletes the free block
635
636 // If there is no space for creating a free block
637 if ( GetOffsetFromPtr(freeRgnT.start, freeRgnT.end) < sizeof(MEMiExpHeapMBlockHead) + MIN_FREE_BLOCK_SIZE )
638 {
639 freeRgnT.end = freeRgnT.start; // Includes the alignment value for the block being used
640 }
641 else
642 {
643 pMBHeadFreePrev = InsertMBlock_( &pEHHead->mbFreeList, InitFreeMBlock_(&freeRgnT), pMBHeadFreePrev );
644 }
645
646 // If there is no space for creating a free block
647 if ( GetOffsetFromPtr(freeRgnB.start, freeRgnB.end) < sizeof(MEMiExpHeapMBlockHead) + MIN_FREE_BLOCK_SIZE )
648 {
649 freeRgnB.start= freeRgnB.end; // Includes the block being used
650 }
651 else
652 {
653 (void)InsertMBlock_( &pEHHead->mbFreeList, InitFreeMBlock_(&freeRgnB), pMBHeadFreePrev );
654 }
655
656 // Fills the memory for debugging
657 FillAllocMemory(
658 GetHeapHeadPtrFromExpHeapHead_(pEHHead),
659 freeRgnT.end,
660 GetOffsetFromPtr(freeRgnT.end, freeRgnB.start)
661 );
662
663 // Creates a new block
664 {
665 MEMiExpHeapMBlockHead* pMBHeadNewUsed;
666 MemRegion region;
667
668 region.start = SubU32ToPtr( mblock, sizeof(MEMiExpHeapMBlockHead) );
669 region.end = freeRgnB.start;
670
671 pMBHeadNewUsed = InitMBlock_(®ion, MBLOCK_USED_SIGNATURE );
672 SetAllocDirForMBlock_( pMBHeadNewUsed, direction );
673 SetAlignmentForMBlock_( pMBHeadNewUsed, (u16)GetOffsetFromPtr(freeRgnT.end, pMBHeadNewUsed) );
674 SetGroupIDForMBlock_( pMBHeadNewUsed, pEHHead->groupID );
675 AppendMBlock_( &pEHHead->mbUsedList, pMBHeadNewUsed );
676 }
677
678 return mblock;
679 }
680
681 /*---------------------------------------------------------------------------*
682 Name: AllocFromHead_
683
684 Description: Allocates the memory block from the top of the heap.
685
686 Arguments: pHeapHd: Pointer to the heap header.
687 size : Size of the memory block to be allocated.
688 alignment: Alignment value.
689
690 Returns: Returns the pointer
691 to the allocated memory block if the allocation is successful.
692 If fails, NULL is returned.
693 *---------------------------------------------------------------------------*/
694 static void*
AllocFromHead_(MEMiHeapHead * pHeapHd,u32 size,int alignment)695 AllocFromHead_(
696 MEMiHeapHead* pHeapHd,
697 u32 size,
698 int alignment
699 )
700 {
701 MEMiExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_(pHeapHd);
702
703 // Allocate the first one found?
704 const BOOL bAllocFirst = GetAllocMode_(pExpHeapHd) == MEM_EXPHEAP_ALLOC_MODE_FIRST;
705
706 MEMiExpHeapMBlockHead* pMBlkHd = NULL;
707 MEMiExpHeapMBlockHead* pMBlkHdFound = NULL;
708 u32 foundSize = 0xffffffff;
709 void* foundMBlock = NULL;
710
711 // Search for free block
712 for ( pMBlkHd = pExpHeapHd->mbFreeList.head; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadNext )
713 {
714 void *const mblock = GetMemPtrForMBlock_(pMBlkHd);
715 void *const reqMBlock = RoundUpPtr( mblock, alignment );
716 const u32 offset = GetOffsetFromPtr( mblock, reqMBlock ); // Generated offset
717
718 if ( pMBlkHd->blockSize >= size + offset
719 && foundSize > pMBlkHd->blockSize )
720 {
721 pMBlkHdFound = pMBlkHd;
722 foundSize = pMBlkHd->blockSize;
723 foundMBlock = reqMBlock;
724
725 if ( bAllocFirst || foundSize == size )
726 {
727 break;
728 }
729 }
730 }
731
732 if ( ! pMBlkHdFound ) // No blocks matching the conditions were found
733 {
734 return NULL;
735 }
736
737 return AllocUsedBlockFromFreeBlock_( // Allocates a region from the free block that was found
738 pExpHeapHd,
739 pMBlkHdFound,
740 foundMBlock,
741 size,
742 MEM_EXPHEAP_ALLOC_DIR_FRONT
743 );
744 }
745
746 /*---------------------------------------------------------------------------*
747 Name: AllocFromTail_
748
749 Description: Allocates a memory block from the tail of the heap.
750
751 Arguments: pHeapHd: Pointer to the heap header.
752 size : Size of the memory block to be allocated.
753 alignment: Alignment value.
754
755 Returns: Returns the pointer
756 to the allocated memory block if the allocation is successful.
757 If fails, NULL is returned.
758 *---------------------------------------------------------------------------*/
759 static void*
AllocFromTail_(MEMiHeapHead * pHeapHd,u32 size,int alignment)760 AllocFromTail_(
761 MEMiHeapHead* pHeapHd,
762 u32 size,
763 int alignment
764 )
765 {
766 MEMiExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_(pHeapHd);
767
768 // Allocate the first one found?
769 const BOOL bAllocFirst = GetAllocMode_(pExpHeapHd) == MEM_EXPHEAP_ALLOC_MODE_FIRST;
770
771 MEMiExpHeapMBlockHead* pMBlkHd = NULL;
772 MEMiExpHeapMBlockHead* pMBlkHdFound = NULL;
773 u32 foundSize = 0xffffffff;
774 void* foundMBlock = NULL;
775
776 // Search for free block
777 for ( pMBlkHd = pExpHeapHd->mbFreeList.tail; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadPrev )
778 {
779 void *const mblock = GetMemPtrForMBlock_(pMBlkHd);
780 void *const mblockEnd = AddU32ToPtr( mblock, pMBlkHd->blockSize );
781 void *const reqMBlock = RoundDownPtr( SubU32ToPtr(mblockEnd, size), alignment ); // Aligned address
782
783 if ( ComparePtr( reqMBlock, mblock ) >= 0
784 && foundSize > pMBlkHd->blockSize )
785 {
786 pMBlkHdFound = pMBlkHd;
787 foundSize = pMBlkHd->blockSize;
788 foundMBlock = reqMBlock;
789
790 if ( bAllocFirst || foundSize == size )
791 {
792 break;
793 }
794 }
795 }
796
797 if ( ! pMBlkHdFound ) // No blocks matching the conditions were found
798 {
799 return NULL;
800 }
801
802 return AllocUsedBlockFromFreeBlock_( // Allocates a region from the free block that was found
803 pExpHeapHd,
804 pMBlkHdFound,
805 foundMBlock,
806 size,
807 MEM_EXPHEAP_ALLOC_DIR_REAR
808 );
809 }
810
811 /*---------------------------------------------------------------------------*
812 Name: RecycleRegion_
813
814 Description: Inserts the empty region in the free memory block.
815 If it is adjacent to the free block it expands the free block.
816 If there is no adjacent block, or the block is not large enough
817 to be used as a free block, the alignment value of the used block adjacent to the end of the memory space is used.
818 If there is no used block next to the end of the free block the function fails.
819
820 Arguments: pEHHead: Pointer to the expanded heap header.
821 pRegion: Pointer to the free region.
822
823 Returns: Returns TRUE if the function is successful.
824 Returns FALSE if it fails.
825 *---------------------------------------------------------------------------*/
826 static BOOL
RecycleRegion_(MEMiExpHeapHead * pEHHead,const MemRegion * pRegion)827 RecycleRegion_(
828 MEMiExpHeapHead* pEHHead,
829 const MemRegion* pRegion
830 )
831 {
832 MEMiExpHeapMBlockHead* pBlkPrFree = NULL; // Immediately preceding free block
833 MemRegion freeRgn = *pRegion;
834
835 // Searches for free area next to the specified one.
836 {
837 MEMiExpHeapMBlockHead* pBlk;
838
839 for ( pBlk = pEHHead->mbFreeList.head; pBlk; pBlk = pBlk->pMBHeadNext )
840 {
841 if ( pBlk < pRegion->start )
842 {
843 pBlkPrFree = pBlk;
844 continue;
845 }
846
847 if ( pBlk == pRegion->end ) // Is the block next to the end?
848 {
849 // Combines the available regions
850 freeRgn.end = GetMBlockEndAddr_(pBlk);
851 (void)RemoveMBlock_( &pEHHead->mbFreeList, pBlk );
852
853 // Pads the header with NoUse
854 FillNoUseMemory( GetHeapHeadPtrFromExpHeapHead_(pEHHead), pBlk, sizeof(MEMiExpHeapMBlockHead) );
855 }
856 break;
857 }
858 }
859
860 // Is the immediately preceding free block adjacent to the front?
861 if ( pBlkPrFree && GetMBlockEndAddr_(pBlkPrFree) == pRegion->start )
862 {
863 // Combines the available regions
864 freeRgn.start = pBlkPrFree;
865 pBlkPrFree = RemoveMBlock_(&pEHHead->mbFreeList, pBlkPrFree);
866 }
867
868 if ( GetOffsetFromPtr(freeRgn.start, freeRgn.end) < sizeof(MEMiExpHeapMBlockHead) ) // Size not suitable for use as a block
869 {
870 return FALSE; // Control reaches this point if an attempt is made to shrink a small-size block using ResizeForMBlockExpHeap() and
871 // there is no free block after it.
872 }
873
874 // Fills the memory for debugging
875 FillFreeMemory( GetHeapHeadPtrFromExpHeapHead_(pEHHead), pRegion->start, GetOffsetFromPtr(pRegion->start, pRegion->end) );
876
877 (void)InsertMBlock_(
878 &pEHHead->mbFreeList,
879 InitFreeMBlock_(&freeRgn), // Creates the free block
880 pBlkPrFree
881 );
882
883 return TRUE;
884 }
885
886
887
888
889
890 /* ========================================================================
891 operation checking functions
892 ======================================================================== */
893 #if defined(_DEBUG)
894
895 /*---------------------------------------------------------------------------*
896 Name: CheckMBlock_
897
898 Description: Checks whether the header contents for the memory block are appropriate.
899
900 Arguments: pMBHead: Pointer to the header for the memory block to be checked.
901 pHeapHd: Pointer to the expanded heap header.
902 signature: Memory block signature
903 heapType: Memory block type (used or free)
904 flag : Flag.
905
906 Returns: Returns TRUE if the header contents for the memory block are appropriate,
907 otherwise returns FALSE.
908 *---------------------------------------------------------------------------*/
909 static BOOL
CheckMBlock_(const MEMiExpHeapMBlockHead * pMBHead,MEMiHeapHead * pHeapHd,u16 signature,const char * heapType,u32 flag)910 CheckMBlock_(
911 const MEMiExpHeapMBlockHead* pMBHead,
912 MEMiHeapHead* pHeapHd,
913 u16 signature,
914 const char* heapType,
915 u32 flag
916 )
917 {
918 const BOOL bPrint = ( 0 != (flag & MEM_HEAP_ERROR_PRINT) );
919 const void *const memBlock = GetMemCPtrForMBlock_(pMBHead);
920
921 if ( pHeapHd )
922 {
923 if ( GetUIntPtr(pMBHead) < GetUIntPtr(pHeapHd->heapStart)
924 || GetUIntPtr(memBlock) > GetUIntPtr(pHeapHd->heapEnd)
925 )
926 {
927 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Bad %s memory block address. - address %08X, heap area [%08X - %08X)\n",
928 heapType, memBlock, pHeapHd->heapStart, pHeapHd->heapEnd);
929 return FALSE;
930 }
931 }
932 else
933 {
934 if ( GetUIntPtr(pMBHead) < 0x80000000 )
935 {
936 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Bad %s memory block address. - address %08X\n",
937 heapType, memBlock);
938 return FALSE;
939 }
940 }
941
942 if ( pMBHead->signature != signature ) // Is the signature different?
943 {
944 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Bad %s memory block signature. - address %08X, signature %04X\n",
945 heapType, memBlock, pMBHead->signature);
946 return FALSE;
947 }
948
949 if ( pMBHead->blockSize >= 0x08000000 ) // Size too big? (128MB or more)
950 {
951 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Too large %s memory block. - address %08X, block size %08X\n",
952 heapType, memBlock, pMBHead->blockSize);
953 return FALSE;
954 }
955
956 if ( pHeapHd )
957 {
958 if ( GetUIntPtr(memBlock) + pMBHead->blockSize > GetUIntPtr(pHeapHd->heapEnd) )
959 {
960 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " wrong size %s memory block. - address %08X, block size %08X\n",
961 heapType, memBlock, pMBHead->blockSize);
962 return FALSE;
963 }
964 }
965
966 return TRUE;
967 }
968
969
970 /*---------------------------------------------------------------------------*
971 Name: CheckUsedMBlock_
972
973 Description: Checks whether the header contents for the memory block being used are appropriate.
974
975 Arguments: pMBHead: Pointer to the header for the memory block to be checked.
976 pHeapHd: Pointer to the expanded heap header.
977 flag : Flag.
978
979 Returns: Returns TRUE if the header contents for the memory block are appropriate,
980 otherwise returns FALSE.
981 *---------------------------------------------------------------------------*/
982 static inline BOOL
CheckUsedMBlock_(const MEMiExpHeapMBlockHead * pMBHead,MEMiHeapHead * pHeapHd,u32 flag)983 CheckUsedMBlock_(
984 const MEMiExpHeapMBlockHead* pMBHead,
985 MEMiHeapHead* pHeapHd,
986 u32 flag
987 )
988 {
989 if ( pHeapHd )
990 {
991 MEMiExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_(pHeapHd);
992 MEMiExpHeapMBlockHead* pMBlkHd = NULL;
993 for ( pMBlkHd = pExpHeapHd->mbUsedList.head; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadNext )
994 {
995 if ( pMBHead == pMBlkHd )
996 {
997 break;
998 }
999 }
1000 if ( pMBlkHd == NULL )
1001 {
1002 return FALSE;
1003 }
1004 }
1005 return CheckMBlock_( pMBHead, pHeapHd, MBLOCK_USED_SIGNATURE, "used", flag );
1006 }
1007
1008 /*---------------------------------------------------------------------------*
1009 Name: CheckFreeMBlock_
1010
1011 Description: Checks whether the header contents for the free memory block are appropriate.
1012
1013 Arguments: pMBHead: Pointer to the header for the memory block to be checked.
1014 pHeapHd: Pointer to the expanded heap header.
1015 flag : Flag.
1016
1017 Returns: Returns TRUE if the header contents for the memory block are appropriate,
1018 otherwise returns FALSE.
1019 *---------------------------------------------------------------------------*/
1020 static inline BOOL
CheckFreeMBlock_(const MEMiExpHeapMBlockHead * pMBHead,MEMiHeapHead * pHeapHd,u32 flag)1021 CheckFreeMBlock_(
1022 const MEMiExpHeapMBlockHead* pMBHead,
1023 MEMiHeapHead* pHeapHd,
1024 u32 flag
1025 )
1026 {
1027 return CheckMBlock_( pMBHead, pHeapHd, MBLOCK_FREE_SIGNATURE, "free", flag );
1028 }
1029
1030
1031 /*---------------------------------------------------------------------------*
1032 Name: CheckMBlockPrevPtr_
1033
1034 Description: Checks whether the link to the front of the memory block is correct.
1035
1036 Arguments: pMBHead: Pointer to the header for the memory block to be checked.
1037 pMBHeadPrev: Pointer to the header for the memory block before the one to be checked.
1038 flag : Flag.
1039
1040 Returns: Returns TRUE if the link to the front of the memory block is correct,
1041 otherwise returns FALSE.
1042 *---------------------------------------------------------------------------*/
1043 static BOOL
CheckMBlockPrevPtr_(const MEMiExpHeapMBlockHead * pMBHead,const MEMiExpHeapMBlockHead * pMBHeadPrev,u32 flag)1044 CheckMBlockPrevPtr_(
1045 const MEMiExpHeapMBlockHead* pMBHead,
1046 const MEMiExpHeapMBlockHead* pMBHeadPrev,
1047 u32 flag
1048 )
1049 {
1050 const BOOL bPrint = ( 0 != (flag & MEM_HEAP_ERROR_PRINT) );
1051
1052 if ( pMBHead->pMBHeadPrev != pMBHeadPrev )
1053 {
1054 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Wrong link memory block. - address %08X, previous address %08X != %08X\n",
1055 GetMemCPtrForMBlock_(pMBHead), pMBHead->pMBHeadPrev, pMBHeadPrev);
1056 return FALSE;
1057 }
1058
1059 return TRUE;
1060 }
1061
1062
1063 /*---------------------------------------------------------------------------*
1064 Name: CheckMBlockNextPtr_
1065
1066 Description: Checks whether the link to the next memory block is correct.
1067
1068 Arguments: pMBHead: Pointer to the header for the memory block to be checked.
1069 pMBHeadNext: Pointer to the header for the memory block after the one to be checked.
1070 flag : Flag.
1071
1072 Returns: Returns TRUE if the link to the next memory block is correct,
1073 otherwise returns FALSE.
1074 *---------------------------------------------------------------------------*/
1075 static BOOL
CheckMBlockNextPtr_(const MEMiExpHeapMBlockHead * pMBHead,const MEMiExpHeapMBlockHead * pMBHeadNext,u32 flag)1076 CheckMBlockNextPtr_(
1077 const MEMiExpHeapMBlockHead* pMBHead,
1078 const MEMiExpHeapMBlockHead* pMBHeadNext,
1079 u32 flag
1080 )
1081 {
1082 const BOOL bPrint = ( 0 != (flag & MEM_HEAP_ERROR_PRINT) );
1083
1084 if (pMBHead->pMBHeadNext != pMBHeadNext)
1085 {
1086 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Wrong link memory block. - address %08X, next address %08X != %08X\n",
1087 GetMemCPtrForMBlock_(pMBHead), pMBHead->pMBHeadNext, pMBHeadNext);
1088 return FALSE;
1089 }
1090
1091 return TRUE;
1092 }
1093
1094
1095 /*---------------------------------------------------------------------------*
1096 Name: CheckMBlockLinkTail_
1097
1098 Description: Checks whether the memory block pointer is at the head or tail of the memory block list.
1099
1100 Arguments: pMBHead: Pointer to the header for the memory block to be checked.
1101 pMBHeadTail: Pointer to the memory block at the head or tail of the memory block list.
1102 headType: String indicating the head or tail.
1103 flag : Flag.
1104
1105 Returns: Returns TRUE if the memory block pointer is at the head or tail of the memory block list,
1106 otherwise returns FALSE.
1107 *---------------------------------------------------------------------------*/
1108 static BOOL
CheckMBlockLinkTail_(const MEMiExpHeapMBlockHead * pMBHead,const MEMiExpHeapMBlockHead * pMBHeadTail,const char * heapType,u32 flag)1109 CheckMBlockLinkTail_(
1110 const MEMiExpHeapMBlockHead* pMBHead,
1111 const MEMiExpHeapMBlockHead* pMBHeadTail,
1112 const char* heapType,
1113 u32 flag
1114 )
1115 {
1116 const BOOL bPrint = 0 != (flag & MEM_HEAP_ERROR_PRINT);
1117
1118 if ( pMBHead != pMBHeadTail )
1119 {
1120 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Wrong memory brock list %s pointer. - address %08X, %s address %08X != %08X\n",
1121 heapType, GetMemCPtrForMBlock_(pMBHead), heapType, pMBHead, pMBHeadTail);
1122 return FALSE;
1123 }
1124
1125 return TRUE;
1126 }
1127
1128
1129 /*---------------------------------------------------------------------------*
1130 Name: IsValidUsedMBlock_
1131
1132 Description: Checks whether the memory block being used is appropriate.
1133
1134 Arguments: memBlock: The memory block to be checked.
1135 heap : The handle for the expanded heap containing the memory block.
1136 If NULL is specified, no check is run to see whether
1137 the memory block is included in the heap.
1138
1139 Returns: Returns TRUE if there is no problem with the specified memory block.
1140 Returns FALSE if there is a problem.
1141 *---------------------------------------------------------------------------*/
1142 static BOOL
IsValidUsedMBlock_(const void * memBlock,MEMHeapHandle heap)1143 IsValidUsedMBlock_(
1144 const void* memBlock,
1145 MEMHeapHandle heap
1146 )
1147 {
1148 MEMiHeapHead* pHeapHd = heap;
1149
1150 if ( ! memBlock)
1151 {
1152 return FALSE;
1153 }
1154
1155 return CheckUsedMBlock_(GetMBlockHeadCPtr_(memBlock), pHeapHd, 0);
1156 }
1157
1158 // #if defined(_DEBUG)
1159 #endif
1160
1161
1162
1163 /* ========================================================================
1164 External Functions (Non-Public)
1165 ======================================================================== */
1166
1167 /*---------------------------------------------------------------------------*
1168 Name: MEMiDumpExpHeap
1169
1170 Description: Shows internal expanded heap information.
1171 This function is for debugging.
1172
1173 Arguments: heap : Handle for expanded heap
1174
1175 Returns: None.
1176 *---------------------------------------------------------------------------*/
1177 #if defined(_DEBUG)
1178
1179 void
MEMiDumpExpHeap(MEMHeapHandle heap)1180 MEMiDumpExpHeap( MEMHeapHandle heap )
1181 {
1182 ASSERT(IsValidExpHeapHandle_(heap));
1183
1184 {
1185 u32 usedSize = 0;
1186 u32 usedCnt = 0;
1187 u32 freeSize = 0;
1188 u32 freeCnt = 0;
1189
1190 MEMiHeapHead* pHeapHd = heap;
1191 MEMiExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHandle_(pHeapHd);
1192
1193 MEMiDumpHeapHead(pHeapHd);
1194
1195 OSReport(" attr address: size gid aln prev_ptr next_ptr\n"); // Header line
1196
1197 // ---------------- UsedBlock Dump ----------------
1198 OSReport(" (Used Blocks)\n" );
1199
1200 if ( pExpHeapHd->mbUsedList.head == NULL )
1201 {
1202 OSReport(" NONE\n");
1203 }
1204 else
1205 {
1206 MEMiExpHeapMBlockHead* pMBHead;
1207
1208 for ( pMBHead = pExpHeapHd->mbUsedList.head; pMBHead; pMBHead = pMBHead->pMBHeadNext )
1209 {
1210 if ( pMBHead->signature != MBLOCK_USED_SIGNATURE )
1211 {
1212 OSReport(" xxxxx %08x: -------- --- --- (-------- --------)\nabort\n", pMBHead);
1213 break;
1214 }
1215
1216 OSReport(" %s %08x: %8d %3d %3d (%08x %08x)\n",
1217 GetAllocDirForMBlock_(pMBHead) == MEM_EXPHEAP_ALLOC_DIR_REAR ? " rear" : "front",
1218 GetMemPtrForMBlock_(pMBHead),
1219 pMBHead->blockSize,
1220 GetGroupIDForMBlock_( pMBHead ),
1221 GetAlignmentForMBlock_( pMBHead ),
1222 pMBHead->pMBHeadPrev ? GetMemPtrForMBlock_(pMBHead->pMBHeadPrev): NULL,
1223 pMBHead->pMBHeadNext ? GetMemPtrForMBlock_(pMBHead->pMBHeadNext): NULL
1224 );
1225
1226 // ---- Use Quantity
1227 usedSize += sizeof(MEMiExpHeapMBlockHead) + pMBHead->blockSize + GetAlignmentForMBlock_(pMBHead);
1228
1229 usedCnt ++;
1230 }
1231 }
1232
1233 // ---------------- FreeBlock Dump ----------------
1234 OSReport(" (Free Blocks)\n" );
1235
1236 if ( pExpHeapHd->mbFreeList.head == NULL )
1237 {
1238 OSReport(" NONE\n" );
1239 }
1240 else
1241 {
1242 MEMiExpHeapMBlockHead* pMBHead;
1243
1244 for ( pMBHead = pExpHeapHd->mbFreeList.head; pMBHead; pMBHead = pMBHead->pMBHeadNext )
1245 {
1246 if ( pMBHead->signature != MBLOCK_FREE_SIGNATURE )
1247 {
1248 OSReport(" xxxxx %08x: -------- --- --- (-------- --------)\nabort\n", pMBHead);
1249 break;
1250 }
1251
1252 OSReport(" %s %08x: %8d %3d %3d (%08x %08x)\n",
1253 " free",
1254 GetMemPtrForMBlock_(pMBHead),
1255 pMBHead->blockSize,
1256 GetGroupIDForMBlock_( pMBHead ),
1257 GetAlignmentForMBlock_( pMBHead ),
1258 pMBHead->pMBHeadPrev ? GetMemPtrForMBlock_(pMBHead->pMBHeadPrev): NULL,
1259 pMBHead->pMBHeadNext ? GetMemPtrForMBlock_(pMBHead->pMBHeadNext): NULL
1260 );
1261
1262 freeCnt ++;
1263 }
1264 }
1265
1266 OSReport("\n");
1267
1268 {
1269 u32 heapSize = GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd); // Heap size (data region size)
1270 OSReport(" %d / %d bytes (%6.2f%%) used (U:%d F:%d)\n",
1271 usedSize, heapSize, 100.0 * usedSize / heapSize, usedCnt, freeCnt);
1272 }
1273
1274 OSReport("\n");
1275 }
1276 }
1277
1278 // #if defined(_DEBUG)
1279 #endif
1280
1281
1282
1283 /* ========================================================================
1284 External functions (public)
1285 ======================================================================== */
1286
1287 /*---------------------------------------------------------------------------*
1288 Name: MEMCreateExpHeapEx
1289
1290 Description: Creates expanded heap
1291
1292 Arguments: startAddress: Start address of heap area
1293 size : Size of heap area
1294 optFlag: Option flag.
1295
1296 Returns: If the function succeeds, a handle for the created expanded heap is returned.
1297 If the function fails, MEM_HEAP_INVALID_HANDLE is returned.
1298 *---------------------------------------------------------------------------*/
1299 MEMHeapHandle
MEMCreateExpHeapEx(void * startAddress,u32 size,u16 optFlag)1300 MEMCreateExpHeapEx(
1301 void* startAddress,
1302 u32 size,
1303 u16 optFlag
1304 )
1305 {
1306 void* endAddress;
1307
1308 ASSERT(startAddress != NULL);
1309
1310 endAddress = RoundDownPtr(AddU32ToPtr(startAddress, size), MIN_ALIGNMENT);
1311 startAddress = RoundUpPtr(startAddress, MIN_ALIGNMENT);
1312
1313 if ( GetUIntPtr(startAddress) > GetUIntPtr(endAddress)
1314 || GetOffsetFromPtr(startAddress, endAddress) <
1315 sizeof(MEMiHeapHead) + sizeof(MEMiExpHeapHead) + sizeof(MEMiExpHeapMBlockHead) + MIN_ALIGNMENT
1316 )
1317 {
1318 return MEM_HEAP_INVALID_HANDLE;
1319 }
1320
1321 { // Initialization for the Expanded heap
1322 MEMiHeapHead* pHeapHd = InitExpHeap_( startAddress, endAddress, optFlag );
1323 return pHeapHd; // The pointer to the heap header is used as-is as the handle value.
1324 }
1325 }
1326
1327 /*---------------------------------------------------------------------------*
1328 Name: MEMDestroyExpHeap
1329
1330 Description: Destroys the expanded heap
1331
1332 Arguments: heap : Handle for expanded heap
1333
1334 Returns: Returns a pointer to the region occupied by the destroyed heap.
1335 *---------------------------------------------------------------------------*/
1336 void*
MEMDestroyExpHeap(MEMHeapHandle heap)1337 MEMDestroyExpHeap( MEMHeapHandle heap )
1338 {
1339 ASSERT( IsValidExpHeapHandle_(heap) );
1340
1341 MEMiFinalizeHeap( heap );
1342 return (void*)heap;
1343 }
1344
1345 /*---------------------------------------------------------------------------*
1346 Name: MEMAllocFromExpHeapEx
1347
1348 Description: Allocates a memory block from the expanded heap.
1349 The memory block alignment can be specified.
1350 If a negative alignment value is specified, an empty region is searched for from the back of the heap.
1351
1352 Arguments: heap : Handle for expanded heap
1353 size : Size of the memory block to be allocated (in bytes)
1354 alignment: Alignment of the memory block to be allocated.
1355 The following values can be specified: �}4, �}8, �}16, �}32, �}64, �}128, ...
1356
1357 Returns: Returns the pointer
1358 to the allocated memory block if the allocation is successful.
1359 If fails, NULL is returned.
1360 *---------------------------------------------------------------------------*/
1361 void*
MEMAllocFromExpHeapEx(MEMHeapHandle heap,u32 size,int alignment)1362 MEMAllocFromExpHeapEx(
1363 MEMHeapHandle heap,
1364 u32 size,
1365 int alignment
1366 )
1367 {
1368 void* memory = NULL;
1369
1370 ASSERT( IsValidExpHeapHandle_(heap) );
1371
1372 // alignment check
1373 ASSERT(alignment % MIN_ALIGNMENT == 0);
1374 ASSERT((abs(alignment) & (abs(alignment) - 1)) == 0);
1375 ASSERT(MIN_ALIGNMENT <= abs(alignment));
1376
1377 if ( size == 0 )
1378 {
1379 size = 1;
1380 }
1381
1382 size = RoundUp( size, MIN_ALIGNMENT ); // The size actually allocated
1383
1384 LockHeap( heap );
1385
1386 if ( alignment >= 0 ) // Allocates from the front
1387 {
1388 memory = AllocFromHead_( heap, size, alignment );
1389 }
1390 else // Allocates from the back
1391 {
1392 memory = AllocFromTail_( heap, size, -alignment );
1393 }
1394
1395 UnlockHeap( heap );
1396
1397 return memory;
1398 }
1399
1400 /*---------------------------------------------------------------------------*
1401 Name: MEMResizeForMBlockExpHeap
1402
1403 Description: Changes the size of the memory block allocated from the expanded heap.
1404
1405 Arguments: heap : Handle for expanded heap
1406 memBlock: Pointer to the memory block to be resized.
1407 size : The new size to be allocated (in bytes).
1408
1409 Returns: Returns the size of the resized memory block (in bytes) if the function is successful.
1410 Returns 0 if the function fails.
1411 *---------------------------------------------------------------------------*/
1412 u32
MEMResizeForMBlockExpHeap(MEMHeapHandle heap,void * memBlock,u32 size)1413 MEMResizeForMBlockExpHeap(
1414 MEMHeapHandle heap,
1415 void* memBlock,
1416 u32 size
1417 )
1418 {
1419 MEMiExpHeapHead *pEHHead;
1420 MEMiExpHeapMBlockHead *pMBHead;
1421
1422 ASSERT(IsValidExpHeapHandle_(heap));
1423 ASSERT(IsValidUsedMBlock_(memBlock, heap));
1424
1425 pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1426 pMBHead = GetMBlockHeadPtr_(memBlock);
1427
1428 size = RoundUp( size, MIN_ALIGNMENT );
1429 if ( size == pMBHead->blockSize ) // If the block size is not changed
1430 {
1431 return size;
1432 }
1433
1434 LockHeap( heap );
1435
1436 // For expanding the new area
1437 if ( size > pMBHead->blockSize )
1438 {
1439 void* crUsedEnd = GetMBlockEndAddr_(pMBHead); // The end address for the block currently being used
1440 MEMiExpHeapMBlockHead* block;
1441
1442 // Searches for the next free block
1443 for ( block = pEHHead->mbFreeList.head; block; block = block->pMBHeadNext )
1444 {
1445 if ( block == crUsedEnd )
1446 {
1447 break;
1448 }
1449 }
1450
1451 // There is no next free block or the size is inadequate
1452 if ( ! block || size > pMBHead->blockSize + sizeof(MEMiExpHeapMBlockHead) + block->blockSize)
1453 {
1454 return 0;
1455 }
1456
1457 {
1458 MemRegion rgnNewFree;
1459 void *oldFreeStart;
1460 MEMiExpHeapMBlockHead *nextBlockPrev;
1461
1462 // Gets the free block region and temporarily removes the free block
1463 GetRegionOfMBlock_( &rgnNewFree, block );
1464 nextBlockPrev = RemoveMBlock_( &pEHHead->mbFreeList, block );
1465
1466 oldFreeStart = rgnNewFree.start;
1467 rgnNewFree.start = AddU32ToPtr( memBlock, size ); // The region position to be newly freed
1468
1469 // If the remainder is smaller than the memory block size
1470 if ( GetOffsetFromPtr(rgnNewFree.start, rgnNewFree.end) < sizeof(MEMiExpHeapMBlockHead) )
1471 {
1472 rgnNewFree.start = rgnNewFree.end; // It is absorbed into the block being used
1473 }
1474
1475 pMBHead->blockSize = GetOffsetFromPtr(memBlock, rgnNewFree.start); // Changes the target block size
1476
1477 // If the remainder is equal to or larger than the memory block size
1478 if ( GetOffsetFromPtr(rgnNewFree.start, rgnNewFree.end) >= sizeof(MEMiExpHeapMBlockHead) )
1479 {
1480 (void)InsertMBlock_(&pEHHead->mbFreeList, InitFreeMBlock_(&rgnNewFree), nextBlockPrev); // Creates a new free block
1481 }
1482
1483 FillAllocMemory( // Extended partial file
1484 heap,
1485 oldFreeStart,
1486 GetOffsetFromPtr(oldFreeStart, rgnNewFree.start));
1487 }
1488 }
1489 // When shrinking the new area
1490 else
1491 {
1492 MemRegion rgnNewFree;
1493 const u32 oldBlockSize = pMBHead->blockSize;
1494
1495 rgnNewFree.start = AddU32ToPtr(memBlock, size); // The region position to be newly freed
1496 rgnNewFree.end = GetMBlockEndAddr_(pMBHead); // The end address for the block currently being used
1497
1498 pMBHead->blockSize = size; // Changes the target block size
1499
1500 if ( ! RecycleRegion_(pEHHead, &rgnNewFree) ) // Tries returning the free list
1501 {
1502 pMBHead->blockSize = oldBlockSize; // Restores to original form if failed
1503 }
1504 }
1505
1506 UnlockHeap( heap );
1507
1508 return pMBHead->blockSize;
1509 }
1510
1511 /*---------------------------------------------------------------------------*
1512 Name: MEMFreeToExpHeap
1513
1514 Description: Returns the memory block to the expanded heap.
1515
1516 Arguments: heap : Handle for expanded heap
1517 memBlock: Pointer to the memory block to be returned.
1518
1519 Returns: None.
1520 *---------------------------------------------------------------------------*/
1521 void
MEMFreeToExpHeap(MEMHeapHandle heap,void * memBlock)1522 MEMFreeToExpHeap(
1523 MEMHeapHandle heap,
1524 void* memBlock
1525 )
1526 {
1527 ASSERT(IsValidExpHeapHandle_(heap));
1528 if ( memBlock == NULL )
1529 {
1530 return;
1531 }
1532
1533 ASSERT(IsValidUsedMBlock_(memBlock, heap));
1534
1535 {
1536 MEMiHeapHead *pHeapHd = heap;
1537 MEMiExpHeapHead *pExpHeapHd = GetExpHeapHeadPtrFromHandle_( pHeapHd );
1538 MEMiExpHeapMBlockHead *pMBHead = GetMBlockHeadPtr_( memBlock );
1539 MemRegion region;
1540
1541 // Is it included in this heap?
1542 ASSERT( pHeapHd->heapStart <= memBlock && memBlock < pHeapHd->heapEnd );
1543
1544 LockHeap( heap );
1545
1546 GetRegionOfMBlock_( ®ion, pMBHead );
1547 (void)RemoveMBlock_( &pExpHeapHd->mbUsedList, pMBHead ); // Remove from the list being used
1548 (void)RecycleRegion_( pExpHeapHd, ®ion ); // Add the specified size from the specified address to the free region
1549
1550 UnlockHeap( heap );
1551 }
1552 }
1553
1554 /*---------------------------------------------------------------------------*
1555 Name: MEMGetTotalFreeSizeForExpHeap
1556
1557 Description: Gets the total size of the empty regions of the expanded heap.
1558
1559 Arguments: heap : Handle for expanded heap
1560
1561 Returns: Returns the total size of the empty regions in the expanded heap (in bytes).
1562 *---------------------------------------------------------------------------*/
1563 u32
MEMGetTotalFreeSizeForExpHeap(MEMHeapHandle heap)1564 MEMGetTotalFreeSizeForExpHeap( MEMHeapHandle heap )
1565 {
1566 u32 sumSize = 0;
1567
1568 ASSERT(IsValidExpHeapHandle_(heap));
1569
1570 LockHeap( heap );
1571
1572 {
1573 MEMiExpHeapHead *pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1574 MEMiExpHeapMBlockHead *pMBHead;
1575
1576 for ( pMBHead = pEHHead->mbFreeList.head; pMBHead; pMBHead = pMBHead->pMBHeadNext )
1577 {
1578 sumSize += pMBHead->blockSize;
1579 }
1580 }
1581
1582 UnlockHeap( heap );
1583 return sumSize;
1584 }
1585
1586 /*---------------------------------------------------------------------------*
1587 Name: MEMGetAllocatableSizeForExpHeapEx
1588
1589 Description: Gets a memory block of the maximum allocatable size from the expanded heap.
1590 The memory block alignment can be specified.
1591
1592 Arguments: heap : Handle for expanded heap
1593 alignment: Alignment of the memory block to be allocated.
1594 The following values can be specified: �}4, �}8, �}16, �}32, �}64, �}128, ...
1595
1596 Returns: Returns the maximum allocatable size from the expanded heap (in bytes).
1597 *---------------------------------------------------------------------------*/
1598 u32
MEMGetAllocatableSizeForExpHeapEx(MEMHeapHandle heap,int alignment)1599 MEMGetAllocatableSizeForExpHeapEx(
1600 MEMHeapHandle heap,
1601 int alignment
1602 )
1603 {
1604 ASSERT(IsValidExpHeapHandle_(heap));
1605
1606 // alignment check
1607 ASSERT(alignment % MIN_ALIGNMENT == 0);
1608 ASSERT((abs(alignment) & (abs(alignment) - 1)) == 0);
1609 ASSERT(MIN_ALIGNMENT <= abs(alignment));
1610
1611 alignment = abs(alignment); // Convert to a positive value just to be sure
1612
1613 LockHeap( heap );
1614
1615 {
1616 MEMiExpHeapHead *pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1617 MEMiExpHeapMBlockHead *pMBlkHd;
1618 u32 maxSize = 0;
1619 u32 offsetMin = 0xFFFFFFFF;
1620
1621 for ( pMBlkHd = pEHHead->mbFreeList.head; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadNext )
1622 {
1623 // Memory block position including the alignment
1624 void* baseAddress = RoundUpPtr(GetMemPtrForMBlock_(pMBlkHd), alignment);
1625
1626 if ( GetUIntPtr(baseAddress) < GetUIntPtr(GetMBlockEndAddr_(pMBlkHd)) )
1627 {
1628 const u32 blockSize = GetOffsetFromPtr(baseAddress, GetMBlockEndAddr_(pMBlkHd));
1629 // Empty area due to the alignment
1630 const u32 offset = GetOffsetFromPtr(GetMemPtrForMBlock_(pMBlkHd), baseAddress);
1631
1632 /*
1633 If the size is large, or the size is the same but wasted space is small,
1634 the memory block is updated
1635 */
1636 if ( maxSize < blockSize
1637 || (maxSize == blockSize && offsetMin > offset)
1638 )
1639 {
1640 maxSize = blockSize;
1641 offsetMin= offset;
1642 }
1643 }
1644 }
1645
1646 UnlockHeap( heap );
1647
1648 return maxSize;
1649 }
1650 }
1651
1652
1653 /*---------------------------------------------------------------------------*
1654 Name: MEMiIsEmptyExpHeap
1655
1656 Description: Checks whether the allocated block exists in the expanded heap.
1657
1658 Arguments: heap : Handle for expanded heap
1659
1660 Returns: If it doesn't exist, returns TRUE;
1661 If it does, returns FALSE.
1662 *---------------------------------------------------------------------------*/
1663 BOOL
MEMiIsEmptyExpHeap(MEMHeapHandle heap)1664 MEMiIsEmptyExpHeap( MEMHeapHandle heap )
1665 {
1666 MEMiExpHeapHead *pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_( heap );
1667 BOOL ret;
1668
1669 LockHeap( heap );
1670
1671 ret = (pExpHeapHd->mbFreeList.head == NULL);
1672
1673 UnlockHeap( heap );
1674
1675 return ret;
1676 }
1677
1678 /*---------------------------------------------------------------------------*
1679 Name: MEMSetAllocModeForExpHeap
1680
1681 Description: Sets the memory allocation mode for the expanded heap.
1682
1683 Arguments: heap : Handle for expanded heap
1684 mode: Memory allocation mode.
1685
1686 Returns: Returns the memory allocation mode for the previous expanded heap.
1687 *---------------------------------------------------------------------------*/
1688 u16
MEMSetAllocModeForExpHeap(MEMHeapHandle heap,u16 mode)1689 MEMSetAllocModeForExpHeap(
1690 MEMHeapHandle heap,
1691 u16 mode
1692 )
1693 {
1694 BOOL enabled;
1695 u16 beforeMode;
1696
1697 ASSERT(IsValidExpHeapHandle_(heap));
1698
1699 enabled = OSDisableInterrupts();
1700 {
1701 MEMiExpHeapHead *const pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1702 beforeMode = GetAllocMode_(pEHHead);
1703 SetAllocMode_(pEHHead, mode);
1704 }
1705 (void)OSRestoreInterrupts( enabled );
1706
1707 return beforeMode;
1708 }
1709
1710 /*---------------------------------------------------------------------------*
1711 Name: MEMGetAllocModeForExpHeap
1712
1713 Description: Gets the memory allocation mode for the expanded heap.
1714
1715 Arguments: heap : Handle for expanded heap
1716
1717 Returns: Returns the memory allocation mode for the expanded heap.
1718 *---------------------------------------------------------------------------*/
1719 u16
MEMGetAllocModeForExpHeap(MEMHeapHandle heap)1720 MEMGetAllocModeForExpHeap( MEMHeapHandle heap )
1721 {
1722 ASSERT(IsValidExpHeapHandle_(heap));
1723 return GetAllocMode_(GetExpHeapHeadPtrFromHandle_(heap));
1724 }
1725
1726 /*---------------------------------------------------------------------------*
1727 Name: MEMSetGroupIDForExpHeap
1728
1729 Description: Sets the group ID for the expanded heap.
1730
1731 Arguments: heap : Handle for expanded heap
1732 groupID: The group ID value to be set.
1733
1734 Returns: Returns the previous group ID value.
1735 *---------------------------------------------------------------------------*/
1736 u16
MEMSetGroupIDForExpHeap(MEMHeapHandle heap,u16 groupID)1737 MEMSetGroupIDForExpHeap(
1738 MEMHeapHandle heap,
1739 u16 groupID
1740 )
1741 {
1742 u16 beforeGroupID;
1743 BOOL enabled;
1744
1745 ASSERT(IsValidExpHeapHandle_(heap));
1746 ASSERT(groupID <= MAX_GROUPID);
1747
1748 enabled = OSDisableInterrupts();
1749 {
1750 MEMiExpHeapHead* pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1751 beforeGroupID = pEHHead->groupID;
1752 pEHHead->groupID = groupID;
1753
1754 }
1755 (void)OSRestoreInterrupts( enabled );
1756
1757 return beforeGroupID;
1758 }
1759
1760 /*---------------------------------------------------------------------------*
1761 Name: MEMGetGroupIDForExpHeap
1762
1763 Description: Gets the group ID for the expanded heap.
1764
1765 Arguments: heap : Handle for expanded heap
1766
1767 Returns: Returns the group ID value.
1768 *---------------------------------------------------------------------------*/
1769 u16
MEMGetGroupIDForExpHeap(MEMHeapHandle heap)1770 MEMGetGroupIDForExpHeap( MEMHeapHandle heap )
1771 {
1772 ASSERT(IsValidExpHeapHandle_(heap));
1773
1774 return GetExpHeapHeadPtrFromHandle_(heap)->groupID;
1775 }
1776
1777 /*---------------------------------------------------------------------------*
1778 Name: MEMVisitAllocatedForExpHeap
1779
1780 Description: Causes the function specified by the user to be called
1781 for all the memory blocks allocated from the expanded heap.
1782 The visitor function is called on these memory blocks in the order they were allocated.
1783
1784 The visitor type HeapVisitor is defined as below.
1785
1786 typedef void (*HeapVisitor)(
1787 void* memBlock,
1788 MEMHeapHandle heap,
1789 u32 userParam);
1790
1791 memBlock: Pointer to the memory block.
1792 heap : Heap including the memory block.
1793 userParam: User parameter.
1794
1795 Arguments: heap : Handle for expanded heap
1796 visitor : Function called for each memory block.
1797 userParam: User-specified parameter to be passed to the visitor function
1798
1799 Returns: None.
1800 *---------------------------------------------------------------------------*/
1801 void
MEMVisitAllocatedForExpHeap(MEMHeapHandle heap,MEMHeapVisitor visitor,u32 userParam)1802 MEMVisitAllocatedForExpHeap(
1803 MEMHeapHandle heap,
1804 MEMHeapVisitor visitor,
1805 u32 userParam
1806 )
1807 {
1808 ASSERT(IsValidExpHeapHandle_(heap));
1809 ASSERT(visitor != NULL);
1810
1811 LockHeap( heap );
1812 {
1813 MEMiExpHeapMBlockHead* pMBHead = GetExpHeapHeadPtrFromHandle_(heap)->mbUsedList.head;
1814
1815 while ( pMBHead )
1816 {
1817 MEMiExpHeapMBlockHead* pMBHeadNext = pMBHead->pMBHeadNext;
1818 (*visitor)(GetMemPtrForMBlock_(pMBHead), heap, userParam);
1819 pMBHead = pMBHeadNext;
1820 }
1821 }
1822 UnlockHeap( heap );
1823 }
1824
1825 /*---------------------------------------------------------------------------*
1826 Name: MEMGetSizeForMBlockExpHeap
1827
1828 Description: Gets the size of the memory block allocated from the expanded heap.
1829
1830 Arguments: memBlock: Pointer to the memory block for getting the size.
1831
1832 Returns: Returns the size of the specified memory block (in bytes).
1833 *---------------------------------------------------------------------------*/
1834 u32
MEMGetSizeForMBlockExpHeap(const void * memBlock)1835 MEMGetSizeForMBlockExpHeap( const void* memBlock )
1836 {
1837 ASSERT(IsValidUsedMBlock_(memBlock, NULL));
1838
1839 return GetMBlockHeadCPtr_( memBlock )->blockSize;
1840 }
1841
1842 /*---------------------------------------------------------------------------*
1843 Name: MEMGetGroupIDForMBlockExpHeap
1844
1845 Description: Gets the group ID for the memory block allocated from the expanded heap.
1846
1847 Arguments: memBlock: Pointer to the memory block for getting the group ID.
1848
1849 Returns: Returns the group ID for the specified memory block.
1850 *---------------------------------------------------------------------------*/
1851 u16
MEMGetGroupIDForMBlockExpHeap(const void * memBlock)1852 MEMGetGroupIDForMBlockExpHeap( const void* memBlock )
1853 {
1854 ASSERT(IsValidUsedMBlock_(memBlock, NULL));
1855
1856 return GetGroupIDForMBlock_( GetMBlockHeadCPtr_(memBlock) );
1857 }
1858
1859 /*---------------------------------------------------------------------------*
1860 Name: MEMGetAllocDirForMBlockExpHeap
1861
1862 Description: Gets the allocation direction for the memory block allocated from the expanded heap.
1863
1864 Arguments: memBlock: Pointer to the memory block.
1865
1866 Returns: Returns the allocation direction for the specified memory block.
1867 *---------------------------------------------------------------------------*/
1868 u16
MEMGetAllocDirForMBlockExpHeap(const void * memBlock)1869 MEMGetAllocDirForMBlockExpHeap( const void* memBlock )
1870 {
1871 ASSERT(IsValidUsedMBlock_( memBlock, NULL ));
1872
1873 return GetAllocDirForMBlock_( GetMBlockHeadCPtr_(memBlock) );
1874 }
1875
1876
1877 /*---------------------------------------------------------------------------*
1878 Name: MEMAdjustExpHeap
1879
1880 Description: Releases the expanded heap's empty region, and reduces the memory available for the expanded heap.
1881 There must not be memory blocks allocated from the back of heap memory.
1882
1883 Arguments: heap : Handle for expanded heap
1884
1885 Returns: Returns the overal expanded heap size after reduction if successful.
1886 (including the header portion)
1887 Returns 0 if unsuccessful.
1888
1889 *---------------------------------------------------------------------------*/
1890 u32
MEMAdjustExpHeap(MEMHeapHandle heap)1891 MEMAdjustExpHeap( MEMHeapHandle heap )
1892 {
1893 ASSERT( IsValidExpHeapHandle_(heap) );
1894
1895 {
1896 MEMiHeapHead *pHeapHd = heap;
1897 MEMiExpHeapHead *pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_( heap );
1898 MEMiExpHeapMBlockHead *pMBlkHd;
1899 u32 retVal;
1900
1901 LockHeap( heap );
1902
1903 pMBlkHd = pExpHeapHd->mbFreeList.tail;
1904
1905 // fails if there are no empty regions
1906 if ( pMBlkHd == NULL )
1907 {
1908 retVal = 0;
1909 goto ret_;
1910 }
1911
1912 {
1913 void * const pMBlk = GetMemPtrForMBlock_( pMBlkHd );
1914 void * const pMBlkEnd = AddU32ToPtr( pMBlk, pMBlkHd->blockSize );
1915 u32 blockSize;
1916
1917 // fails if there are any memory blocks allocated from the end
1918 if ( pMBlkEnd != MEMGetHeapEndAddress( heap ) )
1919 {
1920 retVal = 0;
1921 goto ret_;
1922 }
1923
1924 // Delete released free block from the free list
1925 (void)RemoveMBlock_( &pExpHeapHd->mbFreeList, pMBlkHd );
1926
1927 blockSize = pMBlkHd->blockSize + sizeof( MEMiExpHeapMBlockHead );
1928 pHeapHd->heapEnd = SubU32ToPtr( pHeapHd->heapEnd, blockSize );
1929
1930 retVal = GetOffsetFromPtr( pHeapHd, pHeapHd->heapEnd );
1931 }
1932 ret_:
1933 UnlockHeap( heap );
1934
1935 return retVal;
1936 }
1937 }
1938
1939
1940 #if defined(_DEBUG)
1941
1942 /*---------------------------------------------------------------------------*
1943 Name: MEMCheckExpHeap
1944
1945 Description: Checks whether the expanded heap has been destroyed.
1946
1947 Arguments: heap : Handle for expanded heap
1948 optFlag: Flag.
1949
1950 Returns: Returns TRUE if the heap is normal.
1951 Returns FALSE if the heap has an error.
1952 *---------------------------------------------------------------------------*/
1953 BOOL
MEMCheckExpHeap(MEMHeapHandle heap,u32 optFlag)1954 MEMCheckExpHeap(
1955 MEMHeapHandle heap,
1956 u32 optFlag
1957 )
1958 {
1959 const BOOL bPrint = 0 != (optFlag & MEM_HEAP_ERROR_PRINT);
1960 u32 totalBytes = 0;
1961 BOOL retVal;
1962
1963 if ( ! IsValidExpHeapHandle_(heap) )
1964 {
1965 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Invalid heap handle. - %08X\n", heap);
1966 return FALSE;
1967 }
1968
1969 LockHeap( heap );
1970 {
1971 MEMiHeapHead *const pHeapHd = heap;
1972 MEMiExpHeapHead *const pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_(pHeapHd);
1973 MEMiExpHeapMBlockHead* pMBHead = NULL;
1974 MEMiExpHeapMBlockHead* pMBHeadPrev = NULL;
1975
1976 // Block used
1977 for ( pMBHead = pExpHeapHd->mbUsedList.head; pMBHead; pMBHeadPrev = pMBHead, pMBHead = pMBHead->pMBHeadNext )
1978 {
1979 if ( ! CheckUsedMBlock_(pMBHead, pHeapHd, optFlag)
1980 || ! CheckMBlockPrevPtr_(pMBHead, pMBHeadPrev, optFlag) // Is the pointer to the previous block the same as the pointer to the memory block in the previous loop?
1981 )
1982 {
1983 retVal = FALSE;
1984 goto ret_;
1985 }
1986
1987 // calculates size occupied
1988 totalBytes += sizeof(MEMiExpHeapMBlockHead) + pMBHead->blockSize + GetAlignmentForMBlock_(pMBHead);
1989 }
1990
1991 if ( ! CheckMBlockLinkTail_(pMBHeadPrev, pExpHeapHd->mbUsedList.tail, "tail", optFlag)) // Is the last block referring to the pointer to the final block?
1992 {
1993 retVal = FALSE;
1994 goto ret_;
1995 }
1996
1997 // free block
1998 pMBHead = NULL;
1999 pMBHeadPrev = NULL;
2000 for ( pMBHead = pExpHeapHd->mbFreeList.head; pMBHead; pMBHeadPrev = pMBHead, pMBHead = pMBHead->pMBHeadNext )
2001 {
2002 if ( ! CheckFreeMBlock_(pMBHead, pHeapHd, optFlag)
2003 || ! CheckMBlockPrevPtr_(pMBHead, pMBHeadPrev, optFlag) // Is the pointer to the previous block the same as the pointer to the memory block in the previous loop?
2004 )
2005 {
2006 retVal = FALSE;
2007 goto ret_;
2008 }
2009
2010 // calculates size occupied
2011 totalBytes += sizeof(MEMiExpHeapMBlockHead) + pMBHead->blockSize;
2012 }
2013
2014 if ( ! CheckMBlockLinkTail_(pMBHeadPrev, pExpHeapHd->mbFreeList.tail, "tail", optFlag) ) // Is the last block referring to the pointer to the final block?
2015 {
2016 retVal = FALSE;
2017 goto ret_;
2018 }
2019
2020 // Display all results.
2021 if ( totalBytes != GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd) )
2022 {
2023 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Incorrect total memory block size. - heap size %08X, sum size %08X\n",
2024 GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd), totalBytes);
2025 retVal = FALSE;
2026 goto ret_;
2027 }
2028 retVal = TRUE;
2029 }
2030 ret_:
2031 UnlockHeap( heap );
2032 return retVal;
2033 }
2034
2035
2036 /*---------------------------------------------------------------------------*
2037 Name: MEMCheckForMBlockExpHeap
2038
2039 Description: This function checks if the memory block of the expanded heap was destroyed.
2040
2041 Arguments: memBlock: Pointer to the memory block checked.
2042 heap : Handle for expanded heap
2043 optFlag: Flag.
2044
2045 Returns: If the memory block is valid, TRUE.
2046 If the memory block has an error, FALSE.
2047 *---------------------------------------------------------------------------*/
2048 BOOL
MEMCheckForMBlockExpHeap(const void * memBlock,MEMHeapHandle heap,u32 optFlag)2049 MEMCheckForMBlockExpHeap(
2050 const void* memBlock,
2051 MEMHeapHandle heap,
2052 u32 optFlag
2053 )
2054 {
2055 const MEMiExpHeapMBlockHead* pMBHead = NULL;
2056 MEMiHeapHead *const pHeapHd = heap;
2057
2058 if ( ! memBlock )
2059 {
2060 return FALSE;
2061 }
2062
2063 pMBHead = GetMBlockHeadCPtr_( memBlock );
2064
2065 if ( ! CheckUsedMBlock_( pMBHead, pHeapHd, optFlag ) )
2066 {
2067 return FALSE;
2068 }
2069
2070 if ( pMBHead->pMBHeadPrev )
2071 {
2072 if ( ! CheckUsedMBlock_(pMBHead->pMBHeadPrev, pHeapHd, optFlag) // Check of signature and size of previous block.
2073 || ! CheckMBlockNextPtr_(pMBHead->pMBHeadPrev, pMBHead, optFlag) // Is the pointer for the next block of the previous block pointing to itself?
2074 )
2075 {
2076 return FALSE;
2077 }
2078 }
2079 else
2080 {
2081 if ( pHeapHd )
2082 {
2083 // If prev is NULL the head pointer of the list should be pointing to itself.
2084 if ( ! CheckMBlockLinkTail_(pMBHead, GetExpHeapHeadPtrFromHeapHead_(pHeapHd)->mbUsedList.head, "head", optFlag) )
2085 {
2086 return FALSE;
2087 }
2088 }
2089 }
2090
2091 if ( pMBHead->pMBHeadNext )
2092 {
2093 if ( ! CheckUsedMBlock_(pMBHead->pMBHeadNext, pHeapHd, optFlag) // Check of signature and size of next block.
2094 || ! CheckMBlockPrevPtr_(pMBHead->pMBHeadNext, pMBHead, optFlag) // Is the pointer for the previous block of the next block pointing to itself?
2095 )
2096 {
2097 return FALSE;
2098 }
2099 }
2100 else
2101 {
2102 if ( pHeapHd )
2103 {
2104 // If next is NULL the tail pointer of the list should be pointing to itself.
2105 if ( ! CheckMBlockLinkTail_(pMBHead, GetExpHeapHeadPtrFromHeapHead_(pHeapHd)->mbUsedList.tail, "tail", optFlag) )
2106 {
2107 return FALSE;
2108 }
2109 }
2110 }
2111
2112 return TRUE;
2113 }
2114
2115 // #if defined(_DEBUG)
2116 #endif
2117
2118
2119