/*---------------------------------------------------------------------------* Project: Horizon File: os_Memory.cpp Copyright (C)2009 Nintendo Co., Ltd. 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. $Rev: 17558 $ *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include //--------------------------------------------------------------------------- using namespace nn; using namespace nn::svc; namespace nn{ namespace os{ namespace { uptr s_DeviceMemoryAddress = 0; //!< デバイスメモリのアドレス size_t s_DeviceMemorySize = 0; //!< デバイスメモリのサイズ size_t s_HeapSize = 0; //!< ヒープサイズ } // デバイスメモリを初期化します。 void InitializeDeviceMemory() { if ( s_DeviceMemorySize == 0 ) { Result result; result = SetDeviceMemorySize( DEVICE_MEMORY_SIZE ); NN_UTIL_PANIC_IF_FAILED( result ); } } // デバイスメモリのアドレスを取得します。 uptr GetDeviceMemoryAddress() { NN_TASSERTMSG_(s_DeviceMemoryAddress != NULL, "Device Memory is NOT Initialized."); return s_DeviceMemoryAddress; } // デバイスメモリのサイズを設定します。 Result SetDeviceMemorySize(size_t size) { // CHECK: ページサイズには定数 NN_OS_MEMORY_PAGE_SIZE の使用を推奨します。 // デバイスメモリのサイズは4096の倍数である必要があります。 NN_ALIGN_TASSERT_(size, 4096); Result result; if( size > s_DeviceMemorySize ) { // デバイスメモリを確保します。 // すでにデバイスメモリを確保していれば、直後に足りない分のメモリを確保します。 uptr addr; const size_t mapSize = size - s_DeviceMemorySize; const uptr requestAddress = (s_DeviceMemorySize == 0) ? NULL: (s_DeviceMemoryAddress + s_DeviceMemorySize); // nn::os::MEMORY_OPERATION_FLAG_LINEARを指定して連続したメモリを確保できるようにします。 result = nn::svc::ControlMemory( &addr, requestAddress, NULL, mapSize, (nn::os::MEMORY_OPERATION_COMMIT | nn::os::MEMORY_OPERATION_FLAG_LINEAR), nn::os::MEMORY_PERMISSION_READ_WRITE ); if( result.IsSuccess() ) { // 初回デバイスメモリ確保でなければ、連続したアドレスにメモリを取得できたことをチェックします。 NN_TASSERT_( s_DeviceMemorySize == 0 || addr == requestAddress ); // 初回デバイスメモリ確保時にはアドレスを保存します。 if( s_DeviceMemorySize == 0 ) { s_DeviceMemoryAddress = addr; } s_DeviceMemorySize = size; } } else { // デバイスメモリの末尾から不要なサイズ分を解放します。 uptr addr; const size_t unmapSize = s_DeviceMemorySize - size; const uptr freeAddress = s_DeviceMemoryAddress + size; result = nn::svc::ControlMemory( &addr, freeAddress, NULL, unmapSize, nn::os::MEMORY_OPERATION_FREE, nn::os::MEMORY_PERMISSION_NONE ); if( result.IsSuccess() ) { if( size == 0 ) { s_DeviceMemoryAddress = NULL; } s_DeviceMemorySize = size; } } return result; } // デバイスメモリのサイズを取得します。 size_t GetDeviceMemorySize() { return s_DeviceMemorySize; } // ヒープサイズを設定します。 Result SetHeapSize(size_t size) { // CHECK: ページサイズには定数 NN_OS_MEMORY_PAGE_SIZE の使用を推奨します。 // ヒープのサイズは4096の倍数である必要があります。 NN_ALIGN_TASSERT_(size, 4096); Result result; if( size > s_HeapSize ) { // ヒープの先頭からサイズ分の領域を確保します。 // すでに確保していれば、直後に足りない分のメモリを確保します。 uptr addr; const size_t mapSize = size - s_HeapSize; const uptr requestAddress = NN_OS_ADDR_HEAP_BEGIN + s_HeapSize; result = nn::svc::ControlMemory( &addr, requestAddress, NULL, mapSize, nn::os::MEMORY_OPERATION_COMMIT, nn::os::MEMORY_PERMISSION_READ_WRITE ); if( result.IsSuccess() ) { NN_TASSERT_( addr == requestAddress ); s_HeapSize = size; } } else { // ヒープの末尾から不要になったサイズ分の領域を解放します。 uptr addr; const size_t unmapSize = s_HeapSize - size; const uptr freeAddress = NN_OS_ADDR_HEAP_BEGIN + size; result = nn::svc::ControlMemory( &addr, freeAddress, NULL, unmapSize, nn::os::MEMORY_OPERATION_FREE, nn::os::MEMORY_PERMISSION_NONE ); if( result.IsSuccess() ) { s_HeapSize = size; } } return result; } // ヒープサイズを取得します。 size_t GetHeapSize() { return s_HeapSize; } #if NN_PLATFORM_HAS_MMU void SetupHeapForMemoryBlock(size_t heapSize) { Result result; result = SetHeapSize( heapSize ); NN_UTIL_PANIC_IF_FAILED( result ); InitializeMemoryBlock(GetHeapAddress(), GetHeapSize()); SetDefaultAutoStackManager(); } #endif // if NN_PLATFORM_HAS_MMU }} // namespace nn::os #include using namespace nn::os; extern "C" { void nnosInitializeDeviceMemory() { #pragma push #pragma diag_suppress 1361 nn::os::InitializeDeviceMemory(); #pragma pop } uptr nnosGetDeviceMemoryAddress() { return nn::os::GetDeviceMemoryAddress(); } }