1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00

0023988: Force use of reentrant mode

Reentrant mode switch is eliminated
This commit is contained in:
szv 2013-05-24 09:26:45 +04:00
parent 310659466b
commit bd0c22ce9f
13 changed files with 30 additions and 135 deletions

@ -49,7 +49,6 @@
#include <OSD_Timer.hxx> #include <OSD_Timer.hxx>
#include <Transfer_TransferOutput.hxx> #include <Transfer_TransferOutput.hxx>
#include <ShapeExtend_Explorer.hxx> #include <ShapeExtend_Explorer.hxx>
#include <Message_ProgressSentry.hxx>
#include <Message_Messenger.hxx> #include <Message_Messenger.hxx>
#include <Transfer_ActorOfTransientProcess.hxx> #include <Transfer_ActorOfTransientProcess.hxx>
#include <IGESToBRep_Actor.hxx> #include <IGESToBRep_Actor.hxx>

@ -208,8 +208,6 @@ static Standard_Integer incrementalmesh(Draw_Interpretor& di, Standard_Integer n
di << "Incremental Mesh, multi-threading " di << "Incremental Mesh, multi-threading "
<< (isInParallel ? "ON\n" : "OFF\n"); << (isInParallel ? "ON\n" : "OFF\n");
Standard::SetReentrant(isInParallel);
BRepMesh_IncrementalMesh MESH(aShape, aDeflection, Standard_False, 0.5, isInParallel); BRepMesh_IncrementalMesh MESH(aShape, aDeflection, Standard_False, 0.5, isInParallel);
Standard_Integer statusFlags = MESH.GetStatusFlags(); Standard_Integer statusFlags = MESH.GetStatusFlags();

@ -529,8 +529,6 @@ static int mpparallel (Draw_Interpretor& di, Standard_Integer argc, const char**
{ {
Standard_Boolean isParallelOn = Draw::Atoi (argv[1]) == 1; Standard_Boolean isParallelOn = Draw::Atoi (argv[1]) == 1;
BRepMesh_IncrementalMesh::SetParallelDefault (isParallelOn); BRepMesh_IncrementalMesh::SetParallelDefault (isParallelOn);
if (isParallelOn)
Standard::SetReentrant(Standard_True);
} }
std::cout << "Incremental Mesh, multi-threading " std::cout << "Incremental Mesh, multi-threading "
<< (BRepMesh_IncrementalMesh::IsParallelDefault() ? "ON\n" : "OFF\n"); << (BRepMesh_IncrementalMesh::IsParallelDefault() ? "ON\n" : "OFF\n");

@ -183,9 +183,7 @@ void NCollection_BaseAllocator::StandardCallBack
const Standard_Size /*theSize*/) const Standard_Size /*theSize*/)
{ {
static Standard_Mutex aMutex; static Standard_Mutex aMutex;
Standard_Boolean isReentrant = Standard::IsReentrant(); aMutex.Lock();
if (isReentrant)
aMutex.Lock();
// statistics by storage size // statistics by storage size
NCollection_DataMap<Standard_Size, StorageInfo>& aStMap = StorageMap(); NCollection_DataMap<Standard_Size, StorageInfo>& aStMap = StorageMap();
if (!aStMap.IsBound(theRoundSize)) if (!aStMap.IsBound(theRoundSize))
@ -230,8 +228,7 @@ void NCollection_BaseAllocator::StandardCallBack
} }
} }
if (isReentrant) aMutex.Unlock();
aMutex.Unlock();
} }
//======================================================================= //=======================================================================

