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: 24950 $
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     //! @param[in]   address メモリブロックの先頭アドレスを指定します。
209     //!
210     //! @return      指定されたブロックのサイズです。
211     //---------------------------------------------------------------------------
212     size_t GetMemoryBlockSize(void* address);
213 
214 
215     //! @brief  メインメモリの状態を表示します。
216     void Dump();
217 
218     //! @brief  メモリ確保時の停止条件を設定します。
219     //!
220     //!         指定したアドレスとサイズのメモリ確保が行われるときにプログラムを強制的に一時停止するように設定します。
221     //!         NW_DEBUG_TRAP_ALLOCATOR マクロと NW_DEBUG_BREAK_ALLOCATOR マクロを定義することでこの機能は有効になります。
222     //!         NW_DEBUG_TRAP_ALLOCATOR マクロのみを定義した場合はメッセージ出力のみを行います。
223     //!         サイズに 0 を指定するとアドレスのみを条件とします。
224     //!
225     //!         アドレス、サイズともに Dump() で表示される数値(実際に確保されたアドレスとサイズ)を指定します。
226     //!
227     //! @param  address ブレーク条件のアドレスです。
228     //! @param  size ブレーク条件のサイズです。
SetBreakAlloc(int address,size_t size)229     void SetBreakAlloc(int address, size_t size)
230     {
231 #if defined(NW_DEBUG_TRAP_ALLOCATOR)
232         m_BreakAllocAddress = reinterpret_cast<void *>(address);
233         m_BreakAllocSize = size;
234 #else
235         NW_UNUSED_VARIABLE(address);
236         NW_UNUSED_VARIABLE(size);
237 #endif
238     }
239 
240     //! @brief  メモリ解放時の停止条件を設定します。
241     //!
242     //!         指定したアドレスとサイズのメモリが解放されるときにプログラムを強制的に一時停止するように設定します。
243     //!         NW_DEBUG_TRAP_ALLOCATOR マクロと NW_DEBUG_BREAK_ALLOCATOR マクロを定義することでこの機能は有効になります。
244     //!         NW_DEBUG_TRAP_ALLOCATOR マクロのみを定義した場合はメッセージ出力のみを行います。
245     //!         サイズに 0 を指定するとアドレスのみを条件とします。
246     //!
247     //!         アドレス、サイズともに Dump() で表示される数値(実際に確保されたアドレスとサイズ)を指定します。
248     //!
249     //! @param  address ブレーク条件のアドレスです。
250     //! @param  size ブレーク条件のサイズです。
SetBreakFree(int address,size_t size)251     void SetBreakFree(int address, size_t size)
252     {
253 #if defined(NW_DEBUG_TRAP_ALLOCATOR)
254         m_BreakFreeAddress = reinterpret_cast<void *>(address);
255         m_BreakFreeSize = size;
256 #else
257         NW_UNUSED_VARIABLE(address);
258         NW_UNUSED_VARIABLE(size);
259 #endif
260     }
261 
262     //@}
263 
264 
265 
266 private:
267     uptr m_StartAddress;
268 
269     void* m_BreakAllocAddress;
270     size_t m_BreakAllocSize;
271 
272     void* m_BreakFreeAddress;
273     size_t m_BreakFreeSize;
274 
275     nn::fnd::ExpHeap m_Heap;
276 };
277 
278 } // namespace demo
279 } // namespace nw
280 
281 /* NW_DEMO_MEMORY_H_ */
282 #endif
283 
284