// Created on: 2005-03-15
// Created by: Peter KURNEV
-// Copyright (c) 2005-2012 OPEN CASCADE SAS
+// Copyright (c) 2005-2014 OPEN CASCADE SAS
//
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
//
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
//
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+#ifdef _WIN32
+#include <windows.h>
+#endif
#include <Standard_MMgrOpt.hxx>
#include <Standard_OutOfMemory.hxx>
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <Standard_Assert.hxx>
#include <stdio.h>
+#include <errno.h>
-#ifdef HAVE_STRING_H
-# include <string.h>
+#ifndef _WIN32
+# include <sys/mman.h> /* mmap() */
#endif
-#ifndef WNT
-# include <stdlib.h>
-# include <errno.h>
-#endif
-
-#ifdef WNT
-#include <windows.h>
-#else
-# ifdef HAVE_UNISTD_H
-# include <unistd.h>
-# endif
-# ifdef HAVE_SYS_MMAN_H
-# include <sys/mman.h> /* mmap() */
-# endif
-#endif
-#ifdef HAVE_MALLOC_H
-# include <malloc.h>
-#endif
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <fcntl.h>
//
#if defined (__sun) || defined(SOLARIS)
extern "C" int getpagesize() ;
#endif
+#ifdef _WIN32
+#include <strsafe.h>
+#endif
//======================================================================
// Assumptions
//======================================================================
#elif defined(__APPLE__)
#define MMAP_BASE_ADDRESS 0x80000000
#define MMAP_FLAGS (MAP_ANON | MAP_PRIVATE)
-#elif defined(LIN)
+#elif defined(__linux__)
#define MMAP_BASE_ADDRESS 0x20000000
#define MMAP_FLAGS (MAP_PRIVATE)
-#elif defined(WNT)
+#elif defined(_WIN32)
//static HANDLE myhMap;
#else
#define MMAP_BASE_ADDRESS 0x60000000
#define ROUNDDOWN_CELL(size) ROUNDDOWN8(size)
#define INDEX_CELL(rsize) ((rsize) >> 3)
-// Minimal granularity: 4 bytes (32-bit systems only)
-#ifndef _OCC64
-//#define ROUNDUP_CELL(size) ROUNDUP4(size)
-//#define INDEX_CELL(rsize) ((rsize) >> 2)
-#endif
-
-// Adaptive granularity, less for little blocks and greater for bigger ones:
-/*
-#if _OCC64
-#define ROUNDUP_CELL(size) ((size) <= 0x40 ? ROUNDUP8(size) : ROUNDUP16(size))
-#define INDEX_CELL(rsize) ((rsize) <= 0x40 ? ((rsize) >> 3) : (4 + ((rsize) >> 4)))
-#else
-#define ROUNDUP_CELL(size) ((size) <= 0x40 ? ROUNDUP4(size) : ROUNDUP8(size))
-#define INDEX_CELL(rsize) ((rsize) <= 0x40 ? ((rsize) >> 2) : (8 + ((rsize) >> 3)))
-#endif
-*/
-
-
/* In the allocated block, first bytes are used for storing of memory manager's data.
(size of block). The minimal size of these data is sizeof(int).
The memory allocated in system usually alligned by 16 bytes.Tthe aligment of the
#define GET_USER(block) (((Standard_Size*)(block)) + BLOCK_SHIFT)
#define GET_BLOCK(storage) (((Standard_Size*)(storage))-BLOCK_SHIFT)
-// create static instance of out-of-memory exception to protect
-// against possible lack of memory for its raising
-static Handle(Standard_OutOfMemory) anOutOfMemError = new Standard_OutOfMemory;
-
//=======================================================================
//function : Standard_MMgr
//purpose :
const Standard_Boolean aMMap,
const Standard_Size aCellSize,
const Standard_Integer aNbPages,
- const Standard_Size aThreshold,
- const Standard_Boolean isReentrant)
+ const Standard_Size aThreshold)
{
// check basic assumption
- if ( sizeof(Standard_Size) != sizeof(Standard_Address) )
- {
- cerr << "Fatal error: Open CASCADE Optimized Memory manager: this platform is not supported!" << endl;
- exit(1);
- }
+ Standard_STATIC_ASSERT(sizeof(Standard_Size) == sizeof(Standard_Address));
// clear buffer fields
myFreeListMax = 0;
myCellSize = aCellSize;
myNbPages = aNbPages;
myThreshold = aThreshold;
- myReentrant = isReentrant;
// initialize
Initialize();
myNbPages = 1000;
// get system-dependent page size
-#ifndef WNT
+#ifndef _WIN32
myPageSize = getpagesize();
if ( ! myPageSize )
myMMap = 0;
perror("ERR_MEMRY_FAIL");
#endif
-#if defined(IRIX) || defined(__sgi) || defined(SOLARIS) || defined(__sun) || defined(LIN) || defined(linux) || defined(__FreeBSD__)
+#if defined(IRIX) || defined(__sgi) || defined(SOLARIS) || defined(__sun) || defined(__linux__) || defined(__FreeBSD__) || defined(__ANDROID__)
if ((myMMap = open ("/dev/zero", O_RDWR)) < 0) {
if ((myMMap = open ("/dev/null", O_RDWR)) < 0){
myMMap = 0;
// The unlock is called as soon as possible, for every treatment case.
// We also do not use Sentry, since in case if OCC signal or exception is
// caused by this block we will have deadlock anyway...
- if (myReentrant) myMutex.Lock();
+ myMutex.Lock();
// if free block of the requested size is available, return it
if ( myFreeList[Index] ) {
myFreeList[Index] = *(Standard_Size**)aBlock;
// unlock the mutex
- if ( myReentrant ) myMutex.Unlock();
+ myMutex.Unlock();
// record size of the allocated block in the block header and
// shift the pointer to the beginning of the user part of block
// else if block size is small allocate it in pools
else if ( RoundSize <= myCellSize ) {
// unlock the mutex for free lists
- if ( myReentrant ) myMutex.Unlock();
+ myMutex.Unlock();
// and lock the specific mutex used to protect access to small blocks pools;
// note that this is done by sentry class so as to ensure unlocking in case of
// possible exception that may be thrown from AllocMemory()
- Standard_Mutex::SentryNested aSentry ( myMutexPools, myReentrant );
+ Standard_Mutex::Sentry aSentry (myMutexPools);
// check for availability of requested space in the current pool
Standard_Size *aBlock = myNextAddr;
const Standard_Size aRPSize = ROUNDDOWN_CELL(aPSize);
const Standard_Size aPIndex = INDEX_CELL(aRPSize);
if ( aPIndex > 0 && aPIndex <= myFreeListMax ) {
- if (myReentrant) myMutex.Lock();
+ myMutex.Lock();
*(Standard_Size**)myNextAddr = myFreeList[aPIndex];
myFreeList[aPIndex] = myNextAddr;
- if (myReentrant) myMutex.Unlock();
+ myMutex.Unlock();
}
}
// blocks of medium size are allocated directly
else {
// unlock the mutex immediately, as we do not need further to access any field
- if ( myReentrant ) myMutex.Unlock();
+ myMutex.Unlock();
// we use operator ?: instead of if() since it is faster
Standard_Size *aBlock = (Standard_Size*) (myClear ? calloc( RoundSizeN+BLOCK_SHIFT, sizeof(Standard_Size)) :
aBlock = (Standard_Size*)calloc(RoundSizeN+BLOCK_SHIFT, sizeof(Standard_Size));
// if still not succeeded, raise exception
if ( ! aBlock )
- anOutOfMemError->Reraise ("Standard_MMgrOpt::Allocate(): malloc failed");
+ throw Standard_OutOfMemory("Standard_MMgrOpt::Allocate(): malloc failed");
}
// initialize new block header by its size
//purpose :
//=======================================================================
-void Standard_MMgrOpt::Free(Standard_Address& theStorage)
+void Standard_MMgrOpt::Free(Standard_Address theStorage)
{
// safely return if attempt to free null pointer
if ( ! theStorage )
// of standard library are already protected by their implementation.
// We also do not use Sentry, since in case if OCC signal or exception is
// caused by this block we will have deadlock anyway...
- if (myReentrant) myMutex.Lock();
+ myMutex.Lock();
// in the memory block header, record address of the next free block
*(Standard_Size**)aBlock = myFreeList[Index];
// add new block to be first in the list
myFreeList[Index] = aBlock;
- if (myReentrant) myMutex.Unlock();
+ myMutex.Unlock();
}
// otherwise, we have block of big size which shall be simply released
else
FreeMemory (aBlock, RoundSize);
-
- theStorage = NULL;
}
//=======================================================================
//purpose : Frees all free lists except small blocks (less than CellSize)
//=======================================================================
-Standard_Integer Standard_MMgrOpt::Purge(Standard_Boolean )//isDeleted)
+Standard_Integer Standard_MMgrOpt::Purge(Standard_Boolean )
{
// Lock access to critical data by mutex
- Standard_Mutex::SentryNested aSentry (myMutex, myReentrant);
+ Standard_Mutex::Sentry aSentry (myMutex);
// TODO: implement support for isDeleted = True
}
// Lock access to critical data by mutex
- Standard_Mutex::SentryNested aSentry1 ( myMutexPools, myReentrant );
+ Standard_Mutex::Sentry aSentry1 (myMutexPools);
// release memory pools containing no busy memory;
// for that for each pool count the summary size of blocks
// got from the free lists allocated from this pool
-#ifndef WNT
+#ifndef _WIN32
const Standard_Size PoolSize = myPageSize * myNbPages;
#else
const Standard_Size PoolSize =
void Standard_MMgrOpt::FreePools()
{
// Lock access to critical data by mutex
- Standard_Mutex::SentryNested aSentry ( myMutexPools, myReentrant );
+ Standard_Mutex::Sentry aSentry (myMutexPools);
// last pool is remembered in myAllocList
Standard_Size * aFree = myAllocList;
//purpose :
//=======================================================================
-Standard_Address Standard_MMgrOpt::Reallocate(Standard_Address& theStorage,
+Standard_Address Standard_MMgrOpt::Reallocate(Standard_Address theStorage,
const Standard_Size theNewSize)
{
+ // if theStorage == NULL, just allocate new memory block
+ if (!theStorage)
+ {
+ return Allocate(theNewSize);
+ }
+
Standard_Size * aBlock = GET_BLOCK(theStorage);
Standard_Address newStorage = NULL;
if ( myClear )
memset(((char*)newStorage) + OldSize, 0, theNewSize-OldSize);
}
- theStorage = NULL;
return newStorage;
}
// if MMap option is ON, allocate using memory mapped files
if (myMMap) {
-#ifndef WNT
+#ifndef _WIN32
// align size to page size
const Standard_Size AlignedSize = PAGE_ALIGN(Size, myPageSize);
if ( Purge(Standard_False) )
goto retry;
// if nothing helps, raise exception
- anOutOfMemError->Reraise (strerror(errcode));
+ throw Standard_OutOfMemory(strerror(errcode));
}
// save actually allocated size into argument
Size = AlignedSize;
-#else /* WNT */
+#else /* _WIN32 */
// align size to page size, taking into account additional space needed to
// store handle to the memory map
PAGE_READWRITE,
DWORD(AlignedSize / 0x80000000),
DWORD(AlignedSize % 0x80000000), NULL);
- HANDLE * aMBlock = NULL;
+ HANDLE * aMBlock = (hMap && GetLastError() != ERROR_ALREADY_EXISTS ?
+ (HANDLE*)MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0) : NULL);
// check for error and try allocating address space
- if ( ! hMap || GetLastError() == ERROR_ALREADY_EXISTS ||
- ! (aMBlock = (HANDLE*)MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0)) )
+ if ( ! aMBlock )
{
// close handle if allocated
if ( hMap )
goto retry;
// if nothing helps, make error message and raise exception
const int BUFSIZE=1024;
- char message[BUFSIZE];
- if ( FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, message, BUFSIZE-1, 0) <=0 )
- strcpy (message, "Standard_MMgrOpt::AllocMemory() failed to mmap");
- anOutOfMemError->Reraise (message);
+
+ wchar_t message[BUFSIZE];
+
+ if ( FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0,
+ message, BUFSIZE-1, 0) <=0 )
+ StringCchCopyW(message, _countof(message), L"Standard_MMgrOpt::AllocMemory() failed to mmap");
+
+ char messageA[BUFSIZE];
+ WideCharToMultiByte(CP_UTF8, 0, message, -1, messageA, sizeof(messageA), NULL, NULL);
+ throw Standard_OutOfMemory(messageA);
}
// record map handle in the beginning
if ( Purge(Standard_False) )
goto retry;
// if nothing helps, raise exception
- anOutOfMemError->Reraise ("Standard_MMgrOpt::Allocate(): malloc failed");
+ throw Standard_OutOfMemory("Standard_MMgrOpt::Allocate(): malloc failed");
}
}
// clear whole block if clearing option is set
void Standard_MMgrOpt::FreeMemory (Standard_Address aBlock,
const Standard_Size
-#ifndef WNT
+#ifndef _WIN32
aSize
#endif
)
{
// release memory (either free or unmap)
if ( myMMap ) {
-#ifndef WNT
+#ifndef _WIN32
// align size to page size, just the same as in AllocMemory()
const Standard_Size AlignedSize = PAGE_ALIGN(aSize, myPageSize);
munmap((char*)aBlock, AlignedSize);
else
free(aBlock);
}
-
-//=======================================================================
-//function : SetReentrant
-//purpose :
-//=======================================================================
-
-void Standard_MMgrOpt::SetReentrant(Standard_Boolean isReentrant)
-{
- myReentrant = isReentrant;
-}