/*---------------------------------------------------------------------------* Project: NintendoWare File: ut_HeapBase.cpp Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision:$ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include #include // for GetOffsetFromPtr(), etc... #include /*!--------------------------------------------------------------------------* Name: GetBitValue @brief 特定のビット位置の値を取得します。 @param[in] data 取得するビットデータを含むデータ。 @param[in] st 開始ビット(0から始まる)。 @param[in] bits ビット数(31以下とする)。 @return 特定のビット位置の値を返します。 *---------------------------------------------------------------------------*/ #define GetBitValue(data, st, bits) \ (((data) >>(st)) & ((1 <<(bits)) -1)) /*!--------------------------------------------------------------------------* Name: SetBitValue @brief 特定のビット位置に値をセットします。 @param[in] data セットするビットデータを格納する変数。 @param[in] st 開始ビット(0から始まる)。 @param[in] bits ビット数(31以下とする)。 @param[in] val セットするビットデータ。 @return なし。 *---------------------------------------------------------------------------*/ #define SetBitValue(data, st, bits, val) \ do \ { \ u32 maskBits = (u32)((1 <<(bits)) -1); \ u32 newVal = (val) & maskBits; /* 安全のためマスク */ \ (void)(maskBits <<= st); \ (data) &= ~maskBits; /* セットする領域をクリア */ \ (data) |= newVal <<(st); \ } while(false); namespace nw { namespace ut { namespace { // ルートのヒープリスト HeapBase::HeapList sRootList; // fill 値 u32 sFillVals[ HeapBase::HEAP_FILL_MAX ] = { 0xC3C3C3C3, // ヒープ作成時に埋める値 0xF3F3F3F3, // メモリブロック確保時に埋める値 0xD3D3D3D3, // メモリブロック解放時に埋める値 }; // ヒープを含有する親ヒープを検索し、その親ヒープのリストへのポインタを返します #if 1 NW_INLINE void DumpHeapList() {} #else void DumpHeapList() { HeapBase* pHeapBase = NULL; int count = 0; OS_Printf("Dump HeapBase List\n"); while ( NULL != ( pHeapBase = pHeap->GetNext() ) ) { count += 1; OS_Printf("[%d] -> %p %08X\n", count, pHeap, pHeap->signature ); } } #endif // DumpHeapList } // unnamed namespace /*!--------------------------------------------------------------------------* Name: FindListContainHeap @brief ヒープを含有する親ヒープを検索し、その親ヒープのリストへの ポインタを返します。 @param[out] pHeapBase 検索対象のヒープへのポインタ。 @return 指定したヒープを含有する親ヒープが見つかれば、 親ヒープの子リストへのポインタを返します。 親ヒープが見つからなければルートリストへのポインタが返ります。 *---------------------------------------------------------------------------*/ HeapBase::HeapList* HeapBase::FindListContainHeap( HeapBase* pHeapBase ) { HeapBase::HeapList* pList = &sRootList; HeapBase* pContainHeapBase = HeapBase::FindContainHeap( &sRootList, pHeapBase ); if ( pContainHeapBase ) { pList = &pContainHeapBase->mChildList; } return pList; } /*!--------------------------------------------------------------------------* Name: FindContainHeap @brief 指定されたメモリブロックを含有するヒープをリストから再帰的に 探し出します。 @param[in] pList リストへのポインタ @param[in] memBlock メモリブロックへのポインタ @return 指定されたメモリブロックを確保したヒープが見つかれば、 そのヒープへのポインタを返します。 見つからなかった時は NULL を返します。 *---------------------------------------------------------------------------*/ HeapBase* HeapBase::FindContainHeap( HeapBase::HeapList* pList, const void* memBlock ) { u32 memBlockAddress = reinterpret_cast(memBlock); for ( HeapList::iterator itr = pList->begin(); itr != pList->end(); ) { HeapList::iterator curItr = itr++; if ( reinterpret_cast(curItr->mHeapStart) <= memBlockAddress && reinterpret_cast(curItr->mHeapEnd) > memBlockAddress ) { HeapBase* pChildHeapBase = FindContainHeap( &curItr->mChildList, memBlock ); if ( pChildHeapBase ) { return pChildHeapBase; } return &(*curItr); } } return NULL; } /*!--------------------------------------------------------------------------* Name: FindContainHeap @brief メモリブロックを含有するヒープを検索します。 @param[in] memBlock 検索対象のメモリブロック。 @return 指定したメモリブロックを含むヒープが見つかれば、 そのヒープのハンドルを返します。 見つからなければ、NULL が返ります。 *---------------------------------------------------------------------------*/ HeapBase* HeapBase::FindContainHeap( const void* memBlock ) { return FindContainHeap( &sRootList, memBlock ); } /*!--------------------------------------------------------------------------* Name: FindParentHeap @brief 親ヒープを検索します。 @param[in] heap 検索対象のヒープ @return 指定したメモリブロックを含むヒープが見つかれば、 そのヒープのハンドルを返します。 見つからなければ、NULL が返ります。 *---------------------------------------------------------------------------*/ HeapBase* HeapBase::FindParentHeap( const HeapBase* heap ) { u32 heapAddress = reinterpret_cast(heap); for ( HeapList::iterator itr = sRootList.begin(); itr != sRootList.end(); ) { HeapList::iterator curItr = itr++; // ターゲットのアドレスが含まれているならば、子を検索する if ( reinterpret_cast(curItr->mHeapStart) <= heapAddress && reinterpret_cast(curItr->mHeapEnd) > heapAddress ) { return FindContainHeap( &curItr->mChildList, &(*curItr) ); } } return NULL; } #if 0 // ヒープアドレスを表示します void HeapBase::Dump() { char str[64] = "[nw::ut "; switch ( mSignature ) { case EXPHEAP_SIGNATURE: std::snprintf( str, 64, "%s Exp", str ); break; case FRMHEAP_SIGNATURE: std::snprintf( str, 64, "%s Frame", str ); break; case UNTHEAP_SIGNATURE: std::snprintf( str, 64, "%s Unit", str ); break; default: NW_ASSERT( false ); } OS_Printf("%s Heap]\twhole [%p - %p)\n", str, this, mHeapEnd ); } #endif /*!--------------------------------------------------------------------------* Name: SetFillValForHeap @brief ヒープの作成時やメモリブロックの確保・解放時にメモリに セットする値をセットします。 この関数はデバッグ用の関数です。 最終ROM版ライブラリでは常に0を返します。 @param[in] type 取得する値の種類 @param[in] val セットする値 @return 以前の、メモリブロックの確保時にメモリにセットする値を返します。 *---------------------------------------------------------------------------*/ u32 HeapBase::SetFillValue( FillType type, u32 val ) { NW_ASSERT( type < HEAP_FILL_MAX ); u32 oldVal = sFillVals[ type ]; sFillVals[ type ] = val; return oldVal; } /*!--------------------------------------------------------------------------* Name: GetFillValForHeap @brief ヒープの作成時やメモリブロックの確保・解放時にメモリに セットする値を取得します。 この関数はデバッグ用の関数です。 最終ROM版ライブラリでは常に0を返します。 @param[in] type 取得する値の種類 @return 指定された種類のメモリにセットする値を返します。 *---------------------------------------------------------------------------*/ u32 HeapBase::GetFillValue( FillType type ) { NW_ASSERT( type < HEAP_FILL_MAX ); return sFillVals[ type ]; } /*!--------------------------------------------------------------------------* Name: GetHeapType @brief ヒープハンドルがどの種類のヒープであるかを取得します。 @return ヒープハンドルからヒープの種別を取得します。 *---------------------------------------------------------------------------*/ HeapBase::HeapType HeapBase::GetHeapType() { switch ( mSignature ) { case EXPHEAP_SIGNATURE: return HEAP_TYPE_EXP; case FRMHEAP_SIGNATURE: return HEAP_TYPE_FRM; case UNTHEAP_SIGNATURE: return HEAP_TYPE_UNIT; default: return HEAP_TYPE_UNKNOWN; } } /*!--------------------------------------------------------------------------* Name: Initialize @brief ヒープの初期化を行います。 @param[in] signature シグネチャ。 @param[in] heapStart ヒープメモリの開始アドレス。 @param[in] heapEnd ヒープメモリの終了アドレス +1。 @param[in] optFlag ヒープオプション。 @return なし。 *---------------------------------------------------------------------------*/ void HeapBase::Initialize( u32 signature, void* heapStart, void* heapEnd, u16 optFlag ) { mSignature = signature; mHeapStart = heapStart; mHeapEnd = heapEnd; mAttribute = 0; SetOptionFlag( optFlag ); FillNoUseMemory( heapStart, (u32)GetOffsetFromPtr( heapStart, heapEnd ) ); HeapList* pList = FindListContainHeap( this ); pList->push_back( this ); DumpHeapList(); } /*!--------------------------------------------------------------------------* Name: Finalize @brief ヒープ共通の後始末を行います。 @return なし。 *---------------------------------------------------------------------------*/ void HeapBase::Finalize() { HeapList* pList = FindListContainHeap( this ); pList->erase( this ); mSignature = 0; DumpHeapList(); } /*!--------------------------------------------------------------------------* Name: LockHeap @brief ヒープの排他制御をおこなうためのロック関数 @return なし *---------------------------------------------------------------------------*/ void HeapBase::LockHeap() { #ifdef NW_UT_HEAP_MULTITHREADED if ( GetOptionFlag() & OPT_THREAD_SAFE ) { OS_LockMutex( &mMutex ); } #endif } /*!--------------------------------------------------------------------------* Name: UnlockHeap @brief ヒープの排他制御をおこなうためのアンロック関数 @return なし *---------------------------------------------------------------------------*/ void HeapBase::UnlockHeap() { #ifdef NW_UT_HEAP_MULTITHREADED if ( GetOptionFlag() & OPT_THREAD_SAFE ) { OS_UnlockMutex( &mMutex ); } #endif } /*!--------------------------------------------------------------------------* Name: FillFreeMemory @brief フリー直後のメモリフィル @param[in] address アドレス @param[in] size サイズ @return なし *---------------------------------------------------------------------------*/ void HeapBase::FillFreeMemory( void* address, u32 size ) { if ( GetOptionFlag() & OPT_DEBUG_FILL ) { #ifdef NW_PLATFORM_TWL MI_CpuFill32( address, GetFillValue( HEAP_FILL_FREE ), size ); #else std::memset(address, GetFillValue( HEAP_FILL_FREE ), size); #endif } } /*!--------------------------------------------------------------------------* Name: FillNoUseMemory @brief 未使用メモリのメモリフィル @param[in] address アドレス @param[in] size サイズ @return なし *---------------------------------------------------------------------------*/ void HeapBase::FillNoUseMemory( void* address, u32 size ) { if ( GetOptionFlag() & OPT_DEBUG_FILL ) { #ifdef NW_PLATFORM_TWL MI_CpuFill32( address, GetFillValue( HEAP_FILL_NOUSE ), size ); #else std::memset(address, GetFillValue( HEAP_FILL_NOUSE ), size); #endif } } /*!--------------------------------------------------------------------------* Name: FillAllocMemory @brief アロケート直後のメモリフィル @param[in] address アドレス @param[in] size サイズ @return なし *---------------------------------------------------------------------------*/ void HeapBase::FillAllocMemory( void* address, u32 size ) { if ( GetOptionFlag() & OPT_0_CLEAR ) { #ifdef NW_PLATFORM_TWL MI_CpuFill32( address, 0, size ); #else std::memset(address, 0, size); #endif } else { if ( GetOptionFlag() & OPT_DEBUG_FILL ) { #ifdef NW_PLATFORM_TWL MI_CpuFill32( address, GetFillValue( HEAP_FILL_ALLOC ), size ); #else std::memset(address, GetFillValue( HEAP_FILL_ALLOC ), size); #endif } } } /*!--------------------------------------------------------------------------* Name: GetOptForHeap @brief ヒープからオプションフラグを取得 @return オプションフラグの値 *---------------------------------------------------------------------------*/ u16 HeapBase::GetOptionFlag() { return (u16)GetBitValue( mAttribute, 0, 8 ); } /*!--------------------------------------------------------------------------* Name: SetOptForHeap @brief ヒープへオプションフラグを設定 @param[in] optFlag ヒープへのオプションです。 @return なし。 *---------------------------------------------------------------------------*/ void HeapBase::SetOptionFlag( u16 optFlag ) { SetBitValue( mAttribute, 0, 8, optFlag ); } } // nw::ut } // nw