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