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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <Standard.ixx>
21 #include <Standard_MMgrOpt.hxx>
22 #include <Standard_MMgrRaw.hxx>
23 #include <Standard_MMgrTBBalloc.hxx>
25 #if(defined(_WIN32) || defined(__WIN32__))
31 #if defined(_MSC_VER) || defined(__ANDROID__)
33 #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
34 #include <mm_malloc.h>
36 extern "C" int posix_memalign (void** thePtr, size_t theAlign, size_t theSize);
39 #ifndef OCCT_MMGT_OPT_DEFAULT
40 #define OCCT_MMGT_OPT_DEFAULT 0
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
52 static Standard_MMgrRoot* GetMMgr();
53 ~Standard_MMgrFactory();
56 Standard_MMgrFactory();
57 Standard_MMgrFactory (const Standard_MMgrFactory&);
58 Standard_MMgrFactory& operator= (const Standard_MMgrFactory&);
61 Standard_MMgrRoot* myFMMgr;
64 //=======================================================================
65 //function : Standard_MMgrFactory
66 //purpose : Check environment variables and create appropriate memory manager
67 //=======================================================================
69 Standard_MMgrFactory::Standard_MMgrFactory()
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!
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);
85 aVar = getenv ("MMGT_OPT");
86 Standard_Integer anAllocId = (aVar ? atoi (aVar): OCCT_MMGT_OPT_DEFAULT);
88 #if defined(_WIN32) && !defined(_WIN64)
89 static const DWORD _SSE2_FEATURE_BIT(0x04000000);
92 // CR25396: Check if SSE2 instructions are supported, if not then use MMgrRaw
93 // instead of MMgrTBBalloc. It is to avoid runtime crash when running on a
94 // CPU that supports SSE but does not support SSE2 (some modifications of
96 DWORD volatile dwFeature;
104 // get the CPU feature bits
114 if ((dwFeature & _SSE2_FEATURE_BIT) == 0)
119 aVar = getenv ("MMGT_CLEAR");
120 Standard_Boolean toClear = (aVar ? (atoi (aVar) != 0) : Standard_True);
122 // on Windows (actual for XP and 2000) activate low fragmentation heap
123 // for CRT heap in order to get best performance.
124 // Environment variable MMGT_LFH can be used to switch off this action (if set to 0)
125 #if defined(_MSC_VER)
126 aVar = getenv ("MMGT_LFH");
127 if ( aVar == NULL || atoi (aVar) != 0 )
130 HANDLE aCRTHeap = (HANDLE)_get_heap_handle();
131 HeapSetInformation (aCRTHeap, HeapCompatibilityInformation, &aHeapInfo, sizeof(aHeapInfo));
137 case 1: // OCCT optimized memory allocator
139 aVar = getenv ("MMGT_MMAP");
140 Standard_Boolean bMMap = (aVar ? (atoi (aVar) != 0) : Standard_True);
141 aVar = getenv ("MMGT_CELLSIZE");
142 Standard_Integer aCellSize = (aVar ? atoi (aVar) : 200);
143 aVar = getenv ("MMGT_NBPAGES");
144 Standard_Integer aNbPages = (aVar ? atoi (aVar) : 1000);
145 aVar = getenv ("MMGT_THRESHOLD");
146 Standard_Integer aThreshold = (aVar ? atoi (aVar) : 40000);
147 myFMMgr = new Standard_MMgrOpt (toClear, bMMap, aCellSize, aNbPages, aThreshold);
150 case 2: // TBB memory allocator
151 myFMMgr = new Standard_MMgrTBBalloc (toClear);
154 default: // system default memory allocator
155 myFMMgr = new Standard_MMgrRaw (toClear);
159 //=======================================================================
160 //function : ~Standard_MMgrFactory
162 //=======================================================================
164 Standard_MMgrFactory::~Standard_MMgrFactory()
167 myFMMgr->Purge(Standard_True);
170 //=======================================================================
173 // This static function has a purpose to wrap static holder for memory
176 // Wrapping holder inside a function is needed to ensure that it will
177 // be initialized not later than the first call to memory manager (that
178 // would be impossible to guarantee if holder was static variable on
179 // global or file scope, because memory manager may be called from
180 // constructors of other static objects).
182 // Note that at the same time we could not guarantee that the holder
183 // object is destroyed after last call to memory manager, since that
184 // last call may be from static Handle() object which has been initialized
185 // dynamically during program execution rather than in its constructor.
187 // Therefore holder currently does not call destructor of the memory manager
188 // but only its method Purge() with Standard_True.
190 // To free the memory completely, we probably could use compiler-specific
191 // pragmas (such as '#pragma fini' on SUN Solaris and '#pragma init_seg' on
192 // WNT MSVC++) to put destructing function in code segment that is called
193 // after destructors of other (even static) objects. However, this is not
194 // done by the moment since it is compiler-dependent and there is no guarantee
195 // thatsome other object calling memory manager is not placed also in that segment...
197 // Note that C runtime function atexit() could not help in this problem
198 // since its behaviour is the same as for destructors of static objects
199 // (see ISO 14882:1998 "Programming languages -- C++" 3.6.3)
201 // The correct approach to deal with the problem would be to have memory manager
202 // to properly control its memory allocation and caching free blocks so
203 // as to release all memory as soon as it is returned to it, and probably
204 // even delete itself if all memory it manages has been released and
205 // last call to method Purge() was with True.
207 // Note that one possible method to control memory allocations could
208 // be counting calls to Allocate() and Free()...
210 //=======================================================================
211 Standard_MMgrRoot* Standard_MMgrFactory::GetMMgr()
213 static Standard_MMgrFactory aFactory;
214 return aFactory.myFMMgr;
217 //=======================================================================
218 //function : Allocate
220 //=======================================================================
222 Standard_Address Standard::Allocate(const Standard_Size size)
224 return Standard_MMgrFactory::GetMMgr()->Allocate(size);
227 //=======================================================================
230 //=======================================================================
232 void Standard::Free (Standard_Address theStorage)
234 Standard_MMgrFactory::GetMMgr()->Free(theStorage);
237 //=======================================================================
238 //function : Reallocate
240 //=======================================================================
242 Standard_Address Standard::Reallocate (Standard_Address theStorage,
243 const Standard_Size theSize)
245 return Standard_MMgrFactory::GetMMgr()->Reallocate (theStorage, theSize);
248 //=======================================================================
251 //=======================================================================
253 Standard_Integer Standard::Purge()
255 return Standard_MMgrFactory::GetMMgr()->Purge();
258 //=======================================================================
259 //function : AllocateAligned
261 //=======================================================================
263 Standard_Address Standard::AllocateAligned (const Standard_Size theSize,
264 const Standard_Size theAlign)
266 #if defined(_MSC_VER)
267 return _aligned_malloc (theSize, theAlign);
268 #elif defined(__ANDROID__)
269 return memalign (theAlign, theSize);
270 #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
271 return _mm_malloc (theSize, theAlign);
274 if (posix_memalign (&aPtr, theAlign, theSize))
282 //=======================================================================
283 //function : FreeAligned
285 //=======================================================================
287 void Standard::FreeAligned (Standard_Address thePtrAligned)
289 #if defined(_MSC_VER)
290 _aligned_free (thePtrAligned);
291 #elif defined(__ANDROID__)
292 free (thePtrAligned);
293 #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
294 _mm_free (thePtrAligned);
296 free (thePtrAligned);