Free Electron
src/platform/memory.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __platform_memory_h__
8 #define __platform_memory_h__
9 
10 #if FE_OS==FE_WIN32 || FE_OS==FE_WIN64
11 // NOTE Windows currently being forced to use FE_ALLOC_RAW
12 //#define FE_EXPORT_MEM_VIA_FUNC
13 #else
14 #define FE_EXPORT_MEM_VIA_FUNC
15 #endif
16 
17 #if FE_CODEGEN<=FE_DEBUG
18 #define FE_CHECK_NEW TRUE
19 #else
20 #define FE_CHECK_NEW FALSE
21 #endif
22 
23 //* HACK something with amd64, multi-processor, or a bug causes malloc on stack
24 //* or maybe multi-threaded stacks can reside on either side of the heap
25 #if defined(__x86_64__) || defined(__aarch64__)
26 #define FE_HEAP_CHECKABLE FALSE
27 #else
28 #define FE_HEAP_CHECKABLE FE_CHECK_NEW
29 #endif
30 
31 // isn't required to be the same as FE_CHECK_NEW
32 #if FE_CODEGEN<=FE_DEBUG
33 #define FE_CHECK_HEAP FE_HEAP_CHECKABLE
34 #else
35 #define FE_CHECK_HEAP FALSE
36 #endif
37 
38 #define FE_LOCK_MEMORY (FE_CHECK_HEAP || FE_CHECK_NEW)
39 
40 #ifndef FE_MEM_ALIGNMENT
41 #if FE_SSE!=0
42 #define FE_MEM_ALIGNMENT 16
43 #else
44 #define FE_MEM_ALIGNMENT 0
45 #endif
46 #endif
47 
48 //* delete per-class mutex with last instance of class
49 //* not doing this can cause a python crash shutting down model_view
50 #if FE_OS==FE_WIN32 || FE_OS==FE_WIN64 || defined(__clang__)
51 #define FE_SAFE_COUNTED_MUTEX FALSE
52 #else
53 #define FE_SAFE_COUNTED_MUTEX TRUE
54 #endif
55 
56 namespace fe
57 {
58 
59 extern "C"
60 {
61 
62 typedef void* ( FE_CDECL allocateFunction )( FE_UWORD byteCount );
63 typedef void ( FE_CDECL deallocateFunction )( void* pMemory );
64 typedef void* ( FE_CDECL reallocateFunction )( void* pMemory, FE_UWORD byteCount );
65 typedef void ( FE_CDECL printFunction )( const char* pAscii );
66 
67 } /* extern "C" */
68 
69 #if FE_COMPILER==FE_DMC
70 extern allocateFunction* gs_pAllocateFunction;
71 extern deallocateFunction* gs_pDeallocateFunction;
72 extern reallocateFunction* gs_pReallocateFunction;
73 extern printFunction* gs_pPrintFunction;
74 extern void* gs_pHeapBase;
75 extern I32 gs_newCheck;
76 #else
77 FE_MEM_PORT extern allocateFunction* gs_pAllocateFunction;
78 FE_MEM_PORT extern deallocateFunction* gs_pDeallocateFunction;
79 FE_MEM_PORT extern reallocateFunction* gs_pReallocateFunction;
80 FE_MEM_PORT extern printFunction* gs_pPrintFunction;
81 FE_MEM_PORT extern void* gs_pHeapBase;
82 FE_MEM_PORT extern I32 gs_newCheck;
83 #endif
84 
85 FE_MEM_PORT void * FE_CDECL ex_allocate(FE_UWORD byteCount);
86 FE_MEM_PORT void * FE_CDECL ex_reallocate(void *pMemory, FE_UWORD byteCount);
87 FE_MEM_PORT void FE_CDECL ex_deallocate(void *pMemory);
88 
89 extern "C"
90 {
91 
92 inline
93 void* allocate( FE_UWORD byteCount )
94 {
95 #ifdef FE_ALLOC_RAW
96  return malloc(byteCount);
97 #endif
98 #ifdef FE_EXPORT_MEM_VIA_FUNC
99  return ex_allocate(byteCount);
100 #else
101  return gs_pAllocateFunction( byteCount );
102 #endif
103 }
104 
105 
106 inline
107 void deallocate( void* pMemory )
108 {
109 // assert( gs_pDeallocateFunction );
110 #ifdef FE_ALLOC_RAW
111  free(pMemory);
112  return;
113 #endif
114 
115 #ifdef FE_EXPORT_MEM_VIA_FUNC
116  ex_deallocate(pMemory);
117 #else
118  gs_pDeallocateFunction( pMemory );
119 #endif
120 }
121 
122 inline
123 void* reallocate( void* pMemory, FE_UWORD byteCount )
124 {
125 #ifdef FE_ALLOC_RAW
126  return realloc(pMemory, byteCount);
127 #endif
128 #ifdef FE_EXPORT_MEM_VIA_FUNC
129  return ex_reallocate(pMemory, byteCount);
130 #else
131  return gs_pReallocateFunction( pMemory, byteCount );
132 #endif
133 }
134 
135 } /* extern "C" */
136 
137 /** @brief Basic memory management
138  */
139 class FE_DL_PUBLIC Memory
140 {
141  public:
142 static bool isHeap(void* pPtr);
143 static bool isHeapOrCannotTell(void* pPtr);
144 static bool newWorks(void);
145 
146 #if FE_SAFE_COUNTED_MUTEX
147 static void markForDeath(Mutex*& a_rpMutex,I32* a_pCount);
148 static void markForDeath(RecursiveMutex*& a_rpMutex,I32* a_pCount);
149 static void clearDeadPool(void);
150 #endif
151 
152 #if FE_LOCK_MEMORY
153 #if FE_SAFE_COUNTED_MUTEX
154 static I32 ms_mutexCount;
155 static RecursiveMutex* ms_pMutex;
156 #else
157 static RecursiveMutex ms_mutex;
158 #endif
159 #endif
160  private:
161 
162 #if FE_SAFE_COUNTED_MUTEX
163  class CountedMutex
164  {
165  public:
166  CountedMutex(Mutex*& a_rpMutex,I32* a_pCount)
167  {
168  m_ppMutex= &a_rpMutex;
169  m_pCount=a_pCount;
170  }
171  CountedMutex(RecursiveMutex*& a_rpMutex,I32* a_pCount)
172  {
173  m_ppMutex= reinterpret_cast<Mutex**>(&a_rpMutex);
174  m_pCount=a_pCount;
175  }
176  Mutex** m_ppMutex;
177  I32* m_pCount;
178  };
179 
180 static std::vector<CountedMutex> ms_deadPool;
181 #endif
182 };
183 
184 #if !FE_CHECK_HEAP
185 inline bool Memory::isHeap(void* pPtr)
186 {
187  return false;
188 }
189 #elif FE_OS==FE_LINUX
190 inline bool Memory::isHeap(void* pPtr)
191 {
192  U8 current_stack;
193 // fe_printf("Memory::isHeap %p<%p\n",pPtr,(void*)&current_stack);
194  return pPtr < (void*)&current_stack;
195 }
196 #elif FE_OS==FE_WIN32 || FE_OS==FE_WIN64
197 inline bool Memory::isHeap(void* pPtr)
198 {
199 /* TODO try
200  HANDLE heap=GetProcessHeap();
201  return HeapValidate(heap,0x0,pPtr);
202 */
203 
204  // what was wrong with this one?
205 // return _CrtIsValidHeapPointer(pPtr);
206 
207  // not 64-bit compatible
208  return pPtr >= gs_pHeapBase;
209 }
210 #elif FE_OS==FE_OSX
211 inline bool Memory::isHeap(void* pPtr)
212 {
213  U8 current_stack;
214 // fe_printf("Memory::isHeap %p<%p\n",pPtr,(void*)&current_stack);
215  return pPtr < (void*)&current_stack;
216 }
217 #else
218 #error Memory::isHeap not implemented
219 #endif
220 
221 inline bool Memory::newWorks(void)
222 {
223 #if FE_CHECK_NEW
224  if(!gs_newCheck)
225  {
226  char* byte=new char();
227  delete byte;
228  gs_newCheck=gs_pHeapBase? 1: -1;
229  }
230  return gs_newCheck>0;
231 #else
232  return false;
233 #endif
234 }
235 
236 inline bool Memory::isHeapOrCannotTell(void* pPtr)
237 {
238 #if FE_CHECK_HEAP
239  return !newWorks() || Memory::isHeap(pPtr);
240 #else
241  return true;
242 #endif
243 }
244 
245 FE_DL_EXPORT void FE_CDECL setAllocateFunction(allocateFunction *p_fn);
246 FE_DL_EXPORT void FE_CDECL setDeallocateFunction(deallocateFunction *p_fn);
247 FE_DL_EXPORT void FE_CDECL setPrintFunction(printFunction *p_fn);
248 
249 } /* namespace */
250 
251 #if FALSE
252 inline void* _cdecl operator new( size_t byteCount )
253 { return fe::allocate( byteCount ); }
254 inline void* _cdecl operator new[]( size_t byteCount )
255 { return operator new( byteCount ); }
256 
257 inline void _cdecl operator delete( void* pMemory )
258 { fe::deallocate( pMemory ); }
259 inline void _cdecl operator delete[]( void* pMemory )
260 { operator delete( pMemory ); }
261 #endif
262 
263 //* NOTE ISO C++1z does not allow dynamic exception specifications
264 #if (FE_COMPILER==FE_GNU && __GNUC__>6) || (defined(__clang__) && FE_CPLUSPLUS >= 201703L)
265 #define FE_NO_DYNAMIC_EXCEPTIONS 1
266 #else
267 #define FE_NO_DYNAMIC_EXCEPTIONS 0
268 #endif
269 
270 #ifndef FE_USE_HOST_NEW
271 #if !defined(__clang__)
272 void* FE_CDECL operator new( size_t byteCount );
273 void* FE_CDECL operator new[]( size_t byteCount );
274 void FE_CDECL operator delete( void* pMemory );
275 void FE_CDECL operator delete[]( void* pMemory );
276 #elif FE_CPLUSPLUS >= 201703L
277 void* FE_CDECL operator new( size_t byteCount ) noexcept(false);
278 void* FE_CDECL operator new[]( size_t byteCount ) noexcept(false);
279 void FE_CDECL operator delete( void* pMemory ) throw ();
280 void FE_CDECL operator delete[]( void* pMemory ) throw ();
281 #else
282 void* FE_CDECL operator new( size_t byteCount ) throw (std::bad_alloc);
283 void* FE_CDECL operator new[]( size_t byteCount ) throw (std::bad_alloc);
284 void FE_CDECL operator delete( void* pMemory ) throw ();
285 void FE_CDECL operator delete[]( void* pMemory ) throw ();
286 #endif
287 #endif
288 
289 #endif /* __platform_memory_h__ */
290 
kernel
Definition: namespace.dox:3
Basic memory management.
Definition: src/platform/memory.h:139