@ -98,13 +98,10 @@ static Standard_Size CATCH_ID = 0;
static void Debug_Create(Standard_Address theAlloc) static void Debug_Create(Standard_Address theAlloc)
{ {
static Standard_Mutex aMutex; static Standard_Mutex aMutex;
Standard_Boolean isReentrant = Standard::IsReentrant(); aMutex.Lock();
if (isReentrant)
aMutex.Lock();
StorageIDMap().Bind(theAlloc, ++CurrentID); StorageIDMap().Bind(theAlloc, ++CurrentID);
StorageIDSet().Add(CurrentID); StorageIDSet().Add(CurrentID);
if (isReentrant) aMutex.Unlock();
aMutex.Unlock();
if (CurrentID == CATCH_ID) if (CurrentID == CATCH_ID)
{ {
// Place for break point for creation of investigated allocator // Place for break point for creation of investigated allocator
@ -120,17 +117,14 @@ static void Debug_Create(Standard_Address theAlloc)
static void Debug_Destroy(Standard_Address theAlloc) static void Debug_Destroy(Standard_Address theAlloc)
{ {
static Standard_Mutex aMutex; static Standard_Mutex aMutex;
Standard_Boolean isReentrant = Standard::IsReentrant(); aMutex.Lock();
if (isReentrant)
aMutex.Lock();
if (StorageIDMap().IsBound(theAlloc)) if (StorageIDMap().IsBound(theAlloc))
{ {
Standard_Size anID = StorageIDMap()(theAlloc); Standard_Size anID = StorageIDMap()(theAlloc);
StorageIDSet().Remove(anID); StorageIDSet().Remove(anID);
StorageIDMap().UnBind(theAlloc); StorageIDMap().UnBind(theAlloc);
} }
if (isReentrant) aMutex.Unlock();
aMutex.Unlock();
} }
//======================================================================= //=======================================================================

@ -153,24 +153,4 @@ is
-- and clears the list. -- and clears the list.
-- Returns non-zero if some memory has been actually freed. -- Returns non-zero if some memory has been actually freed.
IsReentrant returns Boolean from Standard;
---Purpose: Returns boolean flag indicating whether OCCT is
-- operating in reentrant mode. This flag affects OCCT
-- memory manager, exception and signal handling,
-- operations with handles etc., making them thread-safe.
--
-- By default, this flag is set to False, in order
-- to avoid performance reduction due to locking.
--
-- In multithreaded applications this flag must be set to
-- True, either by calling method SetReentrant(),
-- or by defining environment variable MMGT_REENTRANT.
SetReentrant (isReentrant: Boolean from Standard);
---Purpose: Sets boolean flag indicating whether OCCT is
-- operating in reentrant mode.
-- See method IsReentrant() for more information.
-- Note: This method may be called only when no any other
-- thread using OCCT exists
end Standard; end Standard;

@ -38,9 +38,6 @@
#define OCCT_MMGT_OPT_DEFAULT 0 #define OCCT_MMGT_OPT_DEFAULT 0
#endif #endif
// Global reentrant flag
static Standard_Boolean Standard_IsReentrant = Standard_True;
//======================================================================= //=======================================================================
//class : Standard_MMgrFactory //class : Standard_MMgrFactory
//purpose : Container for pointer to memory manager; //purpose : Container for pointer to memory manager;
@ -94,10 +91,6 @@ Standard_MMgrFactory::Standard_MMgrFactory()
} }
#endif #endif
aVar = getenv ("MMGT_REENTRANT");
if ( aVar != NULL )
Standard_IsReentrant = (atoi (aVar) != 0);
switch (anAllocId) switch (anAllocId)
{ {
case 1: // OCCT optimized memory allocator case 1: // OCCT optimized memory allocator
@ -106,7 +99,7 @@ Standard_MMgrFactory::Standard_MMgrFactory()
Standard_Integer aCellSize = (aVar = getenv ("MMGT_CELLSIZE" )) ? atoi (aVar) : 200; Standard_Integer aCellSize = (aVar = getenv ("MMGT_CELLSIZE" )) ? atoi (aVar) : 200;
Standard_Integer aNbPages = (aVar = getenv ("MMGT_NBPAGES" )) ? atoi (aVar) : 1000; Standard_Integer aNbPages = (aVar = getenv ("MMGT_NBPAGES" )) ? atoi (aVar) : 1000;
Standard_Integer aThreshold = (aVar = getenv ("MMGT_THRESHOLD")) ? atoi (aVar) : 40000; Standard_Integer aThreshold = (aVar = getenv ("MMGT_THRESHOLD")) ? atoi (aVar) : 40000;
myFMMgr = new Standard_MMgrOpt (toClear, bMMap, aCellSize, aNbPages, aThreshold, Standard_IsReentrant); myFMMgr = new Standard_MMgrOpt (toClear, bMMap, aCellSize, aNbPages, aThreshold);
break; break;
} }
case 2: // TBB memory allocator case 2: // TBB memory allocator
@ -220,24 +213,3 @@ Standard_Integer Standard::Purge()
{ {
return GetMMgr()->Purge(); return GetMMgr()->Purge();
} }
//=======================================================================
//function : IsReentrant
//purpose :
//=======================================================================
Standard_Boolean Standard::IsReentrant()
{
return Standard_IsReentrant;
}
//=======================================================================
//function : SetReentrant
//purpose :
//=======================================================================
void Standard::SetReentrant (const Standard_Boolean isReentrant)
{
Standard_IsReentrant = isReentrant;
GetMMgr()->SetReentrant (isReentrant);
}

@ -68,12 +68,10 @@ Standard_ErrorHandler::Standard_ErrorHandler () :
{ {
myThread = GetThreadID(); myThread = GetThreadID();
if (Standard::IsReentrant()) theMutex.Lock();
theMutex.Lock();
myPrevious = Top; myPrevious = Top;
Top = this; Top = this;
if (Standard::IsReentrant()) theMutex.Unlock();
theMutex.Unlock();
} }
@ -100,8 +98,7 @@ void Standard_ErrorHandler::Destroy()
void Standard_ErrorHandler::Unlink() void Standard_ErrorHandler::Unlink()
{ {
// put a lock on the stack // put a lock on the stack
if (Standard::IsReentrant()) theMutex.Lock();
theMutex.Lock();
Standard_ErrorHandler* aPrevious = 0; Standard_ErrorHandler* aPrevious = 0;
Standard_ErrorHandler* aCurrent = Top; Standard_ErrorHandler* aCurrent = Top;
@ -113,8 +110,7 @@ void Standard_ErrorHandler::Unlink()
} }
if(aCurrent==0) { if(aCurrent==0) {
if (Standard::IsReentrant()) theMutex.Unlock();
theMutex.Unlock();
return; return;
} }
@ -126,8 +122,7 @@ void Standard_ErrorHandler::Unlink()
aPrevious->myPrevious=aCurrent->myPrevious; aPrevious->myPrevious=aCurrent->myPrevious;
} }
myPrevious = 0; myPrevious = 0;
if (Standard::IsReentrant()) theMutex.Unlock();
theMutex.Unlock();
// unlink and destroy all registered callbacks // unlink and destroy all registered callbacks
Standard_Address aPtr = aCurrent->myCallbackPtr; Standard_Address aPtr = aCurrent->myCallbackPtr;
@ -226,8 +221,7 @@ Standard_ErrorHandler* Standard_ErrorHandler::FindHandler(const Standard_Handler
const Standard_Boolean theUnlink) const Standard_Boolean theUnlink)
{ {
// lock the stack // lock the stack
if (Standard::IsReentrant()) theMutex.Lock();
theMutex.Lock();
// Find the current ErrorHandler Accordin tread // Find the current ErrorHandler Accordin tread
Standard_ErrorHandler* aPrevious = 0; Standard_ErrorHandler* aPrevious = 0;
@ -272,8 +266,7 @@ Standard_ErrorHandler* Standard_ErrorHandler::FindHandler(const Standard_Handler
aStop = Standard_True; aStop = Standard_True;
} }
} }
if (Standard::IsReentrant()) theMutex.Unlock();
theMutex.Unlock();
return anActive; return anActive;
} }

