1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     demo_Memory.h
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  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   $Revision: 26651 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NW_DEMO_MEMORY_H_
17 #define NW_DEMO_MEMORY_H_
18 
19 #include <nw/types.h>
20 #include <nw/os/os_Memory.h>
21 #include <nn/dbg.h>
22 #include <nn/fnd.h>
23 
24 namespace nw {
25 namespace demo {
26 
27 class DemoAllocator;
28 
29 // デモではデバイスメモリから全てのメモリを確保するようになっています。
30 
31 // デモで使用するメモリサイズです。
32 const size_t DEMO_MEMORY_SIZE = 0x1000000;
33 
34 // パーティクル用のメモリサイズです。
35 const size_t DEMO_PARTICLE_MEMORY_SIZE = 0x100000;
36 
37 //=====================
38 //! @name メモリアロケーター
39 //@{
40 
41 //! @brief 与えられたデモアロケータを初期化します。
42 //!
43 //! @param[in] allocator 初期化するデモアロケータです。
44 //! @param[in] size アロケータで管理するメモリサイズです。
45 //! @param[in] option 拡張ヒープのオプションです。
46 //!
47 void InitializeDemoAllocator(DemoAllocator* allocator, size_t size, bit32 option = 0 );
48 
49 //! @brief 与えられたデモアロケータを解放します。
50 //!
51 //! @param[in] allocator 解放するデモアロケータです。
52 //!
53 void FinalizeDemoAllocator(DemoAllocator* allocator);
54 
55 //---------------------------------------------------------------------------
56 //! @brief       デモ用にメモリを初期化します。
57 //!
58 //!              明示的に呼ばれなかった場合には、初回のアロケート実行時に実行されます。
59 //---------------------------------------------------------------------------
60 void InitializeDemoMemory();
61 
62 //---------------------------------------------------------------------------
63 //! @brief       アライメントされたメモリを確保したアドレスへ戻します。
64 //!
65 //! @param[in]   memory  アラインされたメモリのポインタです。
66 //!
67 //! @return      アライン前のアドレスを返します。
68 //---------------------------------------------------------------------------
69 void* UnAlignMemory( void* memory );
70 
71 //---------------------------------------------------------------------------
72 //! @brief       メインメモリからメモリ領域を確保します。
73 //!
74 //! @param[in]   size      確保するメモリサイズです。
75 //! @param[in]   alignment 確保するメモリのアライメント値です。
76 //!
77 //! @return      確保したメモリアドレスです。
78 //---------------------------------------------------------------------------
79 void* Alloc(size_t size, u8 alignment = 4);
80 
81 //---------------------------------------------------------------------------
82 //! @brief       ヒープへメモリ領域を解放します。
83 //!
84 //! @param[in]   memory  解放するメモリ領域です。
85 //---------------------------------------------------------------------------
86 void  Free(void* memory);
87 
88 //---------------------------------------------------------------------------
89 //! @brief       メインメモリの状態を表示します。
90 //---------------------------------------------------------------------------
91 void Dump();
92 
93 //@}
94 
95 //---------------------------------------------------------------------------
96 //! @brief   デモ用のメインメモリアロケータです。
97 //---------------------------------------------------------------------------
98 class DemoAllocator : public nw::os::IAllocator
99 {
100 public:
101     //! @brief コンストラクタです。
DemoAllocator()102     DemoAllocator()
103     : m_StartAddress(0),
104       m_BreakAllocAddress(NULL),
105       m_BreakAllocSize(0),
106       m_BreakFreeAddress(NULL),
107       m_BreakFreeSize(0)
108     {}
109 
110     //=====================
111     //! @name 作成/破棄
112     //@{
113 
114     //! @brief デモ用のアロケータを初期化します。
115     //!        内部で拡張ヒープを初期化します。
116     //!
117     //! @param[in] startAddress 先頭アドレスです。
118     //! @param[in] size アロケートできるサイズです。
119     //! @param[in] option 拡張ヒープのオプションです。
120     //!
121     void Initialize(uptr startAddress, size_t size, bit32 option = 0);
122 
123     //! @brief デモ用のアロケータを破棄します。
124     //!
125     void Finalize();
126 
127     //@}
128 
129 
130     //! @brief 初期化時に指定した先頭アドレスを取得します。
131     //!
132     //! @return 先頭アドレスです。
GetStartAddress()133     uptr GetStartAddress() const { return m_StartAddress; }
134 
135     //=====================
136     //! @name メモリの確保と解放
137     //@{
138 
139     //! @brief メインメモリからメモリを確保します。
140     //!
141     //! @param[in] size      確保するメモリサイズです。
142     //! @param[in] alignment アライメントです。
143     //!
144     //! @return 確保したメモリアドレスを返します。
Alloc(size_t size,u8 alignment)145     virtual void* Alloc(size_t size, u8 alignment)
146     {
147         NW_ASSERT(size != 0);
148 
149         void* memory = m_Heap.Allocate(size, alignment);
150 
151 #if defined(NW_DEBUG_TRAP_ALLOCATOR)
152         if (memory != NULL)
153         {
154             void* unalignMemory = UnAlignMemory(memory);
155             if (unalignMemory == m_BreakAllocAddress &&
156                 (m_BreakAllocSize == 0 || GetMemoryBlockSize(unalignMemory) == m_BreakAllocSize))
157             {
158                 NW_DEV_LOG("Alloc(): Specified memory block allocated\n");
159     #if defined(NW_DEBUG_BREAK_ALLOCATOR)
160                 nn::dbg::Break(nn::dbg::BREAK_REASON_USER);
161     #endif
162             }
163         }
164 #endif
165 
166         return memory;
167     }
168 
169     using nw::os::IAllocator::Alloc;
170 
171     //! @brief メインメモリにメモリを返却します。
172     //!
173     //! @param[in] memory    返却するメモリアドレスです。
Free(void * memory)174     virtual void Free(void* memory)
175     {
176 #if defined(NW_DEBUG_TRAP_ALLOCATOR)
177         void* unalignMemory = UnAlignMemory(memory);
178         if (unalignMemory == m_BreakFreeAddress &&
179             (m_BreakFreeSize == 0 || GetMemoryBlockSize(unalignMemory) == m_BreakFreeSize))
180         {
181             NW_DEV_LOG("Free(): Specified memory block freed\n");
182 #if defined(NW_DEBUG_BREAK_ALLOCATOR)
183             nn::dbg::Break(nn::dbg::BREAK_REASON_USER);
184 #endif
185         }
186 #endif
187 
188         m_Heap.Free(memory);
189     }
190 
191     //@}
192     //=====================
193     //! @name デバッグ
194     //@{
195 
196 
197 
198     //---------------------------------------------------------------------------
199     //! @brief       空きメモリサイズを返します。
200     //!
201     //! @return      空きメモリサイズです。
202     //---------------------------------------------------------------------------
203     size_t GetFreeSize();
204 
205     //---------------------------------------------------------------------------
206     //! @brief       割り当てられたメモリサイズを返します。
207     //!
208     //! @return      割り当てられたメモリサイズです。
209     //---------------------------------------------------------------------------
210     size_t GetTotalSize();
211 
212     //---------------------------------------------------------------------------
213     //! @brief       確保されたメモリブロックのサイズを返します。
214     //!
215     //! @param[in]   address メモリブロックの先頭アドレスを指定します。
216     //!
217     //! @return      指定されたブロックのサイズです。
218     //---------------------------------------------------------------------------
219     size_t GetMemoryBlockSize(void* address);
220 
221 
222     //! @brief  メインメモリの状態を表示します。
223     void Dump();
224 
225     //! @brief  メモリ確保時の停止条件を設定します。
226     //!
227     //!         指定したアドレスとサイズのメモリ確保が行われるときにプログラムを強制的に一時停止するように設定します。
228     //!         NW_DEBUG_TRAP_ALLOCATOR マクロと NW_DEBUG_BREAK_ALLOCATOR マクロを定義することでこの機能は有効になります。
229     //!         NW_DEBUG_TRAP_ALLOCATOR マクロのみを定義した場合はメッセージ出力のみを行います。
230     //!         サイズに 0 を指定するとアドレスのみを条件とします。
231     //!
232     //!         アドレス、サイズともに Dump() で表示される数値(実際に確保されたアドレスとサイズ)を指定します。
233     //!
234     //! @param  address ブレーク条件のアドレスです。
235     //! @param  size ブレーク条件のサイズです。
SetBreakAlloc(int address,size_t size)236     void SetBreakAlloc(int address, size_t size)
237     {
238 #if defined(NW_DEBUG_TRAP_ALLOCATOR)
239         m_BreakAllocAddress = reinterpret_cast<void *>(address);
240         m_BreakAllocSize = size;
241 #else
242         NW_UNUSED_VARIABLE(address);
243         NW_UNUSED_VARIABLE(size);
244 #endif
245     }
246 
247     //! @brief  メモリ解放時の停止条件を設定します。
248     //!
249     //!         指定したアドレスとサイズのメモリが解放されるときにプログラムを強制的に一時停止するように設定します。
250     //!         NW_DEBUG_TRAP_ALLOCATOR マクロと NW_DEBUG_BREAK_ALLOCATOR マクロを定義することでこの機能は有効になります。
251     //!         NW_DEBUG_TRAP_ALLOCATOR マクロのみを定義した場合はメッセージ出力のみを行います。
252     //!         サイズに 0 を指定するとアドレスのみを条件とします。
253     //!
254     //!         アドレス、サイズともに Dump() で表示される数値(実際に確保されたアドレスとサイズ)を指定します。
255     //!
256     //! @param  address ブレーク条件のアドレスです。
257     //! @param  size ブレーク条件のサイズです。
SetBreakFree(int address,size_t size)258     void SetBreakFree(int address, size_t size)
259     {
260 #if defined(NW_DEBUG_TRAP_ALLOCATOR)
261         m_BreakFreeAddress = reinterpret_cast<void *>(address);
262         m_BreakFreeSize = size;
263 #else
264         NW_UNUSED_VARIABLE(address);
265         NW_UNUSED_VARIABLE(size);
266 #endif
267     }
268 
269     //@}
270 
271 
272 
273 private:
274     uptr m_StartAddress;
275 
276     void* m_BreakAllocAddress;
277     size_t m_BreakAllocSize;
278 
279     void* m_BreakFreeAddress;
280     size_t m_BreakFreeSize;
281 
282     nn::fnd::ExpHeap m_Heap;
283 };
284 
285 } // namespace demo
286 } // namespace nw
287 
288 /* NW_DEMO_MEMORY_H_ */
289 #endif
290 
291