1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: fnd_FrameHeap.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: 24310 $
14 *---------------------------------------------------------------------------*/
15
16 /* Please see man pages for details
17
18
19 */
20
21 #ifndef NN_FND_FND_FRAMEHEAP_H_
22 #define NN_FND_FND_FRAMEHEAP_H_
23
24 #include <nn/types.h>
25 #include <nn/fnd/fnd_Allocator.h>
26 #include <nn/fnd/fnd_HeapBase.h>
27 #include <nn/fnd/fnd_MemoryRange.h>
28 #include <nn/Assert.h>
29 #include <nn/os.h>
30
31 #ifdef __cplusplus
32
33 #define NN_FND_FRAMEHEAP_FREE_HEAD 1
34 #define NN_FND_FRAMEHEAP_FREE_TAIL 2
35 #define NN_FND_FRAMEHEAP_FREE_ALL (NN_FND_FRAMEHEAP_FREE_HEAD | NN_FND_FRAMEHEAP_FREE_TAIL)
36
37 #define NN_FND_FRAMEHEAP_ADJUST_TAIL 1
38 #define NN_FND_FRAMEHEAP_ADJUST_HEAD -1
39
40 namespace nn { namespace fnd {
41
42 /* Please see man pages for details
43
44
45
46 */
47 class FrameHeapBase : public HeapBase
48 {
49 public:
50
51 class State;
52
53 protected:
54
FrameHeapBase()55 FrameHeapBase() : m_Addr(0) {}
56
57 FrameHeapBase(uptr addr, size_t size, bit32 option = 0) : m_Addr(0) { Initialize(addr, size, option); }
58
59 template <class MemoryBlock>
60 FrameHeapBase(const MemoryBlock& block, bit32 option = 0) : m_Addr(0) { Initialize(block.GetAddress(), block.GetSize(), option); }
61
62 void Initialize(uptr addr, size_t size, bit32 option = 0);
63
Finalize()64 void Finalize() { m_Addr = 0; }
65
~FrameHeapBase()66 virtual ~FrameHeapBase() { Finalize(); }
67
68 void* Allocate(size_t size, s32 alignment);
69
70 size_t ResizeBlock(void* p, size_t newSize);
71
72 void FreeAll(int mode);
73
FreeV(void *)74 virtual void FreeV(void*) {}
75
76 State SaveState();
77
78 void RestoreState(State state);
79
80 MemoryRange Adjust(int mode);
81
82 size_t GetAllocatableSize(s32 alignment) const;
83
GetStartAddress()84 virtual void* GetStartAddress() const { return reinterpret_cast<void*>(m_Addr); }
85
GetTotalSize()86 virtual size_t GetTotalSize() const { return m_Size; }
87
88 virtual void Dump() const;
89
90 virtual bool HasAddress(const void* addr) const;
91
92 private:
93 uptr m_Addr;
94 size_t m_Size;
95 uptr m_CurrentHead;
96 uptr m_CurrentTail;
97 };
98
99 /* Please see man pages for details
100
101 */
102 class FrameHeapBase::State
103 {
104 public:
105
106 /* Please see man pages for details
107
108
109
110 */
State(FrameHeapBase & heap)111 explicit State(FrameHeapBase& heap) : m_Head(heap.m_CurrentHead), m_Tail(heap.m_CurrentTail) {}
112
113 /* Please see man pages for details
114
115 */
State()116 State() : m_Head(0), m_Tail(0) {}
117
118 private:
119 uptr m_Head;
120 uptr m_Tail;
121
State(uptr head,uptr tail)122 explicit State(uptr head, uptr tail) : m_Head(head), m_Tail(tail) {}
123
124 friend class FrameHeapBase;
125 };
126
Allocate(size_t size,s32 alignment)127 inline void* FrameHeapBase::Allocate(size_t size, s32 alignment)
128 {
129 NN_TASSERT_(size > 0);
130 NN_TASSERT_(alignment != 0);
131 uptr ret;
132
133 if ( alignment == 0 )
134 {
135 NN_TPANIC_("invalid argument: alignment == 0");
136 }
137
138 if ( alignment > 0 ) {
139 ret = RoundUp(m_CurrentHead, alignment);
140 uptr current = ret + size;
141
142 if (current > m_CurrentTail)
143 {
144 return 0;
145 }
146
147 m_CurrentHead = current;
148 }
149 else
150 {
151 uptr current = ret = RoundDown(m_CurrentTail-size, -alignment);
152
153 if (current < m_CurrentHead)
154 {
155 return 0;
156 }
157
158 m_CurrentTail = current;
159 }
160
161
162 // Fill options
163 DebugFillMemory(ret, size, HEAP_FILL_TYPE_ALLOC);
164 FillMemoryZero(ret, size);
165
166 return reinterpret_cast<void*>(ret);
167 }
168
FreeAll(int mode)169 inline void FrameHeapBase::FreeAll(int mode)
170 {
171 NN_TASSERT_( mode == NN_FND_FRAMEHEAP_FREE_HEAD ||
172 mode == NN_FND_FRAMEHEAP_FREE_TAIL ||
173 mode == NN_FND_FRAMEHEAP_FREE_ALL);
174
175 if ( mode & NN_FND_FRAMEHEAP_FREE_HEAD )
176 {
177 DebugFillMemory(m_Addr, m_CurrentHead - m_Addr, HEAP_FILL_TYPE_FREE);
178 this->m_CurrentHead = this->m_Addr;
179 }
180
181 if ( mode & NN_FND_FRAMEHEAP_FREE_TAIL )
182 {
183 DebugFillMemory(m_CurrentTail, m_Addr + m_Size - m_CurrentTail, HEAP_FILL_TYPE_FREE);
184 this->m_CurrentTail = this->m_Addr + this->m_Size;
185 }
186 }
187
ResizeBlock(void * p,size_t newSize)188 inline size_t FrameHeapBase::ResizeBlock(void* p, size_t newSize)
189 {
190 // TODO: debug_fill
191 uptr& addr = reinterpret_cast<uptr&>(p);
192 NN_TASSERT_(m_Addr <= addr && addr < m_CurrentTail);
193 NN_TASSERT_(addr <= m_CurrentHead);
194 uptr current = addr + newSize;
195 if (current < m_CurrentTail)
196 {
197 if ( current < this->m_CurrentHead )
198 {
199 DebugFillMemory(current, this->m_CurrentHead - current, HEAP_FILL_TYPE_FREE);
200 }
201 if ( this->m_CurrentHead < current )
202 {
203 FillMemoryZero(this->m_CurrentHead, current - this->m_CurrentHead);
204 }
205 this->m_CurrentHead = current;
206 return newSize;
207 }
208 else
209 {
210 return 0;
211 }
212 }
213
Adjust(int mode)214 inline MemoryRange FrameHeapBase::Adjust(int mode)
215 {
216 // TODO: debug_fill
217 if ( mode == 0 )
218 {
219 NN_TPANIC_("invalid argument: mode == 0");
220 }
221
222 if ( mode > 0 )
223 {
224 if ( m_CurrentTail != m_Addr + m_Size )
225 {
226 NN_TPANIC_("invalid call: tail used");
227 }
228
229 DebugFillMemory(m_CurrentHead, m_Addr + m_Size - m_CurrentHead, HEAP_FILL_TYPE_FREE);
230
231 uptr oldtail = m_Addr + m_Size;
232 this->m_Size = m_CurrentHead - m_Addr;
233 this->m_CurrentTail = m_CurrentHead;
234 return MemoryRange(this->m_CurrentTail, oldtail);
235 }
236 else
237 {
238 if ( m_CurrentHead != m_Addr )
239 {
240 NN_TPANIC_("invalid call: head used");
241 }
242
243 DebugFillMemory(m_Addr, m_CurrentTail - m_Addr, HEAP_FILL_TYPE_FREE);
244
245 uptr oldhead = m_Addr;
246 this->m_Size = m_Addr + m_Size - m_CurrentTail;
247 this->m_CurrentHead = m_CurrentTail;
248 this->m_Addr = m_CurrentTail;
249 return MemoryRange(oldhead, m_Addr);
250 }
251 }
252
SaveState()253 inline FrameHeapBase::State FrameHeapBase::SaveState()
254 {
255 return State(m_CurrentHead, m_CurrentTail);
256 }
257
RestoreState(FrameHeapBase::State state)258 inline void FrameHeapBase::RestoreState(FrameHeapBase::State state)
259 {
260 NN_TASSERT_(this->m_Addr <= state.m_Head && state.m_Head <= this->m_Addr + this->m_Size);
261 NN_TASSERT_(this->m_Addr <= state.m_Tail && state.m_Tail <= this->m_Addr + this->m_Size);
262 NN_TASSERT_(state.m_Head <= this->m_CurrentHead);
263 NN_TASSERT_(state.m_Tail >= this->m_CurrentTail);
264
265 this->m_CurrentHead = state.m_Head;
266 this->m_CurrentTail = state.m_Tail;
267
268 DebugFillMemory(m_CurrentHead, m_CurrentTail - m_CurrentHead, HEAP_FILL_TYPE_FREE);
269 }
270
GetAllocatableSize(s32 alignment)271 inline size_t FrameHeapBase::GetAllocatableSize(s32 alignment) const
272 {
273 NN_TASSERT_(alignment != 0);
274
275 if ( alignment == 0 )
276 {
277 NN_TPANIC_("invalid argument: alignment == 0");
278 }
279
280 if ( alignment < 0 )
281 {
282 alignment = -alignment;
283 }
284
285 uptr addr = RoundUp(m_CurrentHead, alignment);
286 if (addr <= m_CurrentTail)
287 {
288 return m_CurrentTail - addr;
289 }
290 else
291 {
292 return 0;
293 }
294 }
295
HasAddress(const void * addr)296 inline bool FrameHeapBase::HasAddress(const void* addr) const
297 {
298 return m_Addr <= reinterpret_cast<uptr>(addr)
299 && reinterpret_cast<uptr>(addr) < (m_Addr+m_Size);
300 }
301
302 /* Please see man pages for details
303
304
305
306
307
308
309
310
311
312
313
314
315 */
316 template <class LockPolicy>
317 class FrameHeapTemplate : public FrameHeapBase, private LockPolicy::LockObject
318 {
319 private:
320 typedef FrameHeapBase Base;
321 typedef typename LockPolicy::LockObject LockObject;
322 typedef typename LockPolicy::ScopedLock ScopedLock;
323 public:
324
325 /* Please see man pages for details
326
327 */
FrameHeapTemplate()328 FrameHeapTemplate() {}
329
330 /* Please see man pages for details
331
332
333
334
335
336 */
337 FrameHeapTemplate(uptr addr, size_t size, bit32 option = 0) { Initialize(addr, size, option); }
338
339 /* Please see man pages for details
340
341
342
343
344 */
345 template <class MemoryBlock>
346 FrameHeapTemplate(const MemoryBlock& block, bit32 option = 0) { Initialize(block.GetAddress(), block.GetSize(), option); }
347
348 /* Please see man pages for details
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368 */
369 static FrameHeapTemplate* Create(HeapBase* parent, void* addr, size_t size, bit32 option = 0, bit32 placement = HEAP_INFOPLACEMENT_HEAD);
370
371 /* Please see man pages for details
372
373
374
375
376
377
378
379 */
380 void Initialize(uptr addr, size_t size, bit32 option = 0)
381 {
382 Base::Initialize(addr, size, option);
383 LockObject::Initialize();
384 }
385
386 /* Please see man pages for details
387
388
389
390 */
Finalize()391 void Finalize()
392 {
393 LockObject::Finalize();
394 Base::Finalize();
395 }
396
397 /* Please see man pages for details
398
399
400
401 */
~FrameHeapTemplate()402 virtual ~FrameHeapTemplate() {}
403
404 /* Please see man pages for details
405
406
407
408
409
410
411
412
413 */
414 void* Allocate(size_t size, s32 alignment = DEFAULT_ALIGNMENT)
415 {
416 ScopedLock lk(*this);
417 return Base::Allocate(size, alignment);
418 }
419
420 /* Please see man pages for details
421
422
423
424
425
426
427
428
429 */
ResizeBlock(void * p,size_t newSize)430 size_t ResizeBlock(void* p, size_t newSize)
431 {
432 ScopedLock lk(*this);
433 return Base::ResizeBlock(p, newSize);
434 }
435
436 /* Please see man pages for details
437
438
439
440
441
442
443
444
445
446
447
448 */
449 void Free(int mode = NN_FND_FRAMEHEAP_FREE_ALL)
450 {
451 ScopedLock lk(*this);
452 Base::FreeAll(mode);
453 }
454
455 /* Please see man pages for details
456
457
458
459
460
461 */
FreeV(void *)462 virtual void FreeV(void*) { NN_TASSERT_(0); }
463
464 class ScopedFrame;
465
466 /* Please see man pages for details
467
468
469
470 */
SaveState()471 State SaveState()
472 {
473 ScopedLock lk(*this);
474 return Base::SaveState();
475 }
476
477 /* Please see man pages for details
478
479
480
481
482
483 */
RestoreState(State state)484 void RestoreState(State state)
485 {
486 ScopedLock lk(*this);
487 Base::RestoreState(state);
488 }
489
490 /* Please see man pages for details
491
492
493
494
495
496
497
498
499
500
501
502 */
503 MemoryRange Adjust(int mode = NN_FND_FRAMEHEAP_ADJUST_TAIL)
504 {
505 ScopedLock lk(*this);
506 return Base::Adjust(mode);
507 }
508
509 /* Please see man pages for details
510
511
512
513
514
515 */
516 size_t GetAllocatableSize(s32 alignment = DEFAULT_ALIGNMENT) const
517 {
518 ScopedLock lk(*this);
519 return Base::GetAllocatableSize(alignment);
520 }
521
522 /* Please see man pages for details
523
524
525
526 */
GetStartAddress()527 virtual void* GetStartAddress() const
528 {
529 ScopedLock lk(*this);
530 return Base::GetStartAddress();
531 }
532
533 /* Please see man pages for details
534
535
536
537 */
GetTotalSize()538 virtual size_t GetTotalSize() const
539 {
540 ScopedLock lk(*this);
541 return Base::GetTotalSize();
542 }
543
544 /* Please see man pages for details
545
546
547
548
549
550 */
HasAddress(const void * addr)551 virtual bool HasAddress(const void* addr) const
552 {
553 ScopedLock lk(*this);
554 return Base::HasAddress(addr);
555 }
556
557 /* Please see man pages for details
558
559
560
561 */
Dump()562 virtual void Dump() const { Base::Dump(); };
563
564 // FrameHeap allocator is not supported
565 //class Allocator;
566
567 private:
568 uptr m_Addr;
569 size_t m_Size;
570 uptr m_CurrentHead; // First address of the available region
571 uptr m_CurrentTail; // Last address of the available region + 4
572 bit32 m_Option;
573 };
574
575 /* Please see man pages for details
576
577 */
578 template <class LockPolicy>
579 class FrameHeapTemplate<LockPolicy>::ScopedFrame
580 {
581 public:
582 /* Please see man pages for details
583
584
585
586 */
ScopedFrame(FrameHeapTemplate<LockPolicy> & heap)587 explicit ScopedFrame(FrameHeapTemplate<LockPolicy>& heap) : m_State(heap), m_Heap(heap) {}
588 /* Please see man pages for details
589
590 */
~ScopedFrame()591 ~ScopedFrame() { m_Heap.RestoreState(m_State); }
592
593 private:
594 FrameHeapTemplate<LockPolicy>::State m_State;
595 FrameHeapTemplate<LockPolicy>& m_Heap;
596 };
597
598 /* Please see man pages for details
599
600 */
601 typedef FrameHeapTemplate<nn::os::LockPolicy::NoLock> FrameHeap;
602
603 /* Please see man pages for details
604
605 */
606 typedef FrameHeapTemplate<nn::os::LockPolicy::Object<nn::os::CriticalSection> > ThreadSafeFrameHeap;
607
608 template <class LockPolicy>
Create(HeapBase * parent,void * addr,size_t size,bit32 option,bit32 placement)609 FrameHeapTemplate<LockPolicy>* FrameHeapTemplate<LockPolicy>::Create(HeapBase* parent, void* addr, size_t size, bit32 option, bit32 placement)
610 {
611 FrameHeapTemplate* heap;
612
613 if ( parent->FindHeap(addr) != parent ) return 0;
614
615 if ( placement == HEAP_INFOPLACEMENT_HEAD )
616 {
617 heap = new (addr) FrameHeapTemplate(reinterpret_cast<uptr>(addr)+sizeof(FrameHeapTemplate), static_cast<size_t>(size - sizeof(FrameHeapTemplate)), option);
618 }
619 else if ( placement == HEAP_INFOPLACEMENT_TAIL )
620 {
621 void* placeaddr = reinterpret_cast<void*>(reinterpret_cast<uptr>(addr)+static_cast<size_t>(size - sizeof(FrameHeapTemplate)));
622 heap = new (placeaddr) FrameHeapTemplate(reinterpret_cast<uptr>(addr), static_cast<size_t>(size - sizeof(FrameHeapTemplate)), option);
623 }
624 else
625 {
626 return 0;
627 }
628
629 heap->SetParent(parent);
630 return heap;
631 }
632
633 }}
634
635 #endif
636
637 #endif
638