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