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