1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: fnd_DetailHeap.cpp
4
5 Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Rev: 46866 $
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 using 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
131 Description: Gets the pointer to the expanded heap header from the pointer to the heap header.
132
133 Arguments: pHHead: Pointer to the heap header
134
135 Returns: Returns the pointer to the expanded heap header.
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
152 Description: Gets the pointer to the heap header from the pointer to the expanded heap header.
153
154 Arguments: pEHHead: Pointer to the expanded heap header.
155
156 Returns: Returns the pointer to the heap header.
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
167 Description: Gets the pointer to the expanded heap header from the expanded heap handle.
168
169 Arguments: heap: expanded heap handle
170
171 Returns: Returns the pointer to the expanded heap header.
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
188 Description: Gets the pointer to the memory block from the pointer to the NNSiFndExpHeapMBlockHead structure.
189
190
191 Arguments: pMBlkHd: pointer to the NNSiFndExpHeapMBlockHead structure
192
193 Returns: Returns the pointer to the memory block.
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
212 Description: Gets the pointer to the NNSiFndExpHeapMBlockHead structure from the pointer to the memory block.
213
214 Gets the pointer to the memory block.
215
216 Arguments: memBlock: pointer to the memory block
217
218 Returns: Returns the pointer to the NNSiFndExpHeapMBlockHead structure.
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
245 Description: Gets the alignment value for the NNSiFndExpHeapMBlockHead structure.
246
247 Arguments: pMBlkHd: pointer to the NNSiFndExpHeapMBlockHead structure
248
249 Returns: Returns the alignment value for the NNSiFndExpHeapMBlockHead structure.
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
260 Description: Sets the alignment value for the NNSiFndExpHeapMBlockHead structure.
261
262 Arguments: pMBlkHd: pointer to the NNSiFndExpHeapMBlockHead structure
263 alignment: alignment value to be set
264
265 Returns: None.
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
314 Description: Gets the memory allocation mode for the expanded heap.
315
316 Arguments: pEHHead: Pointer to the expanded heap header.
317
318 Returns: Returns the memory allocation mode for the expanded heap.
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
329 Description: Sets the memory allocation mode for the expanded heap.
330
331 Arguments: pEHHead: Pointer to the expanded heap header.
332 mode: Memory allocation mode.
333
334 Returns: None.
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
431 Description: Adds a memory block to the end of the list.
432
433 Arguments: link: List to be added to
434 block: Memory block to add
435
436 Returns: None.
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
450 Description: Initializes a memory block.
451
452 Arguments: pRegion: pointer to the structure representing the region used for the memory block
453 signature: memory block signature
454
455 Returns: Returns the pointer to the initialized memory block.
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
477 Description: Initializes the memory block for use as a free block.
478
479 Arguments: pRegion: pointer to the structure representing the region used for the memory block
480
481 Returns: Returns the pointer to the initialized memory block.
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
494 Description: Initializes the expanded heap.
495
496 Arguments: pHeapHead: Pointer to the heap header.
497 startAddress: memory start address for the expanded heap
498 endAddress: terminal address for the memory for the expanded heap incremented by one
499 optFlag: Option flag
500
501 Returns: Returns the pointer to the heap header.
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
546 Description: Allocates a new memory block from free blocks.
547
548 Arguments: pEHHead: Pointer to the expanded heap header.
549 pMBHeadFree: Pointer to the free block header.
550 mblock: Address for the memory block to be allocated.
551 size: Size of the memory block to be allocated.
552 direction: Allocation direction.
553
554 Returns: Returns a pointer to the start of the allocated memory block.
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
622 Description: Allocates the memory block from the start of the heap.
623
624 Arguments: pHeapHd: Pointer to the heap header
625 size: Size of the memory block to be allocated.
626 alignment: alignment value
627
628 Returns: Returns a pointer to the allocated memory block if the allocation is successful.
629
630 If the operation fails, NULL is returned.
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
686 Description: Allocates a memory block from the end of the heap.
687
688 Arguments: pHeapHd: Pointer to the heap header
689 size: Size of the memory block to be allocated.
690 alignment: alignment value
691
692 Returns: Returns a pointer to the allocated memory block if the allocation is successful.
693
694 If the operation fails, NULL is returned.
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
750 Description: Incorporates an empty region into a free memory block.
751 If it is adjacent to a free block, the free block is expanded.
752 If it is not adjacent to a free block, and if the size is not close to the size of a free block, the empty region takes the alignment value of a used block adjacent to the end of the empty region.
753
754 If there is no used block adjacent to the end of the empty region, the function fails.
755
756 Arguments: pEHHead: Pointer to the expanded heap header.
757 pRegion: pointer to the empty region
758
759 Returns: Returns TRUE if the function is successful.
760 Returns FALSE if it fails.
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; // Try to reduce the size using ResizeForMBlockHeap()
807 // And arrive here if there are not free blocks at the end of the heap
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
823 Description: Checks whether the header contents for the memory block are valid.
824
825 Arguments: pMBHead: pointer to the header for the memory block to be checked
826 pHeapHd: pointer to the expanded heap header
827 signature: memory block signature
828 heapType: memory block type (used or free)
829 flag: Flag.
830
831 Returns: Returns true if the header contents for the memory block are valid, and returns false otherwise.
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
887 Description: Checks whether the header contents for the memory block being used are valid.
888
889 Arguments: pMBHead: pointer to the header for the memory block to be checked
890 pHeapHd: pointer to the expanded heap header
891 flag: Flag.
892
893 Returns: Returns true if the header contents for the memory block are valid, and returns false otherwise.
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
914 Description: Checks whether the header contents for the free memory block are valid.
915
916 Arguments: pMBHead: pointer to the header for the memory block to be checked
917 pHeapHd: pointer to the expanded heap header
918 flag: Flag.
919
920 Returns: Returns true if the header contents for the memory block are valid, and returns false otherwise.
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
941 Description: Checks whether the link to before the memory block is correct.
942
943 Arguments: pMBHead: pointer to the header for the memory block to be checked
944 pMBHeadPrev: pointer to the header for the memory block prior to the one being checked
945 flag: Flag.
946
947 Returns: Returns true if the link to before the memory block is correct, and returns false otherwise.
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
977 Description: Checks whether the link to after the memory block is correct.
978
979 Arguments: pMBHead: pointer to the header for the memory block to be checked
980 pMBHeadNext: pointer to the header for the memory block after the one being checked
981 flag: Flag.
982
983 Returns: Returns true if the link to after the memory block is correct, and returns false otherwise.
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
1013 Description: Checks whether the memory block pointer is at the start or end of the memory block list.
1014
1015 Arguments: pMBHead: pointer to the header for the memory block to be checked
1016 pMBHeadTail: pointer to the memory block at the start or end of the memory block list
1017 headType: string indicating the start or end
1018 flag: Flag.
1019
1020 Returns: Returns true if the memory block pointer is at the start or end of the memory block list, and returns false otherwise.
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
1052 Description: Checks whether the memory block being used is appropriate.
1053
1054 Arguments: memBlock: memory block to be checked
1055 heap: handle for the expanded heap containing the memory block
1056 If NULL is specified, it is not checked whether or not the memory block is contained in a heap.
1057
1058
1059 Returns: Returns TRUE if there is no problem with the specified memory block.
1060 Returns FALSE if there is a problem.
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
1090 Description: Shows internal expanded heap information.
1091 This function is used for debugging.
1092
1093 Arguments: heap: Handle for the expanded heap.
1094
1095 Returns: None.
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
1211 Description: Creates an expanded heap.
1212
1213 Arguments: startAddress: Start address of heap area
1214 size: Size of heap area
1215 optFlag: Option flag
1216
1217 Returns: If the function succeeds, a handle for the created expanded heap is returned.
1218 If the function fails, NN_OS_HEAP_INVALID_HANDLE is returned.
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
1251 Description: Destroys the expanded heap.
1252
1253 Arguments: heap: Handle for the expanded heap.
1254
1255 Returns: None.
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
1268 Description: Allocates a memory block from the expanded heap.
1269 The memory block alignment can be specified.
1270 If a negative alignment value is specified, an available region is searched for from the back of the heap.
1271
1272 Arguments: heap: Handle for the expanded heap.
1273 size: Size of the memory block to be allocated (in bytes)
1274 alignment: Alignment of the memory block to be allocated
1275 Allowable values: 4, 8, 16, 32, 64, 128, -4, -8, -16, -32, -64 or -128
1276
1277 Returns: Returns a pointer to the allocated memory block if the memory block allocation is successful.
1278
1279 If the operation fails, NULL is returned.
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
1317 Description: Changes the size of the memory block allocated from the expanded heap.
1318
1319 Arguments: heap: Handle for the expanded heap.
1320 memBlock: Pointer to the memory block to be resized
1321 size: New size to be allocated (in bytes)
1322
1323 Returns: Returns the size of the resized memory block (in bytes), if the function is successful.
1324 Returns 0 if the function fails.
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
1424 Description: Returns the memory block to the expanded heap.
1425
1426 Arguments: heap: Handle for the expanded heap.
1427 memBlock: Pointer to the memory block to be returned
1428
1429 Returns: None.
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
1457 Description: Gets the total size of the available regions of the expanded heap.
1458
1459 Arguments: heap: Handle for the expanded heap.
1460
1461 Returns: Returns the total size of the available regions in the expanded heap (in bytes).
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
1488 Arguments: heap: Handle for the expanded heap.
1489 alignment: Alignment of the memory block to be allocated
1490 Allowable values: 4, 8, 16, 32, 64 or 128
1491
1492 Returns: Returns the maximum allocatable size from the expanded heap (in bytes).
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 size is larger, or the the same but with 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
1546 Description: Sets the memory allocation mode for the expanded heap.
1547
1548 Arguments: heap: Handle for the expanded heap.
1549 mode: Memory allocation mode.
1550
1551 Returns: Returns the memory allocation mode for the previous expanded heap.
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
1573 Description: Gets the memory allocation mode for the expanded heap.
1574
1575 Arguments: heap: Handle for the expanded heap.
1576
1577 Returns: Returns the memory allocation mode for the expanded heap.
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
1589 Description: Configures whether regions in the gaps that occur during alignment should be reused.
1590
1591 Set to FALSE by default.
1592
1593 Although it may be possible to efficiently utilize small memory blocks if TRUE is set, there is a risk that performance will go down when allocating memory because of generating a large number of free blocks.
1594
1595
1596
1597
1598 Arguments: heap: Expanded heap handle
1599 reuse: If TRUE, reuse regions that are generated during alignment.
1600 If FALSE, do not reuse.
1601
1602 Returns: Returns the value of the previous setting.
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
1623 Description: Sets the group ID for the expanded heap.
1624
1625 Arguments: heap: Handle for the expanded heap.
1626 groupID: Group ID value to be set.
1627
1628 Returns: Returns the previous group ID value.
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
1650 Description: Gets the group ID for the expanded heap.
1651
1652 Arguments: heap: Handle for the expanded heap.
1653
1654 Returns: Returns the group ID value.
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
1667 Description: For all memory blocks that are allocated from expanded heaps, the functions specified by the user are called.
1668
1669 The order of the memory blocks called by the visitor function is the order in which they were allocated.
1670
1671 The visitor type NNSFndHeapVisitor is defined as below.
1672
1673 typedef void (*NNSFndHeapVisitor)(
1674 void* memBlock,
1675 Heap heap,
1676 u32 userParam);
1677
1678 memBlock: pointer to the memory block
1679 heap: heap that includes the memory block
1680 userParam: user parameter
1681
1682 Arguments: heap: Handle for the expanded heap.
1683 visitor: Function called for each memory block
1684 userParam: User-specified parameter passed to the visitor function
1685
1686 Returns: None.
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
1713 Description: Gets the size of the memory block that was allocated from the expanded heap.
1714
1715 Arguments: memBlock: pointer to the memory block for getting the size
1716
1717 Returns: Returns the size of the specified memory block (in bytes).
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
1730 Description: Gets the group ID for the memory block allocated from the expanded heap.
1731
1732 Arguments: memBlock: pointer to the memory block for getting the group ID
1733
1734 Returns: Returns the group ID for the specified memory block.
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
1747 Description: Gets the allocation direction for the memory block allocated from the expanded heap.
1748
1749 Arguments: memBlock: pointer to the memory block
1750
1751 Returns: Returns the allocation direction for the specified memory block.
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
1764 Description: Deallocates the expanded heap's available region, and reduces the memory region that is available for use by the expanded heap.
1765 There must not be memory blocks allocated from the back of heap memory.
1766
1767 Arguments: heap: Handle for the expanded heap.
1768 mode: Specifies whether the end (NN_FND_EXPHEAPD_ADJUST_TAIL) or start (NN_FND_EXPHEAPD_ADJUST_HEAD) is shortened.
1769
1770
1771 Returns: Returns a range of empty memory blocks resulting from adjusting the heap.
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 any memory blocks allocated from the start are present
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
1846 Description: Checks whether the expanded heap has been destroyed.
1847
1848 Arguments: heap: Handle for the expanded heap.
1849 optFlag: Flag.
1850
1851 Returns: Returns TRUE if the heap is normal.
1852 Returns FALSE if the heap has an error.
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
1936 Description: This function checks if the memory block of the expanded heap was destroyed.
1937
1938 Arguments: memBlock: Pointer to the memory block to be checked.
1939 heap: Handle for the expanded heap.
1940 optFlag: Flag.
1941
1942 Returns: Returns TRUE if the memory block is normal.
1943 Returns FALSE if the memory block has an error.
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