1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ut_HeapBase.cpp
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: $
16  *---------------------------------------------------------------------------*/
17 
18 #include "precompiled.h"
19 
20 #include <nw/ut/ut_HeapBase.h>
21 #include <nw/ut/ut_Inlines.h>  // for GetOffsetFromPtr(), etc...
22 #include <cstring>
23 
24 /*!--------------------------------------------------------------------------*
25   Name:        GetBitValue
26 
27   @brief       特定のビット位置の値を取得します。
28 
29   @param[in]   data  取得するビットデータを含むデータ。
30   @param[in]   st    開始ビット(0から始まる)。
31   @param[in]   bits  ビット数(31以下とする)。
32 
33   @return      特定のビット位置の値を返します。
34  *---------------------------------------------------------------------------*/
35 #define     GetBitValue(data, st, bits) \
36     (((data) >>(st)) & ((1 <<(bits)) -1))
37 
38 /*!--------------------------------------------------------------------------*
39   Name:        SetBitValue
40 
41   @brief       特定のビット位置に値をセットします。
42 
43   @param[in]  data  セットするビットデータを格納する変数。
44   @param[in]  st    開始ビット(0から始まる)。
45   @param[in]  bits  ビット数(31以下とする)。
46   @param[in]  val   セットするビットデータ。
47 
48   @return      なし。
49  *---------------------------------------------------------------------------*/
50 #define     SetBitValue(data, st, bits, val)                        \
51                 do                                                          \
52                 {                                                           \
53                     u32 maskBits = (u32)((1 <<(bits)) -1);                   \
54                     u32 newVal = (val) & maskBits; /* 安全のためマスク */    \
55                     (void)(maskBits <<= st);                                 \
56                     (data) &= ~maskBits; /* セットする領域をクリア */        \
57                     (data) |= newVal <<(st);                                 \
58                 } while(false);
59 
60 
61 namespace nw {
62 namespace ut {
63 
64 namespace {
65 
66 // ルートのヒープリスト
67 HeapBase::HeapList sRootList;
68 
69 // fill 値
70 u32 sFillVals[ HeapBase::HEAP_FILL_MAX ] =
71 {
72     0xC3C3C3C3, // ヒープ作成時に埋める値
73     0xF3F3F3F3, // メモリブロック確保時に埋める値
74     0xD3D3D3D3, // メモリブロック解放時に埋める値
75 };
76 
77 // ヒープを含有する親ヒープを検索し、その親ヒープのリストへのポインタを返します
78 
79 #if 1
DumpHeapList()80 NW_INLINE void DumpHeapList() {}
81 
82 #else
83 
DumpHeapList()84 void DumpHeapList()
85 {
86     HeapBase* pHeapBase = NULL;
87     int count = 0;
88 
89     OS_Printf("Dump HeapBase List\n");
90     while ( NULL != ( pHeapBase = pHeap->GetNext() ) )
91     {
92         count += 1;
93         OS_Printf("[%d] -> %p %08X\n", count, pHeap, pHeap->signature );
94     }
95 }
96 
97 #endif  // DumpHeapList
98 
99 } // unnamed namespace
100 
101 /*!--------------------------------------------------------------------------*
102   Name:        FindListContainHeap
103 
104   @brief       ヒープを含有する親ヒープを検索し、その親ヒープのリストへの
105                ポインタを返します。
106 
107   @param[out]  pHeapBase   検索対象のヒープへのポインタ。
108 
109   @return      指定したヒープを含有する親ヒープが見つかれば、
110                親ヒープの子リストへのポインタを返します。
111                親ヒープが見つからなければルートリストへのポインタが返ります。
112  *---------------------------------------------------------------------------*/
FindListContainHeap(HeapBase * pHeapBase)113 HeapBase::HeapList* HeapBase::FindListContainHeap( HeapBase* pHeapBase )
114 {
115     HeapBase::HeapList* pList = &sRootList;
116     HeapBase* pContainHeapBase = HeapBase::FindContainHeap( &sRootList, pHeapBase );
117 
118     if ( pContainHeapBase )
119     {
120         pList = &pContainHeapBase->mChildList;
121     }
122 
123     return pList;
124 }
125 
126 /*!--------------------------------------------------------------------------*
127   Name:        FindContainHeap
128 
129   @brief       指定されたメモリブロックを含有するヒープをリストから再帰的に
130                探し出します。
131 
132   @param[in]   pList      リストへのポインタ
133   @param[in]   memBlock   メモリブロックへのポインタ
134 
135   @return      指定されたメモリブロックを確保したヒープが見つかれば、
136                そのヒープへのポインタを返します。
137                見つからなかった時は NULL を返します。
138  *---------------------------------------------------------------------------*/
FindContainHeap(HeapBase::HeapList * pList,const void * memBlock)139 HeapBase* HeapBase::FindContainHeap( HeapBase::HeapList* pList, const void* memBlock )
140 {
141     u32 memBlockAddress = reinterpret_cast<u32>(memBlock);
142 
143     for ( HeapList::iterator itr = pList->begin(); itr != pList->end();
144         )
145     {
146         HeapList::iterator curItr = itr++;
147         if ( reinterpret_cast<u32>(curItr->mHeapStart) <= memBlockAddress
148           && reinterpret_cast<u32>(curItr->mHeapEnd) > memBlockAddress )
149         {
150             HeapBase* pChildHeapBase = FindContainHeap( &curItr->mChildList, memBlock );
151             if ( pChildHeapBase )
152             {
153                 return pChildHeapBase;
154             }
155             return &(*curItr);
156         }
157     }
158     return NULL;
159 }
160 
161 /*!--------------------------------------------------------------------------*
162   Name:        FindContainHeap
163 
164   @brief       メモリブロックを含有するヒープを検索します。
165 
166   @param[in]   memBlock   検索対象のメモリブロック。
167 
168   @return      指定したメモリブロックを含むヒープが見つかれば、
169                そのヒープのハンドルを返します。
170                見つからなければ、NULL が返ります。
171  *---------------------------------------------------------------------------*/
FindContainHeap(const void * memBlock)172 HeapBase* HeapBase::FindContainHeap( const void* memBlock )
173 {
174     return FindContainHeap( &sRootList, memBlock );
175 }
176 
177 /*!--------------------------------------------------------------------------*
178   Name:        FindParentHeap
179 
180   @brief       親ヒープを検索します。
181 
182   @param[in]   heap   検索対象のヒープ
183 
184   @return      指定したメモリブロックを含むヒープが見つかれば、
185                そのヒープのハンドルを返します。
186                見つからなければ、NULL が返ります。
187  *---------------------------------------------------------------------------*/
FindParentHeap(const HeapBase * heap)188 HeapBase* HeapBase::FindParentHeap( const HeapBase* heap )
189 {
190     u32 heapAddress = reinterpret_cast<u32>(heap);
191 
192     for ( HeapList::iterator itr = sRootList.begin(); itr != sRootList.end(); )
193     {
194         HeapList::iterator curItr = itr++;
195         // ターゲットのアドレスが含まれているならば、子を検索する
196         if ( reinterpret_cast<u32>(curItr->mHeapStart) <= heapAddress
197           && reinterpret_cast<u32>(curItr->mHeapEnd) > heapAddress )
198         {
199             return FindContainHeap( &curItr->mChildList, &(*curItr) );
200         }
201     }
202 
203     return NULL;
204 }
205 
206 #if 0
207 // ヒープアドレスを表示します
208 void HeapBase::Dump()
209 {
210     char str[64] = "[nw::ut ";
211 
212     switch ( mSignature )
213     {
214         case EXPHEAP_SIGNATURE: std::snprintf( str, 64, "%s Exp", str );    break;
215         case FRMHEAP_SIGNATURE: std::snprintf( str, 64, "%s Frame", str );  break;
216         case UNTHEAP_SIGNATURE: std::snprintf( str, 64, "%s Unit", str );   break;
217         default:
218             NW_ASSERT( false );
219     }
220 
221     OS_Printf("%s Heap]\twhole [%p - %p)\n", str, this, mHeapEnd );
222 }
223 #endif
224 
225 /*!--------------------------------------------------------------------------*
226   Name:        SetFillValForHeap
227 
228   @brief       ヒープの作成時やメモリブロックの確保・解放時にメモリに
229                セットする値をセットします。
230                この関数はデバッグ用の関数です。
231                最終ROM版ライブラリでは常に0を返します。
232 
233   @param[in]   type   取得する値の種類
234   @param[in]   val    セットする値
235 
236   @return      以前の、メモリブロックの確保時にメモリにセットする値を返します。
237  *---------------------------------------------------------------------------*/
SetFillValue(FillType type,u32 val)238 u32 HeapBase::SetFillValue( FillType type, u32 val )
239 {
240     NW_ASSERT( type < HEAP_FILL_MAX );
241 
242     u32 oldVal = sFillVals[ type ];
243     sFillVals[ type ] = val;
244     return oldVal;
245 }
246 
247 /*!--------------------------------------------------------------------------*
248   Name:        GetFillValForHeap
249 
250   @brief       ヒープの作成時やメモリブロックの確保・解放時にメモリに
251                セットする値を取得します。
252                この関数はデバッグ用の関数です。
253                最終ROM版ライブラリでは常に0を返します。
254 
255   @param[in]   type   取得する値の種類
256 
257   @return      指定された種類のメモリにセットする値を返します。
258  *---------------------------------------------------------------------------*/
GetFillValue(FillType type)259 u32 HeapBase::GetFillValue( FillType type )
260 {
261     NW_ASSERT( type < HEAP_FILL_MAX );
262     return sFillVals[ type ];
263 }
264 
265 
266 /*!--------------------------------------------------------------------------*
267   Name:        GetHeapType
268 
269   @brief       ヒープハンドルがどの種類のヒープであるかを取得します。
270 
271   @return      ヒープハンドルからヒープの種別を取得します。
272  *---------------------------------------------------------------------------*/
GetHeapType()273 HeapBase::HeapType HeapBase::GetHeapType()
274 {
275     switch ( mSignature )
276     {
277         case EXPHEAP_SIGNATURE: return HEAP_TYPE_EXP;
278         case FRMHEAP_SIGNATURE: return HEAP_TYPE_FRM;
279         case UNTHEAP_SIGNATURE: return HEAP_TYPE_UNIT;
280         default:                return HEAP_TYPE_UNKNOWN;
281     }
282 }
283 
284 /*!--------------------------------------------------------------------------*
285   Name:        Initialize
286 
287   @brief       ヒープの初期化を行います。
288 
289   @param[in]   signature   シグネチャ。
290   @param[in]   heapStart   ヒープメモリの開始アドレス。
291   @param[in]   heapEnd     ヒープメモリの終了アドレス +1。
292   @param[in]   optFlag     ヒープオプション。
293 
294   @return      なし。
295  *---------------------------------------------------------------------------*/
Initialize(u32 signature,void * heapStart,void * heapEnd,u16 optFlag)296 void HeapBase::Initialize( u32 signature, void* heapStart, void* heapEnd, u16 optFlag )
297 {
298     mSignature = signature;
299 
300     mHeapStart = heapStart;
301     mHeapEnd = heapEnd;
302 
303     mAttribute = 0;
304     SetOptionFlag( optFlag );
305 
306     FillNoUseMemory( heapStart, (u32)GetOffsetFromPtr( heapStart, heapEnd ) );
307 
308     HeapList* pList = FindListContainHeap( this );
309     pList->push_back( this );
310     DumpHeapList();
311 }
312 
313 /*!--------------------------------------------------------------------------*
314   Name:        Finalize
315 
316   @brief       ヒープ共通の後始末を行います。
317 
318   @return      なし。
319  *---------------------------------------------------------------------------*/
Finalize()320 void HeapBase::Finalize()
321 {
322     HeapList* pList = FindListContainHeap( this );
323     pList->erase( this );
324     mSignature = 0;
325     DumpHeapList();
326 }
327 
328 /*!--------------------------------------------------------------------------*
329   Name:        LockHeap
330 
331   @brief       ヒープの排他制御をおこなうためのロック関数
332 
333   @return      なし
334  *---------------------------------------------------------------------------*/
LockHeap()335 void HeapBase::LockHeap()
336 {
337 #ifdef NW_UT_HEAP_MULTITHREADED
338     if ( GetOptionFlag() & OPT_THREAD_SAFE )
339     {
340         OS_LockMutex( &mMutex );
341     }
342 #endif
343 }
344 
345 /*!--------------------------------------------------------------------------*
346   Name:        UnlockHeap
347 
348   @brief       ヒープの排他制御をおこなうためのアンロック関数
349 
350   @return      なし
351  *---------------------------------------------------------------------------*/
UnlockHeap()352 void HeapBase::UnlockHeap()
353 {
354 #ifdef NW_UT_HEAP_MULTITHREADED
355     if ( GetOptionFlag() & OPT_THREAD_SAFE )
356     {
357         OS_UnlockMutex( &mMutex );
358     }
359 #endif
360 }
361 
362 
363 /*!--------------------------------------------------------------------------*
364   Name:        FillFreeMemory
365 
366   @brief       フリー直後のメモリフィル
367 
368   @param[in]   address     アドレス
369   @param[in]   size        サイズ
370 
371   @return      なし
372  *---------------------------------------------------------------------------*/
FillFreeMemory(void * address,u32 size)373 void HeapBase::FillFreeMemory( void* address, u32 size )
374 {
375     if ( GetOptionFlag() & OPT_DEBUG_FILL )
376     {
377 #ifdef NW_PLATFORM_TWL
378         MI_CpuFill32( address, GetFillValue( HEAP_FILL_FREE ), size );
379 #else
380         std::memset(address, GetFillValue( HEAP_FILL_FREE ), size);
381 #endif
382     }
383 }
384 
385 /*!--------------------------------------------------------------------------*
386   Name:        FillNoUseMemory
387 
388   @brief       未使用メモリのメモリフィル
389 
390   @param[in]   address     アドレス
391   @param[in]   size        サイズ
392 
393   @return      なし
394  *---------------------------------------------------------------------------*/
FillNoUseMemory(void * address,u32 size)395 void HeapBase::FillNoUseMemory( void* address, u32 size )
396 {
397     if ( GetOptionFlag() & OPT_DEBUG_FILL )
398     {
399 #ifdef NW_PLATFORM_TWL
400         MI_CpuFill32( address, GetFillValue( HEAP_FILL_NOUSE ), size );
401 #else
402         std::memset(address, GetFillValue( HEAP_FILL_NOUSE ), size);
403 #endif
404     }
405 }
406 
407 /*!--------------------------------------------------------------------------*
408   Name:        FillAllocMemory
409 
410   @brief       アロケート直後のメモリフィル
411 
412   @param[in]   address     アドレス
413   @param[in]   size        サイズ
414 
415   @return      なし
416  *---------------------------------------------------------------------------*/
FillAllocMemory(void * address,u32 size)417 void HeapBase::FillAllocMemory( void* address, u32 size )
418 {
419     if ( GetOptionFlag() & OPT_0_CLEAR )
420     {
421 #ifdef NW_PLATFORM_TWL
422         MI_CpuFill32( address, 0, size );
423 #else
424         std::memset(address, 0, size);
425 #endif
426     }
427     else
428     {
429         if ( GetOptionFlag() & OPT_DEBUG_FILL )
430         {
431 #ifdef NW_PLATFORM_TWL
432             MI_CpuFill32( address, GetFillValue( HEAP_FILL_ALLOC ), size );
433 #else
434             std::memset(address, GetFillValue( HEAP_FILL_ALLOC ), size);
435 #endif
436         }
437     }
438 }
439 
440 /*!--------------------------------------------------------------------------*
441   Name:        GetOptForHeap
442 
443   @brief       ヒープからオプションフラグを取得
444 
445   @return      オプションフラグの値
446  *---------------------------------------------------------------------------*/
GetOptionFlag()447 u16 HeapBase::GetOptionFlag()
448 {
449     return (u16)GetBitValue( mAttribute, 0, 8 );
450 }
451 
452 /*!--------------------------------------------------------------------------*
453   Name:        SetOptForHeap
454 
455   @brief       ヒープへオプションフラグを設定
456 
457   @param[in]   optFlag  ヒープへのオプションです。
458 
459   @return      なし。
460  *---------------------------------------------------------------------------*/
SetOptionFlag(u16 optFlag)461 void HeapBase::SetOptionFlag( u16 optFlag )
462 {
463     SetBitValue( mAttribute, 0, 8, optFlag );
464 }
465 
466 } // nw::ut
467 } // nw
468