1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: init_Alloc.cpp
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: 46347 $
14 *---------------------------------------------------------------------------*/
15
16 //---------------------------------------------------------------------------
17
18 #include <new>
19 #include <nn/Result.h>
20 #include <nn/config.h>
21 #include <nn/assert.h>
22 #include <nn/fnd.h>
23 #include <nn/init/init_Allocator.h>
24 #include <nn/os/os_LockPolicy.h>
25 #include <nn/os/os_Memory.h>
26 #include <nn/os/os_MemoryMapSelect.h>
27 #include <nn/os/os_CriticalSection.h>
28 #include <nn/svc/svc_stub.h>
29 #include <nn/util/util_Result.h>
30 #include <nn/util/util_TypeTraits.h>
31
32 #include <algorithm>
33 #include <cstring>
34
35 using namespace nn::os;
36
37 typedef nn::fnd::ExpHeapTemplate<nn::os::LockPolicy::Object<nn::os::CriticalSection> > SystemExpHeap;
38
39 namespace
40 {
41 SystemExpHeap* s_pSystemHeap = 0; //
42 nn::util::aligned_storage<sizeof(SystemExpHeap::Allocator), nn::util::alignment_of<SystemExpHeap::Allocator>::value >::type s_SystemAllocatorBuffer;
43 SystemExpHeap::Allocator* s_pSystemAllocator = 0; //<! Allocator for the system heap
44
45 #if NN_PLATFORM_HAS_MMU
46 nnosMemoryBlock s_HeapMemoryBlock;
47 #endif // if NN_PLATFORM_HAS_MMU
48 }
49
50 extern "C"{
51
malloc(size_t size)52 NN_WEAK_SYMBOL void* malloc(size_t size)
53 {
54 return s_pSystemHeap->Allocate(size);
55 }
56
free(void * p)57 NN_WEAK_SYMBOL void free(void* p)
58 {
59 if (p)
60 {
61 s_pSystemHeap->Free(p);
62 }
63 }
64
calloc(size_t num,size_t size)65 NN_WEAK_SYMBOL void* calloc(size_t num, size_t size)
66 {
67 size_t sum = num * size;
68 void* p = std::malloc(sum);
69
70 if( p != NULL )
71 {
72 std::memset(p, 0, sum);
73 }
74
75 return p;
76 }
77
realloc(void * p,size_t size)78 NN_WEAK_SYMBOL void* realloc(void* p, size_t size)
79 {
80 if( p != NULL )
81 {
82 // If the size is 0, it only frees
83 if( size == 0 )
84 {
85 std::free(p);
86 return NULL;
87 }
88
89 // If can be handled by changing the size of the memory block, do so
90 //
91 size_t newSize = s_pSystemHeap->ResizeBlock(p, size);
92
93 if( newSize != 0 )
94 {
95 return p;
96 }
97
98 // If it could not be handled, allocate and copy in addition
99 void* newMem = std::malloc(size);
100
101 if( newMem != NULL )
102 {
103 size_t oldSize = s_pSystemHeap->GetSizeOf(p);
104 std::memcpy(newMem, p, std::min(size, oldSize));
105 std::free(p);
106 }
107
108 return newMem;
109 }
110 else
111 {
112 // If p is NULL, only do malloc
113 return std::malloc(size);
114 }
115 }
116
117 } // extern "C"
118
119
operator new(size_t size,const::std::nothrow_t &)120 NN_WEAK_SYMBOL void* operator new (size_t size, const ::std::nothrow_t&) throw()
121 {
122 return std::malloc(size);
123 }
124
operator new[](size_t size,const::std::nothrow_t &)125 NN_WEAK_SYMBOL void* operator new[] (size_t size, const ::std::nothrow_t&) throw()
126 {
127 return operator new(size, ::std::nothrow_t());
128 }
129
operator delete(void * p)130 NN_WEAK_SYMBOL void operator delete (void* p) throw()
131 {
132 std::free(p);
133 }
134
operator delete[](void * p)135 NN_WEAK_SYMBOL void operator delete[] (void* p) throw()
136 {
137 operator delete(p);
138 }
139
140 //NN_WEAK_SYMBOL void operator delete (void* p, const ::std::nothrow_t&) throw()
141 //{
142 // if( p != 0 )
143 // {
144 // free(p);
145 // }
146 //}
147
148 //NN_WEAK_SYMBOL void operator delete[] (void* p, const ::std::nothrow_t&) throw()
149 //{
150 // if( p != 0 )
151 // {
152 // free(p);
153 // }
154 //}
155
156 namespace nn { namespace init {
157
158 // Note
159 // Some of these peripheral functions are called from initStartup.
160 // Because initStartup is called before static initializer, if a non-POD class static object is initialized by these peripheral functions, it will be reinitialized with static initializer and not run properly.
161 //
162 //
163 // Implement with aligned_storage + placement new.
164
165 // Create system heap
InitializeAllocator(uptr addr,size_t size)166 void InitializeAllocator(uptr addr, size_t size)
167 {
168 NN_TASSERT_(size >= sizeof(SystemExpHeap));
169 const size_t alignment = nn::util::alignment_of<SystemExpHeap>::value;
170 uptr heapAddr = (((addr - 1) / alignment) + 1) * alignment;
171 uptr headAddr = heapAddr + sizeof(SystemExpHeap);
172 s_pSystemHeap = new (reinterpret_cast<void*>(heapAddr)) SystemExpHeap(headAddr, addr + size - headAddr);
173 s_pSystemAllocator = new (&s_SystemAllocatorBuffer) SystemExpHeap::Allocator(*s_pSystemHeap);
174 }
175
176 #if NN_PLATFORM_HAS_MMU
InitializeAllocator(size_t size)177 void InitializeAllocator(size_t size)
178 {
179 nnosMemoryBlockAllocate(&s_HeapMemoryBlock, size);
180 NN_TASSERT_(nnosMemoryBlockGetSize(&s_HeapMemoryBlock) == size);
181 InitializeAllocator(nnosMemoryBlockGetAddress(&s_HeapMemoryBlock), size);
182 }
183 #endif // if NN_PLATFORM_HAS_MMU
184
GetAllocator(void)185 nn::fnd::IAllocator* GetAllocator(void)
186 {
187 return s_pSystemAllocator;
188 }
189
190 }} // namespace nn::init
191
192