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