1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_SharedMemory.cpp
4
5 Copyright (C)2009 Nintendo Co., Ltd. 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 $Rev: 25458 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/config.h>
17 #if NN_PLATFORM_HAS_MMU
18
19 #include <nn/svc.h>
20 #include <nn/util/util_Result.h>
21 #include <nn/os/os_SharedMemory.h>
22 #include <nn/os/os_CriticalSection.h>
23 #include <nn/os/os_MemoryMapSelect.h>
24 #include "os_AddressSpaceManager.h"
25
26 namespace nn { namespace os {
27
28 namespace
29 {
30 nnosAddressSpaceManager s_SpaceManager;
31
GetPageAlignedSize(size_t size)32 size_t GetPageAlignedSize(size_t size)
33 {
34 return (size + NN_OS_MEMORY_PAGE_SIZE - 1) & ~(NN_OS_MEMORY_PAGE_SIZE - 1);
35 }
36 }
37
38 namespace detail
39 {
InitializeSharedMemory()40 void InitializeSharedMemory()
41 {
42 nnosAddressSpaceManagerInitialize(&s_SpaceManager, NN_OS_ADDR_SHARED_BEGIN, NN_OS_ADDR_SHARED_SIZE);
43 }
AllocateFromSharedMemorySpace(MemoryBlockBase * p,size_t s)44 uptr AllocateFromSharedMemorySpace(MemoryBlockBase* p, size_t s)
45 {
46 AddressSpaceManager* pManager = reinterpret_cast<AddressSpaceManager*>(&s_SpaceManager);
47 return pManager->Allocate(p, s, NN_OS_MEMORY_PAGE_SIZE);
48 }
FreeToSharedMemorySpace(MemoryBlockBase * p)49 void FreeToSharedMemorySpace(MemoryBlockBase* p)
50 {
51 AddressSpaceManager* pManager = reinterpret_cast<AddressSpaceManager*>(&s_SpaceManager);
52 pManager->Free(p);
53 }
54
55 } // detail
56
57
Map(size_t size,bool readOnly)58 void SharedMemoryBlock::Map(size_t size, bool readOnly)
59 {
60 // 未初期化であることをチェックします。
61 NN_TASSERT_( GetAddress() == NULL );
62 NN_ALIGN_TASSERT_( size, NN_OS_MEMORY_PAGE_SIZE );
63
64 // 仮想アドレス空間からメモリを取得します。
65 uptr addr = detail::AllocateFromSharedMemorySpace(this, size);
66 if (addr == NULL)
67 {
68 NN_TPANIC_("failed to allocate address space.");
69 }
70
71 this->MemoryBlockBase::SetReadOnly(readOnly);
72
73 Result result;
74 const bit32 myPermission = readOnly ? MEMORY_PERMISSION_READ : (MEMORY_PERMISSION_READ | MEMORY_PERMISSION_WRITE);
75 result = nn::svc::MapMemoryBlock(GetHandle(), addr, myPermission, os::MEMORY_PERMISSION_DONT_CARE);
76 NN_UTIL_PANIC_IF_FAILED(result);
77 m_SpaceAllocated = true;
78
79 // TODO: nn::svc::QueryMemory の動作が安定したらここのコメントアウトを消す
80 //MemoryInfo memoryInfo;
81 //PageInfo pageInfo;
82 //result = nn::svc::QueryMemory(&memoryInfo, &pageInfo, addr);
83 //if (result.IsFailure())
84 //{
85 // NN_TPANIC_("QueryMemory failed.");
86 //}
87 //
88 //// 取得したサイズでマップし直してあげる手もあり?
89 //if (memoryInfo.size != size)
90 //{
91 // NN_TPANIC_("Mismatch size.");
92 //}
93 }
94
TryInitialize(size_t size,bool readOnly,bool otherReadOnly,bool noMap)95 Result SharedMemoryBlock::TryInitialize(size_t size, bool readOnly, bool otherReadOnly, bool noMap)
96 {
97 size = GetPageAlignedSize(size);
98 bit32 myPermission = readOnly ? MEMORY_PERMISSION_READ : MEMORY_PERMISSION_READ | MEMORY_PERMISSION_WRITE;
99 bit32 otherPermission = otherReadOnly ? MEMORY_PERMISSION_READ : MEMORY_PERMISSION_READ | MEMORY_PERMISSION_WRITE;
100
101 Handle handle;
102 Result result;
103 result = nn::svc::CreateMemoryBlock(&handle, NULL, size, myPermission, otherPermission);
104 NN_UTIL_RETURN_IF_FAILED(result);
105 this->SetHandle(handle);
106
107 if (!noMap)
108 {
109 Map(size, readOnly);
110 }
111 return result;
112 }
113
Initialize(size_t size,bool readOnly,bool otherReadOnly,bool noMap)114 void SharedMemoryBlock::Initialize(size_t size, bool readOnly, bool otherReadOnly, bool noMap)
115 {
116 NN_UTIL_PANIC_IF_FAILED(TryInitialize(size, readOnly, otherReadOnly, noMap));
117 }
118
AttachAndMap(Handle handle,size_t size,bool readOnly)119 void SharedMemoryBlock::AttachAndMap(Handle handle, size_t size, bool readOnly)
120 {
121 // TODO: SVC が整備されたら、サイズや属性のチェックコードを挿入。
122 size = GetPageAlignedSize(size);
123
124 this->SetHandle(handle);
125 Map(size, readOnly);
126 }
127
Unmap()128 void SharedMemoryBlock::Unmap()
129 {
130 if (GetAddress() != NULL)
131 {
132 if( m_SpaceAllocated )
133 {
134 NN_UTIL_PANIC_IF_FAILED(nn::svc::UnmapMemoryBlock(GetHandle(), GetAddress()));
135 detail::FreeToSharedMemorySpace(this);
136 }
137 else
138 {
139 SetAddressAndSize(0, 0);
140 }
141 }
142 }
143
Finalize()144 void SharedMemoryBlock::Finalize()
145 {
146 if (this->IsValid())
147 {
148 Unmap();
149 this->HandleObject::Close();
150 }
151 }
152
153
154 }}
155
156 #include <new>
157 using namespace nn::os;
158
159 // SharedMemoryBlock
160
nnosSharedMemoryBlockAllocate(nnosSharedMemoryBlock * this_,size_t size,bool readOnly,bool otherReadOnly,bool noMap)161 void nnosSharedMemoryBlockAllocate(nnosSharedMemoryBlock* this_, size_t size, bool readOnly, bool otherReadOnly, bool noMap)
162 {
163 new (this_) SharedMemoryBlock(size, readOnly, otherReadOnly, noMap);
164 }
165
nnosSharedMemoryBlockInitializeNoAllocate(nnosSharedMemoryBlock * this_)166 void nnosSharedMemoryBlockInitializeNoAllocate(nnosSharedMemoryBlock* this_)
167 {
168 new (this_) SharedMemoryBlock();
169 }
170
nnosSharedMemoryBlockFree(nnosSharedMemoryBlock * this_)171 void nnosSharedMemoryBlockFree(nnosSharedMemoryBlock* this_)
172 {
173 SharedMemoryBlock* pSharedMemoryBlock = reinterpret_cast<SharedMemoryBlock*>(this_);
174 pSharedMemoryBlock->~SharedMemoryBlock();
175 }
176
nnosSharedMemoryBlockGetAddress(nnosSharedMemoryBlock * this_)177 uptr nnosSharedMemoryBlockGetAddress(nnosSharedMemoryBlock* this_)
178 {
179 SharedMemoryBlock* pSharedMemoryBlock = reinterpret_cast<SharedMemoryBlock*>(this_);
180 return pSharedMemoryBlock->GetAddress();
181 }
182
nnosSharedMemoryBlockGetSize(nnosSharedMemoryBlock * this_)183 size_t nnosSharedMemoryBlockGetSize(nnosSharedMemoryBlock* this_)
184 {
185 SharedMemoryBlock* pSharedMemoryBlock = reinterpret_cast<SharedMemoryBlock*>(this_);
186 return pSharedMemoryBlock->GetSize();
187 }
188
nnosSharedMemoryBlockIsReadOnly(nnosSharedMemoryBlock * this_)189 bool nnosSharedMemoryBlockIsReadOnly(nnosSharedMemoryBlock* this_)
190 {
191 SharedMemoryBlock* pSharedMemoryBlock = reinterpret_cast<SharedMemoryBlock*>(this_);
192 return pSharedMemoryBlock->IsReadOnly();
193 }
194
195 #endif // if NN_PLATFORM_HAS_MMU
196