1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     fnd_UnitHeap.h
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: 34406 $
14  *---------------------------------------------------------------------------*/
15 
16 /* Please see man pages for details
17 
18 
19 */
20 
21 #ifndef NN_FND_FND_UNIT_HEAP_H_
22 #define NN_FND_FND_UNIT_HEAP_H_
23 
24 #include <nn/fnd/fnd_HeapBase.h>
25 #include <nn/util/util_TypeTraits.h>
26 #include <nn/util/util_StaticAssert.h>
27 #include <nn/fnd/fnd_Allocator.h>
28 #include <nn/Assert.h>
29 #include <nn/os.h>
30 
31 
32 #ifdef __cplusplus
33 
34 namespace nn { namespace fnd {
35 
36 /* Please see man pages for details
37 
38 
39 
40  */
41 class UnitHeapBase : public HeapBase
42 {
43 public:
44 
45     /* Please see man pages for details
46 
47 
48 
49 
50 
51      */
52     static size_t GetRequiredHeapSize(size_t unit, size_t numUnit, s32 alignment = DEFAULT_ALIGNMENT);
53 
54 protected:
55 
UnitHeapBase()56     UnitHeapBase() : m_FreeNode(0) {}
57 
58     UnitHeapBase(size_t unit, uptr addr, size_t size, s32 alignment = DEFAULT_ALIGNMENT, bit32 option = 0) : m_FreeNode(0) { Initialize(unit, addr, size, alignment, option); }
59 
60     template <class MemoryBlock>
61     explicit UnitHeapBase(size_t unit, const MemoryBlock& block, s32 alignment = DEFAULT_ALIGNMENT, bit32 option = 0) : m_FreeNode(0) { Initialize(unit, block.GetAddress(), block.GetSize(), alignment, option); }
62 
63     void Initialize(size_t unit, uptr addr, size_t size, s32 alignment = DEFAULT_ALIGNMENT, bit32 option = 0);
64 
65     void Invalidate();
66 
67     void Finalize();
68 
69     virtual ~UnitHeapBase();
70 
71     void* Allocate();
72 
73     void Free(void* p);
74 
75     virtual void FreeV(void* p);
76 
GetUnitSize()77     size_t GetUnitSize() const { return m_Unit; }
78 
GetAllocatableCount()79     size_t GetAllocatableCount() const { return m_Size / m_Unit - m_Count; }
80 
GetAllocatedCount()81     size_t GetAllocatedCount() const { return m_Count; }
82 
GetStartAddress()83     virtual void* GetStartAddress() const { return reinterpret_cast<void*>(m_Addr); }
84 
GetTotalSize()85     virtual size_t GetTotalSize() const { return m_Size; }
86 
87     virtual void Dump() const;
88 
89     virtual bool HasAddress(const void* addr) const;
90 
91 private:
92 
93     bool IsFreeNode(uptr addr) const;
94 
95     struct Node
96     {
97         Node* next;
98     };
99 
100     size_t m_Unit;
101     uptr m_Addr;
102     size_t m_Size;
103     Node* m_FreeNode;
104     s32 m_Alignment;
105     size_t m_Count;
106 
107 };
108 
Finalize()109 inline void UnitHeapBase::Finalize()
110 {
111     if (m_FreeNode == 0)
112     {
113         return;
114     }
115     NN_TASSERT_(m_Count == 0);
116     this->m_FreeNode = 0;
117 }
118 
~UnitHeapBase()119 inline UnitHeapBase::~UnitHeapBase()
120 {
121     Finalize();
122 }
123 
Invalidate()124 inline void UnitHeapBase::Invalidate()
125 {
126     this->m_FreeNode = 0;
127 }
128 
Allocate()129 inline void* UnitHeapBase::Allocate()
130 {
131     void* ret = reinterpret_cast<void*&>(m_FreeNode);
132     if (ret)
133     {
134         this->m_FreeNode = m_FreeNode->next;
135         ++this->m_Count;
136 
137         // Fill options
138         DebugFillMemory(reinterpret_cast<uptr>(ret), m_Unit, HEAP_FILL_TYPE_ALLOC);
139         FillMemoryZero(reinterpret_cast<uptr>(ret), m_Unit);
140     }
141 
142     return ret;
143 }
144 
HasAddress(const void * addr)145 inline bool UnitHeapBase::HasAddress(const void* addr) const
146 {
147     return m_Addr <= reinterpret_cast<uptr>(addr)
148         && reinterpret_cast<uptr>(addr) < (m_Addr+m_Size);
149 }
150 
Free(void * p)151 inline void UnitHeapBase::Free(void* p)
152 {
153     NN_TASSERT_(HasAddress(p));
154 
155     DebugFillMemory(reinterpret_cast<uptr>(p), m_Unit, HEAP_FILL_TYPE_FREE);
156 
157     reinterpret_cast<Node*&>(p)->next = m_FreeNode;
158     this->m_FreeNode = reinterpret_cast<Node*&>(p);
159     --this->m_Count;
160 }
161 
FreeV(void * p)162 inline void UnitHeapBase::FreeV(void* p)
163 {
164     Free(p);
165 }
166 
167 /* Please see man pages for details
168 
169 
170 
171 
172 
173 
174 
175 
176 
177 
178 
179 
180 */
181 template <class LockPolicy>
182 class UnitHeapTemplate : public UnitHeapBase, private LockPolicy::LockObject
183 {
184 private:
185     typedef UnitHeapBase Base;
186     typedef typename LockPolicy::LockObject LockObject;
187     typedef typename LockPolicy::ScopedLock ScopedLock;
188 public:
189 
190     /* Please see man pages for details
191 
192 
193 
194 
195 
196      */
197     static size_t GetRequiredHeapSize(size_t unit, size_t numUnit, s32 alignment = DEFAULT_ALIGNMENT)
198     {
199         return Base::GetRequiredHeapSize(unit, numUnit, alignment);
200     }
201 
202     /* Please see man pages for details
203 
204      */
UnitHeapTemplate()205     UnitHeapTemplate() {}
206 
207     /* Please see man pages for details
208 
209 
210 
211 
212 
213 
214 
215      */
216     UnitHeapTemplate(size_t unit, uptr addr, size_t size, s32 alignment = DEFAULT_ALIGNMENT, bit32 option = 0)
217     {
218         Initialize(unit, addr, size, alignment, option);
219     }
220 
221     /* Please see man pages for details
222 
223 
224 
225 
226 
227 
228      */
229     template <class MemoryBlock>
230     explicit UnitHeapTemplate(size_t unit, const MemoryBlock& block, s32 alignment = DEFAULT_ALIGNMENT, bit32 option = 0)
231     {
232         Initialize(unit, block.GetAddress(), block.GetSize(), alignment, option);
233     }
234 
235     /* Please see man pages for details
236 
237 
238 
239 
240 
241 
242 
243 
244 
245 
246 
247 
248 
249 
250 
251 
252 
253     */
254     static UnitHeapTemplate* Create(HeapBase* parent, size_t unit, void* addr, size_t size, s32 alignment = DEFAULT_ALIGNMENT, bit32 option = 0, bit32 placement = HEAP_INFOPLACEMENT_HEAD);
255 
256     /* Please see man pages for details
257 
258 
259 
260 
261 
262 
263 
264 
265      */
266     void Initialize(size_t unit, uptr addr, size_t size, s32 alignment = DEFAULT_ALIGNMENT, bit32 option = 0)
267     {
268         Base::Initialize(unit, addr, size, alignment, option);
269         LockObject::Initialize();
270     }
271 
272     /* Please see man pages for details
273 
274 
275      */
Invalidate()276     void Invalidate() { Base::Invalidate(); }
277 
278     /* Please see man pages for details
279 
280 
281 
282 
283 
284      */
Finalize()285     void Finalize()
286     {
287         LockObject::Finalize();
288         Base::Finalize();
289     }
290 
291     /* Please see man pages for details
292 
293 
294 
295     */
~UnitHeapTemplate()296     virtual ~UnitHeapTemplate() {}
297 
298     /* Please see man pages for details
299 
300 
301 
302 
303     */
Allocate()304     void* Allocate()
305     {
306         ScopedLock lk(*this);
307         return Base::Allocate();
308     }
309 
310     /* Please see man pages for details
311 
312 
313 
314     */
Free(void * p)315     void Free(void* p)
316     {
317         ScopedLock lk(*this);
318         Base::Free(p);
319     }
320 
321     /* Please see man pages for details
322 
323 
324 
325 
326 
327     */
FreeV(void * p)328     virtual void FreeV(void* p) { Free(p); }
329 
330 
331     /* Please see man pages for details
332 
333 
334 
335     */
GetUnitSize()336     size_t GetUnitSize() const { return Base::GetUnitSize(); }
337 
338     /* Please see man pages for details
339 
340 
341 
342     */
GetAllocatableCount()343     size_t GetAllocatableCount() const
344     {
345         ScopedLock lk(*this);
346         return Base::GetAllocatableCount();
347     }
348 
349     /* Please see man pages for details
350 
351 
352 
353     */
GetAllocatedCount()354     size_t GetAllocatedCount() const {
355         ScopedLock lk(*this);
356         return Base::GetAllocatedCount();
357     }
358 
359     /* Please see man pages for details
360 
361 
362 
363      */
GetStartAddress()364     virtual void* GetStartAddress() const { return Base::GetStartAddress(); }
365 
366     /* Please see man pages for details
367 
368 
369 
370      */
GetTotalSize()371     virtual size_t GetTotalSize() const { return Base::GetTotalSize(); }
372 
373     /* Please see man pages for details
374 
375 
376 
377      */
Dump()378     virtual void Dump() const
379     {
380         ScopedLock lk(*this);
381         Base::Dump();
382     }
383 
384     /* Please see man pages for details
385 
386 
387 
388 
389 
390     */
HasAddress(const void * addr)391     virtual bool HasAddress(const void* addr) const { return Base::HasAddress(addr); }
392 
393     class Allocator;
394 
395 };
396 
397 /* Please see man pages for details
398 
399  */
400 template <class LockPolicy>
401 class UnitHeapTemplate<LockPolicy>::Allocator : public IAllocator
402 {
403 public:
404 
405     /* Please see man pages for details
406 
407 
408 
409      */
Allocator(UnitHeapTemplate<LockPolicy> & heap)410     Allocator(UnitHeapTemplate<LockPolicy>& heap) : m_Heap(&heap) {}
411 
412     /* Please see man pages for details
413 
414      */
Allocator()415     Allocator() : m_Heap(0) {}
416 
417     /* Please see man pages for details
418 
419 
420 
421      */
Initialize(UnitHeapTemplate<LockPolicy> & heap)422     void Initialize(UnitHeapTemplate<LockPolicy>& heap) { m_Heap = &heap; }
423 
424     /* Please see man pages for details
425 
426 
427      */
GetHeap()428     UnitHeapTemplate<LockPolicy>* GetHeap() { return m_Heap; }
429 
430     /* Please see man pages for details
431 
432 
433      */
GetHeap()434     const UnitHeapTemplate<LockPolicy>* GetHeap() const { return m_Heap; }
435 
436     /* Please see man pages for details
437 
438 
439 
440 
441 
442 
443     */
444     virtual void* Allocate(size_t size, s32 alignment);
445 
446     /* Please see man pages for details
447 
448 
449     */
450     virtual void Free(void* p);
451 
452 private:
453     UnitHeapTemplate<LockPolicy>* m_Heap;
454 };
455 
456 template <class LockPolicy>
Allocate(size_t size,s32 alignment)457 inline void* UnitHeapTemplate<LockPolicy>::Allocator::Allocate(size_t size, s32 alignment)
458 {
459     if (size == m_Heap->m_Unit && alignment >= 0 && m_Heap->m_Alignment % alignment == 0)
460     {
461         return m_Heap->Allocate();
462     }
463     else
464     {
465         return 0;
466     }
467 }
468 
469 template <class LockPolicy>
Free(void * p)470 inline void UnitHeapTemplate<LockPolicy>::Allocator::Free(void* p)
471 {
472     m_Heap->Free(p);
473 }
474 
475 /* Please see man pages for details
476 
477 */
478 typedef UnitHeapTemplate<nn::os::LockPolicy::NoLock> UnitHeap;
479 
480 /* Please see man pages for details
481 
482 */
483 typedef UnitHeapTemplate<nn::os::LockPolicy::Object<nn::os::CriticalSection> > ThreadSafeUnitHeap;
484 
485 template <class LockPolicy>
Create(HeapBase * parent,size_t unit,void * addr,size_t size,s32 alignment,bit32 option,bit32 placement)486 UnitHeapTemplate<LockPolicy>* UnitHeapTemplate<LockPolicy>::Create(HeapBase* parent, size_t unit, void* addr, size_t size, s32 alignment, bit32 option, bit32 placement)
487 {
488     UnitHeapTemplate* heap;
489     if ( parent->FindHeap(addr) != parent ) return 0;
490 
491     if ( placement == HEAP_INFOPLACEMENT_HEAD )
492     {
493         heap = new (addr) UnitHeapTemplate(unit, reinterpret_cast<uptr>(addr)+sizeof(UnitHeapTemplate), static_cast<size_t>(size - sizeof(UnitHeapTemplate)), alignment, option);
494     }
495     else if ( placement == HEAP_INFOPLACEMENT_TAIL )
496     {
497         void* placeaddr = reinterpret_cast<void*>(reinterpret_cast<uptr>(addr)+static_cast<size_t>(size - sizeof(UnitHeapTemplate)));
498         heap = new (placeaddr) UnitHeapTemplate(unit, reinterpret_cast<uptr>(addr), static_cast<size_t>(size - sizeof(UnitHeapTemplate)), alignment, option);
499     }
500     else
501     {
502         return 0;
503     }
504 
505     heap->SetParent(parent);
506     return heap;
507 }
508 
509 }}
510 
511 #endif
512 
513 #endif
514