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