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