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