@ -189,8 +189,7 @@ Standard_MMgrOpt::Standard_MMgrOpt(const Standard_Boolean aClear,
const Standard_Boolean aMMap, const Standard_Boolean aMMap,
const Standard_Size aCellSize, const Standard_Size aCellSize,
const Standard_Integer aNbPages, const Standard_Integer aNbPages,
const Standard_Size aThreshold, const Standard_Size aThreshold)
const Standard_Boolean isReentrant)
{ {
// check basic assumption // check basic assumption
if ( sizeof(Standard_Size) != sizeof(Standard_Address) ) if ( sizeof(Standard_Size) != sizeof(Standard_Address) )
@ -213,7 +212,6 @@ Standard_MMgrOpt::Standard_MMgrOpt(const Standard_Boolean aClear,
myCellSize = aCellSize; myCellSize = aCellSize;
myNbPages = aNbPages; myNbPages = aNbPages;
myThreshold = aThreshold; myThreshold = aThreshold;
myReentrant = isReentrant;
// initialize // initialize
Initialize(); Initialize();
@ -364,7 +362,7 @@ Standard_Address Standard_MMgrOpt::Allocate(const Standard_Size aSize)
// The unlock is called as soon as possible, for every treatment case. // 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 // We also do not use Sentry, since in case if OCC signal or exception is
// caused by this block we will have deadlock anyway... // 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 free block of the requested size is available, return it
if ( myFreeList[Index] ) { if ( myFreeList[Index] ) {
@ -375,7 +373,7 @@ Standard_Address Standard_MMgrOpt::Allocate(const Standard_Size aSize)
myFreeList[Index] = *(Standard_Size**)aBlock; myFreeList[Index] = *(Standard_Size**)aBlock;
// unlock the mutex // unlock the mutex
if ( myReentrant ) myMutex.Unlock(); myMutex.Unlock();
// record size of the allocated block in the block header and // record size of the allocated block in the block header and
// shift the pointer to the beginning of the user part of block // shift the pointer to the beginning of the user part of block
@ -389,12 +387,12 @@ Standard_Address Standard_MMgrOpt::Allocate(const Standard_Size aSize)
// else if block size is small allocate it in pools // else if block size is small allocate it in pools
else if ( RoundSize <= myCellSize ) { else if ( RoundSize <= myCellSize ) {
// unlock the mutex for free lists // 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; // 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 // note that this is done by sentry class so as to ensure unlocking in case of
// possible exception that may be thrown from AllocMemory() // possible exception that may be thrown from AllocMemory()
Standard_Mutex::Sentry aSentry (myReentrant ? &myMutexPools : NULL); Standard_Mutex::Sentry aSentry (myMutexPools);
// check for availability of requested space in the current pool // check for availability of requested space in the current pool
Standard_Size *aBlock = myNextAddr; Standard_Size *aBlock = myNextAddr;
@ -410,10 +408,10 @@ Standard_Address Standard_MMgrOpt::Allocate(const Standard_Size aSize)
const Standard_Size aRPSize = ROUNDDOWN_CELL(aPSize); const Standard_Size aRPSize = ROUNDDOWN_CELL(aPSize);
const Standard_Size aPIndex = INDEX_CELL(aRPSize); const Standard_Size aPIndex = INDEX_CELL(aRPSize);
if ( aPIndex > 0 && aPIndex <= myFreeListMax ) { if ( aPIndex > 0 && aPIndex <= myFreeListMax ) {
if (myReentrant) myMutex.Lock(); myMutex.Lock();
*(Standard_Size**)myNextAddr = myFreeList[aPIndex]; *(Standard_Size**)myNextAddr = myFreeList[aPIndex];
myFreeList[aPIndex] = myNextAddr; myFreeList[aPIndex] = myNextAddr;
if (myReentrant) myMutex.Unlock(); myMutex.Unlock();
} }
} }
@ -438,7 +436,7 @@ Standard_Address Standard_MMgrOpt::Allocate(const Standard_Size aSize)
// blocks of medium size are allocated directly // blocks of medium size are allocated directly
else { else {
// unlock the mutex immediately, as we do not need further to access any field // 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 // we use operator ?: instead of if() since it is faster
Standard_Size *aBlock = (Standard_Size*) (myClear ? calloc( RoundSizeN+BLOCK_SHIFT, sizeof(Standard_Size)) : Standard_Size *aBlock = (Standard_Size*) (myClear ? calloc( RoundSizeN+BLOCK_SHIFT, sizeof(Standard_Size)) :
@ -509,14 +507,14 @@ void Standard_MMgrOpt::Free(Standard_Address& theStorage)
// of standard library are already protected by their implementation. // of standard library are already protected by their implementation.
// We also do not use Sentry, since in case if OCC signal or exception is // We also do not use Sentry, since in case if OCC signal or exception is
// caused by this block we will have deadlock anyway... // 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 // in the memory block header, record address of the next free block
*(Standard_Size**)aBlock = myFreeList[Index]; *(Standard_Size**)aBlock = myFreeList[Index];
// add new block to be first in the list // add new block to be first in the list
myFreeList[Index] = aBlock; myFreeList[Index] = aBlock;
if (myReentrant) myMutex.Unlock(); myMutex.Unlock();
} }
// otherwise, we have block of big size which shall be simply released // otherwise, we have block of big size which shall be simply released
else else
@ -530,10 +528,10 @@ void Standard_MMgrOpt::Free(Standard_Address& theStorage)
//purpose : Frees all free lists except small blocks (less than CellSize) //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 // Lock access to critical data by mutex
Standard_Mutex::Sentry aSentry (myReentrant ? &myMutex : NULL); Standard_Mutex::Sentry aSentry (myMutex);
// TODO: implement support for isDeleted = True // TODO: implement support for isDeleted = True
@ -553,7 +551,7 @@ Standard_Integer Standard_MMgrOpt::Purge(Standard_Boolean )//isDeleted)
} }
// Lock access to critical data by mutex // Lock access to critical data by mutex
Standard_Mutex::Sentry aSentry1 (myReentrant ? &myMutexPools : NULL); Standard_Mutex::Sentry aSentry1 (myMutexPools);
// release memory pools containing no busy memory; // release memory pools containing no busy memory;
// for that for each pool count the summary size of blocks // for that for each pool count the summary size of blocks
@ -696,7 +694,7 @@ Standard_Integer Standard_MMgrOpt::Purge(Standard_Boolean )//isDeleted)
void Standard_MMgrOpt::FreePools() void Standard_MMgrOpt::FreePools()
{ {
// Lock access to critical data by mutex // Lock access to critical data by mutex
Standard_Mutex::Sentry aSentry (myReentrant ? &myMutexPools : NULL); Standard_Mutex::Sentry aSentry (myMutexPools);
// last pool is remembered in myAllocList // last pool is remembered in myAllocList
Standard_Size * aFree = myAllocList; Standard_Size * aFree = myAllocList;
@ -873,13 +871,3 @@ void Standard_MMgrOpt::FreeMemory (Standard_Address aBlock,
else else
free(aBlock); free(aBlock);
} }
//=======================================================================
//function : SetReentrant
//purpose :
//=======================================================================
void Standard_MMgrOpt::SetReentrant(Standard_Boolean isReentrant)
{
myReentrant = isReentrant;
}

@ -95,8 +95,7 @@ class Standard_MMgrOpt : public Standard_MMgrRoot
const Standard_Boolean aMMap = Standard_True, const Standard_Boolean aMMap = Standard_True,
const Standard_Size aCellSize = 200, const Standard_Size aCellSize = 200,
const Standard_Integer aNbPages = 10000, const Standard_Integer aNbPages = 10000,
const Standard_Size aThreshold = 40000, const Standard_Size aThreshold = 40000);
const Standard_Boolean isReentrant = Standard_False);
//! Frees all free lists and pools allocated for small blocks //! Frees all free lists and pools allocated for small blocks
Standard_EXPORT virtual ~Standard_MMgrOpt(); Standard_EXPORT virtual ~Standard_MMgrOpt();
@ -118,11 +117,6 @@ class Standard_MMgrOpt : public Standard_MMgrRoot
//! Returns number of actually freed blocks //! Returns number of actually freed blocks
Standard_EXPORT virtual Standard_Integer Purge(Standard_Boolean isDestroyed); Standard_EXPORT virtual Standard_Integer Purge(Standard_Boolean isDestroyed);
//! Set reentrant mode on or off.
//! Note: This method may be called only when no any other thread can
//! access this object simultaneously
Standard_EXPORT virtual void SetReentrant(Standard_Boolean isReentrant);
//! Declaration of a type pointer to the callback function that //! Declaration of a type pointer to the callback function that
//! should accept the following arguments: <br> //! should accept the following arguments: <br>
//! theIsAlloc - true if the data is allocated, false if it is freed; <br> //! theIsAlloc - true if the data is allocated, false if it is freed; <br>
@ -174,7 +168,6 @@ protected:
Standard_Mutex myMutex; //!< Mutex to protect free lists data Standard_Mutex myMutex; //!< Mutex to protect free lists data
Standard_Mutex myMutexPools; //!< Mutex to protect small block pools data Standard_Mutex myMutexPools; //!< Mutex to protect small block pools data
Standard_Boolean myReentrant; //!< Use mutex to provide correct reentrant behaviour
}; };
#endif #endif

@ -39,12 +39,3 @@ Standard_Integer Standard_MMgrRoot::Purge(Standard_Boolean)
{ {
return 0; return 0;
} }
//=======================================================================
//function : SetReentrant
//purpose :
//=======================================================================
void Standard_MMgrRoot::SetReentrant(Standard_Boolean)
{
}

@ -74,12 +74,6 @@ class Standard_MMgrRoot
//! //!
//! Default implementation does nothing and returns 0. //! Default implementation does nothing and returns 0.
Standard_EXPORT virtual Standard_Integer Purge(Standard_Boolean isDestroyed=Standard_False); Standard_EXPORT virtual Standard_Integer Purge(Standard_Boolean isDestroyed=Standard_False);
//! Set reentrant mode on or off.
//! Note: This method may be called only when no any other thread can
//! access this object simultaneously.
//! Default implementation does nothing.
Standard_EXPORT virtual void SetReentrant(Standard_Boolean isReentrant);
}; };
#endif #endif

@ -98,10 +98,8 @@ static Standard_Integer writestl
Standard_Boolean isInParallel = Standard_False; Standard_Boolean isInParallel = Standard_False;
if (argc > 3) { if (argc > 3) {
isASCIIMode = (Draw::Atoi(argv[3]) == 0); isASCIIMode = (Draw::Atoi(argv[3]) == 0);
if (argc > 4) { if (argc > 4)
isInParallel = (Draw::Atoi(argv[4]) == 1); isInParallel = (Draw::Atoi(argv[4]) == 1);
Standard::SetReentrant(isInParallel);
}
} }
StlAPI_Writer aWriter; StlAPI_Writer aWriter;
aWriter.ASCIIMode() = isASCIIMode; aWriter.ASCIIMode() = isASCIIMode;