1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: fnd_DetailHeap.cpp
4
5 Copyright (C)2009 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: 26147 $
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 マクロ定数
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 // フリーメモリブロックのシグネチャ
33 #define MBLOCK_FREE_SIGNATURE ('FR')
34
35 // 使用メモリブロックのシグネチャ
36 #define MBLOCK_USED_SIGNATURE ('UD')
37 #else
38 // フリーメモリブロックのシグネチャ
39 #define MBLOCK_FREE_SIGNATURE 0x00004652 // "FR"
40
41 // 使用メモリブロックのシグネチャ
42 #define MBLOCK_USED_SIGNATURE 0x00005544 // "UD"
43
44 #endif
45
46 // グループIDの最大値
47 #define MAX_GROUPID 0xff
48
49 // グループIDのデフォルト値
50 #define DEFAULT_GROUPID 0
51
52 // アライメントの最小値
53 #define MIN_ALIGNMENT 4
54
55 // アライメントの最大値
56 #define MAX_ALIGNMENT 4096
57
58 // デフォルトのメモリ確保モード
59 #define DEFAULT_ALLOC_MODE NN_OS_EXPHEAP_ALLOC_MODE_FIRST
60
61 // フリーブロックとして登録する最小サイズ (ヘッダは含まないサイズ)
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 構造体定義
70 ======================================================================== */
71 typedef struct NNSiMemRegion NNSiMemRegion;
72
73 struct NNSiMemRegion
74 {
75 void* start;
76 void* end;
77 };
78
79
80 /* ========================================================================
81 マクロ関数
82 ======================================================================== */
83
84 #define HEAP_WARNING NN_TASSERTMSG_
85
86
87 /* ========================================================================
88 static関数
89 ======================================================================== */
90
91 /* ------------------------------------------------------------------------
92 ポインタ操作
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 void* と size でMemoryRangeを作る
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: ヒープヘッダへのポインタから、拡張ヒープヘッダへのポインタを取得します。
132
133 Arguments: pHHead: ヒープヘッダへのポインタ。
134
135 Returns: 拡張ヒープヘッダへのポインタを返します。
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: 拡張ヒープヘッダへのポインタから、ヒープヘッダへのポインタを取得します。
153
154 Arguments: pEHHead: 拡張ヒープヘッダへのポインタ。
155
156 Returns: ヒープヘッダへのポインタを返します。
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: 拡張ヒープハンドルから、拡張ヒープヘッダへのポインタを取得します。
168
169 Arguments: heap: 拡張ヒープハンドル。
170
171 Returns: 拡張ヒープヘッダへのポインタを返します。
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: NNSiFndExpHeapMBlockHead構造体へのポインタから、
189 メモリブロックへのポインタを取得します。
190
191 Arguments: pMBlkHd: NNSiFndExpHeapMBlockHead構造体へのポインタ。
192
193 Returns: メモリブロックへのポインタを返します。
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: メモリブロックへのポインタから、
213 NNSiFndExpHeapMBlockHead構造体へのポインタを取得します。
214 メモリブロックへのポインタを取得します。
215
216 Arguments: memBlock: メモリブロックへのポインタ。
217
218 Returns: NNSiFndExpHeapMBlockHead構造体へのポインタを返します。
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 構造体アクセス関数
240 ------------------------------------------------------------------------ */
241
242 /*---------------------------------------------------------------------------*
243 Name: GetAlignmentForMBlock
244
245 Description: NNSiFndExpHeapMBlockHead構造体のアライメント値を取得します。
246
247 Arguments: pMBlkHd: NNSiFndExpHeapMBlockHead構造体へのポインタ。
248
249 Returns: NNSiFndExpHeapMBlockHead構造体のアライメント値を返します。
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: NNSiFndExpHeapMBlockHead構造体のアライメント値をセットします。
261
262 Arguments: pMBlkHd: NNSiFndExpHeapMBlockHead構造体へのポインタ。
263 alignment: セットするアライメント値
264
265 Returns: なし。
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 構造体アクセス関数
309 ------------------------------------------------------------------------ */
310
311 /*---------------------------------------------------------------------------*
312 Name: GetAllocMode
313
314 Description: 拡張ヒープのメモリ確保モードを取得します。
315
316 Arguments: pEHHead: 拡張ヒープヘッダへのポインタ。
317
318 Returns: 拡張ヒープのメモリ確保モードを返します。
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: 拡張ヒープのメモリ確保モードをセットします。
330
331 Arguments: pEHHead: 拡張ヒープヘッダへのポインタ。
332 mode: メモリ確保モード。
333
334 Returns: なし。
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 メモリブロックリスト操作
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 // 前参照リンク
370 if (prev)
371 {
372 prev->pMBHeadNext = next;
373 }
374 else
375 {
376 list->head = next;
377 }
378
379 // 次参照リンク
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 // 前参照リンク
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 // 次参照リンク
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: メモリブロックをリストの最後に追加します。
432
433 Arguments: link: 追加するリスト
434 block: 追加するメモリブロック
435
436 Returns: なし。
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: メモリブロックの初期化を行います。
451
452 Arguments: pRegion: メモリブロックとするリージョンを表す構造体へのポインタ。
453 signature: メモリブロックのシグネチャ。
454
455 Returns: 初期化したメモリブロックへのポインタを返します。
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: メモリブロックをフリーブロック用に初期化を行います。
478
479 Arguments: pRegion: メモリブロックとするリージョンを表す構造体へのポインタ。
480
481 Returns: 初期化したメモリブロックへのポインタを返します。
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: 拡張ヒープの初期化を行います。
495
496 Arguments: pHeapHead: ヒープヘッダのポインタ
497 startAddress: 拡張ヒープとするメモリの開始アドレス。
498 endAddress: 拡張ヒープとするメモリの終了アドレス +1。
499 optFlag: オプションフラグ。
500
501 Returns: ヒープヘッダへのポインタを返します。
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( // ヒープ共通初期化
515 pHeapHd,
516 NNSI_EXPHEAP_SIGNATURE,
517 startAddress, // heapStart
518 endAddress, // heapEnd
519 optFlag);
520
521 pExpHeapHd->groupID = DEFAULT_GROUPID; // グループID
522 pExpHeapHd->feature = 0;
523 SetAllocMode(pExpHeapHd, DEFAULT_ALLOC_MODE);
524
525 // フリーのブロックを作る
526 {
527 NNSiFndExpHeapMBlockHead* pMBHead;
528 NNSiMemRegion region;
529 region.start = pHeapHd->heapStart;
530 region.end = pHeapHd->heapEnd;
531 pMBHead = InitFreeMBlock(®ion);
532
533 // ブロックリスト
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: フリーブロックの中から新しいメモリブロックを確保します。
547
548 Arguments: pEHHead: 拡張ヒープヘッダへのポインタ。
549 pMBHeadFree: フリーブロックヘッダへのポインタ。
550 mblock: 確保するメモリブロックのアドレス。
551 size: 確保するメモリブロックのサイズ。
552 direction: 確保方向。
553
554 Returns: 確保したメモリブロックの先頭のポインタを返します。
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); // 一旦フリーブロックを削除
575
576 // フリーブロック作る余裕が無い場合
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; // 使用ブロックのアライメント値に含める
581 }
582 else
583 {
584 pMBHeadFreePrev = InsertMBlock(&pEHHead->mbFreeList, InitFreeMBlock(&freeRgnT), pMBHeadFreePrev);
585 }
586
587 // フリーブロック作る余裕が無い場合
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; // 使用ブロックに含める
592 }
593 else
594 {
595 (void)InsertMBlock(&pEHHead->mbFreeList, InitFreeMBlock(&freeRgnB), pMBHeadFreePrev);
596 }
597
598 // デバグ用メモリ充填
599 FillAllocMemory(GetHeapHeadPtrFromHeapHead(pEHHead), freeRgnT.end, GetOffsetFromPtr(freeRgnT.end, freeRgnB.start));
600
601 // 新規ブロック作成
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: ヒープの先頭からメモリブロックを確保します。
623
624 Arguments: pHeapHd: ヒープヘッダへのポインタ。
625 size: 確保するメモリブロックのサイズ。
626 alignment: アライメント値。
627
628 Returns: メモリブロックの確保が成功した場合、確保したメモリブロックへの
629 ポインタが返ります。
630 失敗した場合、NULLが返ります。
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 // 最初にみつかったものを割り当てるか
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 // フリーブロック検索
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); // 発生したずれ
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) // 条件に合うブロックが見つからない
671 {
672 return NULL;
673 }
674
675 return AllocUsedBlockFromFreeBlock( // 発見したフリーブロックから領域確保
676 pExpHeapHd,
677 pMBlkHdFound,
678 foundMBlock,
679 size,
680 NN_OS_EXPHEAP_ALLOC_DIR_FRONT);
681 }
682
683 /*---------------------------------------------------------------------------*
684 Name: AllocFromTail
685
686 Description: ヒープの末尾からメモリブロックを確保します。
687
688 Arguments: pHeapHd: ヒープヘッダへのポインタ。
689 size: 確保するメモリブロックのサイズ。
690 alignment: アライメント値。
691
692 Returns: メモリブロックの確保が成功した場合、確保したメモリブロックへの
693 ポインタが返ります。
694 失敗した場合、NULLが返ります。
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 // 最初にみつかったものを割り当てるか
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 // フリーブロック検索
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); // アライン済みのアドレス
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) // 条件に合うブロックが見つからない
735 {
736 return NULL;
737 }
738
739 return AllocUsedBlockFromFreeBlock( // 発見したフリーブロックから領域確保
740 pExpHeapHd,
741 pMBlkHdFound,
742 foundMBlock,
743 size,
744 NN_OS_EXPHEAP_ALLOC_DIR_REAR);
745 }
746
747 /*---------------------------------------------------------------------------*
748 Name: RecycleRegion
749
750 Description: 空きリージョンをフリーメモリブロックへ組み入れます。
751 フリーブロックと隣接している場合は、フリーブロックを拡張します。
752 フリーブロックと隣接しておらず、かつフリーブロックとするほどの
753 サイズが無い場合は、後方に隣接する使用済みブロックのアライメント値とします。
754 後方に隣接する使用済みブロックが無い場合は、関数は失敗します。
755
756 Arguments: pEHHead: 拡張ヒープヘッダへのポインタ。
757 pRegion: 空きリージョンへのポインタ。
758
759 Returns: 関数が成功すれば true を返します。
760 失敗すれば false を返します。
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; // 直前フリーブロック
769 NNSiMemRegion freeRgn = *pRegion;
770
771 // 指定エリアに隣接したフリーエリアを検索
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) // 後方に隣接するブロックか?
784 {
785 // 空きリージョンを結合
786 freeRgn.end = GetMBlockEndAddr(pBlk);
787 (void)RemoveMBlock(&pEHHead->mbFreeList, pBlk);
788
789 // ヘッダ部をNoUseで埋める
790 FillNoUseMemory(GetHeapHeadPtrFromHeapHead(pEHHead), pBlk, sizeof(NNSiFndExpHeapMBlockHead));
791 }
792 break;
793 }
794 }
795
796 // 直前のフリーブロックが前方に隣接するブロックか?
797 if (pBlkPrFree && GetMBlockEndAddr(pBlkPrFree) == pRegion->start)
798 {
799 // 空きリージョンを結合
800 freeRgn.start = pBlkPrFree;
801 pBlkPrFree = RemoveMBlock(&pEHHead->mbFreeList, pBlkPrFree);
802 }
803
804 if (GetOffsetFromPtr(freeRgn.start, freeRgn.end) < sizeof(NNSiFndExpHeapMBlockHead)) // ブロックになれない大きさ
805 {
806 return false; // ResizeForMBlockHeap()で小さいサイズを縮小しようとしていて、
807 // かつ後ろにフリーブロックが無い場合にここに到達
808 }
809
810 // デバグ用メモリ充填
811 FillFreeMemory(GetHeapHeadPtrFromHeapHead(pEHHead), pRegion->start, GetOffsetFromPtr(pRegion->start, pRegion->end));
812
813 (void)InsertMBlock(&pEHHead->mbFreeList,
814 InitFreeMBlock(&freeRgn), // フリーブロック作成
815 pBlkPrFree);
816
817 return true;
818 }
819
820 /*---------------------------------------------------------------------------*
821 Name: CheckMBlock
822
823 Description: メモリブロックのヘッダの内容が妥当であるかチェックします。
824
825 Arguments: pMBHead: チェックするメモリブロックのヘッダへのポインタ。
826 pHeapHd: 拡張ヒープのヘッダへのポインタ。
827 signature: メモリブロックのシグネチャ。
828 heapType: メモリブロックのタイプ(使用 or フリー)
829 flag: フラグ。
830
831 Returns: メモリブロックのヘッダの内容が妥当なら true、
832 そうでないなら false を返します。
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) // シグネチャが異なる?
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: 使用メモリブロックのヘッダの内容が妥当であるかチェックします。
888
889 Arguments: pMBHead: チェックするメモリブロックのヘッダへのポインタ。
890 pHeapHd: 拡張ヒープのヘッダへのポインタ。
891 flag: フラグ。
892
893 Returns: メモリブロックのヘッダの内容が妥当なら true、
894 そうでないなら false を返します。
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: フリーメモリブロックのヘッダの内容が妥当であるかチェックします。
915
916 Arguments: pMBHead: チェックするメモリブロックのヘッダへのポインタ。
917 pHeapHd: 拡張ヒープのヘッダへのポインタ。
918 flag: フラグ。
919
920 Returns: メモリブロックのヘッダの内容が妥当なら true、
921 そうでないなら false を返します。
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: メモリブロックの前へのリンクが正しいかチェックします。
942
943 Arguments: pMBHead: チェックするメモリブロックのヘッダへのポインタ。
944 pMBHeadPrev: チェックするメモリブロックの前のメモリブロックのヘッダへのポインタ。
945 flag: フラグ。
946
947 Returns: メモリブロックの前へのリンクが正しいなら true、
948 そうでないなら false を返します。
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: メモリブロックの次へのリンクが正しいかチェックします。
978
979 Arguments: pMBHead: チェックするメモリブロックのヘッダへのポインタ。
980 pMBHeadNext: チェックするメモリブロックの次のメモリブロックのヘッダへのポインタ。
981 flag: フラグ。
982
983 Returns: メモリブロックの次へのリンクが正しいなら true、
984 そうでないなら false を返します。
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: メモリブロックのポインタがメモリブロックリストの先頭/末尾であるかチェックします。
1014
1015 Arguments: pMBHead: チェックするメモリブロックのヘッダへのポインタ。
1016 pMBHeadTail: メモリブロックリストの先頭/末尾メモリブロックのヘッダへのポインタ。
1017 headType: 先頭か末尾を表す文字列。
1018 flag: フラグ。
1019
1020 Returns: メモリブロックのポインタがメモリブロックリストの先頭/末尾であるなら true、
1021 そうでないなら false を返します。
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: 使用メモリブロックの妥当性をチェックします。
1053
1054 Arguments: memBlock: チェックするメモリブロック。
1055 heap: メモリブロックを含有する拡張ヒープのハンドル。
1056 NULLを指定すると、メモリブロックがヒープに含まれているかの
1057 チェックは行いません。
1058
1059 Returns: 指定したメモリブロックが問題なければ true を返します。
1060 問題があれば false を返します。
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 外部関数(非公開)
1085 ======================================================================== */
1086
1087 /*---------------------------------------------------------------------------*
1088 Name: NNSi_FndDumpHeap
1089
1090 Description: 拡張ヒープ内部の情報を表示します。
1091 これはデバッグ用の関数です。
1092
1093 Arguments: heap: 拡張ヒープのハンドル。
1094
1095 Returns: なし。
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"); // ヘッダー行
1117
1118 // ---------------- UsedBlock のダンプ ----------------
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 // ---- 使用量
1148 usedSize += sizeof(NNSiFndExpHeapMBlockHead) + pMBHead->blockSize + GetAlignmentForMBlock(pMBHead);
1149
1150 usedCnt ++;
1151 }
1152 }
1153
1154 // ---------------- FreeBlock のダンプ ----------------
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); // ヒープサイズ(データ領域のサイズ)
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 外部関数(公開)
1206 ======================================================================== */
1207
1208 /*---------------------------------------------------------------------------*
1209 Name: CreateHeapEx
1210
1211 Description: 拡張ヒープを作成します。
1212
1213 Arguments: startAddress: ヒープ領域の先頭アドレス。
1214 size: ヒープ領域のサイズ。
1215 optFlag: オプションフラグ。
1216
1217 Returns: 関数が成功した場合、作成された拡張ヒープのハンドルが返ります。
1218 関数が失敗すると、NN_OS_HEAP_INVALID_HANDLE が返ります。
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 { // Expヒープ向け初期化
1243 NNSiFndHeapHead* pHeapHd = InitHeap(heapHandle, startAddress, endAddress, optFlag);
1244 return pHeapHd; // ヒープヘッダへのポインタがそのままハンドル値とする
1245 }
1246 }
1247
1248 /*---------------------------------------------------------------------------*
1249 Name: DestroyHeap
1250
1251 Description: 拡張ヒープを破棄します。
1252
1253 Arguments: heap: 拡張ヒープのハンドル。
1254
1255 Returns: なし。
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: 拡張ヒープからメモリブロックを確保します。
1269 メモリブロックのアライメントを指定できます。
1270 アライメント値を負の値で指定すると、ヒープの空き領域を後方から探します。
1271
1272 Arguments: heap: 拡張ヒープのハンドル。
1273 size: 確保するメモリブロックのサイズ(バイト単位)。
1274 alignment: 確保するメモリブロックのアライメント。
1275 4,8,16,32,64,128,-4,-8,-16,-32,-64,-128のいずれかの値が指定できます。
1276
1277 Returns: メモリブロックの確保が成功した場合、確保したメモリブロックへの
1278 ポインタが返ります。
1279 失敗した場合、NULLが返ります。
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 // 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); // 実際に確保するサイズ
1301
1302 if (alignment >= 0) // 前から確保
1303 {
1304 memory = AllocFromHead(heap, size, alignment);
1305 }
1306 else // 後ろから確保
1307 {
1308 memory = AllocFromTail(heap, size, -alignment);
1309 }
1310
1311 return memory;
1312 }
1313
1314 /*---------------------------------------------------------------------------*
1315 Name: ResizeForMBlockHeap
1316
1317 Description: 拡張ヒープから確保されたメモリブロックのサイズを変更します。
1318
1319 Arguments: heap: 拡張ヒープのハンドル。
1320 memBlock: サイズを変更するメモリブロックへのポインタ。
1321 size: 新しく割り当てるサイズ(バイト単位)。
1322
1323 Returns: 関数が成功した場合、変更されたメモリブロックのサイズを返します(バイト単位)。
1324 関数が失敗した場合、0 が返ります。
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) // ブロックサイズ変更なしの場合
1344 {
1345 return size;
1346 }
1347
1348 // 新しいエリアが拡大するとき
1349 if (size > pMBHead->blockSize)
1350 {
1351 void* crUsedEnd = GetMBlockEndAddr(pMBHead); // 現使用ブロックのend address
1352 NNSiFndExpHeapMBlockHead* block;
1353
1354 // 次のフリーブロックを探す
1355 for (block = pEHHead->mbFreeList.head; block; block = block->pMBHeadNext)
1356 {
1357 if (block == crUsedEnd)
1358 {
1359 break;
1360 }
1361 }
1362
1363 // 次のフリーブロックがないか、サイズが足りない場合
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 // フリーブロックのリージョンを取得し、フリーブロックを一旦外す
1375 GetRegionOfMBlock(&rgnNewFree, block);
1376 nextBlockPrev = RemoveMBlock(&pEHHead->mbFreeList, block);
1377
1378 oldFreeStart = rgnNewFree.start;
1379 rgnNewFree.start = AddU32ToPtr(memBlock, size); // 新しくフリーとなるリージョン位置
1380
1381 // 余りがメモリブロックサイズ未満なら
1382 if (GetOffsetFromPtr(rgnNewFree.start, rgnNewFree.end) < sizeof(NNSiFndExpHeapMBlockHead))
1383 {
1384 rgnNewFree.start = rgnNewFree.end; // 使用ブロックに吸収
1385 }
1386
1387 pMBHead->blockSize = GetOffsetFromPtr(memBlock, rgnNewFree.start); // 対象ブロックサイズ変更
1388
1389 // 余りがメモリブロックサイズ以上なら
1390 if (GetOffsetFromPtr(rgnNewFree.start, rgnNewFree.end) >= sizeof(NNSiFndExpHeapMBlockHead))
1391 {
1392 (void)InsertMBlock(&pEHHead->mbFreeList, InitFreeMBlock(&rgnNewFree), nextBlockPrev); // 新しくフリーブロックを作る
1393 }
1394
1395 FillAllocMemory( // 拡張した部分フィル
1396 heap,
1397 oldFreeStart,
1398 GetOffsetFromPtr(oldFreeStart, rgnNewFree.start));
1399 }
1400 }
1401 // 新しいエリアが縮小するとき
1402 else
1403 {
1404 NNSiMemRegion rgnNewFree;
1405 const u32 oldBlockSize = pMBHead->blockSize;
1406
1407 rgnNewFree.start = AddU32ToPtr(memBlock, size); // 新しくフリーとなるリージョン位置
1408 rgnNewFree.end = GetMBlockEndAddr(pMBHead); // 現使用ブロックのend address
1409
1410 pMBHead->blockSize = size; // 対象ブロックサイズ変更
1411
1412 if (! RecycleRegion(pEHHead, &rgnNewFree)) // フリーリストに返してみる
1413 {
1414 pMBHead->blockSize = oldBlockSize; // 失敗したら、元に戻す
1415 }
1416 }
1417
1418 return pMBHead->blockSize;
1419 }
1420
1421 /*---------------------------------------------------------------------------*
1422 Name: FreeToHeap
1423
1424 Description: 拡張ヒープへメモリブロックを返却します。
1425
1426 Arguments: heap: 拡張ヒープのハンドル。
1427 memBlock: 返却するメモリブロックへのポインタ。
1428
1429 Returns: なし。
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 // このヒープの中に入っているか
1446 NN_TASSERT_(pHeapHd->heapStart <= memBlock && memBlock < pHeapHd->heapEnd);
1447
1448 GetRegionOfMBlock(®ion, pMBHead);
1449 (void)RemoveMBlock(&pExpHeapHd->mbUsedList, pMBHead); // 使用リストからはずす
1450 (void)RecycleRegion(pExpHeapHd, ®ion); // 指定アドレスから指定サイズをフリーに加える
1451 }
1452 }
1453
1454 /*---------------------------------------------------------------------------*
1455 Name: GetTotalFreeSizeForHeap
1456
1457 Description: 拡張ヒープの空き領域のサイズの合計を取得します。
1458
1459 Arguments: heap: 拡張ヒープのハンドル。
1460
1461 Returns: 拡張ヒープの空き領域のサイズの合計を返します(バイト単位)。
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: 拡張ヒープ内の割り当て可能な最大サイズを取得します。
1486 メモリブロックのアライメントを指定できます。
1487
1488 Arguments: heap: 拡張ヒープのハンドル。
1489 alignment: 確保するメモリブロックのアライメント。
1490 4,8,16,32,64,128のいずれかの値が指定できます。
1491
1492 Returns: 拡張ヒープ内の割り当て可能な最大サイズを返します(バイト単位)。
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 // 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); // 念のため正数化
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 // アライメントを考慮したメモリブロック位置
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 // アライメントによる空きエリア
1523 const u32 offset = GetOffsetFromPtr(GetMemPtrForMBlock(pMBlkHd), baseAddress);
1524
1525 /*
1526 サイズが大きい場合、あるいはサイズが同じでも無駄な空間がより小さい場合は、
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: 拡張ヒープのメモリ確保モードをセットします。
1547
1548 Arguments: heap: 拡張ヒープのハンドル。
1549 mode: メモリ確保モード。
1550
1551 Returns: 以前の拡張ヒープのメモリ確保モードを返します。
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: 拡張ヒープのメモリ確保モードを取得します。
1574
1575 Arguments: heap: 拡張ヒープのハンドル。
1576
1577 Returns: 拡張ヒープのメモリ確保モードを返します。
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: アライメントの際に発生する隙間の領域を再利用するかどうかを
1590 設定します。
1591 デフォルトではFALSEに設定されています。
1592
1593 TRUEに設定した場合には小さなメモリ領域が有効に使用できる可能性がありますが、
1594 大量のフリーブロックが生成されメモリ確保時のパフォーマンスが悪化する
1595 危険性があります。
1596
1597
1598 Arguments: heap 拡張ヒープのハンドル
1599 reuse TRUEの場合、アライメントで発生する領域を再利用します。
1600 FALSEの場合は再利用しません。
1601
1602 Returns: 以前の設定値が返ります。
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: 拡張ヒープのグループIDをセットします。
1624
1625 Arguments: heap: 拡張ヒープのハンドル。
1626 groupID: セットするグループID値。
1627
1628 Returns: 以前のグループID値が返ります。
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: 拡張ヒープのグループIDを取得します。
1651
1652 Arguments: heap: 拡張ヒープのハンドル。
1653
1654 Returns: グループID値が返ります。
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: 拡張ヒープから割り当てられたメモリブロック全てに対して、
1668 ユーザが指定した関数を呼ばせます。
1669 visitor関数で呼ばれるメモリブロックの順番は、確保した順番になります。
1670
1671 visitor の型 NNSFndHeapVisitor は次のように定義されています。
1672
1673 typedef void (*NNSFndHeapVisitor)(
1674 void* memBlock,
1675 Heap heap,
1676 u32 userParam);
1677
1678 memBlock: メモリブロックへのポインタ。
1679 heap: メモリブロックを含有するヒープ。
1680 userParam: ユーザー用パラメータ。
1681
1682 Arguments: heap: 拡張ヒープのハンドル。
1683 visitor: 各メモリブロックに対して呼ばせる関数。
1684 userParam: visitor関数に渡すユーザ指定のパラメータ
1685
1686 Returns: なし。
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: 拡張ヒープから確保されたメモリブロックのサイズを取得します。
1714
1715 Arguments: memBlock: サイズを取得するメモリブロックへのポインタ。
1716
1717 Returns: 指定したメモリブロックのサイズを返します(バイト単位)。
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: 拡張ヒープから確保されたメモリブロックのグループIDを取得します。
1731
1732 Arguments: memBlock: グループIDを取得するメモリブロックへのポインタ。
1733
1734 Returns: 指定したメモリブロックのグループIDが返ります。
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: 拡張ヒープから確保されたメモリブロックの確保方向を取得します。
1748
1749 Arguments: memBlock: メモリブロックへのポインタ。
1750
1751 Returns: 指定したメモリブロックの確保方向が返ります。
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: 拡張ヒープの空き領域を解放し、拡張ヒープが使用するメモリ領域を縮小します。
1765 ヒープメモリの後ろから確保されたメモリブロックが存在していてはいけません。
1766
1767 Arguments: heap: 拡張ヒープのハンドル。
1768 mode: 末尾(NN_FND_EXPHEAPD_ADJUST_TAIL)を縮めるか、
1769 先頭(NN_FND_EXPHEAPD_ADJUST_HEAD)を縮めるか指定します。
1770
1771 Returns: ヒープが縮小されることにより空いたメモリ領域の範囲を返します。
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 // 空き領域が無い場合は失敗
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 // 末尾から確保されたメモリブロックが存在する場合は失敗
1796 if ( pMBlkEnd != heap->heapEnd )
1797 {
1798 return MakeMemoryRange(heap->heapEnd, 0);
1799 }
1800
1801 // 解放されたフリーブロックをフリーリストから削除
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 // 空き領域が無い場合は失敗
1816 if ( pMBlkHd == NULL )
1817 {
1818 return MakeMemoryRange(heap->heapStart, 0);
1819 }
1820
1821 // 先頭から確保されたメモリブロックが存在する場合は失敗
1822 if ( pMBlkHd != heap->heapStart )
1823 {
1824 return MakeMemoryRange(heap->heapStart, 0);
1825 }
1826
1827 // 解放されたフリーブロックをフリーリストから削除
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: 拡張ヒープが破壊されていないかどうかをチェックします。
1847
1848 Arguments: heap: 拡張ヒープのハンドル。
1849 optFlag: フラグ。
1850
1851 Returns: ヒープが正常だった場合 true を返します。
1852 ヒープにエラーがあった場合、false を返します。
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 // 使用ブロック
1879 for (pMBHead = pExpHeapHd->mbUsedList.head; pMBHead; pMBHeadPrev = pMBHead, pMBHead = pMBHead->pMBHeadNext)
1880 {
1881 if ( ! CheckUsedMBlock(pMBHead, pHeapHd, optFlag)
1882 || ! CheckMBlockPrevPtr(pMBHead, pMBHeadPrev, optFlag) // 前ブロックへのポインタが1ループ前のメモリブロックのポインタと同じでない?
1883 )
1884 {
1885 return false;
1886 }
1887
1888 // 占有サイズを積算
1889 totalBytes += sizeof(NNSiFndExpHeapMBlockHead) + pMBHead->blockSize + GetAlignmentForMBlock(pMBHead);
1890 }
1891
1892 if (! CheckMBlockLinkTail(pMBHeadPrev, pExpHeapHd->mbUsedList.tail, "tail", optFlag)) // 末尾ブロックが最後のブロックへのポインタを指しているか?
1893 {
1894 return false;
1895 }
1896
1897 // フリーブロック
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) // 前ブロックへのポインタが1ループ前のメモリブロックのポインタと同じでない?
1904 )
1905 {
1906 return false;
1907 }
1908
1909 // 占有サイズを積算
1910 totalBytes += sizeof(NNSiFndExpHeapMBlockHead) + pMBHead->blockSize;
1911 }
1912
1913 if (! CheckMBlockLinkTail(pMBHeadPrev, pExpHeapHd->mbFreeList.tail, "tail", optFlag)) // 末尾ブロックが最後のブロックへのポインタを指しているか?
1914 {
1915 return false;
1916 }
1917
1918 // 全体の結果表示
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: 拡張ヒープのメモリブロックが破壊されていないかどうかをチェックします。
1937
1938 Arguments: memBlock: チェックするメモリブロックへのポインタ。
1939 heap: 拡張ヒープのハンドル。
1940 optFlag: フラグ。
1941
1942 Returns: メモリブロックが正常だった場合 true を返します。
1943 メモリブロックにエラーがあった場合、false を返します。
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) // 前ブロックのシグネチャとサイズのチェック
1972 || ! CheckMBlockNextPtr(pMBHead->pMBHeadPrev, pMBHead, optFlag) // 前ブロックの次ブロックへのポインタが自分を指しているか?
1973 )
1974 {
1975 return false;
1976 }
1977 }
1978 else
1979 {
1980 if (pHeapHd)
1981 {
1982 // prevが NULL のときは、リストのheadポインタは自分を指しているはず
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) // 次ブロックのシグネチャとサイズのチェック
1993 || ! CheckMBlockPrevPtr(pMBHead->pMBHeadNext, pMBHead, optFlag) // 次ブロックの前ブロックへのポインタが自分を指しているか?
1994 )
1995 {
1996 return false;
1997 }
1998 }
1999 else
2000 {
2001 if (pHeapHd)
2002 {
2003 // nextが NULL のときは、リストのtailポインタは自分を指しているはず
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