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