1 /*---------------------------------------------------------------------------*
2 Project: MEM library
3 File: mem_expHeap.c
4 Programmers: Takano Makoto
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 from the pointer to the 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 the pointer to the MEMiExpHeapMBlockHead structure from the pointer to the memory block.
190
191 Gets the pointer to the memory block.
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 ending memory address from the pointer to the memory block.
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 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 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 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 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 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: 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 be added to
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 terminal address 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( // 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 for the time being
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 to the allocated memory block if the memory block was successfully allocated.
691
692 If the operation 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 end 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 to the allocated memory block if the memory block was successfully allocated.
756
757 If the operation 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 an 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 to be used as a free block, the alignment value of the used block adjacent to the end of the memory space is used.
817
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 if there are no free blocks at the end
871 //
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, and FALSE otherwise.
907
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, and FALSE otherwise.
980
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, and FALSE otherwise.
1018
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 previous 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 previous memory block is correct, and FALSE otherwise.
1041
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, and FALSE otherwise.
1073
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 pointer to the memory block is at the head or tail of the memory block list, and FALSE otherwise.
1106
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 the memory block is included in the heap.
1137
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 used 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 // ---- Amount Used
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 an 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 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 available 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: + or - 4, + or - 8, + or - 16, + or - 32, + or - 64, + or - 128, ...
1356
1357 Returns: Returns the pointer to the allocated memory block if the memory block was successfully allocated.
1358
1359 If the operation 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 UnlockHeap( heap );
1455 return 0;
1456 }
1457
1458 {
1459 MemRegion rgnNewFree;
1460 void *oldFreeStart;
1461 MEMiExpHeapMBlockHead *nextBlockPrev;
1462
1463 // Gets the free block region and temporarily removes the free block
1464 GetRegionOfMBlock_( &rgnNewFree, block );
1465 nextBlockPrev = RemoveMBlock_( &pEHHead->mbFreeList, block );
1466
1467 oldFreeStart = rgnNewFree.start;
1468 rgnNewFree.start = AddU32ToPtr( memBlock, size ); // The region position to be newly freed
1469
1470 // If the remainder is smaller than the memory block size
1471 if ( GetOffsetFromPtr(rgnNewFree.start, rgnNewFree.end) < sizeof(MEMiExpHeapMBlockHead) )
1472 {
1473 rgnNewFree.start = rgnNewFree.end; // It is absorbed into the block being used
1474 }
1475
1476 pMBHead->blockSize = GetOffsetFromPtr(memBlock, rgnNewFree.start); // Changes the target block size
1477
1478 // If the remainder is equal to or larger than the memory block size
1479 if ( GetOffsetFromPtr(rgnNewFree.start, rgnNewFree.end) >= sizeof(MEMiExpHeapMBlockHead) )
1480 {
1481 (void)InsertMBlock_(&pEHHead->mbFreeList, InitFreeMBlock_(&rgnNewFree), nextBlockPrev); // Creates a new free block
1482 }
1483
1484 FillAllocMemory( // Extended partial fill
1485 heap,
1486 oldFreeStart,
1487 GetOffsetFromPtr(oldFreeStart, rgnNewFree.start));
1488 }
1489 }
1490 // When shrinking the new area
1491 else
1492 {
1493 MemRegion rgnNewFree;
1494 const u32 oldBlockSize = pMBHead->blockSize;
1495
1496 rgnNewFree.start = AddU32ToPtr(memBlock, size); // The region position to be newly freed
1497 rgnNewFree.end = GetMBlockEndAddr_(pMBHead); // The end address for the block currently being used
1498
1499 pMBHead->blockSize = size; // Changes the target block size
1500
1501 if ( ! RecycleRegion_(pEHHead, &rgnNewFree) ) // Tries returning the free list
1502 {
1503 pMBHead->blockSize = oldBlockSize; // Restores to original form if failed
1504 }
1505 }
1506
1507 UnlockHeap( heap );
1508
1509 return pMBHead->blockSize;
1510 }
1511
1512 /*---------------------------------------------------------------------------*
1513 Name: MEMFreeToExpHeap
1514
1515 Description: Returns the memory block to the expanded heap.
1516
1517 Arguments: heap: Handle for expanded heap
1518 memBlock: Pointer to the memory block to be returned.
1519
1520 Returns: None.
1521 *---------------------------------------------------------------------------*/
1522 void
MEMFreeToExpHeap(MEMHeapHandle heap,void * memBlock)1523 MEMFreeToExpHeap(
1524 MEMHeapHandle heap,
1525 void* memBlock
1526 )
1527 {
1528 ASSERT(IsValidExpHeapHandle_(heap));
1529 if ( memBlock == NULL )
1530 {
1531 return;
1532 }
1533
1534 ASSERT(IsValidUsedMBlock_(memBlock, heap));
1535
1536 {
1537 MEMiHeapHead *pHeapHd = heap;
1538 MEMiExpHeapHead *pExpHeapHd = GetExpHeapHeadPtrFromHandle_( pHeapHd );
1539 MEMiExpHeapMBlockHead *pMBHead = GetMBlockHeadPtr_( memBlock );
1540 MemRegion region;
1541
1542 // Is it included in this heap?
1543 ASSERT( pHeapHd->heapStart <= memBlock && memBlock < pHeapHd->heapEnd );
1544
1545 LockHeap( heap );
1546
1547 GetRegionOfMBlock_( ®ion, pMBHead );
1548 (void)RemoveMBlock_( &pExpHeapHd->mbUsedList, pMBHead ); // Remove from the list being used
1549 (void)RecycleRegion_( pExpHeapHd, ®ion ); // Add the specified size from the specified address to the free region
1550
1551 UnlockHeap( heap );
1552 }
1553 }
1554
1555 /*---------------------------------------------------------------------------*
1556 Name: MEMGetTotalFreeSizeForExpHeap
1557
1558 Description: Gets the total size of the available regions of the expanded heap.
1559
1560 Arguments: heap: Handle for expanded heap
1561
1562 Returns: Returns the total size of the available regions in the expanded heap (in bytes).
1563 *---------------------------------------------------------------------------*/
1564 u32
MEMGetTotalFreeSizeForExpHeap(MEMHeapHandle heap)1565 MEMGetTotalFreeSizeForExpHeap( MEMHeapHandle heap )
1566 {
1567 u32 sumSize = 0;
1568
1569 ASSERT(IsValidExpHeapHandle_(heap));
1570
1571 LockHeap( heap );
1572
1573 {
1574 MEMiExpHeapHead *pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1575 MEMiExpHeapMBlockHead *pMBHead;
1576
1577 for ( pMBHead = pEHHead->mbFreeList.head; pMBHead; pMBHead = pMBHead->pMBHeadNext )
1578 {
1579 sumSize += pMBHead->blockSize;
1580 }
1581 }
1582
1583 UnlockHeap( heap );
1584 return sumSize;
1585 }
1586
1587 /*---------------------------------------------------------------------------*
1588 Name: MEMGetAllocatableSizeForExpHeapEx
1589
1590 Description: Gets a memory block of the maximum allocatable size from the expanded heap.
1591 The memory block alignment can be specified.
1592
1593 Arguments: heap: Handle for expanded heap
1594 alignment: Alignment of the memory block to be allocated
1595 The following values can be specified: + or - 4, + or - 8, + or - 16, + or - 32, + or - 64, + or - 128, ...
1596
1597 Returns: Returns the maximum allocatable size from the expanded heap (in bytes).
1598 *---------------------------------------------------------------------------*/
1599 u32
MEMGetAllocatableSizeForExpHeapEx(MEMHeapHandle heap,int alignment)1600 MEMGetAllocatableSizeForExpHeapEx(
1601 MEMHeapHandle heap,
1602 int alignment
1603 )
1604 {
1605 ASSERT(IsValidExpHeapHandle_(heap));
1606
1607 // alignment check
1608 ASSERT(alignment % MIN_ALIGNMENT == 0);
1609 ASSERT((abs(alignment) & (abs(alignment) - 1)) == 0);
1610 ASSERT(MIN_ALIGNMENT <= abs(alignment));
1611
1612 alignment = abs(alignment); // Convert to a positive value just to be sure
1613
1614 LockHeap( heap );
1615
1616 {
1617 MEMiExpHeapHead *pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1618 MEMiExpHeapMBlockHead *pMBlkHd;
1619 u32 maxSize = 0;
1620 u32 offsetMin = 0xFFFFFFFF;
1621
1622 for ( pMBlkHd = pEHHead->mbFreeList.head; pMBlkHd; pMBlkHd = pMBlkHd->pMBHeadNext )
1623 {
1624 // Memory block position including the alignment
1625 void* baseAddress = RoundUpPtr(GetMemPtrForMBlock_(pMBlkHd), alignment);
1626
1627 if ( GetUIntPtr(baseAddress) < GetUIntPtr(GetMBlockEndAddr_(pMBlkHd)) )
1628 {
1629 const u32 blockSize = GetOffsetFromPtr(baseAddress, GetMBlockEndAddr_(pMBlkHd));
1630 // Empty area due to the alignment
1631 const u32 offset = GetOffsetFromPtr(GetMemPtrForMBlock_(pMBlkHd), baseAddress);
1632
1633 /*
1634 If the size is large or the size is the same but wasted space is small, the memory block is updated.
1635
1636 */
1637 if ( maxSize < blockSize
1638 || (maxSize == blockSize && offsetMin > offset)
1639 )
1640 {
1641 maxSize = blockSize;
1642 offsetMin= offset;
1643 }
1644 }
1645 }
1646
1647 UnlockHeap( heap );
1648
1649 return maxSize;
1650 }
1651 }
1652
1653
1654 /*---------------------------------------------------------------------------*
1655 Name: MEMiIsEmptyExpHeap
1656
1657 Description: Checks whether the allocated block exists in the expanded heap.
1658
1659 Arguments: heap: Handle for expanded heap
1660
1661 Returns: If it doesn't exist, returns TRUE; otherwise returns FALSE.
1662
1663 *---------------------------------------------------------------------------*/
1664 BOOL
MEMiIsEmptyExpHeap(MEMHeapHandle heap)1665 MEMiIsEmptyExpHeap( MEMHeapHandle heap )
1666 {
1667 MEMiExpHeapHead *pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_( heap );
1668 BOOL ret;
1669
1670 LockHeap( heap );
1671
1672 ret = (pExpHeapHd->mbFreeList.head == NULL);
1673
1674 UnlockHeap( heap );
1675
1676 return ret;
1677 }
1678
1679 /*---------------------------------------------------------------------------*
1680 Name: MEMSetAllocModeForExpHeap
1681
1682 Description: Sets the memory allocation mode for the expanded heap.
1683
1684 Arguments: heap: Handle for expanded heap
1685 mode: Memory allocation mode.
1686
1687 Returns: Returns the memory allocation mode for the previous expanded heap.
1688 *---------------------------------------------------------------------------*/
1689 u16
MEMSetAllocModeForExpHeap(MEMHeapHandle heap,u16 mode)1690 MEMSetAllocModeForExpHeap(
1691 MEMHeapHandle heap,
1692 u16 mode
1693 )
1694 {
1695 BOOL enabled;
1696 u16 beforeMode;
1697
1698 ASSERT(IsValidExpHeapHandle_(heap));
1699
1700 enabled = OSDisableInterrupts();
1701 {
1702 MEMiExpHeapHead *const pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1703 beforeMode = GetAllocMode_(pEHHead);
1704 SetAllocMode_(pEHHead, mode);
1705 }
1706 (void)OSRestoreInterrupts( enabled );
1707
1708 return beforeMode;
1709 }
1710
1711 /*---------------------------------------------------------------------------*
1712 Name: MEMGetAllocModeForExpHeap
1713
1714 Description: Gets the memory allocation mode for the expanded heap.
1715
1716 Arguments: heap: Handle for expanded heap
1717
1718 Returns: Returns the memory allocation mode for the expanded heap.
1719 *---------------------------------------------------------------------------*/
1720 u16
MEMGetAllocModeForExpHeap(MEMHeapHandle heap)1721 MEMGetAllocModeForExpHeap( MEMHeapHandle heap )
1722 {
1723 ASSERT(IsValidExpHeapHandle_(heap));
1724 return GetAllocMode_(GetExpHeapHeadPtrFromHandle_(heap));
1725 }
1726
1727 /*---------------------------------------------------------------------------*
1728 Name: MEMSetGroupIDForExpHeap
1729
1730 Description: Sets the group ID for the expanded heap.
1731
1732 Arguments: heap: Handle for expanded heap
1733 groupID: The group ID value to be set.
1734
1735 Returns: Returns the previous group ID value.
1736 *---------------------------------------------------------------------------*/
1737 u16
MEMSetGroupIDForExpHeap(MEMHeapHandle heap,u16 groupID)1738 MEMSetGroupIDForExpHeap(
1739 MEMHeapHandle heap,
1740 u16 groupID
1741 )
1742 {
1743 u16 beforeGroupID;
1744 BOOL enabled;
1745
1746 ASSERT(IsValidExpHeapHandle_(heap));
1747 ASSERT(groupID <= MAX_GROUPID);
1748
1749 enabled = OSDisableInterrupts();
1750 {
1751 MEMiExpHeapHead* pEHHead = GetExpHeapHeadPtrFromHandle_(heap);
1752 beforeGroupID = pEHHead->groupID;
1753 pEHHead->groupID = groupID;
1754
1755 }
1756 (void)OSRestoreInterrupts( enabled );
1757
1758 return beforeGroupID;
1759 }
1760
1761 /*---------------------------------------------------------------------------*
1762 Name: MEMGetGroupIDForExpHeap
1763
1764 Description: Gets the group ID for the expanded heap.
1765
1766 Arguments: heap: Handle for expanded heap
1767
1768 Returns: Returns the group ID value.
1769 *---------------------------------------------------------------------------*/
1770 u16
MEMGetGroupIDForExpHeap(MEMHeapHandle heap)1771 MEMGetGroupIDForExpHeap( MEMHeapHandle heap )
1772 {
1773 ASSERT(IsValidExpHeapHandle_(heap));
1774
1775 return GetExpHeapHeadPtrFromHandle_(heap)->groupID;
1776 }
1777
1778 /*---------------------------------------------------------------------------*
1779 Name: MEMVisitAllocatedForExpHeap
1780
1781 Description: Causes the function specified by the user to be called for all the memory blocks allocated from the expanded heap.
1782
1783 The visitor function is called on these memory blocks in the order they were allocated.
1784
1785 The visitor type HeapVisitor is defined as below.
1786
1787 typedef void (*HeapVisitor)(
1788 void* memBlock,
1789 MEMHeapHandle heap,
1790 u32 userParam);
1791
1792 memBlock: Pointer to the memory block.
1793 heap: Heap including the memory block.
1794 userParam: User parameter.
1795
1796 Arguments: heap: Handle for expanded heap
1797 visitor: Function called for each memory block.
1798 userParam: User-specified parameter to be passed to the visitor function
1799
1800 Returns: None.
1801 *---------------------------------------------------------------------------*/
1802 void
MEMVisitAllocatedForExpHeap(MEMHeapHandle heap,MEMHeapVisitor visitor,u32 userParam)1803 MEMVisitAllocatedForExpHeap(
1804 MEMHeapHandle heap,
1805 MEMHeapVisitor visitor,
1806 u32 userParam
1807 )
1808 {
1809 ASSERT(IsValidExpHeapHandle_(heap));
1810 ASSERT(visitor != NULL);
1811
1812 LockHeap( heap );
1813 {
1814 MEMiExpHeapMBlockHead* pMBHead = GetExpHeapHeadPtrFromHandle_(heap)->mbUsedList.head;
1815
1816 while ( pMBHead )
1817 {
1818 MEMiExpHeapMBlockHead* pMBHeadNext = pMBHead->pMBHeadNext;
1819 (*visitor)(GetMemPtrForMBlock_(pMBHead), heap, userParam);
1820 pMBHead = pMBHeadNext;
1821 }
1822 }
1823 UnlockHeap( heap );
1824 }
1825
1826 /*---------------------------------------------------------------------------*
1827 Name: MEMGetSizeForMBlockExpHeap
1828
1829 Description: Gets the size of the memory block that was allocated from the expanded heap.
1830
1831 Arguments: memBlock: Pointer to the memory block for getting the size.
1832
1833 Returns: Returns the size of the specified memory block (in bytes).
1834 *---------------------------------------------------------------------------*/
1835 u32
MEMGetSizeForMBlockExpHeap(const void * memBlock)1836 MEMGetSizeForMBlockExpHeap( const void* memBlock )
1837 {
1838 ASSERT(IsValidUsedMBlock_(memBlock, NULL));
1839
1840 return GetMBlockHeadCPtr_( memBlock )->blockSize;
1841 }
1842
1843 /*---------------------------------------------------------------------------*
1844 Name: MEMGetGroupIDForMBlockExpHeap
1845
1846 Description: Gets the group ID for the memory block allocated from the expanded heap.
1847
1848 Arguments: memBlock: Pointer to the memory block for getting the group ID.
1849
1850 Returns: Returns the group ID for the specified memory block.
1851 *---------------------------------------------------------------------------*/
1852 u16
MEMGetGroupIDForMBlockExpHeap(const void * memBlock)1853 MEMGetGroupIDForMBlockExpHeap( const void* memBlock )
1854 {
1855 ASSERT(IsValidUsedMBlock_(memBlock, NULL));
1856
1857 return GetGroupIDForMBlock_( GetMBlockHeadCPtr_(memBlock) );
1858 }
1859
1860 /*---------------------------------------------------------------------------*
1861 Name: MEMGetAllocDirForMBlockExpHeap
1862
1863 Description: Gets the allocation direction for the memory block allocated from the expanded heap.
1864
1865 Arguments: memBlock: Pointer to the memory block.
1866
1867 Returns: Returns the allocation direction for the specified memory block.
1868 *---------------------------------------------------------------------------*/
1869 u16
MEMGetAllocDirForMBlockExpHeap(const void * memBlock)1870 MEMGetAllocDirForMBlockExpHeap( const void* memBlock )
1871 {
1872 ASSERT(IsValidUsedMBlock_( memBlock, NULL ));
1873
1874 return GetAllocDirForMBlock_( GetMBlockHeadCPtr_(memBlock) );
1875 }
1876
1877
1878 /*---------------------------------------------------------------------------*
1879 Name: MEMAdjustExpHeap
1880
1881 Description: Deallocates the expanded heap's available region, and reduces the memory available for the expanded heap.
1882 There must not be memory blocks allocated from the back of heap memory.
1883
1884 Arguments: heap: Handle for expanded heap
1885
1886 Returns: Returns the overall expanded heap size after reduction if successful.
1887 (Including the header portion.)
1888 Returns 0 if unsuccessful.
1889
1890 *---------------------------------------------------------------------------*/
1891 u32
MEMAdjustExpHeap(MEMHeapHandle heap)1892 MEMAdjustExpHeap( MEMHeapHandle heap )
1893 {
1894 ASSERT( IsValidExpHeapHandle_(heap) );
1895
1896 {
1897 MEMiHeapHead *pHeapHd = heap;
1898 MEMiExpHeapHead *pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_( heap );
1899 MEMiExpHeapMBlockHead *pMBlkHd;
1900 u32 retVal;
1901
1902 LockHeap( heap );
1903
1904 pMBlkHd = pExpHeapHd->mbFreeList.tail;
1905
1906 // fails if there are no available regions
1907 if ( pMBlkHd == NULL )
1908 {
1909 retVal = 0;
1910 goto ret_;
1911 }
1912
1913 {
1914 void * const pMBlk = GetMemPtrForMBlock_( pMBlkHd );
1915 void * const pMBlkEnd = AddU32ToPtr( pMBlk, pMBlkHd->blockSize );
1916 u32 blockSize;
1917
1918 // fails if there are any memory blocks allocated from the end
1919 if ( pMBlkEnd != MEMGetHeapEndAddress( heap ) )
1920 {
1921 retVal = 0;
1922 goto ret_;
1923 }
1924
1925 // Delete deallocated free block from the free list
1926 (void)RemoveMBlock_( &pExpHeapHd->mbFreeList, pMBlkHd );
1927
1928 blockSize = pMBlkHd->blockSize + sizeof( MEMiExpHeapMBlockHead );
1929 pHeapHd->heapEnd = SubU32ToPtr( pHeapHd->heapEnd, blockSize );
1930
1931 retVal = GetOffsetFromPtr( pHeapHd, pHeapHd->heapEnd );
1932 }
1933 ret_:
1934 UnlockHeap( heap );
1935
1936 return retVal;
1937 }
1938 }
1939
1940
1941 #if defined(_DEBUG)
1942
1943 /*---------------------------------------------------------------------------*
1944 Name: MEMCheckExpHeap
1945
1946 Description: Checks whether the expanded heap has been destroyed.
1947
1948 Arguments: heap: Handle for expanded heap
1949 optFlag: Flag.
1950
1951 Returns: Returns TRUE if the heap is normal.
1952 Returns FALSE if the heap has an error.
1953 *---------------------------------------------------------------------------*/
1954 BOOL
MEMCheckExpHeap(MEMHeapHandle heap,u32 optFlag)1955 MEMCheckExpHeap(
1956 MEMHeapHandle heap,
1957 u32 optFlag
1958 )
1959 {
1960 const BOOL bPrint = 0 != (optFlag & MEM_HEAP_ERROR_PRINT);
1961 u32 totalBytes = 0;
1962 BOOL retVal;
1963
1964 if ( ! IsValidExpHeapHandle_(heap) )
1965 {
1966 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Invalid heap handle. - %08X\n", heap);
1967 return FALSE;
1968 }
1969
1970 LockHeap( heap );
1971 {
1972 MEMiHeapHead *const pHeapHd = heap;
1973 MEMiExpHeapHead *const pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_(pHeapHd);
1974 MEMiExpHeapMBlockHead* pMBHead = NULL;
1975 MEMiExpHeapMBlockHead* pMBHeadPrev = NULL;
1976
1977 // Block used
1978 for ( pMBHead = pExpHeapHd->mbUsedList.head; pMBHead; pMBHeadPrev = pMBHead, pMBHead = pMBHead->pMBHeadNext )
1979 {
1980 if ( ! CheckUsedMBlock_(pMBHead, pHeapHd, optFlag)
1981 || ! CheckMBlockPrevPtr_(pMBHead, pMBHeadPrev, optFlag) // Is the pointer to the previous block the same as the pointer to the memory block in the previous loop?
1982 )
1983 {
1984 retVal = FALSE;
1985 goto ret_;
1986 }
1987
1988 // calculates size occupied
1989 totalBytes += sizeof(MEMiExpHeapMBlockHead) + pMBHead->blockSize + GetAlignmentForMBlock_(pMBHead);
1990 }
1991
1992 if ( ! CheckMBlockLinkTail_(pMBHeadPrev, pExpHeapHd->mbUsedList.tail, "tail", optFlag)) // Is the last block referring to the pointer to the final block?
1993 {
1994 retVal = FALSE;
1995 goto ret_;
1996 }
1997
1998 // free block
1999 pMBHead = NULL;
2000 pMBHeadPrev = NULL;
2001 for ( pMBHead = pExpHeapHd->mbFreeList.head; pMBHead; pMBHeadPrev = pMBHead, pMBHead = pMBHead->pMBHeadNext )
2002 {
2003 if ( ! CheckFreeMBlock_(pMBHead, pHeapHd, optFlag)
2004 || ! CheckMBlockPrevPtr_(pMBHead, pMBHeadPrev, optFlag) // Is the pointer to the previous block the same as the pointer to the memory block in the previous loop?
2005 )
2006 {
2007 retVal = FALSE;
2008 goto ret_;
2009 }
2010
2011 // calculates size occupied
2012 totalBytes += sizeof(MEMiExpHeapMBlockHead) + pMBHead->blockSize;
2013 }
2014
2015 if ( ! CheckMBlockLinkTail_(pMBHeadPrev, pExpHeapHd->mbFreeList.tail, "tail", optFlag) ) // Is the last block referring to the pointer to the final block?
2016 {
2017 retVal = FALSE;
2018 goto ret_;
2019 }
2020
2021 // Display all results.
2022 if ( totalBytes != GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd) )
2023 {
2024 HEAP_WARNING(bPrint, "[OS Foundation " "Exp" " Heap]" " Incorrect total memory block size. - heap size %08X, sum size %08X\n",
2025 GetOffsetFromPtr(pHeapHd->heapStart, pHeapHd->heapEnd), totalBytes);
2026 retVal = FALSE;
2027 goto ret_;
2028 }
2029 retVal = TRUE;
2030 }
2031 ret_:
2032 UnlockHeap( heap );
2033 return retVal;
2034 }
2035
2036
2037 /*---------------------------------------------------------------------------*
2038 Name: MEMCheckForMBlockExpHeap
2039
2040 Description: This function checks if the memory block of the expanded heap was destroyed.
2041
2042 Arguments: memBlock: Pointer to the memory block checked.
2043 heap: Handle for expanded heap
2044 optFlag: Flag.
2045
2046 Returns: If the memory block is valid, returns TRUE.
2047 If the memory block has an error, returns FALSE.
2048 *---------------------------------------------------------------------------*/
2049 BOOL
MEMCheckForMBlockExpHeap(const void * memBlock,MEMHeapHandle heap,u32 optFlag)2050 MEMCheckForMBlockExpHeap(
2051 const void* memBlock,
2052 MEMHeapHandle heap,
2053 u32 optFlag
2054 )
2055 {
2056 const MEMiExpHeapMBlockHead* pMBHead = NULL;
2057 MEMiHeapHead *const pHeapHd = heap;
2058
2059 if ( ! memBlock )
2060 {
2061 return FALSE;
2062 }
2063
2064 pMBHead = GetMBlockHeadCPtr_( memBlock );
2065
2066 if ( ! CheckUsedMBlock_( pMBHead, pHeapHd, optFlag ) )
2067 {
2068 return FALSE;
2069 }
2070
2071 if ( pMBHead->pMBHeadPrev )
2072 {
2073 if ( ! CheckUsedMBlock_(pMBHead->pMBHeadPrev, pHeapHd, optFlag) // Check of signature and size of previous block.
2074 || ! CheckMBlockNextPtr_(pMBHead->pMBHeadPrev, pMBHead, optFlag) // Is the previous block's pointer to the next block pointing to the current block?
2075 )
2076 {
2077 return FALSE;
2078 }
2079 }
2080 else
2081 {
2082 if ( pHeapHd )
2083 {
2084 // If prev is NULL the head pointer of the list should be pointing to current (block).
2085 if ( ! CheckMBlockLinkTail_(pMBHead, GetExpHeapHeadPtrFromHeapHead_(pHeapHd)->mbUsedList.head, "head", optFlag) )
2086 {
2087 return FALSE;
2088 }
2089 }
2090 }
2091
2092 if ( pMBHead->pMBHeadNext )
2093 {
2094 if ( ! CheckUsedMBlock_(pMBHead->pMBHeadNext, pHeapHd, optFlag) // Check of signature and size of next block.
2095 || ! CheckMBlockPrevPtr_(pMBHead->pMBHeadNext, pMBHead, optFlag) // Is the next block's pointer to the previous block pointing to current block?
2096 )
2097 {
2098 return FALSE;
2099 }
2100 }
2101 else
2102 {
2103 if ( pHeapHd )
2104 {
2105 // If next is NULL the tail pointer of the list should be pointing to current (block).
2106 if ( ! CheckMBlockLinkTail_(pMBHead, GetExpHeapHeadPtrFromHeapHead_(pHeapHd)->mbUsedList.tail, "tail", optFlag) )
2107 {
2108 return FALSE;
2109 }
2110 }
2111 }
2112
2113 return TRUE;
2114 }
2115
2116 // #if defined(_DEBUG)
2117 #endif
2118
2119
2120