1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_AddressSpaceManager.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: 17610 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/config.h>
17 #if NN_PLATFORM_HAS_MMU
18
19 #include "os_AddressSpaceManager.h"
20 #include <nn/os/os_MemoryBlock.h>
21
22 namespace nn {
23 namespace os {
24
Initialize(uptr begin,size_t size)25 void AddressSpaceManager::Initialize(uptr begin, size_t size)
26 {
27 m_Lock.Initialize();
28
29 // CHECK: �������ς݂��ǂ������m�F���邱�Ƃ����܂��B
30
31 m_SpaceBegin = begin;
32 m_SpaceEnd = begin + size;
33 NN_MIN_TASSERT_(m_SpaceEnd, m_SpaceBegin);
34 }
35
Allocate(MemoryBlockBase * pBlock,size_t size,size_t skipSize)36 uptr AddressSpaceManager::Allocate(MemoryBlockBase* pBlock, size_t size, size_t skipSize)
37 {
38 NN_NULL_TASSERT_(pBlock);
39 NN_ALIGN_TASSERT_(size, NN_OS_MEMORY_PAGE_SIZE);
40 NN_ALIGN_TASSERT_(skipSize, NN_OS_MEMORY_PAGE_SIZE);
41
42 Lock::ScopedLock scopedLock(m_Lock);
43
44 MemoryBlockBase* pPrev = FindSpace(size, skipSize);
45 uptr allocatedAddress;
46
47 if( pPrev != NULL )
48 {
49 // pPrev �� GetNext(pPrev) �܂��� SpaceEnd �̊Ԃ̋�Ԃ������Ă���
50
51 allocatedAddress = pPrev->GetAddress() + pPrev->GetSize() + skipSize;
52 MemoryBlockBase* pNext = m_BlockList.GetNext(pPrev);
53
54 if( pNext != NULL )
55 {
56 NN_MAX_TASSERT_(allocatedAddress + size + skipSize, pNext->GetAddress());
57
58 m_BlockList.Insert(pNext, pBlock);
59 }
60 else
61 {
62 NN_MAX_TASSERT_(allocatedAddress + size + skipSize, m_SpaceEnd);
63
64 m_BlockList.PushBack(pBlock);
65 }
66 }
67 else
68 {
69 // SpaceBegin �� GetFront() �܂��� SpaceEnd �̊Ԃ̋�Ԃ������Ă���
70 // �܂��́A�����Ă��Ȃ��B
71
72 allocatedAddress = m_SpaceBegin;
73 MemoryBlockBase* pNext = m_BlockList.GetFront();
74
75 if( pNext != NULL )
76 {
77 const uptr allocatedEnd = allocatedAddress + size;
78 const uptr nextBegin = pNext->GetAddress();
79
80 if( nextBegin < allocatedEnd + skipSize )
81 {
82 // �A�h���X��Ԃ̐擪���玟�̃������u���b�N�܂ł̊Ԃ� size ���̋����݂��܂���B
83 return NULL;
84 }
85
86 m_BlockList.Insert(pNext, pBlock);
87 }
88 else
89 {
90 // �S��Ԃ��Ă����ꍇ
91 const uptr allocatedEnd = allocatedAddress + size;
92
93 if( m_SpaceEnd < allocatedEnd )
94 {
95 // �Ǘ����Ă���A�h���X��Ԃ̗̈�ł� size ���̋����݂��܂���B
96 return NULL;
97 }
98
99 m_BlockList.PushBack(pBlock);
100 }
101 }
102
103 pBlock->SetAddressAndSize(allocatedAddress, size);
104
105 return allocatedAddress;
106 }
107
108 // �������u���b�N���A�h���X��Ԃɉ�����܂��B
Free(MemoryBlockBase * pBlock)109 void AddressSpaceManager::Free(MemoryBlockBase* pBlock)
110 {
111 // TODO: pBlock��NULL�`�F�b�N���K�v�ł��B
112 Lock::ScopedLock scopedLock(m_Lock);
113
114 m_BlockList.Erase(pBlock);
115 pBlock->SetAddressAndSize(NULL, 0);
116 }
117
118 // �������u���b�N�̏��� pFrom ���� pTo �Ɉڂ��܂��B
Switch(MemoryBlockBase * pTo,MemoryBlockBase * pFrom)119 void AddressSpaceManager::Switch(MemoryBlockBase* pTo, MemoryBlockBase* pFrom)
120 {
121 // TODO: pTo��NULL�`�F�b�N���K�v�ł��B
122 // TODO: pFrom��NULL�`�F�b�N���K�v�ł��B
123 Lock::ScopedLock scopedLock(m_Lock);
124
125 pTo->SetAddressAndSize(pFrom->GetAddress(), pFrom->GetSize());
126 m_BlockList.Insert(pFrom, pTo);
127
128 pFrom->SetAddressAndSize(NULL, 0);
129 m_BlockList.Erase(pFrom);
130 }
131
132 // �w�肵���T�C�Y+�y�[�W�T�C�Y���̋�����̈��T�����܂��B
FindSpace(size_t size,size_t skipSize)133 MemoryBlockBase* AddressSpaceManager::FindSpace(size_t size, size_t skipSize)
134 {
135 MemoryBlockBase* pItem = m_BlockList.GetBack();
136 uptr end = m_SpaceEnd;
137 NN_MIN_TASSERT_(end, m_SpaceBegin);
138
139 while( pItem != NULL )
140 {
141 const uptr nextBegin = pItem->GetAddress();
142 const uptr nextEnd = nextBegin + pItem->GetSize();
143 const size_t spaceSize = end - nextEnd;
144 NN_MAX_TASSERT_(nextEnd, end);
145
146 if( spaceSize >= size + skipSize )
147 {
148 // pItem �̌�낪�����Ă���
149 return pItem;
150 }
151
152 end = nextBegin - skipSize;
153 pItem = m_BlockList.GetPrevious(pItem);
154 }
155
156 // �S��Ԃ������Ă���
157 // �܂��́A�擪�̋�Ԃ������Ă���
158 // �܂��́A�����Ă��Ȃ�
159 return NULL;
160 }
161
162 // �A�h���X��Ԃɑ��݂��郁�����u���b�N���X�g���f�o�b�O�o�͂��܂��B
Dump()163 void AddressSpaceManager::Dump()
164 {
165 // CHECK: �_���v���ɑ��̃X���b�h���烊�X�g�̓��e���ύX����Ȃ��悤�Ƀ��b�N���邱�Ƃ����܂��B
166
167 MemoryBlockBase* pItem = m_BlockList.GetFront();
168
169 NN_TLOG_(" -------- %08x %08x\n", m_SpaceBegin, m_SpaceEnd);
170 while( pItem != NULL )
171 {
172 NN_TLOG_(" %08x %08x %08x\n", pItem, pItem->GetAddress(), pItem->GetAddress() + pItem->GetSize());
173 pItem = m_BlockList.GetNext(pItem);
174 }
175
176 NN_TPANIC_("dump complete");
177 }
178
179 }
180 }
181
182
183
184 #include <new>
185 using namespace nn::os;
186
187 extern "C" {
188
nnosAddressSpaceManagerInitialize(nnosAddressSpaceManager * p,uptr begin,size_t size)189 void nnosAddressSpaceManagerInitialize(nnosAddressSpaceManager* p, uptr begin, size_t size)
190 {
191 AddressSpaceManager* pThis = new (p) AddressSpaceManager();
192 pThis->Initialize(begin, size);
193 }
194
nnosAddressSpaceManagerAllocate(nnosAddressSpaceManager * p,nnosMemoryBlockBase * p2,size_t size,size_t skipSize)195 uptr nnosAddressSpaceManagerAllocate(nnosAddressSpaceManager* p, nnosMemoryBlockBase* p2, size_t size, size_t skipSize)
196 {
197 AddressSpaceManager* pThis = reinterpret_cast<AddressSpaceManager*>(p);
198 MemoryBlockBase* pBlock = reinterpret_cast<MemoryBlockBase*>(p2);
199 return pThis->Allocate(pBlock, size, skipSize);
200 }
201
nnosAddressSpaceManagerFree(nnosAddressSpaceManager * p,nnosMemoryBlockBase * p2)202 void nnosAddressSpaceManagerFree(nnosAddressSpaceManager* p, nnosMemoryBlockBase* p2)
203 {
204 AddressSpaceManager* pThis = reinterpret_cast<AddressSpaceManager*>(p);
205 MemoryBlockBase* pBlock = reinterpret_cast<MemoryBlockBase*>(p2);
206 pThis->Free(pBlock);
207 }
208
nnosAddressSpaceManagerSwitch(nnosAddressSpaceManager * p,nnosMemoryBlockBase * p2,nnosMemoryBlockBase * p3)209 void nnosAddressSpaceManagerSwitch(nnosAddressSpaceManager* p, nnosMemoryBlockBase* p2, nnosMemoryBlockBase* p3)
210 {
211 AddressSpaceManager* pThis = reinterpret_cast<AddressSpaceManager*>(p);
212 MemoryBlockBase* pTo = reinterpret_cast<MemoryBlockBase*>(p2);
213 MemoryBlockBase* pFrom = reinterpret_cast<MemoryBlockBase*>(p3);
214 pThis->Switch(pTo, pFrom);
215 }
216
217 }
218
219
220 #endif // if NN_PLATFORM_HAS_MMU
221