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: 29199 $
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           128
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(&region);
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(&region, 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(&region, pMBHead);
1449         (void)RemoveMBlock(&pExpHeapHd->mbUsedList, pMBHead);   // 使用リストからはずす
1450         (void)RecycleRegion(pExpHeapHd, &region);   // 指定アドレスから指定サイズをフリーに加える
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