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