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