0027801: Configuration - fix compilation of Standard.cxx when using MinGW-W64
[occt.git] / src / Standard / Standard.cxx
1 // Created on: 2005-03-15
2 // Created by: Peter KURNEV
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <Standard.hxx>
19 #include <Standard_MMgrOpt.hxx>
20 #include <Standard_MMgrRaw.hxx>
21 #include <Standard_MMgrTBBalloc.hxx>
22 #include <Standard_Assert.hxx>
23
24 #include <stdlib.h>
25 #if(defined(_WIN32) || defined(__WIN32__))
26   #include <windows.h>
27   #include <malloc.h>
28   #include <locale.h>
29 #endif
30
31 #if defined(_MSC_VER) || defined(__ANDROID__) || defined(__QNX__)
32   #include <malloc.h>
33 #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && (defined(__i386) || defined(__x86_64)))
34   #include <mm_malloc.h>
35 #else
36   extern "C" int posix_memalign (void** thePtr, size_t theAlign, size_t theSize);
37 #endif
38
39 #ifndef OCCT_MMGT_OPT_DEFAULT
40 #define OCCT_MMGT_OPT_DEFAULT 0
41 #endif
42
43 //=======================================================================
44 //class    : Standard_MMgrFactory 
45 //purpose  : Container for pointer to memory manager;
46 //           used to construct appropriate memory manager according
47 //           to environment settings, and to ensure destruction upon exit
48 //=======================================================================
49 class Standard_MMgrFactory
50 {
51 public:
52   static Standard_MMgrRoot* GetMMgr();
53   ~Standard_MMgrFactory();
54
55 private:
56   Standard_MMgrFactory();
57   Standard_MMgrFactory (const Standard_MMgrFactory&);
58   Standard_MMgrFactory& operator= (const Standard_MMgrFactory&);
59
60 private:
61   Standard_MMgrRoot* myFMMgr;
62 };
63
64 //=======================================================================
65 //function : Standard_MMgrFactory
66 //purpose  : Check environment variables and create appropriate memory manager
67 //=======================================================================
68
69 Standard_MMgrFactory::Standard_MMgrFactory()
70 : myFMMgr (NULL)
71 {
72 /*#if defined(_MSC_VER) && (_MSC_VER > 1400)
73   // Turn ON thread-safe C locale globally to avoid side effects by setlocale() calls between threads.
74   // After this call all following _configthreadlocale() will be ignored assuming
75   // Notice that this is MSVCRT feature - on POSIX systems xlocale API (uselocale instead of setlocale)
76   // should be used explicitly to ensure thread-safety!
77
78   // This is not well documented call because _ENABLE_PER_THREAD_LOCALE_GLOBAL flag is defined but not implemented for some reason.
79   // -1 will set global locale flag to force _ENABLE_PER_THREAD_LOCALE_GLOBAL + _ENABLE_PER_THREAD_LOCALE_NEW behaviour
80   // although there NO way to turn it off again and following calls will have no effect (locale will be changed only for current thread).
81   _configthreadlocale (-1);
82 #endif*/
83
84   // Check basic assumption.
85   // If assertion happens, then OCCT should be corrected for compatibility with such CPU architecture.
86   Standard_STATIC_ASSERT(sizeof(Standard_Utf8Char)  == 1);
87   Standard_STATIC_ASSERT(sizeof(short) == 2);
88   Standard_STATIC_ASSERT(sizeof(Standard_Utf16Char) == 2);
89   Standard_STATIC_ASSERT(sizeof(Standard_Utf32Char) == 4);
90
91   char* aVar;
92   aVar = getenv ("MMGT_OPT");
93   Standard_Integer anAllocId   = (aVar ?  atoi (aVar): OCCT_MMGT_OPT_DEFAULT);
94
95 #if defined(_WIN32) && !defined(_WIN64) && !defined(__MINGW32__)
96   static const DWORD _SSE2_FEATURE_BIT(0x04000000);
97   if ( anAllocId == 2 )
98   {
99     // CR25396: Check if SSE2 instructions are supported, if not then use MMgrRaw
100     // instead of MMgrTBBalloc. It is to avoid runtime crash when running on a 
101     // CPU that supports SSE but does not support SSE2 (some modifications of
102     // AMD Sempron).
103     DWORD volatile dwFeature;
104     _asm
105     {
106       push eax
107       push ebx
108       push ecx
109       push edx
110
111       // get the CPU feature bits
112       mov eax, 1
113       cpuid
114       mov dwFeature, edx
115
116       pop edx
117       pop ecx
118       pop ebx
119       pop eax
120     }
121     if ((dwFeature & _SSE2_FEATURE_BIT) == 0)
122       anAllocId = 0;
123   }
124 #endif
125
126   aVar = getenv ("MMGT_CLEAR");
127   Standard_Boolean toClear     = (aVar ? (atoi (aVar) != 0) : Standard_True);
128
129   // on Windows (actual for XP and 2000) activate low fragmentation heap
130   // for CRT heap in order to get best performance.
131   // Environment variable MMGT_LFH can be used to switch off this action (if set to 0)
132 #if defined(_MSC_VER)
133   aVar = getenv ("MMGT_LFH");
134   if ( aVar == NULL || atoi (aVar) != 0 )
135   {
136     ULONG aHeapInfo = 2;
137     HANDLE aCRTHeap = (HANDLE)_get_heap_handle();
138     HeapSetInformation (aCRTHeap, HeapCompatibilityInformation, &aHeapInfo, sizeof(aHeapInfo));
139   }
140 #endif
141
142   switch (anAllocId)
143   {
144     case 1:  // OCCT optimized memory allocator
145     {
146       aVar = getenv ("MMGT_MMAP");
147       Standard_Boolean bMMap       = (aVar ? (atoi (aVar) != 0) : Standard_True);
148       aVar = getenv ("MMGT_CELLSIZE");
149       Standard_Integer aCellSize   = (aVar ?  atoi (aVar) : 200);
150       aVar = getenv ("MMGT_NBPAGES");
151       Standard_Integer aNbPages    = (aVar ?  atoi (aVar) : 1000);
152       aVar = getenv ("MMGT_THRESHOLD");
153       Standard_Integer aThreshold  = (aVar ?  atoi (aVar) : 40000);
154       myFMMgr = new Standard_MMgrOpt (toClear, bMMap, aCellSize, aNbPages, aThreshold);
155       break;
156     }
157     case 2:  // TBB memory allocator
158       myFMMgr = new Standard_MMgrTBBalloc (toClear);
159       break;
160     case 0:
161     default: // system default memory allocator
162       myFMMgr = new Standard_MMgrRaw (toClear);
163   }
164 }
165
166 //=======================================================================
167 //function : ~Standard_MMgrFactory
168 //purpose  : 
169 //=======================================================================
170
171 Standard_MMgrFactory::~Standard_MMgrFactory()
172 {
173   if (  myFMMgr )
174     myFMMgr->Purge(Standard_True);
175 }
176
177 //=======================================================================
178 // function: GetMMgr
179 //
180 // This static function has a purpose to wrap static holder for memory 
181 // manager instance. 
182 //
183 // Wrapping holder inside a function is needed to ensure that it will
184 // be initialized not later than the first call to memory manager (that
185 // would be impossible to guarantee if holder was static variable on 
186 // global or file scope, because memory manager may be called from 
187 // constructors of other static objects).
188 //
189 // Note that at the same time we could not guarantee that the holder 
190 // object is destroyed after last call to memory manager, since that 
191 // last call may be from static Handle() object which has been initialized
192 // dynamically during program execution rather than in its constructor.
193 //
194 // Therefore holder currently does not call destructor of the memory manager 
195 // but only its method Purge() with Standard_True.
196 //
197 // To free the memory completely, we probably could use compiler-specific 
198 // pragmas (such as '#pragma fini' on SUN Solaris and '#pragma init_seg' on 
199 // WNT MSVC++) to put destructing function in code segment that is called
200 // after destructors of other (even static) objects. However, this is not 
201 // done by the moment since it is compiler-dependent and there is no guarantee 
202 // thatsome other object calling memory manager is not placed also in that segment...
203 //
204 // Note that C runtime function atexit() could not help in this problem 
205 // since its behaviour is the same as for destructors of static objects 
206 // (see ISO 14882:1998 "Programming languages -- C++" 3.6.3)
207 //
208 // The correct approach to deal with the problem would be to have memory manager 
209 // to properly control its memory allocation and caching free blocks so 
210 // as to release all memory as soon as it is returned to it, and probably
211 // even delete itself if all memory it manages has been released and 
212 // last call to method Purge() was with True.
213 //
214 // Note that one possible method to control memory allocations could
215 // be counting calls to Allocate() and Free()...
216 //
217 //=======================================================================
218 Standard_MMgrRoot* Standard_MMgrFactory::GetMMgr()
219 {
220   static Standard_MMgrFactory aFactory;
221   return aFactory.myFMMgr;
222 }
223
224 //=======================================================================
225 //function : Allocate
226 //purpose  : 
227 //=======================================================================
228
229 Standard_Address Standard::Allocate(const Standard_Size size)
230 {
231   return Standard_MMgrFactory::GetMMgr()->Allocate(size);
232 }
233
234 //=======================================================================
235 //function : Free
236 //purpose  : 
237 //=======================================================================
238
239 void Standard::Free (Standard_Address theStorage)
240 {
241   Standard_MMgrFactory::GetMMgr()->Free(theStorage);
242 }
243
244 //=======================================================================
245 //function : Reallocate
246 //purpose  : 
247 //=======================================================================
248
249 Standard_Address Standard::Reallocate (Standard_Address theStorage,
250                                        const Standard_Size theSize)
251 {
252   return Standard_MMgrFactory::GetMMgr()->Reallocate (theStorage, theSize);
253 }
254
255 //=======================================================================
256 //function : Purge
257 //purpose  : 
258 //=======================================================================
259
260 Standard_Integer Standard::Purge()
261 {
262   return Standard_MMgrFactory::GetMMgr()->Purge();
263 }
264
265 //=======================================================================
266 //function : AllocateAligned
267 //purpose  :
268 //=======================================================================
269
270 Standard_Address Standard::AllocateAligned (const Standard_Size theSize,
271                                             const Standard_Size theAlign)
272 {
273 #if defined(_MSC_VER)
274   return _aligned_malloc (theSize, theAlign);
275 #elif defined(__ANDROID__) || defined(__QNX__)
276   return memalign (theAlign, theSize);
277 #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && (defined(__i386) || defined(__x86_64)))
278   return _mm_malloc (theSize, theAlign);
279 #else
280   void* aPtr;
281   if (posix_memalign (&aPtr, theAlign, theSize))
282   {
283     return NULL;
284   }
285   return aPtr;
286 #endif
287 }
288
289 //=======================================================================
290 //function : FreeAligned
291 //purpose  :
292 //=======================================================================
293
294 void Standard::FreeAligned (Standard_Address thePtrAligned)
295 {
296 #if defined(_MSC_VER)
297   _aligned_free (thePtrAligned);
298 #elif defined(__ANDROID__) || defined(__QNX__)
299   free (thePtrAligned);
300 #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && (defined(__i386) || defined(__x86_64)))
301   _mm_free (thePtrAligned);
302 #else
303   free (thePtrAligned);
304 #endif
305 }