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