Moved OpenThreads directly into OpenSceneGraph/trunk rather than being introduced via svn:externals.
This change has been done to make it easier for OpenSceneGraph users to check out the svn via https without any conflicts introduced with a http externals.
This commit is contained in:
parent
73b87274b0
commit
323ce02f23
100
include/OpenThreads/Barrier
Normal file
100
include/OpenThreads/Barrier
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Barrier - C++ barrier class
|
||||||
|
// ~~~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _OPENTHREADS_BARRIER_
|
||||||
|
#define _OPENTHREADS_BARRIER_
|
||||||
|
|
||||||
|
#include <OpenThreads/Exports>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Barrier
|
||||||
|
* @brief This class provides an object-oriented thread barrier interface
|
||||||
|
*
|
||||||
|
* @warning It is unwise to use the construct "Barrier barrier" in the
|
||||||
|
* global namespace on sgi's. The object "barrier"
|
||||||
|
* will confilict with the c-library sproc function "barrier" and
|
||||||
|
* unpredictable results may occur. You have been warned.
|
||||||
|
*/
|
||||||
|
class OPENTHREAD_EXPORT_DIRECTIVE Barrier {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
Barrier(int numThreads=0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
virtual ~Barrier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the barrier to it's original state.
|
||||||
|
*/
|
||||||
|
virtual void reset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Block until numThreads threads have entered the barrier.
|
||||||
|
*/
|
||||||
|
virtual void block(unsigned int numThreads=0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release the barrier, now.
|
||||||
|
*/
|
||||||
|
virtual void release();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of threads currently blocked in the barrier,
|
||||||
|
* Return -1 if error.
|
||||||
|
*/
|
||||||
|
virtual int numThreadsCurrentlyBlocked();
|
||||||
|
|
||||||
|
|
||||||
|
void invalidate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private copy constructor, to prevent tampering.
|
||||||
|
*/
|
||||||
|
Barrier(const Barrier &/*b*/) {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private copy assignment, to prevent tampering.
|
||||||
|
*/
|
||||||
|
Barrier &operator=(const Barrier &/*b*/) {return *(this);};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation-specific private data.
|
||||||
|
*/
|
||||||
|
void *_prvData;
|
||||||
|
|
||||||
|
|
||||||
|
bool _valid;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !_OPENTHREADS_BARRIER_
|
||||||
|
|
177
include/OpenThreads/Block
Normal file
177
include/OpenThreads/Block
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
/* -*-c++-*- OpenThreads - Copyright (C) 1998-2007 Robert Osfield
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _OPENTHREADS_BLOCK_
|
||||||
|
#define _OPENTHREADS_BLOCK_
|
||||||
|
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <OpenThreads/Barrier>
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
#include <OpenThreads/ScopedLock>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
/** Block is a block that can be used to halt a thread that is waiting another thread to release it.*/
|
||||||
|
class Block
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Block():
|
||||||
|
_released(false) {}
|
||||||
|
|
||||||
|
~Block()
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool block()
|
||||||
|
{
|
||||||
|
ScopedLock<OpenThreads::Mutex> mutlock(_mut);
|
||||||
|
if( !_released )
|
||||||
|
{
|
||||||
|
return _cond.wait(&_mut)==0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool block(unsigned long timeout)
|
||||||
|
{
|
||||||
|
ScopedLock<OpenThreads::Mutex> mutlock(_mut);
|
||||||
|
if( !_released )
|
||||||
|
{
|
||||||
|
return _cond.wait(&_mut, timeout)==0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void release()
|
||||||
|
{
|
||||||
|
ScopedLock<OpenThreads::Mutex> mutlock(_mut);
|
||||||
|
if (!_released)
|
||||||
|
{
|
||||||
|
_released = true;
|
||||||
|
_cond.broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void reset()
|
||||||
|
{
|
||||||
|
ScopedLock<OpenThreads::Mutex> mutlock(_mut);
|
||||||
|
_released = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set(bool doRelease)
|
||||||
|
{
|
||||||
|
if (doRelease!=_released)
|
||||||
|
{
|
||||||
|
if (doRelease) release();
|
||||||
|
else reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Mutex _mut;
|
||||||
|
Condition _cond;
|
||||||
|
bool _released;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Block(const Block&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** BlockCount is a block that can be used to halt a thread that is waiting for a specified number of operations to be completed.*/
|
||||||
|
class BlockCount
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
BlockCount(unsigned int blockCount):
|
||||||
|
_blockCount(blockCount),
|
||||||
|
_currentCount(0) {}
|
||||||
|
|
||||||
|
~BlockCount()
|
||||||
|
{
|
||||||
|
_blockCount = 0;
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void completed()
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
|
||||||
|
if (_currentCount>0)
|
||||||
|
{
|
||||||
|
--_currentCount;
|
||||||
|
|
||||||
|
if (_currentCount==0)
|
||||||
|
{
|
||||||
|
// osg::notify(osg::NOTICE)<<"Released"<<std::endl;
|
||||||
|
_cond.broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void block()
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
|
||||||
|
if (_currentCount)
|
||||||
|
_cond.wait(&_mut);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void reset()
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
|
||||||
|
if (_currentCount!=_blockCount)
|
||||||
|
{
|
||||||
|
if (_blockCount==0) _cond.broadcast();
|
||||||
|
_currentCount = _blockCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void release()
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
|
||||||
|
if (_currentCount)
|
||||||
|
{
|
||||||
|
_currentCount = 0;
|
||||||
|
_cond.broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setBlockCount(unsigned int blockCount) { _blockCount = blockCount; }
|
||||||
|
|
||||||
|
inline unsigned int getBlockCount() const { return _blockCount; }
|
||||||
|
|
||||||
|
inline unsigned int getCurrentCount() const { return _currentCount; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
OpenThreads::Mutex _mut;
|
||||||
|
OpenThreads::Condition _cond;
|
||||||
|
unsigned int _blockCount;
|
||||||
|
unsigned int _currentCount;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
BlockCount(const BlockCount&) {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
93
include/OpenThreads/Condition
Normal file
93
include/OpenThreads/Condition
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Condition - C++ condition class
|
||||||
|
// ~~~~~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _OPENTHREADS_CONDITION_
|
||||||
|
#define _OPENTHREADS_CONDITION_
|
||||||
|
|
||||||
|
#include <OpenThreads/Exports>
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Condition
|
||||||
|
* @brief This class provides an object-oriented thread condition interface.
|
||||||
|
*/
|
||||||
|
class OPENTHREAD_EXPORT_DIRECTIVE Condition {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
Condition();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
virtual ~Condition();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait on a mutex.
|
||||||
|
*/
|
||||||
|
virtual int wait(Mutex *mutex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait on a mutex for a given amount of time (ms)
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
virtual int wait(Mutex *mutex, unsigned long int ms);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal a SINGLE thread to wake if it's waiting.
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
virtual int signal();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wake all threads waiting on this condition.
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
virtual int broadcast();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private copy constructor, to prevent tampering.
|
||||||
|
*/
|
||||||
|
Condition(const Condition &/*c*/) {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private copy assignment, to prevent tampering.
|
||||||
|
*/
|
||||||
|
Condition &operator=(const Condition &/*c*/) {return *(this);};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation-specific data
|
||||||
|
*/
|
||||||
|
void *_prvData;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !_OPENTHREADS_CONDITION_
|
43
include/OpenThreads/Exports
Normal file
43
include/OpenThreads/Exports
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _OPENTHREAD_EXPORTS_H_
|
||||||
|
#define _OPENTHREAD_EXPORTS_H_
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#define OPENTHREAD_EXPORT_DIRECTIVE
|
||||||
|
#else
|
||||||
|
#if defined( OT_LIBRARY_STATIC )
|
||||||
|
#define OPENTHREAD_EXPORT_DIRECTIVE
|
||||||
|
#elif defined( OPENTHREADS_EXPORTS )
|
||||||
|
#define OPENTHREAD_EXPORT_DIRECTIVE __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define OPENTHREAD_EXPORT_DIRECTIVE __declspec(dllimport)
|
||||||
|
|
||||||
|
#if 0 // Commented out for now
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#pragma comment(lib ,"OpenThreadsWin32d")
|
||||||
|
#else
|
||||||
|
#pragma comment(lib, "OpenThreadsWin32")
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
89
include/OpenThreads/Mutex
Normal file
89
include/OpenThreads/Mutex
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mutex - C++ mutex class
|
||||||
|
// ~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _OPENTHREADS_MUTEX_
|
||||||
|
#define _OPENTHREADS_MUTEX_
|
||||||
|
|
||||||
|
#include <OpenThreads/Exports>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Mutex
|
||||||
|
* @brief This class provides an object-oriented thread mutex interface.
|
||||||
|
*/
|
||||||
|
class OPENTHREAD_EXPORT_DIRECTIVE Mutex {
|
||||||
|
|
||||||
|
friend class Condition;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
Mutex();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
virtual ~Mutex();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock the mutex
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
virtual int lock();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlock the mutex
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
virtual int unlock();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if mutex can be locked.
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
virtual int trylock();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private copy constructor, to prevent tampering.
|
||||||
|
*/
|
||||||
|
Mutex(const Mutex &/*m*/) {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private copy assignment, to prevent tampering.
|
||||||
|
*/
|
||||||
|
Mutex &operator=(const Mutex &/*m*/) {return *(this);};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation-specific private data.
|
||||||
|
*/
|
||||||
|
void *_prvData;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _OPENTHREADS_MUTEX_
|
110
include/OpenThreads/ReadWriteMutex
Normal file
110
include/OpenThreads/ReadWriteMutex
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/* -*-c++-*- OpenThreads - Copyright (C) 1998-2007 Robert Osfield
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _OPENTHREADS_READWRITEMUTEX_
|
||||||
|
#define _OPENTHREADS_READWRITEMUTEX_
|
||||||
|
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <OpenThreads/ReentrantMutex>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class ReadWriteMutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ReadWriteMutex():
|
||||||
|
_readCount(0) {}
|
||||||
|
|
||||||
|
virtual ~ReadWriteMutex() {}
|
||||||
|
|
||||||
|
virtual int readLock()
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_readCountMutex);
|
||||||
|
int result = 0;
|
||||||
|
if (_readCount==0)
|
||||||
|
{
|
||||||
|
result = _readWriteMutex.lock();
|
||||||
|
}
|
||||||
|
++_readCount;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual int readUnlock()
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_readCountMutex);
|
||||||
|
int result = 0;
|
||||||
|
if (_readCount>0)
|
||||||
|
{
|
||||||
|
--_readCount;
|
||||||
|
if (_readCount==0)
|
||||||
|
{
|
||||||
|
result = _readWriteMutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int writeLock()
|
||||||
|
{
|
||||||
|
return _readWriteMutex.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int writeUnlock()
|
||||||
|
{
|
||||||
|
return _readWriteMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
ReadWriteMutex(const ReadWriteMutex&) {}
|
||||||
|
ReadWriteMutex& operator = (const ReadWriteMutex&) { return *(this); }
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
ReentrantMutex _readWriteMutex;
|
||||||
|
ReentrantMutex _readCountMutex;
|
||||||
|
#else
|
||||||
|
OpenThreads::Mutex _readWriteMutex;
|
||||||
|
OpenThreads::Mutex _readCountMutex;
|
||||||
|
#endif
|
||||||
|
unsigned int _readCount;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScopedReadLock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ScopedReadLock(ReadWriteMutex& mutex):_mutex(mutex) { _mutex.readLock(); }
|
||||||
|
~ScopedReadLock() { _mutex.readUnlock(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ReadWriteMutex& _mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ScopedWriteLock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ScopedWriteLock(ReadWriteMutex& mutex):_mutex(mutex) { _mutex.writeLock(); }
|
||||||
|
~ScopedWriteLock() { _mutex.writeUnlock(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ReadWriteMutex& _mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
125
include/OpenThreads/ReentrantMutex
Normal file
125
include/OpenThreads/ReentrantMutex
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/* -*-c++-*- OpenThreads - Copyright (C) 1998-2007 Robert Osfield
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _OPENTHREADS_REENTRANTMUTEX_
|
||||||
|
#define _OPENTHREADS_REENTRANTMUTEX_
|
||||||
|
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
#include <OpenThreads/ScopedLock>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class ReentrantMutex : public OpenThreads::Mutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ReentrantMutex():
|
||||||
|
_threadHoldingMutex(0),
|
||||||
|
_lockCount(0) {}
|
||||||
|
|
||||||
|
virtual ~ReentrantMutex() {}
|
||||||
|
|
||||||
|
virtual int lock()
|
||||||
|
{
|
||||||
|
if (_threadHoldingMutex==OpenThreads::Thread::CurrentThread() && _lockCount>0)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
|
||||||
|
++_lockCount;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int result = Mutex::lock();
|
||||||
|
if (result==0)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
|
||||||
|
|
||||||
|
_threadHoldingMutex = OpenThreads::Thread::CurrentThread();
|
||||||
|
_lockCount = 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual int unlock()
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
|
||||||
|
#if 0
|
||||||
|
if (_threadHoldingMutex==OpenThreads::Thread::CurrentThread() && _lockCount>0)
|
||||||
|
{
|
||||||
|
--_lockCount;
|
||||||
|
if (_lockCount<=0)
|
||||||
|
{
|
||||||
|
_threadHoldingMutex = 0;
|
||||||
|
return Mutex::unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
osg::notify(osg::NOTICE)<<"Error: ReentrantMutex::unlock() - unlocking from the wrong thread."<<std::endl;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (_lockCount>0)
|
||||||
|
{
|
||||||
|
--_lockCount;
|
||||||
|
if (_lockCount<=0)
|
||||||
|
{
|
||||||
|
_threadHoldingMutex = 0;
|
||||||
|
return Mutex::unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual int trylock()
|
||||||
|
{
|
||||||
|
if (_threadHoldingMutex==OpenThreads::Thread::CurrentThread() && _lockCount>0)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
|
||||||
|
++_lockCount;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int result = Mutex::trylock();
|
||||||
|
if (result==0)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
|
||||||
|
|
||||||
|
_threadHoldingMutex = OpenThreads::Thread::CurrentThread();
|
||||||
|
_lockCount = 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ReentrantMutex(const ReentrantMutex&):OpenThreads::Mutex() {}
|
||||||
|
|
||||||
|
ReentrantMutex& operator =(const ReentrantMutex&) { return *(this); }
|
||||||
|
|
||||||
|
OpenThreads::Thread* _threadHoldingMutex;
|
||||||
|
|
||||||
|
OpenThreads::Mutex _lockCountMutex;
|
||||||
|
unsigned int _lockCount;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
47
include/OpenThreads/ScopedLock
Normal file
47
include/OpenThreads/ScopedLock
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// ScopedLock and ReverseScopedLock templates
|
||||||
|
// ~~~~~~~
|
||||||
|
//
|
||||||
|
#ifndef _ScopedLock_
|
||||||
|
#define _ScopedLock_
|
||||||
|
|
||||||
|
namespace OpenThreads{
|
||||||
|
|
||||||
|
template <class M> class ScopedLock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
M& m_lock;
|
||||||
|
ScopedLock(const ScopedLock&); // prevent copy
|
||||||
|
ScopedLock& operator=(const ScopedLock&); // prevent assign
|
||||||
|
public:
|
||||||
|
explicit ScopedLock(M& m):m_lock(m) {m_lock.lock();}
|
||||||
|
~ScopedLock(){m_lock.unlock();}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class M> class ReverseScopedLock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
M& m_lock;
|
||||||
|
ReverseScopedLock(const ReverseScopedLock&); // prevent copy
|
||||||
|
ReverseScopedLock& operator=(const ReverseScopedLock&); // prevent assign
|
||||||
|
public:
|
||||||
|
explicit ReverseScopedLock(M& m):m_lock(m) {m_lock.unlock();}
|
||||||
|
~ReverseScopedLock(){m_lock.lock();}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
389
include/OpenThreads/Thread
Normal file
389
include/OpenThreads/Thread
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Thread - C++ Thread class
|
||||||
|
// ~~~~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _OPENTHREADS_THREAD_
|
||||||
|
#define _OPENTHREADS_THREAD_
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of processors.
|
||||||
|
*
|
||||||
|
* Note, systems where no support exists for querrying the number of processors, 1 is returned.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
extern OPENTHREAD_EXPORT_DIRECTIVE int GetNumberOfProcessors();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the processor affinity of current thread.
|
||||||
|
*
|
||||||
|
* Note, systems where no support exists no affinity will be set, and -1 will be returned.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
extern OPENTHREAD_EXPORT_DIRECTIVE int SetProcessorAffinityOfCurrentThread(unsigned int cpunum);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Thread
|
||||||
|
* @brief This class provides an object-oriented thread interface.
|
||||||
|
*/
|
||||||
|
class OPENTHREAD_EXPORT_DIRECTIVE Thread {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the concurrency level for a running application. This method
|
||||||
|
* only has effect if the pthreads thread model is being used, and
|
||||||
|
* then only when that model is many-to-one (eg. irix).
|
||||||
|
* in other cases it is ignored. The concurrency level is only a
|
||||||
|
* *hint* as to the number of execution vehicles to use, the actual
|
||||||
|
* implementation may do anything it wants. Setting the value
|
||||||
|
* to 0 returns things to their default state.
|
||||||
|
*
|
||||||
|
* @return previous concurrency level, -1 indicates no-op.
|
||||||
|
*/
|
||||||
|
static int SetConcurrency(int concurrencyLevel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the concurrency level for a running application. In this
|
||||||
|
* case, a return code of 0 means that the application is in default
|
||||||
|
* mode. A return code of -1 means that the application is incapable
|
||||||
|
* of setting an arbitrary concurrency, because it is a one-to-one
|
||||||
|
* execution model (sprocs, linuxThreads)
|
||||||
|
*/
|
||||||
|
static int GetConcurrency();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumerated Type for thread priority
|
||||||
|
*/
|
||||||
|
enum ThreadPriority {
|
||||||
|
|
||||||
|
THREAD_PRIORITY_MAX, /**< The maximum possible priority */
|
||||||
|
THREAD_PRIORITY_HIGH, /**< A high (but not max) setting */
|
||||||
|
THREAD_PRIORITY_NOMINAL, /**< An average priority */
|
||||||
|
THREAD_PRIORITY_LOW, /**< A low (but not min) setting */
|
||||||
|
THREAD_PRIORITY_MIN, /**< The miniumum possible priority */
|
||||||
|
THREAD_PRIORITY_DEFAULT /**< Priority scheduling default */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumerated Type for thread scheduling policy
|
||||||
|
*/
|
||||||
|
enum ThreadPolicy {
|
||||||
|
|
||||||
|
THREAD_SCHEDULE_FIFO, /**< First in, First out scheduling */
|
||||||
|
THREAD_SCHEDULE_ROUND_ROBIN, /**< Round-robin scheduling (LINUX_DEFAULT) */
|
||||||
|
THREAD_SCHEDULE_TIME_SHARE, /**< Time-share scheduling (IRIX DEFAULT) */
|
||||||
|
THREAD_SCHEDULE_DEFAULT /**< Default scheduling */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
Thread();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
virtual ~Thread();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a pointer to the current running thread
|
||||||
|
*/
|
||||||
|
static Thread *CurrentThread();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize Threading in a program. This method must be called before
|
||||||
|
* you can do any threading in a program.
|
||||||
|
*/
|
||||||
|
static void Init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Yield the processor.
|
||||||
|
*
|
||||||
|
* @note This method operates on the calling process. And is
|
||||||
|
* equivalent to calling sched_yield().
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
static int YieldCurrentThread();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will return the ThreadPriority of the master process.
|
||||||
|
* (ie, the one calling the thread->start() methods for the first time)
|
||||||
|
* The method will almost certainly return
|
||||||
|
* Thread::THREAD_PRIORITY_DEFAULT if
|
||||||
|
* Init() has not been called.
|
||||||
|
*
|
||||||
|
* @return the Thread::ThreadPriority of the master thread.
|
||||||
|
*/
|
||||||
|
static ThreadPriority GetMasterPriority() {return s_masterThreadPriority;};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a unique thread id. This id is monotonically increasing.
|
||||||
|
*
|
||||||
|
* @return a unique thread identifier
|
||||||
|
*/
|
||||||
|
int getThreadId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the thread's process id. This is the pthread_t or pid_t value
|
||||||
|
* depending on the threading model being used.
|
||||||
|
*
|
||||||
|
* @return thread process id.
|
||||||
|
*/
|
||||||
|
size_t getProcessId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the thread. This method will configure the thread, set
|
||||||
|
* it's priority, and spawn it.
|
||||||
|
*
|
||||||
|
* @note if the stack size specified setStackSize is smaller than the
|
||||||
|
* smallest allowable stack size, the threads stack size will be set to
|
||||||
|
* the minimum allowed, and may be retrieved via the getStackSize()
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
int start();
|
||||||
|
int startThread();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the cancel state of the thread. If the thread has been canceled
|
||||||
|
* this method will cause the thread to exit now. This method operates
|
||||||
|
* on the calling thread.
|
||||||
|
*
|
||||||
|
* Returns 0 if normal, -1 if called from a thread other that this.
|
||||||
|
*/
|
||||||
|
int testCancel();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel the thread. Equivalent to SIGKILL.
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
virtual int cancel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the thread's schedule priority. This is a complex method.
|
||||||
|
* Beware of thread priorities when using a many-to-many kernel
|
||||||
|
* entity implemenation (such as IRIX pthreads). If one is not carefull
|
||||||
|
* to manage the thread priorities, a priority inversion deadlock can
|
||||||
|
* easily occur (Although the OpenThreads::Mutex & OpenThreads::Barrier
|
||||||
|
* constructs have been designed with this senario in mind). Unless
|
||||||
|
* you have explicit need to set the schedule pirorites for a given
|
||||||
|
* task, it is best to leave them alone.
|
||||||
|
*
|
||||||
|
* @note some implementations (notably LinuxThreads and IRIX Sprocs)
|
||||||
|
* only alow you to decrease thread priorities dynamically. Thus,
|
||||||
|
* a lower priority thread will not allow it's priority to be raised
|
||||||
|
* on the fly.
|
||||||
|
*
|
||||||
|
* @note seting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
|
||||||
|
* will output scheduling information for each thread to stdout.
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
int setSchedulePriority(ThreadPriority priority);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the thread's schedule priority (if able)
|
||||||
|
*
|
||||||
|
* @note seting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
|
||||||
|
* will output scheduling information for each thread to stdout.
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
int getSchedulePriority();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the thread's scheduling policy (if able)
|
||||||
|
*
|
||||||
|
* @note On some implementations (notably IRIX Sprocs & LinuxThreads)
|
||||||
|
* The policy may prohibit the use of SCHEDULE_ROUND_ROBIN and
|
||||||
|
* SCHEDULE_FIFO policies - due to their real-time nature, and
|
||||||
|
* the danger of deadlocking the machine when used as super-user.
|
||||||
|
* In such cases, the command is a no-op.
|
||||||
|
*
|
||||||
|
* @note seting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
|
||||||
|
* will output scheduling information for each thread to stdout.
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
int setSchedulePolicy(ThreadPolicy policy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the thread's policy (if able)
|
||||||
|
*
|
||||||
|
* @note seting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
|
||||||
|
* will output scheduling information for each thread to stdout.
|
||||||
|
*
|
||||||
|
* @return policy if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
int getSchedulePolicy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the thread's desired stack size (in bytes).
|
||||||
|
* This method is an attribute of the thread and must be called
|
||||||
|
* *before* the start() method is invoked.
|
||||||
|
*
|
||||||
|
* @note a return code of 13 (EACESS) means that the thread stack
|
||||||
|
* size can no longer be changed.
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
int setStackSize(size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the thread's desired stack size.
|
||||||
|
*
|
||||||
|
* @return the thread's stack size. 0 indicates that the stack size
|
||||||
|
* has either not yet been initialized, or not yet been specified by
|
||||||
|
* the application.
|
||||||
|
*/
|
||||||
|
size_t getStackSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print the thread's scheduling information to stdout.
|
||||||
|
*/
|
||||||
|
void printSchedulingInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detach the thread from the calling process.
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
int detach();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join the calling process with the thread
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
int join();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable thread cancelation altogether. Thread::cancel() has no effect.
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
int setCancelModeDisable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the thread to cancel aysncronously on Thread::cancel().
|
||||||
|
* (May not be available with process-level implementations).
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
int setCancelModeAsynchronous();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the thread to cancel at the earliest convenience on
|
||||||
|
* Thread::cancel() (This is the default)
|
||||||
|
*
|
||||||
|
* @return 0 if normal, -1 if errno set, errno code otherwise.
|
||||||
|
*/
|
||||||
|
int setCancelModeDeferred();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the thread's running status
|
||||||
|
*
|
||||||
|
* @return true if running, false if not.
|
||||||
|
*/
|
||||||
|
bool isRunning();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread's run method. Must be implemented by derived classes.
|
||||||
|
* This is where the action happens.
|
||||||
|
*/
|
||||||
|
virtual void run() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread's cancel cleanup routine, called upon cancel(), after the
|
||||||
|
* cancelation has taken place, but before the thread exits completely.
|
||||||
|
* This method should be used to repair parts of the thread's data
|
||||||
|
* that may have been damaged by a pre-mature cancel. No-op by default.
|
||||||
|
*/
|
||||||
|
virtual void cancelCleanup() {};
|
||||||
|
|
||||||
|
void* getImplementation(){ return _prvData; };
|
||||||
|
|
||||||
|
/** Thread's processor affinity method. This binds a thread to a
|
||||||
|
* processor whenever possible. This call must be made before
|
||||||
|
* start() or startThread() and has no effect after the thread
|
||||||
|
* has been running. In the pthreads implementation, this is only
|
||||||
|
* implemented on sgi, through a pthread extension. On other pthread
|
||||||
|
* platforms this is ignored. Returns 0 on success, implementation's
|
||||||
|
* error on failure, or -1 if ignored.
|
||||||
|
*/
|
||||||
|
int setProcessorAffinity( unsigned int cpunum );
|
||||||
|
|
||||||
|
/** microSleep method, equivilant to the posix usleep(microsec).
|
||||||
|
* This is not strictly thread API but is used
|
||||||
|
* so often with threads. It's basically UNIX usleep. Parameter is
|
||||||
|
* number of microseconds we current thread to sleep. Returns 0 on
|
||||||
|
* succes, non-zero on failure (UNIX errno or GetLastError() will give
|
||||||
|
* detailed description.
|
||||||
|
*/
|
||||||
|
static int microSleep( unsigned int microsec);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Private Actions class is allowed to operate on private data.
|
||||||
|
*/
|
||||||
|
friend class ThreadPrivateActions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private copy constructor, to prevent tampering.
|
||||||
|
*/
|
||||||
|
Thread(const Thread &/*t*/) {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private copy assignment, to prevent tampering.
|
||||||
|
*/
|
||||||
|
Thread &operator=(const Thread &/*t*/) {return *(this);};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation-specific data
|
||||||
|
*/
|
||||||
|
void * _prvData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Master thread's priority, set by Thread::Init.
|
||||||
|
*/
|
||||||
|
static ThreadPriority s_masterThreadPriority;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is initialized flag
|
||||||
|
*/
|
||||||
|
static bool s_isInitialized;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !_OPENTHREADS_THREAD_
|
38
include/OpenThreads/Version
Normal file
38
include/OpenThreads/Version
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OPENTHREADS_VERSION
|
||||||
|
#define OPENTHREADS_VERSION 1
|
||||||
|
|
||||||
|
#include <OpenThreads/Exports>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
#define OPENTHREADS_MAJOR_VERSION 2
|
||||||
|
#define OPENTHREADS_MINOR_VERSION 2
|
||||||
|
#define OPENTHREADS_PATCH_VERSION 0
|
||||||
|
#define OPENTHREADS_SOVERSION 9
|
||||||
|
|
||||||
|
/** OpenThreadsGetVersion() returns the library version number.
|
||||||
|
* Numbering convention : OpenThreads-1.0 will return 1.0 from OpenThreadsGetVersion. */
|
||||||
|
extern OPENTHREAD_EXPORT_DIRECTIVE const char* OpenThreadsGetVersion();
|
||||||
|
|
||||||
|
/** The OpenThreadsGetSOVersion() method returns the OpenSceneGraph soversion number. */
|
||||||
|
extern OPENTHREAD_EXPORT_DIRECTIVE const char* OpenThreadsGetSOVersion();
|
||||||
|
|
||||||
|
/** The OpenThreadsGetLibraryName() method returns the library name in human-friendly form. */
|
||||||
|
extern OPENTHREAD_EXPORT_DIRECTIVE const char* OpenThreadsGetLibraryName();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
72
src/OpenThreads/CMakeLists.txt
Normal file
72
src/OpenThreads/CMakeLists.txt
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# This is mainly for Windows declspec, but other platforms know
|
||||||
|
# what to do with it.
|
||||||
|
ADD_DEFINITIONS(-DOPENTHREADS_EXPORTS)
|
||||||
|
|
||||||
|
SET(OPENTHREADS_MAJOR_VERSION 2)
|
||||||
|
SET(OPENTHREADS_MINOR_VERSION 2)
|
||||||
|
SET(OPENTHREADS_PATCH_VERSION 0)
|
||||||
|
SET(OPENTHREADS_SOVERSION 9)
|
||||||
|
|
||||||
|
SET(OPENTHREADS_VERSION ${OPENTHREADS_MAJOR_VERSION}.${OPENTHREADS_MINOR_VERSION}.${OPENTHREADS_PATCH_VERSION})
|
||||||
|
|
||||||
|
SET(HEADER_PATH ${OpenThreads_SOURCE_DIR}/include/OpenThreads)
|
||||||
|
SET(OpenThreads_PUBLIC_HEADERS
|
||||||
|
${HEADER_PATH}/Barrier
|
||||||
|
${HEADER_PATH}/Block
|
||||||
|
${HEADER_PATH}/Condition
|
||||||
|
${HEADER_PATH}/Exports
|
||||||
|
${HEADER_PATH}/Mutex
|
||||||
|
${HEADER_PATH}/ReadWriteMutex
|
||||||
|
${HEADER_PATH}/ReentrantMutex
|
||||||
|
${HEADER_PATH}/ScopedLock
|
||||||
|
${HEADER_PATH}/Thread
|
||||||
|
${HEADER_PATH}/Version
|
||||||
|
)
|
||||||
|
|
||||||
|
# User Options
|
||||||
|
OPTION(DYNAMIC_OPENTHREADS "Set to ON to build OpenThreads for dynamic linking. Use OFF for static." ON)
|
||||||
|
IF (DYNAMIC_OPENTHREADS)
|
||||||
|
SET(OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC "SHARED")
|
||||||
|
ELSE (DYNAMIC_OPENTHREADS)
|
||||||
|
SET(OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC "STATIC")
|
||||||
|
ENDIF(DYNAMIC_OPENTHREADS)
|
||||||
|
|
||||||
|
# Use our modified version of FindThreads.cmake which has Sproc hacks.
|
||||||
|
FIND_PACKAGE(Threads)
|
||||||
|
|
||||||
|
# Do we have sproc?
|
||||||
|
IF(CMAKE_SYSTEM MATCHES IRIX)
|
||||||
|
IF(CMAKE_USE_SPROC_INIT)
|
||||||
|
# In this case, only Sproc exists, so no option.
|
||||||
|
SET(OPENTHREADS_USE_SPROC_INSTEAD_OF_PTHREADS 1)
|
||||||
|
ELSE(CMAKE_USE_SPROC_INIT)
|
||||||
|
IF(CMAKE_HAVE_SPROC_H)
|
||||||
|
OPTION(OPENTHREADS_USE_SPROC_INSTEAD_OF_PTHREADS "Set to ON to build OpenThreads against sproc instead of pthreads" OFF)
|
||||||
|
ENDIF(CMAKE_HAVE_SPROC_H)
|
||||||
|
ENDIF(CMAKE_USE_SPROC_INIT)
|
||||||
|
ENDIF(CMAKE_SYSTEM MATCHES IRIX)
|
||||||
|
|
||||||
|
# Maybe we should be using the FindThreads.cmake module?
|
||||||
|
IF(WIN32)
|
||||||
|
# So I think Cygwin wants to use pthreads
|
||||||
|
IF(CYGWIN)
|
||||||
|
SUBDIRS(pthreads)
|
||||||
|
ELSE(CYGWIN)
|
||||||
|
# Everybody else including Msys should probably go here
|
||||||
|
SUBDIRS(win32)
|
||||||
|
# examples)
|
||||||
|
ENDIF(CYGWIN)
|
||||||
|
ELSE(WIN32)
|
||||||
|
IF(UNIX)
|
||||||
|
IF(OPENTHREADS_USE_SPROC_INSTEAD_OF_PTHREADS)
|
||||||
|
SUBDIRS(sproc)
|
||||||
|
ELSE(OPENTHREADS_USE_SPROC_INSTEAD_OF_PTHREADS)
|
||||||
|
SUBDIRS(pthreads)
|
||||||
|
ENDIF(OPENTHREADS_USE_SPROC_INSTEAD_OF_PTHREADS)
|
||||||
|
ELSE(UNIX)
|
||||||
|
MESSAGE("Sorry, OpenThreads may not support your platform")
|
||||||
|
ENDIF(UNIX)
|
||||||
|
ENDIF(WIN32)
|
||||||
|
|
||||||
|
|
||||||
|
|
57
src/OpenThreads/common/Version.cpp
Normal file
57
src/OpenThreads/common/Version.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <OpenThreads/Version>
|
||||||
|
#include <string>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* These functions expect OPENTHREADS_MAJOR_VERSION,
|
||||||
|
* OPENTHREADS_MINOR_VERSION, OPENTHREADS_PATCH_VERSION, and
|
||||||
|
* OPENTHREADS_SOVERSION to be defined by the build system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
const char* OpenThreadsGetVersion()
|
||||||
|
{
|
||||||
|
static char OpenThreads_version[256];
|
||||||
|
static int OpenThreads_version_init = 1;
|
||||||
|
if (OpenThreads_version_init)
|
||||||
|
{
|
||||||
|
sprintf(OpenThreads_version,"%d.%d.%d",OPENTHREADS_MAJOR_VERSION,OPENTHREADS_MINOR_VERSION,OPENTHREADS_PATCH_VERSION);
|
||||||
|
OpenThreads_version_init = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OpenThreads_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* OpenThreadsGetSOVersion()
|
||||||
|
{
|
||||||
|
static char OpenThreads_soversion[32];
|
||||||
|
static int OpenThreads_soversion_init = 1;
|
||||||
|
if (OpenThreads_soversion_init)
|
||||||
|
{
|
||||||
|
sprintf(OpenThreads_soversion,"%d",OPENTHREADS_SOVERSION);
|
||||||
|
OpenThreads_soversion_init = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OpenThreads_soversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* OpenThreadsGetLibraryName()
|
||||||
|
{
|
||||||
|
return "OpenThreads Library";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
116
src/OpenThreads/pthreads/CMakeLists.txt
Normal file
116
src/OpenThreads/pthreads/CMakeLists.txt
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
# This file should only be included when using Pthreads
|
||||||
|
|
||||||
|
INCLUDE (CheckFunctionExists)
|
||||||
|
INCLUDE (CheckLibraryExists)
|
||||||
|
INCLUDE (CheckSymbolExists)
|
||||||
|
INCLUDE (CheckCXXSourceCompiles)
|
||||||
|
|
||||||
|
SET(LIB_NAME OpenThreads)
|
||||||
|
SET(LIB_PUBLIC_HEADERS ${OpenThreads_PUBLIC_HEADERS})
|
||||||
|
|
||||||
|
ADD_LIBRARY(${LIB_NAME}
|
||||||
|
${OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC}
|
||||||
|
${LIB_PUBLIC_HEADERS}
|
||||||
|
PThread.c++
|
||||||
|
PThreadBarrier.c++
|
||||||
|
PThreadBarrierPrivateData.h
|
||||||
|
PThreadCondition.c++
|
||||||
|
PThreadConditionPrivateData.h
|
||||||
|
PThreadMutex.c++
|
||||||
|
PThreadMutexPrivateData.h
|
||||||
|
PThreadPrivateData.h
|
||||||
|
../common/Version.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
IF(OPENTHREADS_SONAMES)
|
||||||
|
SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${OPENTHREADS_VERSION} SOVERSION ${OPENTHREADS_SOVERSION})
|
||||||
|
ENDIF(OPENTHREADS_SONAMES)
|
||||||
|
|
||||||
|
SET(CMAKE_REQUIRED_LIBRARIES_SAFE "${CMAKE_REQUIRED_LIBRARIES}")
|
||||||
|
SET(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}")
|
||||||
|
|
||||||
|
CHECK_FUNCTION_EXISTS(pthread_yield HAVE_PTHREAD_YIELD)
|
||||||
|
IF(HAVE_PTHREAD_YIELD)
|
||||||
|
ADD_DEFINITIONS(-DHAVE_PTHREAD_YIELD)
|
||||||
|
ELSE(HAVE_PTHREAD_YIELD)
|
||||||
|
# sched_yield appears not in libc, pthreads or whatever on some systems
|
||||||
|
CHECK_FUNCTION_EXISTS(sched_yield HAVE_SCHED_YIELD)
|
||||||
|
IF(NOT HAVE_SCHED_YIELD)
|
||||||
|
CHECK_LIBRARY_EXISTS(rt sched_yield "" HAVE_SCHED_YIELD)
|
||||||
|
IF(HAVE_SCHED_YIELD)
|
||||||
|
SET(CMAKE_THREAD_LIBS_INIT "${CMAKE_THREAD_LIBS_INIT} -lrt")
|
||||||
|
ENDIF(HAVE_SCHED_YIELD)
|
||||||
|
ENDIF(NOT HAVE_SCHED_YIELD)
|
||||||
|
IF(HAVE_SCHED_YIELD)
|
||||||
|
ADD_DEFINITIONS(-DHAVE_SCHED_YIELD)
|
||||||
|
ENDIF(HAVE_SCHED_YIELD)
|
||||||
|
ENDIF(HAVE_PTHREAD_YIELD)
|
||||||
|
|
||||||
|
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||||
|
# need to have that for pthread_setaffinity_np on linux
|
||||||
|
ADD_DEFINITIONS(-D_GNU_SOURCE)
|
||||||
|
SET(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE")
|
||||||
|
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||||
|
|
||||||
|
CHECK_FUNCTION_EXISTS(pthread_setconcurrency HAVE_PTHREAD_SETCONCURRENCY)
|
||||||
|
IF(HAVE_PTHREAD_SETCONCURRENCY)
|
||||||
|
ADD_DEFINITIONS(-DHAVE_PTHREAD_SETCONCURRENCY)
|
||||||
|
ENDIF(HAVE_PTHREAD_SETCONCURRENCY)
|
||||||
|
|
||||||
|
CHECK_FUNCTION_EXISTS(pthread_getconcurrency HAVE_PTHREAD_GETCONCURRENCY)
|
||||||
|
IF(HAVE_PTHREAD_GETCONCURRENCY)
|
||||||
|
ADD_DEFINITIONS(-DHAVE_PTHREAD_GETCONCURRENCY)
|
||||||
|
ENDIF(HAVE_PTHREAD_GETCONCURRENCY)
|
||||||
|
|
||||||
|
CHECK_FUNCTION_EXISTS(pthread_setaffinity_np HAVE_PTHREAD_SETAFFINITY_NP)
|
||||||
|
IF(HAVE_PTHREAD_SETAFFINITY_NP)
|
||||||
|
ADD_DEFINITIONS(-DHAVE_PTHREAD_SETAFFINITY_NP)
|
||||||
|
ELSE(HAVE_PTHREAD_SETAFFINITY_NP)
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <sched.h>
|
||||||
|
int main() {
|
||||||
|
cpu_set_t cpumask;
|
||||||
|
sched_setaffinity( 0, sizeof(cpumask), &cpumask );
|
||||||
|
return 0;
|
||||||
|
}" HAVE_THREE_PARAM_SCHED_SETAFFINITY)
|
||||||
|
IF(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
|
||||||
|
ADD_DEFINITIONS(-DHAVE_THREE_PARAM_SCHED_SETAFFINITY)
|
||||||
|
ELSE(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <sched.h>
|
||||||
|
int main() {
|
||||||
|
cpu_set_t cpumask;
|
||||||
|
sched_setaffinity( 0, &cpumask );
|
||||||
|
return 0;
|
||||||
|
}" HAVE_TWO_PARAM_SCHED_SETAFFINITY)
|
||||||
|
IF(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
|
||||||
|
ADD_DEFINITIONS(-DHAVE_TWO_PARAM_SCHED_SETAFFINITY)
|
||||||
|
ENDIF(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
|
||||||
|
ENDIF(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
|
||||||
|
ENDIF(HAVE_PTHREAD_SETAFFINITY_NP)
|
||||||
|
|
||||||
|
SET(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES_SAFE}")
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES(${LIB_NAME}
|
||||||
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Since we're building different platforms binaries in
|
||||||
|
# their respective directories, we need to set the
|
||||||
|
# link directory so it can find this location.
|
||||||
|
LINK_DIRECTORIES(
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
INSTALL(
|
||||||
|
TARGETS OpenThreads
|
||||||
|
ARCHIVE DESTINATION lib${LIB_POSTFIX}
|
||||||
|
LIBRARY DESTINATION lib${LIB_POSTFIX}
|
||||||
|
RUNTIME DESTINATION bin
|
||||||
|
)
|
||||||
|
INSTALL(
|
||||||
|
FILES ${OpenThreads_PUBLIC_HEADERS}
|
||||||
|
DESTINATION include/OpenThreads
|
||||||
|
)
|
||||||
|
|
||||||
|
#commented out# INCLUDE(ModuleInstall OPTIONAL)
|
46
src/OpenThreads/pthreads/GNUmakefile
Normal file
46
src/OpenThreads/pthreads/GNUmakefile
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
TOPDIR = ../.
|
||||||
|
include $(TOPDIR)/Make/makedefs
|
||||||
|
|
||||||
|
C++FILES = \
|
||||||
|
PThread.c++ \
|
||||||
|
PThreadMutex.c++ \
|
||||||
|
PThreadCondition.c++ \
|
||||||
|
PThreadBarrier.c++ \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
INC += -I$(TOPDIR)/include -I.
|
||||||
|
|
||||||
|
ifeq ($(OS),Linux)
|
||||||
|
DEF += -fPIC -DLinux -DGL_GLEXT_PROTOTYPES
|
||||||
|
LIBS += -lpthread
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),SunOS)
|
||||||
|
LIBS += -lpthread -lposix4
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),IRIX)
|
||||||
|
LIBS += -lpthread
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),Darwin)
|
||||||
|
LIBS += -lpthread
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),CYGWIN)
|
||||||
|
LIBS += -lpthread
|
||||||
|
DEF += -DOPENTHREADS_EXPORTS
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),MINGW)
|
||||||
|
LIBS += -lpthread -lwinmm
|
||||||
|
DEF += -DOPENTHREADS_EXPORTS
|
||||||
|
endif
|
||||||
|
|
||||||
|
TARGET_BASENAME = OpenThreads
|
||||||
|
LIB = $(LIB_PREFIX)$(TARGET_BASENAME)
|
||||||
|
|
||||||
|
ifeq ($(COMPILE_USING_TWO_PARAM_sched_setaffinity),yes)
|
||||||
|
DEF += -DCOMPILE_USING_TWO_PARAM_sched_setaffinity
|
||||||
|
endif
|
||||||
|
include $(TOPDIR)/Make/makerules
|
992
src/OpenThreads/pthreads/PThread.c++
Normal file
992
src/OpenThreads/pthreads/PThread.c++
Normal file
@ -0,0 +1,992 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PThread.c++ - C++ Thread class built on top of posix threads.
|
||||||
|
// ~~~~~~~~~~~
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#if defined __linux || defined __sun || defined __APPLE__
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <sys/unistd.h>
|
||||||
|
#endif
|
||||||
|
#if defined(__sgi)
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if defined(__hpux)
|
||||||
|
#include <sys/mpctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY) || defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
|
||||||
|
# include <sched.h>
|
||||||
|
#endif
|
||||||
|
#if defined (__FreeBSD__) || defined (__APPLE__) || defined (__MACH__)
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include "PThreadPrivateData.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace OpenThreads;
|
||||||
|
|
||||||
|
extern int errno;
|
||||||
|
const char *OPENTHREAD_VERSION_STRING = "OpenThreads v1.2preAlpha, Posix Threads (Public Implementation)";
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
# define DPRINTF(arg) printf arg
|
||||||
|
#else
|
||||||
|
# define DPRINTF(arg)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Initialize the static unique ids.
|
||||||
|
//
|
||||||
|
int PThreadPrivateData::nextId = 0;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Initialize thread master priority level
|
||||||
|
//
|
||||||
|
Thread::ThreadPriority Thread::s_masterThreadPriority =
|
||||||
|
Thread::THREAD_PRIORITY_DEFAULT;
|
||||||
|
|
||||||
|
bool Thread::s_isInitialized = false;
|
||||||
|
pthread_key_t PThreadPrivateData::s_tls_key;
|
||||||
|
|
||||||
|
struct ThreadCleanupStruct {
|
||||||
|
|
||||||
|
OpenThreads::Thread *thread;
|
||||||
|
volatile bool *runflag;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// This cleanup handler is necessary to ensure that the thread will cleanup
|
||||||
|
// and set its isRunning flag properly.
|
||||||
|
//
|
||||||
|
void thread_cleanup_handler(void *arg) {
|
||||||
|
|
||||||
|
ThreadCleanupStruct *tcs = static_cast<ThreadCleanupStruct *>(arg);
|
||||||
|
|
||||||
|
tcs->thread->cancelCleanup();
|
||||||
|
*(tcs->runflag) = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Class to support some static methods necessary for pthread's to work
|
||||||
|
// correctly.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class ThreadPrivateActions {
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// We're friendly to Thread, so it can issue the methods.
|
||||||
|
//
|
||||||
|
friend class Thread;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// pthreads standard start routine.
|
||||||
|
//
|
||||||
|
static void *StartThread(void *data) {
|
||||||
|
|
||||||
|
Thread *thread = static_cast<Thread *>(data);
|
||||||
|
|
||||||
|
PThreadPrivateData *pd =
|
||||||
|
static_cast<PThreadPrivateData *>(thread->_prvData);
|
||||||
|
|
||||||
|
|
||||||
|
if (pd->cpunum>=0)
|
||||||
|
{
|
||||||
|
#if defined(__sgi)
|
||||||
|
pthread_setrunon_np( pd->cpunum );
|
||||||
|
#elif defined(HAVE_PTHREAD_SETAFFINITY_NP) || defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY) || defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
|
||||||
|
cpu_set_t cpumask;
|
||||||
|
CPU_ZERO( &cpumask );
|
||||||
|
CPU_SET( pd->cpunum, &cpumask );
|
||||||
|
|
||||||
|
#if defined(HAVE_PTHREAD_SETAFFINITY_NP)
|
||||||
|
pthread_setaffinity_np( pthread_self(), sizeof(cpumask), &cpumask);
|
||||||
|
#elif defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
|
||||||
|
sched_setaffinity( 0, sizeof(cpumask), &cpumask );
|
||||||
|
#elif defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
|
||||||
|
sched_setaffinity( 0, &cpumask );
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ThreadCleanupStruct tcs;
|
||||||
|
tcs.thread = thread;
|
||||||
|
tcs.runflag = &pd->isRunning;
|
||||||
|
|
||||||
|
// Set local storage so that Thread::CurrentThread() can return the right thing
|
||||||
|
int status = pthread_setspecific(PThreadPrivateData::s_tls_key, thread);
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
printf("Error: pthread_setspecific(,) returned error status, status = %d\n",status);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_cleanup_push(thread_cleanup_handler, &tcs);
|
||||||
|
|
||||||
|
#ifdef ALLOW_PRIORITY_SCHEDULING
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Set the proper scheduling priorities
|
||||||
|
//
|
||||||
|
SetThreadSchedulingParams(thread);
|
||||||
|
|
||||||
|
#endif // ] ALLOW_PRIORITY_SCHEDULING
|
||||||
|
|
||||||
|
pd->isRunning = true;
|
||||||
|
|
||||||
|
// release the thread that created this thread.
|
||||||
|
pd->threadStartedBlock.release();
|
||||||
|
|
||||||
|
thread->run();
|
||||||
|
|
||||||
|
pd->isRunning = false;
|
||||||
|
|
||||||
|
pthread_cleanup_pop(0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Print information related to thread schduling parameters.
|
||||||
|
//
|
||||||
|
static void PrintThreadSchedulingInfo(Thread *thread) {
|
||||||
|
|
||||||
|
#ifdef ALLOW_PRIORITY_SCHEDULING // [
|
||||||
|
|
||||||
|
if(sysconf(_POSIX_THREAD_PRIORITY_SCHEDULING)) {
|
||||||
|
|
||||||
|
int status, my_policy, min_priority, max_priority;
|
||||||
|
struct sched_param my_param;
|
||||||
|
|
||||||
|
status = pthread_getschedparam(thread->getProcessId(),
|
||||||
|
&my_policy,
|
||||||
|
&my_param);
|
||||||
|
|
||||||
|
if(status != 0) {
|
||||||
|
printf("THREAD INFO (%d) : Get sched: %s\n",
|
||||||
|
thread->getProcessId(),
|
||||||
|
strerror(status));
|
||||||
|
} else {
|
||||||
|
printf(
|
||||||
|
"THREAD INFO (%d) : Thread running at %s / Priority: %d\n",
|
||||||
|
thread->getProcessId(),
|
||||||
|
(my_policy == SCHED_FIFO ? "SCHEDULE_FIFO"
|
||||||
|
: (my_policy == SCHED_RR ? "SCHEDULE_ROUND_ROBIN"
|
||||||
|
: (my_policy == SCHED_OTHER ? "SCHEDULE_OTHER"
|
||||||
|
: "UNKNOWN"))),
|
||||||
|
my_param.sched_priority);
|
||||||
|
|
||||||
|
max_priority = sched_get_priority_max(my_policy);
|
||||||
|
min_priority = sched_get_priority_min(my_policy);
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"THREAD INFO (%d) : Max priority: %d, Min priority: %d\n",
|
||||||
|
thread->getProcessId(),
|
||||||
|
max_priority, min_priority);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf(
|
||||||
|
"THREAD INFO (%d) POSIX Priority scheduling not available\n",
|
||||||
|
thread->getProcessId());
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
#endif // ] ALLOW_PRIORITY_SCHEDULING
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Set thread scheduling parameters. Unfortunately on Linux, there's no
|
||||||
|
// good way to set this, as pthread_setschedparam is mostly a no-op.
|
||||||
|
//
|
||||||
|
static int SetThreadSchedulingParams(Thread *thread) {
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
#ifdef ALLOW_PRIORITY_SCHEDULING // [
|
||||||
|
|
||||||
|
if(sysconf(_POSIX_THREAD_PRIORITY_SCHEDULING)) {
|
||||||
|
|
||||||
|
int th_policy;
|
||||||
|
int max_priority, nominal_priority, min_priority;
|
||||||
|
sched_param th_param;
|
||||||
|
pthread_getschedparam(thread->getProcessId(),
|
||||||
|
&th_policy, &th_param);
|
||||||
|
|
||||||
|
#ifndef __linux__
|
||||||
|
|
||||||
|
switch(thread->getSchedulePolicy()) {
|
||||||
|
|
||||||
|
case Thread::THREAD_SCHEDULE_FIFO:
|
||||||
|
th_policy = SCHED_FIFO;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Thread::THREAD_SCHEDULE_ROUND_ROBIN:
|
||||||
|
th_policy = SCHED_RR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Thread::THREAD_SCHEDULE_TIME_SHARE:
|
||||||
|
th_policy = SCHED_OTHER;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
#ifdef __sgi
|
||||||
|
th_policy = SCHED_RR;
|
||||||
|
#else
|
||||||
|
th_policy = SCHED_FIFO;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
th_policy = SCHED_OTHER; // Must protect linux from realtime.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
|
max_priority = 0;
|
||||||
|
min_priority = 20;
|
||||||
|
nominal_priority = (max_priority + min_priority)/2;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
max_priority = sched_get_priority_max(th_policy);
|
||||||
|
min_priority = sched_get_priority_min(th_policy);
|
||||||
|
nominal_priority = (max_priority + min_priority)/2;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch(thread->getSchedulePriority()) {
|
||||||
|
|
||||||
|
case Thread::THREAD_PRIORITY_MAX:
|
||||||
|
th_param.sched_priority = max_priority;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Thread::THREAD_PRIORITY_HIGH:
|
||||||
|
th_param.sched_priority = (max_priority + nominal_priority)/2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Thread::THREAD_PRIORITY_NOMINAL:
|
||||||
|
th_param.sched_priority = nominal_priority;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Thread::THREAD_PRIORITY_LOW:
|
||||||
|
th_param.sched_priority = (min_priority + nominal_priority)/2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Thread::THREAD_PRIORITY_MIN:
|
||||||
|
th_param.sched_priority = min_priority;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
th_param.sched_priority = max_priority;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
status = pthread_setschedparam(thread->getProcessId(),
|
||||||
|
th_policy,
|
||||||
|
&th_param);
|
||||||
|
|
||||||
|
|
||||||
|
if(getenv("OUTPUT_THREADLIB_SCHEDULING_INFO") != 0)
|
||||||
|
PrintThreadSchedulingInfo(thread);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ] ALLOW_PRIORITY_SCHEDULING
|
||||||
|
|
||||||
|
return status;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the concurrency level (no-op)
|
||||||
|
//
|
||||||
|
// Use static public
|
||||||
|
//
|
||||||
|
int Thread::SetConcurrency(int concurrencyLevel) {
|
||||||
|
|
||||||
|
#if defined (HAVE_PTHREAD_SETCONCURRENCY)
|
||||||
|
return pthread_setconcurrency(concurrencyLevel);
|
||||||
|
#else
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the concurrency level
|
||||||
|
//
|
||||||
|
// Use static public
|
||||||
|
//
|
||||||
|
int Thread::GetConcurrency() {
|
||||||
|
|
||||||
|
#if defined (HAVE_PTHREAD_GETCONCURRENCY)
|
||||||
|
return pthread_getconcurrency();
|
||||||
|
#else
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Constructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Thread::Thread() {
|
||||||
|
|
||||||
|
if(!s_isInitialized) Init();
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = new PThreadPrivateData();
|
||||||
|
pd->stackSize = 0;
|
||||||
|
pd->stackSizeLocked = false;
|
||||||
|
pd->idSet = false;
|
||||||
|
pd->isRunning = false;
|
||||||
|
pd->isCanceled = false;
|
||||||
|
pd->uniqueId = pd->nextId;
|
||||||
|
pd->nextId++;
|
||||||
|
pd->threadPriority = Thread::THREAD_PRIORITY_DEFAULT;
|
||||||
|
pd->threadPolicy = Thread::THREAD_SCHEDULE_DEFAULT;
|
||||||
|
pd->cpunum = -1;
|
||||||
|
|
||||||
|
_prvData = static_cast<void *>(pd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Destructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Thread::~Thread()
|
||||||
|
{
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
if(pd->isRunning)
|
||||||
|
{
|
||||||
|
std::cout<<"Error: Thread "<<this<<" still running in destructor"<<std::endl;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Kill the thread when it is destructed
|
||||||
|
//
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete pd;
|
||||||
|
|
||||||
|
_prvData = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread *Thread::CurrentThread()
|
||||||
|
{
|
||||||
|
|
||||||
|
Thread *thread =
|
||||||
|
static_cast<Thread *>(pthread_getspecific(PThreadPrivateData::s_tls_key));
|
||||||
|
|
||||||
|
return thread;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Initialize Threading
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
void Thread::Init() {
|
||||||
|
|
||||||
|
if(s_isInitialized) return;
|
||||||
|
|
||||||
|
// Allocate a key to be used to access thread local storage
|
||||||
|
int status = pthread_key_create(&PThreadPrivateData::s_tls_key, NULL);
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
printf("Error: pthread_key_create(,) returned error status, status = %d\n",status);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ALLOW_PRIORITY_SCHEDULING
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// If we've got priority scheduling, set things to nominal.
|
||||||
|
//
|
||||||
|
if(sysconf(_POSIX_THREAD_PRIORITY_SCHEDULING)) {
|
||||||
|
|
||||||
|
int max_priority, nominal_priority, min_priority;
|
||||||
|
|
||||||
|
int th_policy;
|
||||||
|
sched_param th_param;
|
||||||
|
pthread_getschedparam(pthread_self(),
|
||||||
|
&th_policy, &th_param);
|
||||||
|
|
||||||
|
max_priority = sched_get_priority_max(th_policy);
|
||||||
|
min_priority = sched_get_priority_min(th_policy);
|
||||||
|
nominal_priority = (max_priority + min_priority)/2;
|
||||||
|
|
||||||
|
th_param.sched_priority = nominal_priority;
|
||||||
|
|
||||||
|
pthread_setschedparam(pthread_self(),
|
||||||
|
th_policy,
|
||||||
|
&th_param);
|
||||||
|
|
||||||
|
s_masterThreadPriority = Thread::THREAD_PRIORITY_NOMINAL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
s_masterThreadPriority = Thread::THREAD_PRIORITY_DEFAULT;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ] ALLOW_PRIORITY_SCHEDULING
|
||||||
|
|
||||||
|
s_isInitialized = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get a unique identifier for this thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::getThreadId() {
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
return pd->uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the thread's process id
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
size_t Thread::getProcessId() {
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
if(pd->idSet == false) return (size_t)(pthread_self());
|
||||||
|
|
||||||
|
return (size_t)(pd->tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's processor affinity
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setProcessorAffinity(unsigned int cpunum)
|
||||||
|
{
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
pd->cpunum = cpunum;
|
||||||
|
if (pd->cpunum<0) return -1;
|
||||||
|
|
||||||
|
#ifdef __sgi
|
||||||
|
|
||||||
|
int status;
|
||||||
|
pthread_attr_t thread_attr;
|
||||||
|
|
||||||
|
status = pthread_attr_init( &thread_attr );
|
||||||
|
if(status != 0) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = pthread_attr_setscope( &thread_attr, PTHREAD_SCOPE_BOUND_NP );
|
||||||
|
return status;
|
||||||
|
|
||||||
|
#elif defined(HAVE_PTHREAD_SETAFFINITY_NP) || defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY) || defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
|
||||||
|
|
||||||
|
if (pd->isRunning && Thread::CurrentThread()==this)
|
||||||
|
{
|
||||||
|
cpu_set_t cpumask;
|
||||||
|
CPU_ZERO( &cpumask );
|
||||||
|
CPU_SET( pd->cpunum, &cpumask );
|
||||||
|
#if defined(HAVE_PTHREAD_SETAFFINITY_NP)
|
||||||
|
pthread_setaffinity_np (pthread_self(), sizeof(cpumask), &cpumask);
|
||||||
|
#elif defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
|
||||||
|
sched_setaffinity( 0, sizeof(cpumask), &cpumask );
|
||||||
|
#elif defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
|
||||||
|
sched_setaffinity( 0, &cpumask );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Determine if the thread is running
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
bool Thread::isRunning() {
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
return pd->isRunning;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Start the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::start() {
|
||||||
|
|
||||||
|
int status;
|
||||||
|
pthread_attr_t thread_attr;
|
||||||
|
|
||||||
|
status = pthread_attr_init( &thread_attr );
|
||||||
|
if(status != 0) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
size_t defaultStackSize;
|
||||||
|
pthread_attr_getstacksize( &thread_attr, &defaultStackSize);
|
||||||
|
if(status != 0) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(defaultStackSize < pd->stackSize) {
|
||||||
|
|
||||||
|
pthread_attr_setstacksize( &thread_attr, pd->stackSize);
|
||||||
|
if(status != 0) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Now get what we actually have...
|
||||||
|
//
|
||||||
|
pthread_attr_getstacksize( &thread_attr, &defaultStackSize);
|
||||||
|
if(status != 0) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
pd->stackSize = defaultStackSize;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Prohibit the stack size from being changed.
|
||||||
|
//
|
||||||
|
pd->stackSizeLocked = true;
|
||||||
|
|
||||||
|
#ifdef ALLOW_PRIORITY_SCHEDULING
|
||||||
|
|
||||||
|
status = pthread_attr_setinheritsched( &thread_attr,
|
||||||
|
PTHREAD_EXPLICIT_SCHED );
|
||||||
|
|
||||||
|
pthread_attr_setscope(&thread_attr, PTHREAD_SCOPE_SYSTEM);
|
||||||
|
|
||||||
|
#endif // ] ALLOW_PRIORITY_SCHEDULING
|
||||||
|
|
||||||
|
if(status != 0) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
pd->threadStartedBlock.reset();
|
||||||
|
|
||||||
|
status = pthread_create(&(pd->tid), &thread_attr,
|
||||||
|
ThreadPrivateActions::StartThread,
|
||||||
|
static_cast<void *>(this));
|
||||||
|
|
||||||
|
// wait till the thread has actually started.
|
||||||
|
pd->threadStartedBlock.block();
|
||||||
|
|
||||||
|
if(status != 0) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
pd->idSet = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Alternate thread start routine.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::startThread()
|
||||||
|
{
|
||||||
|
if (_prvData) return start();
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Join the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::detach() {
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
return pthread_detach(pd->tid);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Join the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::join() {
|
||||||
|
|
||||||
|
void *threadResult = 0; // Dummy var.
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
return pthread_join(pd->tid, &threadResult);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: test the cancel state of the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::testCancel() {
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
if(pthread_self() != pd->tid)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pthread_testcancel();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Cancel the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::cancel() {
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
if (pd->isRunning)
|
||||||
|
{
|
||||||
|
pd->isCanceled = true;
|
||||||
|
int status = pthread_cancel(pd->tid);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Disable cancelibility
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setCancelModeDisable() {
|
||||||
|
|
||||||
|
return pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, 0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: set the thread to cancel immediately
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setCancelModeAsynchronous() {
|
||||||
|
|
||||||
|
int status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
||||||
|
if(status != 0) return status;
|
||||||
|
|
||||||
|
return pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: set the thread to cancel at the next convienent point.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setCancelModeDeferred() {
|
||||||
|
|
||||||
|
int status = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
|
||||||
|
if(status != 0) return status;
|
||||||
|
|
||||||
|
return pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's schedule priority (if able)
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setSchedulePriority(ThreadPriority priority) {
|
||||||
|
|
||||||
|
#ifdef ALLOW_PRIORITY_SCHEDULING
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
pd->threadPriority = priority;
|
||||||
|
|
||||||
|
if(pd->isRunning)
|
||||||
|
return ThreadPrivateActions::SetThreadSchedulingParams(this);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the thread's schedule priority (if able)
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::getSchedulePriority() {
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
return pd->threadPriority;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's scheduling policy (if able)
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setSchedulePolicy(ThreadPolicy policy) {
|
||||||
|
|
||||||
|
#ifdef ALLOW_PRIORITY_SCHEDULING
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
pd->threadPolicy = policy;
|
||||||
|
|
||||||
|
if(pd->isRunning)
|
||||||
|
return ThreadPrivateActions::SetThreadSchedulingParams(this);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's scheduling policy (if able)
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::getSchedulePolicy() {
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
return pd->threadPolicy;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's desired stack size
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setStackSize(size_t stackSize) {
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
if(pd->stackSizeLocked == true) return 13; // EACESS
|
||||||
|
|
||||||
|
pd->stackSize = stackSize;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the thread's stack size.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
size_t Thread::getStackSize() {
|
||||||
|
|
||||||
|
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
return pd->stackSize;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Print the thread's scheduling information to stdout.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
void Thread::printSchedulingInfo() {
|
||||||
|
|
||||||
|
ThreadPrivateActions::PrintThreadSchedulingInfo(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Yield the processor
|
||||||
|
//
|
||||||
|
// Use: protected
|
||||||
|
//
|
||||||
|
int Thread::YieldCurrentThread()
|
||||||
|
{
|
||||||
|
#if defined(HAVE_PTHREAD_YIELD)
|
||||||
|
pthread_yield();
|
||||||
|
return 0;
|
||||||
|
#elif defined(HAVE_SCHED_YIELD)
|
||||||
|
return sched_yield();
|
||||||
|
#else
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Description: sleep
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::microSleep(unsigned int microsec)
|
||||||
|
{
|
||||||
|
return ::usleep(microsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the number of processors
|
||||||
|
//
|
||||||
|
int OpenThreads::GetNumberOfProcessors()
|
||||||
|
{
|
||||||
|
#if defined(__linux__)
|
||||||
|
long ret = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
if (ret == -1)
|
||||||
|
return 0;
|
||||||
|
return ret;
|
||||||
|
#elif defined(__sun__)
|
||||||
|
long ret = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
if (ret == -1)
|
||||||
|
return 0;
|
||||||
|
return ret;
|
||||||
|
#elif defined(__sgi)
|
||||||
|
long ret = sysconf(_SC_NPROC_ONLN);
|
||||||
|
if (ret == -1)
|
||||||
|
return 0;
|
||||||
|
return ret;
|
||||||
|
#elif defined(__hpux)
|
||||||
|
int ret = mpctl(MPC_GETNUMSPUS, 0, NULL);
|
||||||
|
if (ret == -1)
|
||||||
|
return 0;
|
||||||
|
return ret;
|
||||||
|
#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(__MACH__)
|
||||||
|
uint64_t num_cpus = 0;
|
||||||
|
size_t num_cpus_length = sizeof(num_cpus);
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
|
sysctlbyname("hw.ncpu", &num_cpus, &num_cpus_length, NULL, 0);
|
||||||
|
#else
|
||||||
|
sysctlbyname("hw.activecpu", &num_cpus, &num_cpus_length, NULL, 0);
|
||||||
|
#endif
|
||||||
|
return num_cpus;
|
||||||
|
#else
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int OpenThreads::SetProcessorAffinityOfCurrentThread(unsigned int cpunum)
|
||||||
|
{
|
||||||
|
if (cpunum<0) return -1;
|
||||||
|
|
||||||
|
Thread::Init();
|
||||||
|
|
||||||
|
Thread* thread = Thread::CurrentThread();
|
||||||
|
if (thread)
|
||||||
|
{
|
||||||
|
return thread->setProcessorAffinity(cpunum);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(HAVE_PTHREAD_SETAFFINITY_NP) || defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY) || defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
|
||||||
|
cpu_set_t cpumask;
|
||||||
|
CPU_ZERO( &cpumask );
|
||||||
|
CPU_SET( cpunum, &cpumask );
|
||||||
|
|
||||||
|
#if defined(HAVE_PTHREAD_SETAFFINITY_NP)
|
||||||
|
pthread_setaffinity_np( pthread_self(), sizeof(cpumask), &cpumask);
|
||||||
|
#elif defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
|
||||||
|
sched_setaffinity( 0, sizeof(cpumask), &cpumask );
|
||||||
|
#elif defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
|
||||||
|
sched_setaffinity( 0, &cpumask );
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
242
src/OpenThreads/pthreads/PThreadBarrier.c++
Normal file
242
src/OpenThreads/pthreads/PThreadBarrier.c++
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PThreadBarrier.c++ - C++ Barrier class built on top of POSIX threads.
|
||||||
|
// ~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <OpenThreads/Barrier>
|
||||||
|
#include "PThreadBarrierPrivateData.h"
|
||||||
|
|
||||||
|
using namespace OpenThreads;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// This cancel cleanup handler is necessary to ensure that the barrier's
|
||||||
|
// mutex gets unlocked on cancel. Otherwise deadlocks could occur with
|
||||||
|
// later joins.
|
||||||
|
//
|
||||||
|
void barrier_cleanup_handler(void *arg) {
|
||||||
|
|
||||||
|
pthread_mutex_t *mutex = static_cast<pthread_mutex_t *>(arg);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(mutex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Constructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Barrier::Barrier(int numThreads) {
|
||||||
|
|
||||||
|
PThreadBarrierPrivateData *pd = new PThreadBarrierPrivateData();
|
||||||
|
|
||||||
|
pd->cnt = 0;
|
||||||
|
pd->phase = 0;
|
||||||
|
pd->maxcnt = numThreads;
|
||||||
|
|
||||||
|
_valid = true;
|
||||||
|
|
||||||
|
pthread_mutexattr_t mutex_attr;
|
||||||
|
pthread_mutexattr_init( &mutex_attr );
|
||||||
|
|
||||||
|
#ifndef __linux__ // (not available until NPTL) [
|
||||||
|
pthread_mutexattr_settype( &mutex_attr, PTHREAD_MUTEX_ERRORCHECK );
|
||||||
|
#endif // ] __linux__
|
||||||
|
|
||||||
|
#ifdef ALLOW_PRIORITY_SCHEDULING // [
|
||||||
|
|
||||||
|
#ifdef __sun // [
|
||||||
|
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_NONE);
|
||||||
|
#endif // ] __sun
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Initialization is a bit tricky, since we have to be able to be aware
|
||||||
|
// that on many-to-many execution vehicle systems, we may run into
|
||||||
|
// priority inversion deadlocks if a mutex is shared between threads
|
||||||
|
// of differing priorities. Systems that do this should provide the
|
||||||
|
// following protocol attributes to prevent deadlocks. Check at runtime.
|
||||||
|
//
|
||||||
|
// PRIO_INHERIT causes any thread locking the mutex to temporarily become
|
||||||
|
// the same priority as the highest thread also blocked on the mutex.
|
||||||
|
// Although more expensive, this is the prefered method.
|
||||||
|
//
|
||||||
|
// PRIO_PROTECT causes any thread locking the mutex to assume the priority
|
||||||
|
// specified by setprioceiling. pthread_mutex_lock will fail if
|
||||||
|
// the priority ceiling is lower than the thread's priority. Therefore,
|
||||||
|
// the priority ceiling must be set to the max priority in order to
|
||||||
|
// garantee no deadlocks will occur.
|
||||||
|
//
|
||||||
|
#if defined (_POSIX_THREAD_PRIO_INHERIT) || defined (_POSIX_THREAD_PRIO_PROTECT) // [
|
||||||
|
|
||||||
|
if(sysconf(_POSIX_THREAD_PRIO_INHERIT)) {
|
||||||
|
|
||||||
|
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT);
|
||||||
|
|
||||||
|
} else if (sysconf(_POSIX_THREAD_PRIO_PROTECT)) {
|
||||||
|
|
||||||
|
int th_policy;
|
||||||
|
struct sched_param th_param;
|
||||||
|
pthread_getschedparam(pthread_self(), &th_policy, &th_param);
|
||||||
|
|
||||||
|
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_PROTECT);
|
||||||
|
pthread_mutexattr_setprioceiling(&mutex_attr,
|
||||||
|
sched_get_priority_max(th_policy));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ] Priority sheduling
|
||||||
|
|
||||||
|
#endif // ] ALLOW_PRIORITY_SCHEDULING
|
||||||
|
|
||||||
|
pthread_mutex_init(&(pd->lock), &mutex_attr);
|
||||||
|
|
||||||
|
pthread_cond_init(&(pd->cond), NULL);
|
||||||
|
|
||||||
|
_prvData = static_cast<void *>(pd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Destructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Barrier::~Barrier() {
|
||||||
|
|
||||||
|
PThreadBarrierPrivateData *pd =
|
||||||
|
static_cast<PThreadBarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&(pd->lock));
|
||||||
|
|
||||||
|
pthread_cond_destroy(&(pd->cond));
|
||||||
|
|
||||||
|
delete pd;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Reset the barrier to its original state
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
void Barrier::reset() {
|
||||||
|
|
||||||
|
PThreadBarrierPrivateData *pd =
|
||||||
|
static_cast<PThreadBarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
pd->cnt = 0;
|
||||||
|
pd->phase = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Block until numThreads threads have entered the barrier.
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
void Barrier::block(unsigned int numThreads) {
|
||||||
|
|
||||||
|
PThreadBarrierPrivateData *pd =
|
||||||
|
static_cast<PThreadBarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
if(numThreads != 0) pd->maxcnt = numThreads;
|
||||||
|
|
||||||
|
int my_phase;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(pd->lock));
|
||||||
|
if( _valid )
|
||||||
|
{
|
||||||
|
my_phase = pd->phase;
|
||||||
|
++pd->cnt;
|
||||||
|
|
||||||
|
if (pd->cnt == pd->maxcnt) { // I am the last one
|
||||||
|
pd->cnt = 0; // reset for next use
|
||||||
|
pd->phase = 1 - my_phase; // toggle phase
|
||||||
|
pthread_cond_broadcast(&(pd->cond));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pd->phase == my_phase) {
|
||||||
|
|
||||||
|
pthread_cleanup_push(barrier_cleanup_handler, &(pd->lock));
|
||||||
|
|
||||||
|
pthread_cond_wait(&(pd->cond), &(pd->lock));
|
||||||
|
|
||||||
|
pthread_cleanup_pop(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&(pd->lock));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Barrier::invalidate()
|
||||||
|
{
|
||||||
|
PThreadBarrierPrivateData *pd =
|
||||||
|
static_cast<PThreadBarrierPrivateData*>(_prvData);
|
||||||
|
pthread_mutex_lock(&(pd->lock));
|
||||||
|
_valid = false;
|
||||||
|
pthread_mutex_unlock(&(pd->lock));
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Release the barrier, now.
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
void Barrier::release() {
|
||||||
|
|
||||||
|
PThreadBarrierPrivateData *pd =
|
||||||
|
static_cast<PThreadBarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
int my_phase;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(pd->lock));
|
||||||
|
my_phase = pd->phase;
|
||||||
|
|
||||||
|
pd->cnt = 0; // reset for next use
|
||||||
|
pd->phase = 1 - my_phase; // toggle phase
|
||||||
|
pthread_cond_broadcast(&(pd->cond));
|
||||||
|
pthread_mutex_unlock(&(pd->lock));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Return the number of threads currently blocked in the barrier
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Barrier::numThreadsCurrentlyBlocked() {
|
||||||
|
|
||||||
|
PThreadBarrierPrivateData *pd = static_cast<PThreadBarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
|
||||||
|
int numBlocked = -1;
|
||||||
|
pthread_mutex_lock(&(pd->lock));
|
||||||
|
numBlocked = pd->cnt;
|
||||||
|
pthread_mutex_unlock(&(pd->lock));
|
||||||
|
|
||||||
|
return numBlocked;
|
||||||
|
}
|
52
src/OpenThreads/pthreads/PThreadBarrierPrivateData.h
Normal file
52
src/OpenThreads/pthreads/PThreadBarrierPrivateData.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PThreadBarrierPrivateData.h - private data structure for barrier
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _PTHREADBARRIERPRIVATEDATA_H_
|
||||||
|
#define _PTHREADBARRIERPRIVATEDATA_H_
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <OpenThreads/Barrier>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class PThreadBarrierPrivateData {
|
||||||
|
|
||||||
|
friend class Barrier;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
PThreadBarrierPrivateData() {};
|
||||||
|
|
||||||
|
virtual ~PThreadBarrierPrivateData() {};
|
||||||
|
|
||||||
|
pthread_cond_t cond; // cv for waiters at barrier
|
||||||
|
|
||||||
|
pthread_mutex_t lock; // mutex for waiters at barrier
|
||||||
|
|
||||||
|
volatile int maxcnt; // number of threads to wait for
|
||||||
|
|
||||||
|
volatile int cnt; // number of waiting threads
|
||||||
|
|
||||||
|
volatile int phase; // flag to seperate two barriers
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //_PTHREADBARRIERPRIVATEDATA_H_
|
218
src/OpenThreads/pthreads/PThreadCondition.c++
Normal file
218
src/OpenThreads/pthreads/PThreadCondition.c++
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PThreadCondition.c++ - C++ Condition class built on top of posix threads.
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
# include <time.h>
|
||||||
|
#else
|
||||||
|
# include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
#include "PThreadConditionPrivateData.h"
|
||||||
|
#include "PThreadMutexPrivateData.h"
|
||||||
|
|
||||||
|
using namespace OpenThreads;
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
int gettimeofday(struct timeval* tp, void* tzp) {
|
||||||
|
LARGE_INTEGER t;
|
||||||
|
|
||||||
|
if(QueryPerformanceCounter(&t)) {
|
||||||
|
/* hardware supports a performance counter */
|
||||||
|
static int been_here = 0;
|
||||||
|
static LARGE_INTEGER f;
|
||||||
|
if( !been_here )
|
||||||
|
{
|
||||||
|
been_here = 1;
|
||||||
|
QueryPerformanceFrequency(&f);
|
||||||
|
}
|
||||||
|
tp->tv_sec = t.QuadPart/f.QuadPart;
|
||||||
|
tp->tv_usec = ((float)t.QuadPart/f.QuadPart*1000*1000)
|
||||||
|
- (tp->tv_sec*1000*1000);
|
||||||
|
} else {
|
||||||
|
/* hardware doesn't support a performance counter, so get the
|
||||||
|
time in a more traditional way. */
|
||||||
|
DWORD t;
|
||||||
|
t = timeGetTime();
|
||||||
|
tp->tv_sec = t / 1000;
|
||||||
|
tp->tv_usec = t % 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 0 indicates that the call succeeded. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// This cancel cleanup handler is necessary to ensure that the barrier's
|
||||||
|
// mutex gets unlocked on cancel. Otherwise deadlocks could occur with
|
||||||
|
// later joins.
|
||||||
|
//
|
||||||
|
void condition_cleanup_handler(void *arg) {
|
||||||
|
|
||||||
|
pthread_mutex_t *mutex = static_cast<pthread_mutex_t *>(arg);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(mutex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Constructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Condition::Condition() {
|
||||||
|
|
||||||
|
PThreadConditionPrivateData *pd =
|
||||||
|
new PThreadConditionPrivateData();
|
||||||
|
|
||||||
|
int status = pthread_cond_init( &pd->condition, NULL );
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
printf("Error: pthread_cond_init(,) returned error status, status = %d\n",status);
|
||||||
|
}
|
||||||
|
|
||||||
|
_prvData = static_cast<void *>(pd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Destructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Condition::~Condition() {
|
||||||
|
|
||||||
|
PThreadConditionPrivateData *pd =
|
||||||
|
static_cast<PThreadConditionPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
int status = pthread_cond_destroy( &pd->condition );
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
printf("Error: pthread_cond_destroy(,) returned error status, status = %d\n",status);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete pd;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: wait on a condition
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Condition::wait(Mutex *mutex) {
|
||||||
|
|
||||||
|
PThreadConditionPrivateData *pd =
|
||||||
|
static_cast<PThreadConditionPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
PThreadMutexPrivateData *mpd =
|
||||||
|
static_cast<PThreadMutexPrivateData *>(mutex->_prvData);
|
||||||
|
|
||||||
|
int status;
|
||||||
|
|
||||||
|
pthread_cleanup_push(condition_cleanup_handler, &mpd->mutex);
|
||||||
|
|
||||||
|
status = pthread_cond_wait( &pd->condition, &mpd->mutex );
|
||||||
|
|
||||||
|
pthread_cleanup_pop(0);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: wait on a condition, for a specified period of time
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Condition::wait(Mutex *mutex, unsigned long int ms) {
|
||||||
|
|
||||||
|
PThreadConditionPrivateData *pd =
|
||||||
|
static_cast<PThreadConditionPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
PThreadMutexPrivateData *mpd =
|
||||||
|
static_cast<PThreadMutexPrivateData *>(mutex->_prvData);
|
||||||
|
|
||||||
|
|
||||||
|
// wait time is now in ms milliseconds, so need to convert to seconds and nanoseconds for timespec strucuture.
|
||||||
|
unsigned int sec = ms / 1000;
|
||||||
|
unsigned int nsec = (ms % 1000) * 1000000;
|
||||||
|
|
||||||
|
// add to the current time
|
||||||
|
struct ::timeval now;
|
||||||
|
::gettimeofday( &now, 0 );
|
||||||
|
|
||||||
|
sec += now.tv_sec;
|
||||||
|
nsec += now.tv_usec*1000;
|
||||||
|
|
||||||
|
// now pass on any overflow from nsec onto seconds.
|
||||||
|
sec += nsec / 1000000000;
|
||||||
|
nsec = nsec % 1000000000;
|
||||||
|
|
||||||
|
struct timespec abstime;
|
||||||
|
abstime.tv_sec = sec;
|
||||||
|
abstime.tv_nsec = nsec;
|
||||||
|
|
||||||
|
int status;
|
||||||
|
|
||||||
|
pthread_cleanup_push(condition_cleanup_handler, &mpd->mutex);
|
||||||
|
|
||||||
|
status = pthread_cond_timedwait( &pd->condition, &mpd->mutex, &abstime );
|
||||||
|
|
||||||
|
pthread_cleanup_pop(0);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: signal a thread to wake up.
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Condition::signal() {
|
||||||
|
|
||||||
|
PThreadConditionPrivateData *pd =
|
||||||
|
static_cast<PThreadConditionPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
return pthread_cond_signal( &pd->condition );
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: signal many threads to wake up.
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Condition::broadcast() {
|
||||||
|
|
||||||
|
PThreadConditionPrivateData *pd =
|
||||||
|
static_cast<PThreadConditionPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
return pthread_cond_broadcast( &pd->condition );
|
||||||
|
}
|
44
src/OpenThreads/pthreads/PThreadConditionPrivateData.h
Normal file
44
src/OpenThreads/pthreads/PThreadConditionPrivateData.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PThreadConditionPrivateData.h - Private data structure for Condition
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _PTHREADCONDITIONPRIVATEDATA_H_
|
||||||
|
#define _PTHREADCONDITIONPRIVATEDATA_H_
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class PThreadConditionPrivateData {
|
||||||
|
|
||||||
|
friend class Condition;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
PThreadConditionPrivateData() {};
|
||||||
|
|
||||||
|
virtual ~PThreadConditionPrivateData() {};
|
||||||
|
|
||||||
|
pthread_cond_t condition;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !_PTHREADCONDITIONPRIVATEDATA_H_
|
154
src/OpenThreads/pthreads/PThreadMutex.c++
Normal file
154
src/OpenThreads/pthreads/PThreadMutex.c++
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PThreadMutex.c++ - C++ Mutex class built on top of posix threads.
|
||||||
|
// ~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
#include "PThreadMutexPrivateData.h"
|
||||||
|
|
||||||
|
using namespace OpenThreads;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Constructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Mutex::Mutex() {
|
||||||
|
|
||||||
|
pthread_mutexattr_t mutex_attr;
|
||||||
|
pthread_mutexattr_init( &mutex_attr );
|
||||||
|
|
||||||
|
PThreadMutexPrivateData *pd = new PThreadMutexPrivateData();
|
||||||
|
|
||||||
|
#ifndef __linux__ // (not available until NPTL) [
|
||||||
|
pthread_mutexattr_settype( &mutex_attr, PTHREAD_MUTEX_ERRORCHECK );
|
||||||
|
#endif // ] __linux__
|
||||||
|
|
||||||
|
#ifdef ALLOW_PRIORITY_SCHEDULING // [
|
||||||
|
|
||||||
|
#ifdef __sun // [
|
||||||
|
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_NONE);
|
||||||
|
#endif // ] __sun
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Initialization is a bit tricky, since we have to be able to be aware
|
||||||
|
// that on many-to-many execution vehicle systems, we may run into
|
||||||
|
// priority inversion deadlocks if a mutex is shared between threads
|
||||||
|
// of differing priorities. Systems that do this should provide the
|
||||||
|
// following protocol attributes to prevent deadlocks. Check at runtime.
|
||||||
|
//
|
||||||
|
// PRIO_INHERIT causes any thread locking the mutex to temporarily become
|
||||||
|
// the same priority as the highest thread also blocked on the mutex.
|
||||||
|
// Although more expensive, this is the prefered method.
|
||||||
|
//
|
||||||
|
// PRIO_PROTECT causes any thread locking the mutex to assume the priority
|
||||||
|
// specified by setprioceiling. pthread_mutex_lock will fail if
|
||||||
|
// the priority ceiling is lower than the thread's priority. Therefore,
|
||||||
|
// the priority ceiling must be set to the max priority in order to
|
||||||
|
// garantee no deadlocks will occur.
|
||||||
|
//
|
||||||
|
#if defined (_POSIX_THREAD_PRIO_INHERIT) || defined (_POSIX_THREAD_PRIO_PROTECT) // [
|
||||||
|
|
||||||
|
if(sysconf(_POSIX_THREAD_PRIO_INHERIT)) {
|
||||||
|
|
||||||
|
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT);
|
||||||
|
|
||||||
|
} else if (sysconf(_POSIX_THREAD_PRIO_PROTECT)) {
|
||||||
|
|
||||||
|
int th_policy;
|
||||||
|
struct sched_param th_param;
|
||||||
|
pthread_getschedparam(pthread_self(), &th_policy, &th_param);
|
||||||
|
|
||||||
|
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_PROTECT);
|
||||||
|
pthread_mutexattr_setprioceiling(&mutex_attr,
|
||||||
|
sched_get_priority_max(th_policy));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ] Priority Scheduling.
|
||||||
|
|
||||||
|
#endif // ] ALLOW_PRIORITY_SCHEDULING
|
||||||
|
|
||||||
|
pthread_mutex_init(&pd->mutex, &mutex_attr);
|
||||||
|
_prvData = static_cast<void *>(pd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Destructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Mutex::~Mutex() {
|
||||||
|
|
||||||
|
PThreadMutexPrivateData *pd =
|
||||||
|
static_cast<PThreadMutexPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&pd->mutex);
|
||||||
|
|
||||||
|
delete pd;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: lock the mutex
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Mutex::lock() {
|
||||||
|
|
||||||
|
PThreadMutexPrivateData *pd =
|
||||||
|
static_cast<PThreadMutexPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
return pthread_mutex_lock(&pd->mutex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: unlock the mutex
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Mutex::unlock() {
|
||||||
|
|
||||||
|
PThreadMutexPrivateData *pd =
|
||||||
|
static_cast<PThreadMutexPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
return pthread_mutex_unlock(&pd->mutex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: test if the mutex may be locked
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Mutex::trylock() {
|
||||||
|
|
||||||
|
PThreadMutexPrivateData *pd =
|
||||||
|
static_cast<PThreadMutexPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
return pthread_mutex_trylock(&pd->mutex);
|
||||||
|
|
||||||
|
}
|
47
src/OpenThreads/pthreads/PThreadMutexPrivateData.h
Normal file
47
src/OpenThreads/pthreads/PThreadMutexPrivateData.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PThreadMutexPrivateData.h - Private data structure for Mutex
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _PTHREADMUTEXPRIVATEDATA_H_
|
||||||
|
#define _PTHREADMUTEXPRIVATEDATA_H_
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class PThreadMutexPrivateData {
|
||||||
|
|
||||||
|
friend class Mutex;
|
||||||
|
|
||||||
|
friend class Condition;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
PThreadMutexPrivateData() {};
|
||||||
|
|
||||||
|
virtual ~PThreadMutexPrivateData() {};
|
||||||
|
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !_PTHREADMUTEXPRIVATEDATA_H_
|
||||||
|
|
78
src/OpenThreads/pthreads/PThreadPrivateData.h
Normal file
78
src/OpenThreads/pthreads/PThreadPrivateData.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PThreadPrivateData.h - Private data structure for Thread
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#ifndef _PTHREADPRIVATEDATA_H_
|
||||||
|
#define _PTHREADPRIVATEDATA_H_
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <OpenThreads/Block>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class PThreadPrivateData {
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// We're friendly to Thread, so it can use our data.
|
||||||
|
//
|
||||||
|
friend class Thread;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// We're friendly to PThreadPrivateActions, so it can get at some
|
||||||
|
// variables.
|
||||||
|
//
|
||||||
|
friend class ThreadPrivateActions;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
PThreadPrivateData() {};
|
||||||
|
|
||||||
|
virtual ~PThreadPrivateData() {};
|
||||||
|
|
||||||
|
volatile unsigned int stackSize;
|
||||||
|
|
||||||
|
volatile bool stackSizeLocked;
|
||||||
|
|
||||||
|
volatile bool isRunning;
|
||||||
|
|
||||||
|
Block threadStartedBlock;
|
||||||
|
|
||||||
|
volatile bool isCanceled;
|
||||||
|
|
||||||
|
volatile bool idSet;
|
||||||
|
|
||||||
|
volatile Thread::ThreadPriority threadPriority;
|
||||||
|
|
||||||
|
volatile Thread::ThreadPolicy threadPolicy;
|
||||||
|
|
||||||
|
pthread_t tid;
|
||||||
|
|
||||||
|
volatile int uniqueId;
|
||||||
|
|
||||||
|
volatile int cpunum;
|
||||||
|
|
||||||
|
|
||||||
|
static int nextId;
|
||||||
|
|
||||||
|
static pthread_key_t s_tls_key;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !_PTHREADPRIVATEDATA_H_
|
49
src/OpenThreads/sproc/CMakeLists.txt
Normal file
49
src/OpenThreads/sproc/CMakeLists.txt
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# This file should only be included when using Sproc
|
||||||
|
|
||||||
|
SET(LIB_NAME OpenThreads)
|
||||||
|
SET(LIB_PUBLIC_HEADERS ${OpenThreads_PUBLIC_HEADERS})
|
||||||
|
|
||||||
|
ADD_LIBRARY(${LIB_NAME}
|
||||||
|
${OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC}
|
||||||
|
${LIB_PUBLIC_HEADERS}
|
||||||
|
SharedArena.c++
|
||||||
|
SharedArena.h
|
||||||
|
SprocBarrier.c++
|
||||||
|
SprocBarrierPrivateData.h
|
||||||
|
SprocCondition.c++
|
||||||
|
SprocConditionPrivateData.h
|
||||||
|
SprocMutex.c++
|
||||||
|
SprocMutexPrivateData.h
|
||||||
|
SprocThread.c++
|
||||||
|
SprocThreadPrivateActions.h
|
||||||
|
SprocThreadPrivateData.h
|
||||||
|
../common/Version.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
IF(OPENTHREADS_SONAMES)
|
||||||
|
SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${OPENTHREADS_VERSION} SOVERSION ${OPENTHREADS_SOVERSION})
|
||||||
|
ENDIF(OPENTHREADS_SONAMES)
|
||||||
|
|
||||||
|
# Do we need to link against anything for Sproc?
|
||||||
|
#TARGET_LINK_LIBRARIES(${LIB_NAME}
|
||||||
|
#)
|
||||||
|
|
||||||
|
# Since we're building different platforms binaries in
|
||||||
|
# their respective directories, we need to set the
|
||||||
|
# link directory so it can find this location.
|
||||||
|
LINK_DIRECTORIES(
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
INSTALL(
|
||||||
|
TARGETS OpenThreads
|
||||||
|
ARCHIVE DESTINATION lib${LIB_POSTFIX}
|
||||||
|
LIBRARY DESTINATION lib${LIB_POSTFIX}
|
||||||
|
RUNTIME DESTINATION bin
|
||||||
|
)
|
||||||
|
INSTALL(
|
||||||
|
FILES ${OpenThreads_PUBLIC_HEADERS}
|
||||||
|
DESTINATION include/OpenThreads
|
||||||
|
)
|
||||||
|
|
||||||
|
#commented out# INCLUDE(ModuleInstall OPTIONAL)
|
17
src/OpenThreads/sproc/GNUmakefile
Normal file
17
src/OpenThreads/sproc/GNUmakefile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
TOPDIR = ../.
|
||||||
|
include $(TOPDIR)/Make/makedefs
|
||||||
|
|
||||||
|
C++FILES = \
|
||||||
|
SprocThread.c++ \
|
||||||
|
SprocMutex.c++ \
|
||||||
|
SprocBarrier.c++ \
|
||||||
|
SprocCondition.c++ \
|
||||||
|
SharedArena.c++ \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
INC += -I$(TOPDIR)/include -I.
|
||||||
|
|
||||||
|
TARGET_BASENAME = OpenThreads
|
||||||
|
LIB = libOpenThreads
|
||||||
|
|
||||||
|
include $(TOPDIR)/Make/makerules
|
256
src/OpenThreads/sproc/SharedArena.c++
Executable file
256
src/OpenThreads/sproc/SharedArena.c++
Executable file
@ -0,0 +1,256 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// SharedArena.c++ - Facilities for creating/destroying shared arenas
|
||||||
|
// ~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <bstring.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "SharedArena.h"
|
||||||
|
|
||||||
|
using namespace OpenThreads;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
# define DPRINTF(arg) printf arg
|
||||||
|
#else
|
||||||
|
# define DPRINTF(arg)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_PROCS 1024
|
||||||
|
|
||||||
|
#define SEMAPHORE_ARENA_SIZE 500000
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Static arena initialization
|
||||||
|
//
|
||||||
|
usptr_t *SharedArena::_arena = 0;
|
||||||
|
|
||||||
|
int SharedArena::_numLocks = 0;
|
||||||
|
|
||||||
|
char *SharedArena::_arenaName = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void SharedArena::initArena() {
|
||||||
|
|
||||||
|
_arenaName = tmpnam(0);
|
||||||
|
DPRINTF(("Creating arena: %s\n", _arenaName));
|
||||||
|
|
||||||
|
if (unlink(_arenaName) < 0) {
|
||||||
|
if (errno != ENOENT) {
|
||||||
|
perror("unlink");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usconfig(CONF_INITUSERS, MAX_PROCS) < 0) {
|
||||||
|
perror("usconfig1");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef OT_USESHAREDONLY
|
||||||
|
if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0) {
|
||||||
|
perror("usconfig2");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *sema_arena_size_string = getenv("OPENTHREADS_SEMAPHORE_ARENA_SIZE");
|
||||||
|
unsigned long int sema_arena_size;
|
||||||
|
if(sema_arena_size_string != 0L) {
|
||||||
|
sema_arena_size = atol(sema_arena_size_string);
|
||||||
|
} else {
|
||||||
|
sema_arena_size = SEMAPHORE_ARENA_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usconfig(CONF_INITSIZE,sema_arena_size) < 0) {
|
||||||
|
perror("usconfig3");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ((_arena = usinit(_arenaName)) == 0) {
|
||||||
|
perror("usinit");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedArena::removeArena() {
|
||||||
|
|
||||||
|
DPRINTF(("Removing arena: %s\n", _arenaName));
|
||||||
|
#ifndef OT_USESHAREDONLY
|
||||||
|
|
||||||
|
if (unlink(_arenaName) < 0) {
|
||||||
|
perror("unlink");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ulock_t SharedArena::allocLock() {
|
||||||
|
|
||||||
|
if(_numLocks == 0) initArena();
|
||||||
|
|
||||||
|
assert(_arena != 0);
|
||||||
|
|
||||||
|
ulock_t lock;
|
||||||
|
if ((lock = usnewlock(_arena)) == 0) {
|
||||||
|
perror("usnewlock");
|
||||||
|
printf("Num Locks: %d\n", _numLocks);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
++_numLocks;
|
||||||
|
return lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
barrier_t *SharedArena::allocBarrier() {
|
||||||
|
|
||||||
|
if(_numLocks == 0) initArena();
|
||||||
|
|
||||||
|
assert(_arena != 0);
|
||||||
|
barrier_t *bar;
|
||||||
|
if ((bar= new_barrier(_arena)) == 0) {
|
||||||
|
perror("new_barrier");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
++_numLocks;
|
||||||
|
return bar;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedArena::lock(ulock_t lock) {
|
||||||
|
|
||||||
|
return ussetlock(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedArena::unlock(ulock_t lock) {
|
||||||
|
|
||||||
|
return usunsetlock(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedArena::trylock(ulock_t lock) {
|
||||||
|
|
||||||
|
return ustestlock(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedArena::deleteLock(ulock_t lock) {
|
||||||
|
|
||||||
|
assert(_arena != 0);
|
||||||
|
usfreelock(lock, _arena);
|
||||||
|
--_numLocks;
|
||||||
|
if(_numLocks == 0) {
|
||||||
|
removeArena();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedArena::initBarrier(barrier_t *b) {
|
||||||
|
init_barrier(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedArena::freeBarrier(barrier_t *b) {
|
||||||
|
assert(_arena != 0);
|
||||||
|
free_barrier(b);
|
||||||
|
b = 0;
|
||||||
|
--_numLocks;
|
||||||
|
if(_numLocks == 0) {
|
||||||
|
removeArena();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedArena::block(barrier_t *b, unsigned int n) {
|
||||||
|
barrier(b, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
usema_t *SharedArena::allocSema() {
|
||||||
|
|
||||||
|
if(_numLocks == 0) initArena();
|
||||||
|
assert(_arena != 0);
|
||||||
|
|
||||||
|
usema_t *sema;
|
||||||
|
sema = usnewpollsema(_arena, 0);
|
||||||
|
if(sema == 0) {
|
||||||
|
perror("usnewpollsema");
|
||||||
|
printf("NUM SEMAS: %d\n", _numLocks);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
++_numLocks;
|
||||||
|
return sema;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedArena::getSemaFd(usema_t *sema) {
|
||||||
|
|
||||||
|
int returnval;
|
||||||
|
returnval = usopenpollsema(sema, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||||
|
if(0 > returnval) {
|
||||||
|
perror("usopenpollsema");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return returnval;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int SharedArena::pSema(usema_t *sema) {
|
||||||
|
|
||||||
|
return uspsema(sema);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedArena::vSema(usema_t *sema) {
|
||||||
|
|
||||||
|
return usvsema(sema);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedArena::testSema(usema_t *sema) {
|
||||||
|
|
||||||
|
return ustestsema(sema);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedArena::closeSemaFd(usema_t *sema) {
|
||||||
|
|
||||||
|
int returnval;
|
||||||
|
returnval = usclosepollsema(sema);
|
||||||
|
if(returnval != 0) {
|
||||||
|
perror("usclosepollsema");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnval;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedArena::freeSema(usema_t *sema) {
|
||||||
|
|
||||||
|
assert(_arena != 0);
|
||||||
|
usfreepollsema(sema, _arena);
|
||||||
|
--_numLocks;
|
||||||
|
if(_numLocks == 0) {
|
||||||
|
removeArena();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef OT_USESHAREDONLY
|
87
src/OpenThreads/sproc/SharedArena.h
Executable file
87
src/OpenThreads/sproc/SharedArena.h
Executable file
@ -0,0 +1,87 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// SharedArena.h - Facilities for creating/destroying shared arenas
|
||||||
|
// ~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#ifndef _SHAREDARENA_H_
|
||||||
|
#define _SHAREDARENA_H_
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <ulocks.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
#define OT_USESHAREDONLY
|
||||||
|
|
||||||
|
class SharedArena {
|
||||||
|
|
||||||
|
friend class Mutex;
|
||||||
|
|
||||||
|
friend class Barrier;
|
||||||
|
|
||||||
|
friend class Condition;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static void initArena();
|
||||||
|
|
||||||
|
static void removeArena();
|
||||||
|
|
||||||
|
static ulock_t allocLock();
|
||||||
|
|
||||||
|
static barrier_t *allocBarrier();
|
||||||
|
|
||||||
|
static usema_t *allocSema();
|
||||||
|
|
||||||
|
static int getSemaFd(usema_t *sema);
|
||||||
|
|
||||||
|
static int pSema(usema_t *sema);
|
||||||
|
|
||||||
|
static int vSema(usema_t *sema);
|
||||||
|
|
||||||
|
static int testSema(usema_t *sema);
|
||||||
|
|
||||||
|
static int closeSemaFd(usema_t *sema);
|
||||||
|
|
||||||
|
static int freeSema(usema_t *sema);
|
||||||
|
|
||||||
|
static int lock(ulock_t lock);
|
||||||
|
|
||||||
|
static int unlock(ulock_t lock);
|
||||||
|
|
||||||
|
static int trylock(ulock_t lock);
|
||||||
|
|
||||||
|
static void deleteLock(ulock_t lock);
|
||||||
|
|
||||||
|
static void initBarrier(barrier_t *b);
|
||||||
|
|
||||||
|
static void freeBarrier(barrier_t *b);
|
||||||
|
|
||||||
|
static void block(barrier_t *b, unsigned int n);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static usptr_t *_arena;
|
||||||
|
|
||||||
|
static int _numLocks;
|
||||||
|
|
||||||
|
static char *_arenaName;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !_SHAREDARENA_H_
|
229
src/OpenThreads/sproc/SprocBarrier.c++
Executable file
229
src/OpenThreads/sproc/SprocBarrier.c++
Executable file
@ -0,0 +1,229 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// SprocBarrier.c++ - C++ Barrier class built on top of IRIX process threads.
|
||||||
|
// ~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#include <ulocks.h>
|
||||||
|
#include <OpenThreads/Barrier>
|
||||||
|
#include "SprocBarrierPrivateData.h"
|
||||||
|
#include "SharedArena.h"
|
||||||
|
#include "SprocThreadPrivateActions.h"
|
||||||
|
|
||||||
|
#ifndef USE_IRIX_NATIVE_BARRIER
|
||||||
|
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define DPRINTF(arg) printf arg; fflush(stdout);
|
||||||
|
#else
|
||||||
|
#define DPRINTF(arg)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace OpenThreads;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// This cancel cleanup handler is necessary to ensure that the barrier's
|
||||||
|
// mutex gets unlocked on cancel. Otherwise deadlocks could occur with
|
||||||
|
// later joins.
|
||||||
|
//
|
||||||
|
void barrier_cleanup_handler(void *arg) {
|
||||||
|
|
||||||
|
DPRINTF(("(SPROC BARRIER) cleanup handler called on pid %d\n", getpid()));
|
||||||
|
|
||||||
|
Mutex *mutex = static_cast<Mutex *>(arg);
|
||||||
|
|
||||||
|
if(mutex->trylock() == 1)
|
||||||
|
mutex->unlock();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Constructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Barrier::Barrier(int numThreads) {
|
||||||
|
|
||||||
|
SprocBarrierPrivateData *pd = new SprocBarrierPrivateData();
|
||||||
|
|
||||||
|
#ifdef USE_IRIX_NATIVE_BARRIER
|
||||||
|
|
||||||
|
pd->barrier = SharedArena::allocBarrier();
|
||||||
|
pd->numThreads = numThreads;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
pd->cnt = 0;
|
||||||
|
pd->phase = 0;
|
||||||
|
pd->maxcnt = numThreads;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_prvData = static_cast<void *>(pd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Destructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Barrier::~Barrier() {
|
||||||
|
|
||||||
|
SprocBarrierPrivateData *pd =
|
||||||
|
static_cast<SprocBarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
#ifdef USE_IRIX_NATIVE_BARRIER
|
||||||
|
|
||||||
|
SharedArena::freeBarrier(pd->barrier);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
delete pd;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Reset the barrier to its original state
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
void Barrier::reset() {
|
||||||
|
|
||||||
|
SprocBarrierPrivateData *pd =
|
||||||
|
static_cast<SprocBarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
#ifdef USE_IRIX_NATIVE_BARRIER
|
||||||
|
|
||||||
|
SharedArena::initBarrier(pd->barrier);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
pd->cnt = 0;
|
||||||
|
pd->phase = 0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Block until numThreads threads have entered the barrier.
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
void Barrier::block(unsigned int numThreads) {
|
||||||
|
|
||||||
|
SprocBarrierPrivateData *pd =
|
||||||
|
static_cast<SprocBarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
#ifdef USE_IRIX_NATIVE_BARRIER
|
||||||
|
|
||||||
|
if(numThreads == 0) {
|
||||||
|
SharedArena::block(pd->barrier, pd->numThreads);
|
||||||
|
} else {
|
||||||
|
SharedArena::block(pd->barrier, numThreads);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
pd->_mutex.lock();
|
||||||
|
|
||||||
|
if(numThreads != 0) pd->maxcnt = numThreads;
|
||||||
|
|
||||||
|
int my_phase;
|
||||||
|
|
||||||
|
my_phase = pd->phase;
|
||||||
|
++pd->cnt;
|
||||||
|
|
||||||
|
DPRINTF(("(SPROC BARRIER %d) block, count=%d, maxThreads=%d, phase=%d\n",
|
||||||
|
getpid(), pd->cnt, pd->maxcnt, pd->phase));
|
||||||
|
|
||||||
|
if(pd->cnt == pd->maxcnt) { // I am the last one
|
||||||
|
pd->cnt = 0; // reset for next use
|
||||||
|
pd->phase = 1 - my_phase; // toggle phase
|
||||||
|
pd->_cond.broadcast();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pd->phase == my_phase) {
|
||||||
|
ThreadPrivateActions::PushCancelFunction(barrier_cleanup_handler,
|
||||||
|
&pd->_mutex);
|
||||||
|
pd->_cond.wait(&pd->_mutex);
|
||||||
|
|
||||||
|
ThreadPrivateActions::PopCancelFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
pd->_mutex.unlock();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Release the barrier, now.
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
void Barrier::release() {
|
||||||
|
|
||||||
|
SprocBarrierPrivateData *pd =
|
||||||
|
static_cast<SprocBarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
#ifdef USE_IRIX_NATIVE_BARRIER
|
||||||
|
|
||||||
|
printf("ERROR >>>>> Barrier::release() cannot be implemented using native IRIX Barriers !!!\n");
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int my_phase;
|
||||||
|
pd->_mutex.lock();
|
||||||
|
|
||||||
|
my_phase = pd->phase;
|
||||||
|
|
||||||
|
pd->cnt = 0; // reset for next use
|
||||||
|
pd->phase = 1 - my_phase; // toggle phase
|
||||||
|
pd->_cond.broadcast();
|
||||||
|
|
||||||
|
pd->_mutex.unlock();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Return the number of threads currently blocked in the barrier
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Barrier::numThreadsCurrentlyBlocked() {
|
||||||
|
|
||||||
|
SprocBarrierPrivateData *pd =
|
||||||
|
static_cast<SprocBarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
int numBlocked = -1;
|
||||||
|
pd->_mutex.lock();
|
||||||
|
numBlocked = pd->cnt;
|
||||||
|
pd->_cond.broadcast();
|
||||||
|
return numBlocked;
|
||||||
|
|
||||||
|
}
|
67
src/OpenThreads/sproc/SprocBarrierPrivateData.h
Executable file
67
src/OpenThreads/sproc/SprocBarrierPrivateData.h
Executable file
@ -0,0 +1,67 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// SprocBarrierPrivateData.h - private data structure for barrier
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#ifndef _SPROCBARRIERPRIVATEDATA_H_
|
||||||
|
#define _SPROCBARRIERPRIVATEDATA_H_
|
||||||
|
|
||||||
|
#include <ulocks.h>
|
||||||
|
#include <OpenThreads/Barrier>
|
||||||
|
|
||||||
|
#ifndef USE_IRIX_NATIVE_BARRIER
|
||||||
|
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class SprocBarrierPrivateData {
|
||||||
|
|
||||||
|
friend class Barrier;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
SprocBarrierPrivateData() {};
|
||||||
|
|
||||||
|
virtual ~SprocBarrierPrivateData() {};
|
||||||
|
|
||||||
|
#ifdef USE_IRIX_NATIVE_BARRIER
|
||||||
|
|
||||||
|
barrier_t *barrier;
|
||||||
|
|
||||||
|
unsigned int numThreads;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
OpenThreads::Condition _cond;
|
||||||
|
|
||||||
|
OpenThreads::Mutex _mutex;
|
||||||
|
|
||||||
|
volatile int maxcnt;
|
||||||
|
|
||||||
|
volatile int cnt;
|
||||||
|
|
||||||
|
volatile int phase;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //_SPROCBARRIERPRIVATEDATA_H_
|
306
src/OpenThreads/sproc/SprocCondition.c++
Executable file
306
src/OpenThreads/sproc/SprocCondition.c++
Executable file
@ -0,0 +1,306 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// SprocCondition.c++ - C++ Condition class built on sprocs.
|
||||||
|
// ~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
#include "SprocConditionPrivateData.h"
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
#include "SharedArena.h"
|
||||||
|
#include "SprocThreadPrivateActions.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
using namespace OpenThreads;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
#define DPRINTF(arg) printf arg; fflush(stdout);
|
||||||
|
#define DPRINTLIST(arg) ConditionDebug::printList arg; fflush(stdout);
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class ConditionDebug {
|
||||||
|
|
||||||
|
friend class Condition;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static void printList(std::list<pid_t> &pid_list) {
|
||||||
|
|
||||||
|
std::list<pid_t>::iterator iter;
|
||||||
|
int counter = 0;
|
||||||
|
printf("(SPROC CONDITION %d) ", getpid());
|
||||||
|
for(iter=pid_list.begin(); iter!=pid_list.end();++iter) {
|
||||||
|
printf("Pid [%d]=%d, ", counter, *iter);
|
||||||
|
++counter;
|
||||||
|
}
|
||||||
|
printf("\b\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define DPRINTF(arg)
|
||||||
|
#define DPRINTLIST(arg)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void condition_alarm_handler(int signal) {
|
||||||
|
|
||||||
|
//DPRINTF(("(SPROC CONDITION) signal alarm handler called.\n"));
|
||||||
|
|
||||||
|
sigset(SIGALRM, SIG_DFL);
|
||||||
|
|
||||||
|
unblockproc(getpid());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Constructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Condition::Condition() {
|
||||||
|
|
||||||
|
SprocConditionPrivateData *pd =
|
||||||
|
new SprocConditionPrivateData();
|
||||||
|
|
||||||
|
_prvData = static_cast<void *>(pd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Destructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Condition::~Condition() {
|
||||||
|
|
||||||
|
SprocConditionPrivateData *pd =
|
||||||
|
static_cast<SprocConditionPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
pd->mutex.lock();
|
||||||
|
DPRINTF(("(SPROC CONDITION) : In destructor\n"));
|
||||||
|
DPRINTLIST((pd->pid_list));
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Destroy all remaining in the linked-list of waiters (pids).
|
||||||
|
//
|
||||||
|
pd->pid_list.clear();
|
||||||
|
|
||||||
|
delete pd;
|
||||||
|
_prvData = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: wait on a condition
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Condition::wait(Mutex *mutex) {
|
||||||
|
|
||||||
|
return wait(mutex, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: wait on a condition
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Condition::wait(Mutex *mutex, unsigned long int ms) {
|
||||||
|
|
||||||
|
unsigned int sec;
|
||||||
|
unsigned int usec;
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
pid_t mypid = getpid();
|
||||||
|
|
||||||
|
SprocConditionPrivateData *pd =
|
||||||
|
static_cast<SprocConditionPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
if(ms != 0) {
|
||||||
|
|
||||||
|
// Wait for ms milliseconds
|
||||||
|
sec = ms / 1000;
|
||||||
|
usec = (ms % 1000) * 1000;
|
||||||
|
tv.tv_sec = sec;
|
||||||
|
tv.tv_usec = usec;
|
||||||
|
|
||||||
|
DPRINTF(("(SPROC CONDITION) : PID %d timeout values [%d | %d]\n",
|
||||||
|
mypid, tv.tv_sec, tv.tv_usec));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pd->mutex.lock();
|
||||||
|
|
||||||
|
pd->pid_list.push_front(mypid);
|
||||||
|
|
||||||
|
pd->mutex.unlock();
|
||||||
|
|
||||||
|
DPRINTF(("(SPROC CONDITION) : PID %d going to blockproc\n",
|
||||||
|
mypid));
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
status = setblockproccnt(mypid, 0);
|
||||||
|
|
||||||
|
// If we're doing a timout, setup the signal handler to deal with it.
|
||||||
|
if(tv.tv_sec != 0 || tv.tv_usec != 0) {
|
||||||
|
|
||||||
|
DPRINTF(("(SPROC CONDITION) : PID %d setting timeout condition\n",
|
||||||
|
mypid));
|
||||||
|
|
||||||
|
sigset(SIGALRM, condition_alarm_handler);
|
||||||
|
|
||||||
|
struct timeval recur;
|
||||||
|
recur.tv_sec = 0;
|
||||||
|
recur.tv_usec = 0;
|
||||||
|
|
||||||
|
itimerval itv;
|
||||||
|
itv.it_interval = recur;
|
||||||
|
itv.it_value = tv;
|
||||||
|
|
||||||
|
setitimer(ITIMER_REAL, &itv, NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex->unlock();
|
||||||
|
|
||||||
|
ThreadPrivateActions::ThreadCancelTest();
|
||||||
|
|
||||||
|
status = blockproc(mypid);
|
||||||
|
|
||||||
|
ThreadPrivateActions::ThreadCancelTest();
|
||||||
|
|
||||||
|
mutex->lock();
|
||||||
|
|
||||||
|
DPRINTF(("(SPROC CONDITION) : PID %d, returned from blockproc %d\n",
|
||||||
|
mypid, status));
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Pull the pid from the list
|
||||||
|
//
|
||||||
|
pd->mutex.lock();
|
||||||
|
|
||||||
|
DPRINTLIST((pd->pid_list));
|
||||||
|
|
||||||
|
#ifndef DEBUG
|
||||||
|
|
||||||
|
// KLUDGE - can optimized this by just doing -remove()-
|
||||||
|
std::list<pid_t>::iterator iter;
|
||||||
|
iter = pd->pid_list.begin();
|
||||||
|
while(iter != pd->pid_list.end()) {
|
||||||
|
|
||||||
|
if(*iter == mypid) {
|
||||||
|
DPRINTF(("(SPROC CONDITION) : PID %d removed itself from the list\n",
|
||||||
|
mypid));
|
||||||
|
|
||||||
|
pd->pid_list.remove(mypid);
|
||||||
|
iter = pd->pid_list.begin();
|
||||||
|
} else {
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
pd->pid_list.remove(mypid);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DPRINTLIST((pd->pid_list));
|
||||||
|
|
||||||
|
pd->mutex.unlock();
|
||||||
|
|
||||||
|
if(status == -1) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: signal a thread to wake up.
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Condition::signal() {
|
||||||
|
|
||||||
|
ThreadPrivateActions::ThreadCancelTest();
|
||||||
|
|
||||||
|
SprocConditionPrivateData *pd =
|
||||||
|
static_cast<SprocConditionPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
pd->mutex.lock();
|
||||||
|
if(pd->pid_list.empty()) {
|
||||||
|
DPRINTF(("(SPROC CONDITION) : No threads to signal\n"));
|
||||||
|
pd->mutex.unlock(); // Remember to release the mutex.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Perform an unblockproc on the first pid in the list.
|
||||||
|
//
|
||||||
|
DPRINTF(("(SPROC CONDITION) : PID %d signaling pid %d\n",
|
||||||
|
getpid(), pd->pid_list.front()));
|
||||||
|
int status = unblockproc(pd->pid_list.front());
|
||||||
|
pd->mutex.unlock();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: signal all threads to wake up.
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Condition::broadcast() {
|
||||||
|
|
||||||
|
|
||||||
|
ThreadPrivateActions::ThreadCancelTest();
|
||||||
|
|
||||||
|
SprocConditionPrivateData *pd =
|
||||||
|
static_cast<SprocConditionPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
pd->mutex.lock();
|
||||||
|
|
||||||
|
std::list<pid_t>::iterator iter;
|
||||||
|
for(iter = pd->pid_list.begin();
|
||||||
|
iter != pd->pid_list.end();
|
||||||
|
++iter) {
|
||||||
|
|
||||||
|
DPRINTF(("(SPROC CONDITION) Broadcast to pid[%d]\n", *iter));
|
||||||
|
unblockproc(*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
pd->mutex.unlock();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
82
src/OpenThreads/sproc/SprocConditionPrivateData.h
Executable file
82
src/OpenThreads/sproc/SprocConditionPrivateData.h
Executable file
@ -0,0 +1,82 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// SprocConditionPrivateData.h - Private data structure for Condition
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#ifndef _SPROCCONDITIONPRIVATEDATA_H_
|
||||||
|
#define _SPROCCONDITIONPRIVATEDATA_H_
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <bstring.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <ulocks.h>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class SemaLink {
|
||||||
|
|
||||||
|
friend class SprocConditionPrivatedata;
|
||||||
|
|
||||||
|
friend class Condition;
|
||||||
|
|
||||||
|
friend class ConditionDebug;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
SemaLink() {};
|
||||||
|
|
||||||
|
virtual ~SemaLink() {};
|
||||||
|
|
||||||
|
SemaLink *next;
|
||||||
|
|
||||||
|
usema_t *sema;
|
||||||
|
|
||||||
|
int select_cond; // 0=pre-select, 1=in-select, 2=post-select
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class SprocConditionPrivateData {
|
||||||
|
|
||||||
|
friend class Condition;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
SprocConditionPrivateData() {
|
||||||
|
|
||||||
|
pid_list.clear();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~SprocConditionPrivateData() {
|
||||||
|
|
||||||
|
pid_list.clear();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
std::list<pid_t> pid_list;
|
||||||
|
|
||||||
|
Mutex mutex;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !_SPROCCONDITIONPRIVATEDATA_H_
|
126
src/OpenThreads/sproc/SprocMutex.c++
Executable file
126
src/OpenThreads/sproc/SprocMutex.c++
Executable file
@ -0,0 +1,126 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// SprocMutex.c++ - C++ Mutex class built on top of posix threads.
|
||||||
|
// ~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <ulocks.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
#include "SharedArena.h"
|
||||||
|
#include "SprocMutexPrivateData.h"
|
||||||
|
#include "SprocThreadPrivateActions.h"
|
||||||
|
|
||||||
|
using namespace OpenThreads;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Constructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Mutex::Mutex() {
|
||||||
|
|
||||||
|
SprocMutexPrivateData *pd = new SprocMutexPrivateData();
|
||||||
|
|
||||||
|
pd->mutex = SharedArena::allocLock();
|
||||||
|
|
||||||
|
_prvData = static_cast<void *>(pd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Destructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Mutex::~Mutex() {
|
||||||
|
|
||||||
|
SprocMutexPrivateData *pd =
|
||||||
|
static_cast<SprocMutexPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
SharedArena::deleteLock(pd->mutex);
|
||||||
|
|
||||||
|
delete pd;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: lock the mutex
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Mutex::lock() {
|
||||||
|
|
||||||
|
ThreadPrivateActions::ThreadCancelTest();
|
||||||
|
|
||||||
|
SprocMutexPrivateData *pd =
|
||||||
|
static_cast<SprocMutexPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
int status = SharedArena::lock(pd->mutex);
|
||||||
|
|
||||||
|
if(status == -1) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(status == 1) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: unlock the mutex
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Mutex::unlock() {
|
||||||
|
|
||||||
|
SprocMutexPrivateData *pd =
|
||||||
|
static_cast<SprocMutexPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
int status = SharedArena::unlock(pd->mutex);
|
||||||
|
|
||||||
|
ThreadPrivateActions::ThreadCancelTest();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: test if the mutex may be locked
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Mutex::trylock() {
|
||||||
|
|
||||||
|
SprocMutexPrivateData *pd =
|
||||||
|
static_cast<SprocMutexPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
int status = SharedArena::trylock(pd->mutex);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
45
src/OpenThreads/sproc/SprocMutexPrivateData.h
Executable file
45
src/OpenThreads/sproc/SprocMutexPrivateData.h
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// SprocMutexPrivateData.h - Private data structure for Mutex
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#ifndef _SPROCMUTEXPRIVATEDATA_H_
|
||||||
|
#define _SPROCMUTEXPRIVATEDATA_H_
|
||||||
|
|
||||||
|
#include <ulocks.h>
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class SprocMutexPrivateData {
|
||||||
|
|
||||||
|
friend class SprocThreadPrivateActions;
|
||||||
|
|
||||||
|
friend class Mutex;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
SprocMutexPrivateData() {};
|
||||||
|
|
||||||
|
virtual ~SprocMutexPrivateData() {};
|
||||||
|
|
||||||
|
ulock_t mutex;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _SPROCMUTEXPRIVATEDATA_H_
|
823
src/OpenThreads/sproc/SprocThread.c++
Executable file
823
src/OpenThreads/sproc/SprocThread.c++
Executable file
@ -0,0 +1,823 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// SprocThread.c++ - C++ Thread class built on top of IRIX sproc.
|
||||||
|
// ~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/sysmp.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <list>
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include "SprocMutexPrivateData.h"
|
||||||
|
#include "SprocThreadPrivateData.h"
|
||||||
|
#include "SprocThreadPrivateActions.h"
|
||||||
|
|
||||||
|
using namespace OpenThreads;
|
||||||
|
|
||||||
|
extern int errno;
|
||||||
|
const char *OPENTHREAD_VERSION_STRING = "Sproc Thread Model, v1.1 ("__DATE__" "__TIME__")";
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define DPRINTF(arg) printf arg; fflush(stdout);
|
||||||
|
#else
|
||||||
|
#define DPRINTF(ARG)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void sproc_dead_child_sig_handler(int sigid);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Initialize the static unique ids.
|
||||||
|
//
|
||||||
|
int SprocThreadPrivateData::nextId = 0;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Initialize thread master priority level
|
||||||
|
//
|
||||||
|
Thread::ThreadPriority Thread::s_masterThreadPriority =
|
||||||
|
Thread::THREAD_PRIORITY_MAX;
|
||||||
|
|
||||||
|
bool Thread::s_isInitialized = false;
|
||||||
|
|
||||||
|
std::list<Thread *> ThreadPrivateActions::s_threadList;
|
||||||
|
|
||||||
|
void ThreadPrivateActions::ThreadCancelTest() {
|
||||||
|
|
||||||
|
OpenThreads::Thread *t = GetThread(getpid());
|
||||||
|
|
||||||
|
if(t != 0L) {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *>(t->_prvData);
|
||||||
|
|
||||||
|
bool *dieflag = GetDeathFlag(t);
|
||||||
|
|
||||||
|
if(*dieflag==false) return;
|
||||||
|
|
||||||
|
DPRINTF(("(SPROC THREAD) Thread Cancel Test Passed for %d\n",
|
||||||
|
getpid()));
|
||||||
|
|
||||||
|
if(!pd->cancelFuncStack.empty())
|
||||||
|
pd->cancelFuncStack.top().routine(pd->cancelFuncStack.top().arg);
|
||||||
|
|
||||||
|
t->cancelCleanup();
|
||||||
|
pd->isRunning = false;
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool *ThreadPrivateActions::GetDeathFlag(Thread *thread) {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *>(thread->_prvData);
|
||||||
|
|
||||||
|
return (bool *)(&(pd->dieFlag));
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread *ThreadPrivateActions::GetThread(pid_t thread_id) {
|
||||||
|
|
||||||
|
std::list<Thread *>::iterator iter;
|
||||||
|
for(iter = s_threadList.begin();
|
||||||
|
iter != s_threadList.end();
|
||||||
|
++iter) {
|
||||||
|
|
||||||
|
Thread *t = *iter;
|
||||||
|
if(t->getProcessId() == thread_id) return t;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0L; // no thread found;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void ThreadPrivateActions::ThreadCancelHandler(int sigid) {
|
||||||
|
|
||||||
|
Thread *t = GetThread(getpid());
|
||||||
|
|
||||||
|
if(t != 0L) {
|
||||||
|
|
||||||
|
bool * dieflag = GetDeathFlag(t);
|
||||||
|
|
||||||
|
*dieflag = true;
|
||||||
|
|
||||||
|
sigset(SIGINT, SIG_DFL);
|
||||||
|
unblockproc(getpid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// standard start routine.
|
||||||
|
//
|
||||||
|
void ThreadPrivateActions::StartThread(void *data)
|
||||||
|
{
|
||||||
|
|
||||||
|
Thread *thread = static_cast<Thread *>(data);
|
||||||
|
|
||||||
|
if (thread->_prvData==0) return;
|
||||||
|
|
||||||
|
AddThread(thread);
|
||||||
|
|
||||||
|
*((Thread **)&PRDA->usr_prda) = (Thread *)thread;
|
||||||
|
|
||||||
|
SetThreadSchedulingParams(thread);
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *>(thread->_prvData);
|
||||||
|
|
||||||
|
sigset(SIGINT, ThreadCancelHandler);
|
||||||
|
|
||||||
|
size_t defaultStackSize;
|
||||||
|
prctl(PR_GETSTACKSIZE, &defaultStackSize);
|
||||||
|
|
||||||
|
if(defaultStackSize < pd->stackSize) {
|
||||||
|
prctl(PR_SETSTACKSIZE, pd->stackSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
prctl(PR_GETSTACKSIZE, &pd->stackSize);
|
||||||
|
|
||||||
|
pd->stackSizeLocked = true;
|
||||||
|
|
||||||
|
pd->isRunning = true;
|
||||||
|
|
||||||
|
// release the thread that created this thread.
|
||||||
|
pd->threadStartedBlock.release();
|
||||||
|
|
||||||
|
thread->run();
|
||||||
|
|
||||||
|
pd->isRunning = false;
|
||||||
|
|
||||||
|
RemoveThread(thread);
|
||||||
|
|
||||||
|
if(pd->detached == true ) {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void ThreadPrivateActions::AddThread(Thread *thread) {
|
||||||
|
|
||||||
|
s_threadList.push_front(thread);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void ThreadPrivateActions::RemoveThread(Thread *thread) {
|
||||||
|
s_threadList.remove(thread);
|
||||||
|
};
|
||||||
|
|
||||||
|
void ThreadPrivateActions::PrintThreadSchedulingInfo(Thread *thread) {
|
||||||
|
|
||||||
|
int status, my_policy, min_priority, max_priority;
|
||||||
|
struct sched_param my_param;
|
||||||
|
|
||||||
|
status = sched_getparam(thread->getProcessId(),
|
||||||
|
&my_param);
|
||||||
|
|
||||||
|
my_policy = sched_getscheduler(thread->getProcessId());
|
||||||
|
|
||||||
|
if(status != 0 || my_policy == -1) {
|
||||||
|
|
||||||
|
printf("THREAD INFO (%d) : Get sched param: %s/%s\n",
|
||||||
|
thread->getProcessId(),
|
||||||
|
strerror(status),
|
||||||
|
strerror(errno));
|
||||||
|
} else {
|
||||||
|
printf(
|
||||||
|
"THREAD INFO (%d) : Thread running at %s / Priority: %d\n",
|
||||||
|
thread->getProcessId(),
|
||||||
|
(my_policy == SCHED_FIFO ? "SCHEDULE_FIFO"
|
||||||
|
: (my_policy == SCHED_RR ? "SCHEDULE_ROUND_ROBIN"
|
||||||
|
: (my_policy == SCHED_TS ? "SCHEDULE_TIME_SHARE"
|
||||||
|
: (my_policy == SCHED_OTHER ? "SCHEDULE_OTHER"
|
||||||
|
: "UNKNOWN")))),
|
||||||
|
my_param.sched_priority);
|
||||||
|
|
||||||
|
max_priority = sched_get_priority_max(my_policy);
|
||||||
|
min_priority = sched_get_priority_min(my_policy);
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"THREAD INFO (%d) : Max priority: %d, Min priority: %d\n",
|
||||||
|
thread->getProcessId(),
|
||||||
|
max_priority, min_priority);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int ThreadPrivateActions::SetThreadSchedulingParams(Thread *thread) {
|
||||||
|
|
||||||
|
int status;
|
||||||
|
|
||||||
|
int th_priority;
|
||||||
|
int max_priority, nominal_priority, min_priority;
|
||||||
|
|
||||||
|
max_priority = 0; // This is as high as we can regularly go.
|
||||||
|
min_priority = 20;
|
||||||
|
nominal_priority = (max_priority + min_priority)/2;
|
||||||
|
|
||||||
|
switch(thread->getSchedulePriority()) {
|
||||||
|
|
||||||
|
case Thread::THREAD_PRIORITY_MAX:
|
||||||
|
th_priority = max_priority;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Thread::THREAD_PRIORITY_HIGH:
|
||||||
|
th_priority = (max_priority + nominal_priority)/2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Thread::THREAD_PRIORITY_NOMINAL:
|
||||||
|
th_priority = nominal_priority;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Thread::THREAD_PRIORITY_LOW:
|
||||||
|
th_priority = (min_priority + nominal_priority)/2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Thread::THREAD_PRIORITY_MIN:
|
||||||
|
th_priority = min_priority;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
th_priority = max_priority;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
status = setpriority(PRIO_PROCESS, thread->getProcessId(),
|
||||||
|
th_priority);
|
||||||
|
|
||||||
|
if(getenv("OUTPUT_THREADLIB_SCHEDULING_INFO") != 0)
|
||||||
|
PrintThreadSchedulingInfo(thread);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ThreadPrivateActions::PushCancelFunction(void (*routine)(void *), void *arg) {
|
||||||
|
|
||||||
|
Thread *thread = GetThread(getpid());
|
||||||
|
|
||||||
|
if(thread != 0L) {
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *>(thread->_prvData);
|
||||||
|
|
||||||
|
SprocThreadPrivateData::CancelFuncStruct c;
|
||||||
|
|
||||||
|
pd->cancelFuncStack.push(c);
|
||||||
|
|
||||||
|
SprocThreadPrivateData::CancelFuncStruct *cft = &(pd->cancelFuncStack.top());
|
||||||
|
|
||||||
|
cft->routine = routine;
|
||||||
|
cft->arg = arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadPrivateActions::PopCancelFunction() {
|
||||||
|
|
||||||
|
Thread *thread = GetThread(getpid());
|
||||||
|
|
||||||
|
if(thread != 0L) {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *>(thread->_prvData);
|
||||||
|
|
||||||
|
if(!pd->cancelFuncStack.empty())
|
||||||
|
pd->cancelFuncStack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the concurrency level (no-op)
|
||||||
|
//
|
||||||
|
// Use static public
|
||||||
|
//
|
||||||
|
int Thread::SetConcurrency(int concurrencyLevel) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the concurrency level
|
||||||
|
//
|
||||||
|
// Use static public
|
||||||
|
//
|
||||||
|
int Thread::GetConcurrency() {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Constructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Thread::Thread() {
|
||||||
|
|
||||||
|
if(!s_isInitialized) Init();
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd = new SprocThreadPrivateData();
|
||||||
|
pd->stackSize = 128*1024; // Set a minimum of 128K bytes if possible.
|
||||||
|
pd->stackSizeLocked = false;
|
||||||
|
pd->isRunning = false;
|
||||||
|
pd->isCanceled = false;
|
||||||
|
pd->idSet = false;
|
||||||
|
pd->cancelActive = true;
|
||||||
|
pd->detached = false;
|
||||||
|
pd->uniqueId = pd->nextId;
|
||||||
|
pd->nextId++;
|
||||||
|
pd->threadPriority = Thread::THREAD_PRIORITY_DEFAULT;
|
||||||
|
pd->threadPolicy = Thread::THREAD_SCHEDULE_DEFAULT;
|
||||||
|
|
||||||
|
_prvData = static_cast<void *>(pd);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decription: Destructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Thread::~Thread()
|
||||||
|
{
|
||||||
|
DPRINTF(("(SPROC THREAD) %s:%d, In OpenThreads::Thread destructor\n",
|
||||||
|
__FILE__, __LINE__));
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
if(pd->isRunning)
|
||||||
|
{
|
||||||
|
|
||||||
|
DPRINTF(("(SPROC THREAD) %s:%d, about to kill OpenThreads::Thread\n",
|
||||||
|
__FILE__, __LINE__));
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Kill the process when the thread is destroyed.
|
||||||
|
//
|
||||||
|
cancel();
|
||||||
|
|
||||||
|
while (pd->isRunning == true) {
|
||||||
|
::usleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DPRINTF(("(SPROC THREAD) %s:%d, Thread destroying private data.\n",
|
||||||
|
__FILE__, __LINE__));
|
||||||
|
|
||||||
|
|
||||||
|
delete pd;
|
||||||
|
|
||||||
|
_prvData = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Initialize Threading
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
void Thread::Init() {
|
||||||
|
|
||||||
|
if(s_isInitialized) return;
|
||||||
|
|
||||||
|
#ifdef GP_DEBUG
|
||||||
|
fprintf(stderr, "%s\n", OPENTHREAD_VERSION_STRING);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
s_masterThreadPriority = Thread::THREAD_PRIORITY_MAX;
|
||||||
|
|
||||||
|
s_isInitialized = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Return a pointer to the currently executing thread
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
Thread *Thread::CurrentThread() {
|
||||||
|
|
||||||
|
return (*(Thread **)&PRDA->usr_prda);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get a unique identifier for this thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::getThreadId() {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
return pd->uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the thread's process id
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
size_t Thread::getProcessId() {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
if(pd->idSet == false) return getpid();
|
||||||
|
|
||||||
|
return (size_t)(pd->pid);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Determine if the thread is running
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
bool Thread::isRunning() {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
return pd->isRunning;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Start the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::start() {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
pd->threadStartedBlock.reset();
|
||||||
|
|
||||||
|
int pid = sproc(ThreadPrivateActions::StartThread,
|
||||||
|
PR_SALL,
|
||||||
|
static_cast<void *>(this));
|
||||||
|
|
||||||
|
// PR_SADDR | PR_SDIR | PR_SUMASK | PR_SULIMIT | PR_SID,
|
||||||
|
|
||||||
|
if(pid < 0) {
|
||||||
|
perror("sproc encountered an error");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
// Make the thread runnable anywhere.
|
||||||
|
//
|
||||||
|
sysmp(MP_RUNANYWHERE_PID, pid);
|
||||||
|
|
||||||
|
pd->pid = pid;
|
||||||
|
pd->idSet = true;
|
||||||
|
|
||||||
|
// wait till the thread has actually started.
|
||||||
|
pd->threadStartedBlock.block();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Alternate thread start routine.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::startThread()
|
||||||
|
{
|
||||||
|
if (_prvData) return start();
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Join the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::detach() {
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
pd->detached=true;
|
||||||
|
sigset(SIGCLD, sproc_dead_child_sig_handler);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Join the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::join() {
|
||||||
|
|
||||||
|
int status;
|
||||||
|
|
||||||
|
return waitpid((pid_t)getProcessId(), &status, 0);
|
||||||
|
//return status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: test the cancel state of the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::testCancel() {
|
||||||
|
|
||||||
|
if(getpid() != getProcessId()) return -1;
|
||||||
|
|
||||||
|
ThreadPrivateActions::ThreadCancelTest();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Cancel the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::cancel() {
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
if(pd->cancelActive) {
|
||||||
|
|
||||||
|
status = kill((pid_t)getProcessId(), SIGINT);
|
||||||
|
};
|
||||||
|
|
||||||
|
return status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Disable cancelibility
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setCancelModeDisable() {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
pd->cancelActive = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: set the thread to cancel immediately
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setCancelModeAsynchronous() {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
pd->cancelActive = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: set the thread to cancel at the next convienent point.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setCancelModeDeferred() {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
pd->cancelActive = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's schedule priority (if able)
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setSchedulePriority(ThreadPriority priority) {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
pd->threadPriority = priority;
|
||||||
|
|
||||||
|
if(pd->isRunning)
|
||||||
|
return ThreadPrivateActions::SetThreadSchedulingParams(this);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the thread's schedule priority (if able)
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::getSchedulePriority() {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
return pd->threadPriority;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's scheduling policy (if able)
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setSchedulePolicy(ThreadPolicy policy) {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's scheduling policy (if able)
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::getSchedulePolicy() {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
return pd->threadPolicy;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's desired stack size
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setStackSize(size_t stackSize) {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
if(pd->stackSizeLocked == true) return 13; // EACESS
|
||||||
|
|
||||||
|
pd->stackSize = stackSize;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the thread's stack size.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
size_t Thread::getStackSize() {
|
||||||
|
|
||||||
|
SprocThreadPrivateData *pd =
|
||||||
|
static_cast<SprocThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
return pd->stackSize;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Print the thread's scheduling information to stdout.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
void Thread::printSchedulingInfo() {
|
||||||
|
|
||||||
|
ThreadPrivateActions::PrintThreadSchedulingInfo(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Yield the processor
|
||||||
|
//
|
||||||
|
// Use: protected
|
||||||
|
//
|
||||||
|
int Thread::YieldCurrentThread() {
|
||||||
|
|
||||||
|
return sched_yield();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Description: sleep
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::microSleep(unsigned int microsec)
|
||||||
|
{
|
||||||
|
return ::usleep(microsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sproc_dead_child_sig_handler(int sigid) {
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
int pid, status;
|
||||||
|
pid = wait(&status);
|
||||||
|
DPRINTF(("(SPROC THREAD) Dead Child Handler Caught Signal, Reaped %d\n",
|
||||||
|
pid));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sigset(SIGCLD, sproc_dead_child_sig_handler);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int Thread::setProcessorAffinity( unsigned int cpunum )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the number of processors
|
||||||
|
//
|
||||||
|
int OpenThreads::GetNumberOfProcessors()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OpenThreads::SetProcessorAffinityOfCurrentThread(unsigned int cpunum)
|
||||||
|
{
|
||||||
|
if (cpunum<0) return -1;
|
||||||
|
|
||||||
|
Thread::Init();
|
||||||
|
|
||||||
|
Thread* thread = Thread::CurrentThread();
|
||||||
|
if (thread)
|
||||||
|
{
|
||||||
|
return thread->setProcessorAffinity(cpunum);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// non op right now, needs implementation.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
71
src/OpenThreads/sproc/SprocThreadPrivateActions.h
Executable file
71
src/OpenThreads/sproc/SprocThreadPrivateActions.h
Executable file
@ -0,0 +1,71 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// SprocThreadPrivateActions.c++ - Thread private actions for sprocs
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#ifndef SPROC_THREAD_PRIVATE_ACTIONS
|
||||||
|
#define SPROC_THREAD_PRIVATE_ACTIONS
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class ThreadPrivateActions {
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// We're friendly to Thread, so it can issue the methods.
|
||||||
|
//
|
||||||
|
friend class Thread;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static void ThreadCancelTest();
|
||||||
|
|
||||||
|
static void PushCancelFunction(void (*routine)(void *), void *arg);
|
||||||
|
|
||||||
|
static void PopCancelFunction();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static bool *GetDeathFlag(Thread *thread);
|
||||||
|
|
||||||
|
static Thread *GetThread(pid_t thread_id);
|
||||||
|
|
||||||
|
static void ThreadCancelHandler(int sigid);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// standard start routine.
|
||||||
|
//
|
||||||
|
static void StartThread(void *data);
|
||||||
|
|
||||||
|
static void AddThread(Thread *thread);
|
||||||
|
|
||||||
|
static void RemoveThread(Thread *thread);
|
||||||
|
|
||||||
|
static void PrintThreadSchedulingInfo(Thread *thread);
|
||||||
|
|
||||||
|
static int SetThreadSchedulingParams(Thread *thread);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static std::list<Thread *> s_threadList;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !SPROC_THREAD_PRIVATE_ACTIONS
|
84
src/OpenThreads/sproc/SprocThreadPrivateData.h
Executable file
84
src/OpenThreads/sproc/SprocThreadPrivateData.h
Executable file
@ -0,0 +1,84 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// SprocThreadPrivateData.h - private data for sproc thread
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#ifndef _SPROCTHREADPRIVATEDATA_H_
|
||||||
|
#define _SPROCTHREADPRIVATEDATA_H_
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <ulocks.h>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <OpenThreads/Block>
|
||||||
|
#include "SprocThreadPrivateActions.h"
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class SprocThreadPrivateData {
|
||||||
|
|
||||||
|
friend class Thread;
|
||||||
|
|
||||||
|
friend class ThreadPrivateActions;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct CancelFuncStruct {
|
||||||
|
|
||||||
|
void (*routine)(void *);
|
||||||
|
void *arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
SprocThreadPrivateData() {};
|
||||||
|
|
||||||
|
virtual ~SprocThreadPrivateData() {};
|
||||||
|
|
||||||
|
volatile unsigned int stackSize;
|
||||||
|
|
||||||
|
volatile bool stackSizeLocked;
|
||||||
|
|
||||||
|
volatile bool isRunning;
|
||||||
|
|
||||||
|
Block threadStartedBlock;
|
||||||
|
|
||||||
|
volatile bool isCanceled;
|
||||||
|
|
||||||
|
volatile bool idSet;
|
||||||
|
|
||||||
|
volatile bool cancelActive;
|
||||||
|
|
||||||
|
volatile bool detached;
|
||||||
|
|
||||||
|
volatile bool dieFlag;
|
||||||
|
|
||||||
|
volatile Thread::ThreadPriority threadPriority;
|
||||||
|
|
||||||
|
volatile Thread::ThreadPolicy threadPolicy;
|
||||||
|
|
||||||
|
volatile pid_t pid;
|
||||||
|
|
||||||
|
volatile int uniqueId;
|
||||||
|
|
||||||
|
std::stack<CancelFuncStruct> cancelFuncStack;
|
||||||
|
|
||||||
|
static int nextId;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !_SPROCTHREADPRIVATEDATA_H_
|
52
src/OpenThreads/win32/CMakeLists.txt
Normal file
52
src/OpenThreads/win32/CMakeLists.txt
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# This file should only be included when WIN32
|
||||||
|
|
||||||
|
SET(LIB_NAME OpenThreads)
|
||||||
|
SET(LIB_PUBLIC_HEADERS ${OpenThreads_PUBLIC_HEADERS})
|
||||||
|
|
||||||
|
SOURCE_GROUP("Header Files" FILES ${LIB_PUBLIC_HEADERS})
|
||||||
|
SET_SOURCE_FILES_PROPERTIES(${LIB_PUBLIC_HEADERS} PROPERTIES HEADER_FILE_ONLY ON)
|
||||||
|
|
||||||
|
ADD_LIBRARY(${LIB_NAME}
|
||||||
|
${OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC}
|
||||||
|
${LIB_PUBLIC_HEADERS}
|
||||||
|
HandleHolder.h
|
||||||
|
Win32BarrierPrivateData.h
|
||||||
|
WIN32Condition.cpp
|
||||||
|
Win32Condition.h
|
||||||
|
Win32ConditionPrivateData.h
|
||||||
|
Win32Mutex.cpp
|
||||||
|
Win32MutexPrivateData.h
|
||||||
|
Win32Thread.cpp
|
||||||
|
Win32ThreadBarrier.cpp
|
||||||
|
Win32ThreadPrivateData.h
|
||||||
|
../common/Version.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
IF(OPENTHREADS_SONAMES)
|
||||||
|
SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${OPENTHREADS_VERSION} SOVERSION ${OPENTHREADS_SOVERSION})
|
||||||
|
ENDIF(OPENTHREADS_SONAMES)
|
||||||
|
|
||||||
|
# Since we're building different platforms binaries in
|
||||||
|
# their respective directories, we need to set the
|
||||||
|
# link directory so it can find this location.
|
||||||
|
LINK_DIRECTORIES(
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
IF(MSVC AND OSG_MSVC_VERSIONED_DLL)
|
||||||
|
HANDLE_MSVC_DLL(ot ${OPENTHREADS_SOVERSION})
|
||||||
|
ENDIF(MSVC AND OSG_MSVC_VERSIONED_DLL)
|
||||||
|
|
||||||
|
INSTALL(
|
||||||
|
TARGETS OpenThreads
|
||||||
|
ARCHIVE DESTINATION lib
|
||||||
|
LIBRARY DESTINATION lib
|
||||||
|
RUNTIME DESTINATION bin
|
||||||
|
)
|
||||||
|
INSTALL(
|
||||||
|
FILES ${OpenThreads_PUBLIC_HEADERS}
|
||||||
|
DESTINATION include/OpenThreads
|
||||||
|
)
|
||||||
|
|
||||||
|
#commented out# INCLUDE(ModuleInstall OPTIONAL)
|
38
src/OpenThreads/win32/GNUmakefile
Executable file
38
src/OpenThreads/win32/GNUmakefile
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
TOPDIR = ../.
|
||||||
|
include $(TOPDIR)/Make/makedefs
|
||||||
|
|
||||||
|
CXXFILES = \
|
||||||
|
WIN32Condition.cpp \
|
||||||
|
Win32Mutex.cpp \
|
||||||
|
Win32Thread.cpp \
|
||||||
|
Win32ThreadBarrier.cpp \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
INC += -I$(TOPDIR)/include -I.
|
||||||
|
|
||||||
|
ifeq ($(OS),Linux)
|
||||||
|
DEF += -fPIC -DLinux -DGL_GLEXT_PROTOTYPES
|
||||||
|
LIBS += -lpthread
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),SunOS)
|
||||||
|
LIBS += -lpthread -lposix4
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),IRIX)
|
||||||
|
LIBS += -lpthread
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),Darwin)
|
||||||
|
LIBS += -lpthread
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),MINGW)
|
||||||
|
LIBS +=
|
||||||
|
DEF += -DOPENTHREADS_EXPORTS
|
||||||
|
endif
|
||||||
|
|
||||||
|
TARGET_BASENAME = OpenThreads
|
||||||
|
LIB = $(LIB_PREFIX)$(TARGET_BASENAME)
|
||||||
|
|
||||||
|
include $(TOPDIR)/Make/makerules
|
89
src/OpenThreads/win32/HandleHolder.h
Normal file
89
src/OpenThreads/win32/HandleHolder.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Win32BarrierPrivateData.h - private data structure for barrier
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
#ifndef _HandleHolder_H_
|
||||||
|
#define _HandleHolder_H_
|
||||||
|
|
||||||
|
#ifndef _WINDOWS_
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Class that holds HANDLES ensuring proper destruction */
|
||||||
|
/* It is design decision to make this class noncopyable. */
|
||||||
|
/* It makes design much cleaner. If one wants to copy handle than one */
|
||||||
|
/* can do hv.set(DuplicateHandle(....)) */
|
||||||
|
/************************************************************************/
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class HandleHolder{
|
||||||
|
private:
|
||||||
|
HANDLE _handle;
|
||||||
|
|
||||||
|
inline void close(){
|
||||||
|
if( _handle != INVALID_HANDLE_VALUE) CloseHandle(_handle);
|
||||||
|
_handle = INVALID_HANDLE_VALUE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// copy constructor - disallow
|
||||||
|
HandleHolder(const HandleHolder& rhs);
|
||||||
|
|
||||||
|
// assignment operator - disallow
|
||||||
|
HandleHolder& operator=(const HandleHolder& rhs );
|
||||||
|
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
HandleHolder()
|
||||||
|
:_handle(INVALID_HANDLE_VALUE)
|
||||||
|
{};
|
||||||
|
|
||||||
|
// constructor from HANDLE
|
||||||
|
explicit HandleHolder(HANDLE h)
|
||||||
|
:_handle(h)
|
||||||
|
{};
|
||||||
|
|
||||||
|
// destructor - CloseHandle()
|
||||||
|
~HandleHolder()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
};
|
||||||
|
|
||||||
|
// accessor
|
||||||
|
const HANDLE& get() const {
|
||||||
|
return _handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mutator
|
||||||
|
void set (HANDLE h) {
|
||||||
|
if( _handle != INVALID_HANDLE_VALUE ) close();
|
||||||
|
_handle = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool (){
|
||||||
|
return _handle != INVALID_HANDLE_VALUE && _handle != NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
18
src/OpenThreads/win32/Makefile
Normal file
18
src/OpenThreads/win32/Makefile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Makefile - OpenThreads.dsw
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: \
|
||||||
|
OpenThreads
|
||||||
|
|
||||||
|
.PHONY: OpenThreads
|
||||||
|
OpenThreads:
|
||||||
|
$(MAKE) -f OpenThreads.mak
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
$(MAKE) -f OpenThreads.mak clean
|
||||||
|
|
||||||
|
.PHONY: depends
|
||||||
|
depends:
|
||||||
|
$(MAKE) -f OpenThreads.mak depends
|
||||||
|
|
231
src/OpenThreads/win32/OpenThreads.dsp
Executable file
231
src/OpenThreads/win32/OpenThreads.dsp
Executable file
@ -0,0 +1,231 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="OpenThreads" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||||
|
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||||
|
|
||||||
|
CFG=OpenThreads - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "OpenThreads.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "OpenThreads.mak" CFG="OpenThreads - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "OpenThreads - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "OpenThreads - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "OpenThreads - Win32 Release Static" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE "OpenThreads - Win32 Debug Static" (based on "Win32 (x86) Static Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "OpenThreads - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "../bin/$(PlatformName)"
|
||||||
|
# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
CPP=cl.exe
|
||||||
|
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPENTHREADS_EXPORTS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPENTHREADS_EXPORTS" /YX /FD /c
|
||||||
|
MTL=midl.exe
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
RSC=rc.exe
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /opt:ref /opt:icf /out:"$(OutDir)/OpenThreadsWin32.dll" /implib:"../lib/$(PlatformName)/OpenThreadsWin32.lib"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "OpenThreads - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "../bin/$(PlatformName)"
|
||||||
|
# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
CPP=cl.exe
|
||||||
|
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPENTHREADS_EXPORTS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPENTHREADS_EXPORTS" /YX /FD /GZ /c
|
||||||
|
MTL=midl.exe
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
RSC=rc.exe
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /out:"$(OutDir)/OpenThreadsWin32d.dll" /implib:"../lib/$(PlatformName)/OpenThreadsWin32d.lib"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "OpenThreads - Win32 Release Static"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release_Static"
|
||||||
|
# PROP BASE Intermediate_Dir "Release_Static"
|
||||||
|
# PROP BASE Ignore_Export_Lib 0
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "../lib/$(PlatformName)"
|
||||||
|
# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)_Static"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
MTL=midl.exe
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
CPP=cl.exe
|
||||||
|
# ADD BASE CPP /nologo /MT /W3 /GR /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "OT_LIBRARY_STATIC" /D "OPENTHREADS_EXPORTS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "OT_LIBRARY_STATIC" /YX /FD /c
|
||||||
|
RSC=rc.exe
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LIB32=link.exe -lib
|
||||||
|
# ADD BASE LIB32 /nologo
|
||||||
|
# ADD LIB32 /nologo /out:"../lib/$(PlatformName)/OpenThreadsWin32_s.lib"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "OpenThreads - Win32 Debug Static"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug_Static"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug_Static"
|
||||||
|
# PROP BASE Ignore_Export_Lib 0
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "../lib/$(PlatformName)"
|
||||||
|
# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)_Static"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
MTL=midl.exe
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
CPP=cl.exe
|
||||||
|
# ADD BASE CPP /nologo /MTd /W3 /Gm /GR /GX /Z7 /Od /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "OT_LIBRARY_STATIC" /D "OPENTHREADS_EXPORTS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /Z7 /Od /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "OT_LIBRARY_STATIC" /YX /FD /GZ /c
|
||||||
|
RSC=rc.exe
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LIB32=link.exe -lib
|
||||||
|
# ADD BASE LIB32 /nologo
|
||||||
|
# ADD LIB32 /nologo /out:"../lib/$(PlatformName)/OpenThreadsWin32d_s.lib"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "OpenThreads - Win32 Release"
|
||||||
|
# Name "OpenThreads - Win32 Debug"
|
||||||
|
# Name "OpenThreads - Win32 Release Static"
|
||||||
|
# Name "OpenThreads - Win32 Debug Static"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\WIN32Condition.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Win32Mutex.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Win32Thread.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Win32ThreadBarrier.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\OpenThreads\Barrier
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\OpenThreads\Condition
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\OpenThreads\Exports
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\HandleHolder.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\OpenThreads\Mutex
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\OpenThreads\ScopedLock
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\OpenThreads\Thread
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Win32BarrierPrivateData.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Win32ConditionPrivateData.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Win32MutexPrivateData.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Win32ThreadPrivateData.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
29
src/OpenThreads/win32/OpenThreads.dsw
Executable file
29
src/OpenThreads/win32/OpenThreads.dsw
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "OpenThreads"=.\OpenThreads.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
89
src/OpenThreads/win32/OpenThreads.mak
Normal file
89
src/OpenThreads/win32/OpenThreads.mak
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
# Makefile - OpenThreads.dsp
|
||||||
|
|
||||||
|
ifndef CFG
|
||||||
|
CFG=OpenThreads - Win32 Release
|
||||||
|
endif
|
||||||
|
CC=gcc
|
||||||
|
CFLAGS=
|
||||||
|
CXX=g++
|
||||||
|
CXXFLAGS=$(CFLAGS)
|
||||||
|
RC=windres -O COFF
|
||||||
|
ifeq "$(CFG)" "OpenThreads - Win32 Release"
|
||||||
|
CFLAGS+=-W -fexceptions -O2 -I../include -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -D_USRDLL -DOPENTHREADS_EXPORTS
|
||||||
|
LD=g++
|
||||||
|
LDFLAGS=-shared -Wl,--out-implib,../bin/Win32/OpenThreadsWin32.dll.a -Wl,--export-all-symbols
|
||||||
|
TARGET=../bin/Win32/OpenThreadsWin32.dll
|
||||||
|
LDFLAGS+=
|
||||||
|
LIBS+=-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32
|
||||||
|
else
|
||||||
|
ifeq "$(CFG)" "OpenThreads - Win32 Debug"
|
||||||
|
CFLAGS+=-W -fexceptions -g -O0 -I../include -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -D_USRDLL -DOPENTHREADS_EXPORTS
|
||||||
|
LD=g++
|
||||||
|
LDFLAGS=-shared -Wl,--out-implib,../bin/Win32/OpenThreadsWin32d.dll.a -Wl,--export-all-symbols
|
||||||
|
TARGET=../bin/Win32/OpenThreadsWin32d.dll
|
||||||
|
LDFLAGS+=
|
||||||
|
LIBS+=-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef TARGET
|
||||||
|
TARGET=OpenThreads.dll
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
%.o: %.cc
|
||||||
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
%.o: %.cxx
|
||||||
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
%.res: %.rc
|
||||||
|
$(RC) $(CPPFLAGS) -o $@ -i $<
|
||||||
|
|
||||||
|
SOURCE_FILES= \
|
||||||
|
WIN32Condition.cpp \
|
||||||
|
Win32Mutex.cpp \
|
||||||
|
Win32Thread.cpp \
|
||||||
|
Win32ThreadBarrier.cpp
|
||||||
|
|
||||||
|
HEADER_FILES= \
|
||||||
|
../include/OpenThreads/Barrier \
|
||||||
|
../include/OpenThreads/Condition \
|
||||||
|
../include/OpenThreads/Exports \
|
||||||
|
../include/OpenThreads/Mutex \
|
||||||
|
../include/OpenThreads/ScopedLock \
|
||||||
|
../include/OpenThreads/Thread \
|
||||||
|
Win32BarrierPrivateData.h \
|
||||||
|
Win32Condition.h \
|
||||||
|
Win32ConditionPrivateData.h \
|
||||||
|
Win32MutexPrivateData.h \
|
||||||
|
Win32ThreadPrivateData.h \
|
||||||
|
HandleHolder.h
|
||||||
|
|
||||||
|
RESOURCE_FILES=
|
||||||
|
|
||||||
|
SRCS=$(SOURCE_FILES) $(HEADER_FILES) $(RESOURCE_FILES)
|
||||||
|
|
||||||
|
OBJS=$(patsubst %.rc,%.res,$(patsubst %.cxx,%.o,$(patsubst %.cpp,%.o,$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(filter %.c %.cc %.cpp %.cxx %.rc,$(SRCS)))))))
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
-rm -f $(OBJS) $(TARGET) OpenThreads.dep
|
||||||
|
|
||||||
|
.PHONY: depends
|
||||||
|
depends:
|
||||||
|
-$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $(filter %.c %.cc %.cpp %.cxx,$(SRCS)) > OpenThreads.dep
|
||||||
|
|
||||||
|
-include OpenThreads.dep
|
||||||
|
|
100
src/OpenThreads/win32/WIN32Condition.cpp
Normal file
100
src/OpenThreads/win32/WIN32Condition.cpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Win32Condition.c++ - C++ Condition class built on top of posix threads.
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include "Win32ConditionPrivateData.h"
|
||||||
|
|
||||||
|
using namespace OpenThreads;
|
||||||
|
Win32ConditionPrivateData::~Win32ConditionPrivateData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Constructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Condition::Condition() {
|
||||||
|
Win32ConditionPrivateData *pd =
|
||||||
|
new Win32ConditionPrivateData();
|
||||||
|
_prvData = static_cast<void *>(pd);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Destructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Condition::~Condition() {
|
||||||
|
Win32ConditionPrivateData *pd =
|
||||||
|
static_cast<Win32ConditionPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
delete pd;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: wait on a condition
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Condition::wait(Mutex *mutex) {
|
||||||
|
|
||||||
|
Win32ConditionPrivateData *pd =
|
||||||
|
static_cast<Win32ConditionPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
return pd->wait(*mutex, INFINITE);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: wait on a condition, for a specified period of time
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Condition::wait(Mutex *mutex, unsigned long ms) {
|
||||||
|
|
||||||
|
Win32ConditionPrivateData *pd =
|
||||||
|
static_cast<Win32ConditionPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
return pd->wait(*mutex, ms);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: signal a thread to wake up.
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Condition::signal() {
|
||||||
|
|
||||||
|
Win32ConditionPrivateData *pd =
|
||||||
|
static_cast<Win32ConditionPrivateData *>(_prvData);
|
||||||
|
return pd->signal();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: signal many threads to wake up.
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Condition::broadcast() {
|
||||||
|
|
||||||
|
Win32ConditionPrivateData *pd =
|
||||||
|
static_cast<Win32ConditionPrivateData *>(_prvData);
|
||||||
|
return pd->broadcast();
|
||||||
|
}
|
69
src/OpenThreads/win32/Win32BarrierPrivateData.h
Normal file
69
src/OpenThreads/win32/Win32BarrierPrivateData.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Win32BarrierPrivateData.h - private data structure for barrier
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
#ifndef _Win32BARRIERPRIVATEDATA_H_
|
||||||
|
#define _Win32BARRIERPRIVATEDATA_H_
|
||||||
|
|
||||||
|
#ifndef _WINDOWS_
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class Barrier;
|
||||||
|
|
||||||
|
class Win32BarrierPrivateData {
|
||||||
|
friend class Barrier;
|
||||||
|
private:
|
||||||
|
Win32BarrierPrivateData() {};
|
||||||
|
~Win32BarrierPrivateData();
|
||||||
|
|
||||||
|
Condition cond; // cv for waiters at barrier
|
||||||
|
|
||||||
|
Mutex lock; // mutex for waiters at barrier
|
||||||
|
|
||||||
|
volatile int maxcnt; // number of threads to wait for
|
||||||
|
|
||||||
|
volatile int cnt; // number of waiting threads
|
||||||
|
|
||||||
|
volatile int phase; // flag to seperate two barriers
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //_Win32BARRIERPRIVATEDATA_H_
|
||||||
|
|
||||||
|
|
||||||
|
|
159
src/OpenThreads/win32/Win32Condition.h
Normal file
159
src/OpenThreads/win32/Win32Condition.h
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _WIN32VODITIONPRODUCER_CONDITION
|
||||||
|
#define PRODUCER_CONDITION
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#include "Mutex.h"
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class Win32ConditionImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// number of waiters.
|
||||||
|
long waiters_;
|
||||||
|
|
||||||
|
Condition(long max = 0L)
|
||||||
|
{
|
||||||
|
waiters_ = 0;
|
||||||
|
sema_ = CreateSemaphore(NULL,0,0x7fffffff,NULL);
|
||||||
|
waiters_done_ = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Condition()
|
||||||
|
{
|
||||||
|
// CloseHandle(sema_);
|
||||||
|
// CloseHandle(waiters_done_);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int broadcast ()
|
||||||
|
{
|
||||||
|
waiters_lock_.lock();
|
||||||
|
int have_waiters = 0;
|
||||||
|
|
||||||
|
if (waiters_ > 0)
|
||||||
|
{
|
||||||
|
// We are broadcasting, even if there is just one waiter...
|
||||||
|
// Record the fact that we are broadcasting. This helps the
|
||||||
|
// wait() method know how to optimize itself. Be sure to
|
||||||
|
// set this with the <waiters_lock_> held.
|
||||||
|
was_broadcast_ = 1;
|
||||||
|
have_waiters = 1;
|
||||||
|
}
|
||||||
|
waiters_lock_.unlock();
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
if (have_waiters)
|
||||||
|
{
|
||||||
|
// Wake up all the waiters.
|
||||||
|
ReleaseSemaphore(sema_,waiters_,NULL);
|
||||||
|
WaitForSingleObject(waiters_done_,INFINITE) ;
|
||||||
|
// This is okay, even without the <waiters_lock_> held because
|
||||||
|
// no other waiter threads can wake up to access it.
|
||||||
|
was_broadcast_ = 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int wait (Mutex& external_mutex)
|
||||||
|
{
|
||||||
|
// Prevent race conditions on the <waiters_> count.
|
||||||
|
waiters_lock_.lock();
|
||||||
|
waiters_++;
|
||||||
|
waiters_lock_.unlock();
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
external_mutex.unlock();
|
||||||
|
|
||||||
|
DWORD dwResult = WaitForSingleObject(sema_,INFINITE);
|
||||||
|
if(dwResult != WAIT_OBJECT_0)
|
||||||
|
result = (int)dwResult;
|
||||||
|
|
||||||
|
// Reacquire lock to avoid race conditions on the <waiters_> count.
|
||||||
|
waiters_lock_.lock();
|
||||||
|
|
||||||
|
// We're ready to return, so there's one less waiter.
|
||||||
|
waiters_--;
|
||||||
|
|
||||||
|
int last_waiter = was_broadcast_ && waiters_ == 0;
|
||||||
|
|
||||||
|
// Release the lock so that other collaborating threads can make
|
||||||
|
// progress.
|
||||||
|
waiters_lock_.unlock();
|
||||||
|
|
||||||
|
if (result != -1 && last_waiter)
|
||||||
|
SetEvent(waiters_done_);
|
||||||
|
|
||||||
|
external_mutex.lock();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/// Serialize access to the waiters count.
|
||||||
|
Mutex waiters_lock_;
|
||||||
|
|
||||||
|
/// Queue up threads waiting for the condition to become signaled.
|
||||||
|
HANDLE sema_;
|
||||||
|
/**
|
||||||
|
* An auto reset event used by the broadcast/signal thread to wait
|
||||||
|
* for the waiting thread(s) to wake up and get a chance at the
|
||||||
|
* semaphore.
|
||||||
|
*/
|
||||||
|
HANDLE waiters_done_;
|
||||||
|
|
||||||
|
/// Keeps track of whether we were broadcasting or just signaling.
|
||||||
|
size_t was_broadcast_;
|
||||||
|
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
namespace Producer {
|
||||||
|
|
||||||
|
class PR_EXPORT Condition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// number of waiters.
|
||||||
|
Condition(long max)
|
||||||
|
{
|
||||||
|
pthread_cond_init( &_cond, 0L );
|
||||||
|
}
|
||||||
|
|
||||||
|
~Condition()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int broadcast ()
|
||||||
|
{
|
||||||
|
return pthread_cond_broadcast(&_cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int wait (Mutex& external_mutex)
|
||||||
|
{
|
||||||
|
return pthread_cond_wait(&_cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
pthread_cond_t _cond;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
163
src/OpenThreads/win32/Win32ConditionPrivateData.h
Normal file
163
src/OpenThreads/win32/Win32ConditionPrivateData.h
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// WIN32ConditionPrivateData.h - Private data structure for Condition
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
#ifndef _WIN32CONDITIONPRIVATEDATA_H_
|
||||||
|
#define _WIN32CONDITIONPRIVATEDATA_H_
|
||||||
|
|
||||||
|
#ifndef _WINDOWS_
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <OpenThreads/ScopedLock>
|
||||||
|
|
||||||
|
#include "Win32ThreadPrivateData.h"
|
||||||
|
#include "HandleHolder.h"
|
||||||
|
|
||||||
|
#define InterlockedGet(x) InterlockedExchangeAdd(x,0)
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class Condition;
|
||||||
|
|
||||||
|
class Win32ConditionPrivateData {
|
||||||
|
public:
|
||||||
|
friend class Condition;
|
||||||
|
/// number of waiters.
|
||||||
|
long waiters_;
|
||||||
|
|
||||||
|
Win32ConditionPrivateData ()
|
||||||
|
:waiters_(0),
|
||||||
|
sema_(CreateSemaphore(NULL,0,0x7fffffff,NULL)),
|
||||||
|
waiters_done_(CreateEvent(NULL,FALSE,FALSE,NULL))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~Win32ConditionPrivateData ();
|
||||||
|
|
||||||
|
inline int broadcast ()
|
||||||
|
{
|
||||||
|
int have_waiters = 0;
|
||||||
|
long w = InterlockedGet(&waiters_);
|
||||||
|
|
||||||
|
if (w > 0)
|
||||||
|
{
|
||||||
|
// we are broadcasting.
|
||||||
|
was_broadcast_ = 1;
|
||||||
|
have_waiters = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
if (have_waiters)
|
||||||
|
{
|
||||||
|
// Wake up all the waiters.
|
||||||
|
ReleaseSemaphore(sema_.get(),waiters_,NULL);
|
||||||
|
|
||||||
|
cooperativeWait(waiters_done_.get(), INFINITE);
|
||||||
|
|
||||||
|
//end of broadcasting
|
||||||
|
was_broadcast_ = 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int signal()
|
||||||
|
{
|
||||||
|
long w = InterlockedGet(&waiters_);
|
||||||
|
int have_waiters = w > 0;
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (have_waiters)
|
||||||
|
{
|
||||||
|
if( !ReleaseSemaphore(sema_.get(),1,NULL) )
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int wait (Mutex& external_mutex, long timeout_ms)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Prevent race conditions on the <waiters_> count.
|
||||||
|
InterlockedIncrement(&waiters_);
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
ReverseScopedLock<Mutex> lock(external_mutex);
|
||||||
|
|
||||||
|
// wait in timeslices, giving testCancel() a change to
|
||||||
|
// exit the thread if requested.
|
||||||
|
try {
|
||||||
|
DWORD dwResult = cooperativeWait(sema_.get(), timeout_ms);
|
||||||
|
if(dwResult != WAIT_OBJECT_0)
|
||||||
|
result = (int)dwResult;
|
||||||
|
}
|
||||||
|
catch(...){
|
||||||
|
// thread is canceled in cooperative wait , do cleanup
|
||||||
|
InterlockedDecrement(&waiters_);
|
||||||
|
long w = InterlockedGet(&waiters_);
|
||||||
|
int last_waiter = was_broadcast_ && w == 0;
|
||||||
|
|
||||||
|
if (last_waiter) SetEvent(waiters_done_.get());
|
||||||
|
// rethrow
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// We're ready to return, so there's one less waiter.
|
||||||
|
InterlockedDecrement(&waiters_);
|
||||||
|
long w = InterlockedGet(&waiters_);
|
||||||
|
int last_waiter = was_broadcast_ && w == 0;
|
||||||
|
|
||||||
|
if (result != -1 && last_waiter)
|
||||||
|
SetEvent(waiters_done_.get());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/// Serialize access to the waiters count.
|
||||||
|
/// Mutex waiters_lock_;
|
||||||
|
/// Queue up threads waiting for the condition to become signaled.
|
||||||
|
HandleHolder sema_;
|
||||||
|
/**
|
||||||
|
* An auto reset event used by the broadcast/signal thread to wait
|
||||||
|
* for the waiting thread(s) to wake up and get a chance at the
|
||||||
|
* semaphore.
|
||||||
|
*/
|
||||||
|
HandleHolder waiters_done_;
|
||||||
|
/// Keeps track of whether we were broadcasting or just signaling.
|
||||||
|
size_t was_broadcast_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef InterlockedGet
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !_WIN32CONDITIONPRIVATEDATA_H_
|
||||||
|
|
||||||
|
|
||||||
|
|
222
src/OpenThreads/win32/Win32Mutex.cpp
Normal file
222
src/OpenThreads/win32/Win32Mutex.cpp
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Win32Mutex.c++ - C++ Mutex class .
|
||||||
|
// The idea for it is borrowed from SGI STL
|
||||||
|
// It looks like it's hard to use win32 CRITICALL_SECTIONS withour introducing race
|
||||||
|
// conditions on InitializeCriticalSection() . So we use spin mutex here.
|
||||||
|
// ~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
#include "Win32MutexPrivateData.h"
|
||||||
|
using namespace OpenThreads;
|
||||||
|
|
||||||
|
Win32MutexPrivateData::Win32MutexPrivateData()
|
||||||
|
{
|
||||||
|
#ifdef USE_CRITICAL_SECTION
|
||||||
|
InitializeCriticalSection( &_cs );
|
||||||
|
#else
|
||||||
|
mutex = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
Win32MutexPrivateData::~Win32MutexPrivateData()
|
||||||
|
{
|
||||||
|
#ifdef USE_CRITICAL_SECTION
|
||||||
|
DeleteCriticalSection( &_cs );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef USE_CRITICAL_SECTION
|
||||||
|
|
||||||
|
template <int instance>
|
||||||
|
struct WIN32MutexSpin {
|
||||||
|
|
||||||
|
enum { __low_max = 30, __high_max = 1000 };
|
||||||
|
// Low if we suspect uniprocessor, high for multiprocessor.
|
||||||
|
static unsigned __max;
|
||||||
|
static unsigned __last;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int instance>
|
||||||
|
unsigned WIN32MutexSpin <instance>::__max = WIN32MutexSpin <instance>::__low_max;
|
||||||
|
|
||||||
|
template <int instance>
|
||||||
|
unsigned WIN32MutexSpin <instance>::__last = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void _S_nsec_sleep(int __log_nsec) {
|
||||||
|
|
||||||
|
if (__log_nsec <= 20) {
|
||||||
|
SwitchToThread(); //Sleep(0); // adegli replaced it Sleep by SwitchToThread
|
||||||
|
} else {
|
||||||
|
Sleep(1 << (__log_nsec - 20));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER <= 1300
|
||||||
|
template WIN32MutexSpin <0>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // USE_CRITICAL_SECTION
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Constructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Mutex::Mutex() {
|
||||||
|
Win32MutexPrivateData *pd = new Win32MutexPrivateData();
|
||||||
|
_prvData = static_cast<void *>(pd);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Destructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Mutex::~Mutex() {
|
||||||
|
unlock();
|
||||||
|
delete static_cast<Win32MutexPrivateData*>(_prvData);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: lock the mutex
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Mutex::lock() {
|
||||||
|
Win32MutexPrivateData *pd =
|
||||||
|
static_cast<Win32MutexPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
#ifdef USE_CRITICAL_SECTION
|
||||||
|
|
||||||
|
// Block until we can take this lock.
|
||||||
|
EnterCriticalSection( &(pd->_cs) );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
volatile unsigned long* lock = &pd->mutex;
|
||||||
|
// InterlockedExchange returns old value
|
||||||
|
// if old_value == 0 mutex wasn't locked , now it is
|
||||||
|
if( !InterlockedExchange((long*)lock, 1L)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned my_spin_max = WIN32MutexSpin<0>::__max;
|
||||||
|
unsigned my_last_spins = WIN32MutexSpin<0>::__last;
|
||||||
|
volatile unsigned junk = 17;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < my_spin_max; i++) {
|
||||||
|
if (i < my_last_spins/2 || *lock) {
|
||||||
|
junk *= junk; junk *= junk;
|
||||||
|
junk *= junk; junk *= junk;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!InterlockedExchange((long*)lock, 1L)) {
|
||||||
|
// got it!
|
||||||
|
// Spinning worked. Thus we're probably not being scheduled
|
||||||
|
// against the other process with which we were contending.
|
||||||
|
// Thus it makes sense to spin longer the next time.
|
||||||
|
WIN32MutexSpin<0>::__last = i;
|
||||||
|
WIN32MutexSpin<0>::__max = WIN32MutexSpin<0>::__high_max;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We are probably being scheduled against the other process. Sleep.
|
||||||
|
WIN32MutexSpin<0>::__max = WIN32MutexSpin<0>::__low_max;
|
||||||
|
for (i = 0 ;; ++i) {
|
||||||
|
int __log_nsec = i + 6;
|
||||||
|
if (__log_nsec > 27) __log_nsec = 27;
|
||||||
|
if (!InterlockedExchange((long*)lock, 1L)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_S_nsec_sleep(__log_nsec);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#endif // USE_CRITICAL_SECTION
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: unlock the mutex
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Mutex::unlock() {
|
||||||
|
Win32MutexPrivateData *pd =
|
||||||
|
static_cast<Win32MutexPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
#ifdef USE_CRITICAL_SECTION
|
||||||
|
|
||||||
|
// Release this lock. CRITICAL_SECTION is nested, thus
|
||||||
|
// unlock() calls must be paired with lock() calls.
|
||||||
|
LeaveCriticalSection( &(pd->_cs) );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
volatile unsigned long* lock = &pd->mutex;
|
||||||
|
*lock = 0;
|
||||||
|
// This is not sufficient on many multiprocessors, since
|
||||||
|
// writes to protected variables and the lock may be reordered.
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#endif // USE_CRITICAL_SECTION
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: test if the mutex may be locked
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
int Mutex::trylock() {
|
||||||
|
Win32MutexPrivateData *pd =
|
||||||
|
static_cast<Win32MutexPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
#ifdef USE_CRITICAL_SECTION
|
||||||
|
|
||||||
|
// Take the lock if we can; regardless don't block.
|
||||||
|
// 'result' is FALSE if we took the lock or already held
|
||||||
|
// it amd TRUE if another thread already owns the lock.
|
||||||
|
BOOL result = TryEnterCriticalSection( &(pd->_cs) );
|
||||||
|
|
||||||
|
return( (result==TRUE) ? 0 : 1 );
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
volatile unsigned long* lock = &pd->mutex;
|
||||||
|
|
||||||
|
if( !InterlockedExchange((long*)lock, 1L)) {
|
||||||
|
return 1; // TRUE
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; // FALSE
|
||||||
|
|
||||||
|
#endif // USE_CRITICAL_SECTION
|
||||||
|
}
|
||||||
|
|
55
src/OpenThreads/win32/Win32MutexPrivateData.h
Normal file
55
src/OpenThreads/win32/Win32MutexPrivateData.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Win32MutexPrivateData.h - Private data structure for Mutex
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _Win32MUTEXPRIVATEDATA_H_
|
||||||
|
#define _Win32MUTEXPRIVATEDATA_H_
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _WINDOWS_
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define _WIN32_WINNT 0x0400 // was missing : adegli
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class Win32MutexPrivateData {
|
||||||
|
friend class Mutex;
|
||||||
|
friend class Condition;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Win32MutexPrivateData();
|
||||||
|
|
||||||
|
~Win32MutexPrivateData();
|
||||||
|
#define USE_CRITICAL_SECTION
|
||||||
|
#ifdef USE_CRITICAL_SECTION
|
||||||
|
CRITICAL_SECTION _cs;
|
||||||
|
#else
|
||||||
|
volatile unsigned long mutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !_Win32MUTEXPRIVATEDATA_H_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
682
src/OpenThreads/win32/Win32Thread.cpp
Normal file
682
src/OpenThreads/win32/Win32Thread.cpp
Normal file
@ -0,0 +1,682 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Win32Thread.c++
|
||||||
|
// ~~~~~~~~~~~
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER < 1300)
|
||||||
|
#ifdef __SGI_STL
|
||||||
|
using std::size_t;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
using std::size_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning( disable : 4996 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "Win32ThreadPrivateData.h"
|
||||||
|
|
||||||
|
struct Win32ThreadCanceled{};
|
||||||
|
|
||||||
|
using namespace OpenThreads;
|
||||||
|
|
||||||
|
DWORD OpenThreads::cooperativeWait(HANDLE waitHandle, unsigned long timeout){
|
||||||
|
Thread* current = Thread::CurrentThread();
|
||||||
|
DWORD dwResult ;
|
||||||
|
if(current)
|
||||||
|
{
|
||||||
|
HANDLE cancelHandle = static_cast<Win32ThreadPrivateData*>(current->getImplementation())->cancelEvent.get();
|
||||||
|
HANDLE handleSet[2] = {waitHandle, cancelHandle};
|
||||||
|
|
||||||
|
dwResult = WaitForMultipleObjects(2,handleSet,FALSE,timeout);
|
||||||
|
if(dwResult == WAIT_OBJECT_0 + 1 ) throw Win32ThreadCanceled();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dwResult = WaitForSingleObject(waitHandle,timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dwResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
Win32ThreadPrivateData::TlsHolder Win32ThreadPrivateData::TLS;
|
||||||
|
|
||||||
|
Win32ThreadPrivateData::~Win32ThreadPrivateData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string OPENTHREAD_VERSION_STRING = "OpenThread v1.2preAlpha, WindowThreads (Public Implementation)";
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Initialize thread master priority level
|
||||||
|
//
|
||||||
|
Thread::ThreadPriority Thread::s_masterThreadPriority = Thread::THREAD_PRIORITY_DEFAULT;
|
||||||
|
|
||||||
|
bool Thread::s_isInitialized = false;
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Class to support some static methods necessary for pthread's to work
|
||||||
|
// correctly.
|
||||||
|
//
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class ThreadPrivateActions {
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// We're friendly to Thread, so it can issue the methods.
|
||||||
|
//
|
||||||
|
friend class Thread;
|
||||||
|
private:
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Win32Threads standard start routine.
|
||||||
|
//
|
||||||
|
static unsigned int __stdcall StartThread(void *data) {
|
||||||
|
|
||||||
|
Thread *thread = static_cast<Thread *>(data);
|
||||||
|
|
||||||
|
Win32ThreadPrivateData *pd =
|
||||||
|
static_cast<Win32ThreadPrivateData *>(thread->_prvData);
|
||||||
|
|
||||||
|
if (thread->_prvData==0) return 0;
|
||||||
|
|
||||||
|
TlsSetValue(Win32ThreadPrivateData::TLS.ID ,data);
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Set the proper scheduling priorities
|
||||||
|
//
|
||||||
|
SetThreadSchedulingParams(thread);
|
||||||
|
|
||||||
|
pd->isRunning = true;
|
||||||
|
|
||||||
|
// release the thread that created this thread.
|
||||||
|
pd->threadStartedBlock.release();
|
||||||
|
|
||||||
|
try{
|
||||||
|
thread->run();
|
||||||
|
}
|
||||||
|
catch(Win32ThreadCanceled&)
|
||||||
|
{
|
||||||
|
// thread is canceled do cleanup
|
||||||
|
try {
|
||||||
|
thread->cancelCleanup();
|
||||||
|
} catch(...) { }
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
// abnormal termination but must be caught in win32 anyway
|
||||||
|
}
|
||||||
|
|
||||||
|
pd->isRunning = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Print information related to thread schduling parameters.
|
||||||
|
//
|
||||||
|
static void PrintThreadSchedulingInfo(Thread *thread) {
|
||||||
|
Win32ThreadPrivateData *pd =
|
||||||
|
static_cast<Win32ThreadPrivateData *>(thread->_prvData);
|
||||||
|
|
||||||
|
std::cout<<"Thread "<< thread <<" priority : ";
|
||||||
|
|
||||||
|
switch(thread->getSchedulePriority()) {
|
||||||
|
case Thread::THREAD_PRIORITY_MAX:
|
||||||
|
std::cout<<"MAXIMAL"<<std::endl;
|
||||||
|
break;
|
||||||
|
case Thread::THREAD_PRIORITY_HIGH:
|
||||||
|
std::cout<<"HIGH"<<std::endl;
|
||||||
|
break;
|
||||||
|
case Thread::THREAD_PRIORITY_DEFAULT:
|
||||||
|
case Thread::THREAD_PRIORITY_NOMINAL:
|
||||||
|
std::cout<<"NORMAL"<<std::endl;
|
||||||
|
break;
|
||||||
|
case Thread::THREAD_PRIORITY_LOW:
|
||||||
|
std::cout<<"LOW"<<std::endl;
|
||||||
|
break;
|
||||||
|
case Thread::THREAD_PRIORITY_MIN:
|
||||||
|
std::cout<<"MINIMAL"<<std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Set thread scheduling parameters.
|
||||||
|
// Note that time-critical priority is ommited :
|
||||||
|
// 1) It's not sensible thing to do
|
||||||
|
// 2) there's no enum for that in Thread interface
|
||||||
|
// Also, on Windows, effective thread priority is :
|
||||||
|
// process priority (manipulated with Get/SetProrityClass) + thread priority (here).
|
||||||
|
//
|
||||||
|
//
|
||||||
|
static int SetThreadSchedulingParams(Thread *thread) {
|
||||||
|
|
||||||
|
Win32ThreadPrivateData *pd =
|
||||||
|
static_cast<Win32ThreadPrivateData *>(thread->_prvData);
|
||||||
|
|
||||||
|
int prio = THREAD_PRIORITY_NORMAL;
|
||||||
|
|
||||||
|
switch(thread->getSchedulePriority()) {
|
||||||
|
case Thread::THREAD_PRIORITY_MAX:
|
||||||
|
prio = THREAD_PRIORITY_HIGHEST;
|
||||||
|
break;
|
||||||
|
case Thread::THREAD_PRIORITY_HIGH:
|
||||||
|
prio = THREAD_PRIORITY_ABOVE_NORMAL;
|
||||||
|
break;
|
||||||
|
case Thread::THREAD_PRIORITY_NOMINAL:
|
||||||
|
prio = THREAD_PRIORITY_NORMAL;
|
||||||
|
break;
|
||||||
|
case Thread::THREAD_PRIORITY_LOW:
|
||||||
|
prio = THREAD_PRIORITY_BELOW_NORMAL;
|
||||||
|
break;
|
||||||
|
case Thread::THREAD_PRIORITY_MIN:
|
||||||
|
prio = THREAD_PRIORITY_IDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = SetThreadPriority( pd->tid.get(), prio);
|
||||||
|
|
||||||
|
if(getenv("OUTPUT_THREADLIB_SCHEDULING_INFO") != 0)
|
||||||
|
PrintThreadSchedulingInfo(thread);
|
||||||
|
|
||||||
|
return status!=0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Thread* Thread::CurrentThread()
|
||||||
|
{
|
||||||
|
return (Thread* )TlsGetValue(Win32ThreadPrivateData::TLS.ID);
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the concurrency level (no-op)
|
||||||
|
//
|
||||||
|
// Use static public
|
||||||
|
//
|
||||||
|
int Thread::SetConcurrency(int) {
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the concurrency level
|
||||||
|
//
|
||||||
|
// Use static public
|
||||||
|
//
|
||||||
|
int Thread::GetConcurrency() {
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Constructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Thread::Thread() {
|
||||||
|
|
||||||
|
// there's no need for this
|
||||||
|
// if(!s_isInitialized) Init();
|
||||||
|
|
||||||
|
Win32ThreadPrivateData *pd = new Win32ThreadPrivateData();
|
||||||
|
|
||||||
|
pd->stackSize = 0;
|
||||||
|
pd->isRunning = false;
|
||||||
|
pd->cancelMode = 0;
|
||||||
|
pd->uniqueId = 0;
|
||||||
|
pd->threadPriority = Thread::THREAD_PRIORITY_DEFAULT;
|
||||||
|
pd->threadPolicy = Thread::THREAD_SCHEDULE_DEFAULT;
|
||||||
|
pd->detached = false;
|
||||||
|
pd->cancelEvent.set(CreateEvent(NULL,TRUE,FALSE,NULL));
|
||||||
|
|
||||||
|
_prvData = static_cast<void *>(pd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Destructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Thread::~Thread()
|
||||||
|
{
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *>(_prvData);
|
||||||
|
|
||||||
|
if(pd->isRunning)
|
||||||
|
{
|
||||||
|
std::cout<<"Error: Thread "<<this<<" still running in destructor"<<std::endl;
|
||||||
|
pd->cancelMode = 0;
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete pd;
|
||||||
|
|
||||||
|
_prvData = 0;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Initialize Threading
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
void Thread::Init() {
|
||||||
|
// if(s_isInitialized) return;
|
||||||
|
// s_masterThreadPriority = Thread::THREAD_PRIORITY_DEFAULT;
|
||||||
|
s_isInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get a unique identifier for this thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::getThreadId() {
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
return pd->uniqueId;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the thread's process id
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
size_t Thread::getProcessId() {
|
||||||
|
|
||||||
|
return (size_t) GetCurrentProcessId();
|
||||||
|
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Determine if the thread is running
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
bool Thread::isRunning() {
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
return pd->isRunning;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Start the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::start() {
|
||||||
|
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Prohibit the stack size from being changed.
|
||||||
|
// (bb 5/13/2005) it actually doesn't matter.
|
||||||
|
// 1) usually setStackSize()/start() sequence is serialized.
|
||||||
|
// 2) if not than we're in trouble anyway - nothing is protected
|
||||||
|
// pd->stackSizeLocked = true;
|
||||||
|
unsigned int ID;
|
||||||
|
|
||||||
|
pd->threadStartedBlock.reset();
|
||||||
|
|
||||||
|
pd->tid.set( (void*)_beginthreadex(NULL,pd->stackSize,ThreadPrivateActions::StartThread,static_cast<void *>(this),0,&ID));
|
||||||
|
|
||||||
|
pd->uniqueId = (int)ID;
|
||||||
|
|
||||||
|
// wait till the thread has actually started.
|
||||||
|
pd->threadStartedBlock.block();
|
||||||
|
|
||||||
|
if(!pd->tid) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int Thread::startThread()
|
||||||
|
{
|
||||||
|
if (_prvData) return start();
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Join the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::join() {
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
if( pd->detached )
|
||||||
|
return -1; // cannot wait for detached ;
|
||||||
|
|
||||||
|
if( WaitForSingleObject(pd->tid.get(),INFINITE) != WAIT_OBJECT_0)
|
||||||
|
return -1 ;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int Thread::detach()
|
||||||
|
{
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
pd->detached = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Cancel the thread.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::cancel()
|
||||||
|
{
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
if (pd->isRunning)
|
||||||
|
{
|
||||||
|
if( pd->cancelMode == 2 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// signal all interested parties that we are going to exit
|
||||||
|
SetEvent(pd->cancelEvent.get());
|
||||||
|
|
||||||
|
// cancelMode == 1 (asynch)-> kill em
|
||||||
|
// cancelMode == 0 (deffered) -> wait a little then kill em
|
||||||
|
|
||||||
|
// if( (pd->cancelMode == 1) || (WaitForSingleObject(pd->tid,INFINITE)!=WAIT_OBJECT_0) )
|
||||||
|
if( pd->cancelMode == 1 )
|
||||||
|
{
|
||||||
|
// did not terminate cleanly force termination
|
||||||
|
pd->isRunning = false;
|
||||||
|
return TerminateThread(pd->tid.get(),(DWORD)-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int Thread::testCancel()
|
||||||
|
{
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
if(WaitForSingleObject(pd->cancelEvent.get(),0) != WAIT_OBJECT_0) return 0;
|
||||||
|
|
||||||
|
if(pd->cancelMode == 2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
DWORD curr = GetCurrentThreadId();
|
||||||
|
|
||||||
|
if( pd->uniqueId != (int)curr )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// pd->isRunning = false;
|
||||||
|
// ExitThread(0);
|
||||||
|
throw Win32ThreadCanceled();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Disable cancelibility
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setCancelModeDisable() {
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
pd->cancelMode = 2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: set the thread to cancel immediately
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setCancelModeAsynchronous() {
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
pd->cancelMode = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: set the thread to cancel at the next convenient point.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setCancelModeDeferred() {
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
pd->cancelMode = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's schedule priority (if able)
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setSchedulePriority(ThreadPriority priority) {
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
pd->threadPriority = priority;
|
||||||
|
|
||||||
|
if(pd->isRunning)
|
||||||
|
return ThreadPrivateActions::SetThreadSchedulingParams(this);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the thread's schedule priority (if able)
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::getSchedulePriority() {
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
return pd->threadPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's scheduling policy (if able)
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setSchedulePolicy(ThreadPolicy policy) {
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
|
||||||
|
pd->threadPolicy = policy;
|
||||||
|
|
||||||
|
if(pd->isRunning)
|
||||||
|
return ThreadPrivateActions::SetThreadSchedulingParams(this);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's scheduling policy (if able)
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::getSchedulePolicy() {
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
return pd->threadPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Set the thread's desired stack size
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setStackSize(size_t stackSize) {
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
if(pd->isRunning) return 13; // cannot set stack size of running thread return EACESS
|
||||||
|
pd->stackSize = stackSize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the thread's stack size.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
size_t Thread::getStackSize() {
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
return pd->stackSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: set processor affinity for the thread
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Thread::setProcessorAffinity( unsigned int cpunum )
|
||||||
|
{
|
||||||
|
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
|
||||||
|
DWORD affinityMask = 0x1 << cpunum ; // thread affinity mask
|
||||||
|
DWORD_PTR res =
|
||||||
|
SetThreadAffinityMask
|
||||||
|
(
|
||||||
|
pd->tid.get(), // handle to thread
|
||||||
|
affinityMask // thread affinity mask
|
||||||
|
);
|
||||||
|
/*
|
||||||
|
This one is funny.
|
||||||
|
This is "non-mandatory" affinity , windows will try to use dwIdealProcessor
|
||||||
|
whenever possible ( when Bill's account is over 50B, maybe :-) ).
|
||||||
|
|
||||||
|
DWORD SetThreadIdealProcessor(
|
||||||
|
HANDLE hThread, // handle to the thread
|
||||||
|
DWORD dwIdealProcessor // ideal processor number
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
// return value 1 means call is ignored ( 9x/ME/SE )
|
||||||
|
if( res == 1 ) return -1;
|
||||||
|
// return value 0 is failure
|
||||||
|
return (res == 0) ? GetLastError() : 0 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Print the thread's scheduling information to stdout.
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
void Thread::printSchedulingInfo() {
|
||||||
|
ThreadPrivateActions::PrintThreadSchedulingInfo(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Yield the processor
|
||||||
|
//
|
||||||
|
// Use: protected
|
||||||
|
//
|
||||||
|
#if _WIN32_WINNT < 0x0400 // simulate
|
||||||
|
int SwitchToThread (void)
|
||||||
|
{
|
||||||
|
::Sleep(10);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int Thread::YieldCurrentThread()
|
||||||
|
{
|
||||||
|
return SwitchToThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Thread::microSleep(unsigned int microsec)
|
||||||
|
{
|
||||||
|
#if _WIN32_WINNT < 0x0400 // simulate
|
||||||
|
::Sleep(microsec/1000);
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
HandleHolder sleepTimer(CreateWaitableTimer(NULL, TRUE, NULL));
|
||||||
|
|
||||||
|
if( !sleepTimer )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
LARGE_INTEGER t;
|
||||||
|
|
||||||
|
t.QuadPart= -(LONGLONG)microsec*10; // in 100ns units
|
||||||
|
// negative sign means relative,
|
||||||
|
|
||||||
|
if (!SetWaitableTimer(sleepTimer.get(), &t, 0, NULL, NULL, 0))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the timer.
|
||||||
|
if (WaitForSingleObject(sleepTimer.get(), INFINITE) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Get the number of processors
|
||||||
|
//
|
||||||
|
int OpenThreads::GetNumberOfProcessors()
|
||||||
|
{
|
||||||
|
SYSTEM_INFO sysInfo;
|
||||||
|
GetSystemInfo(&sysInfo);
|
||||||
|
|
||||||
|
return sysInfo.dwNumberOfProcessors;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OpenThreads::SetProcessorAffinityOfCurrentThread(unsigned int cpunum)
|
||||||
|
{
|
||||||
|
if (cpunum<0) return -1;
|
||||||
|
|
||||||
|
Thread::Init();
|
||||||
|
|
||||||
|
Thread* thread = Thread::CurrentThread();
|
||||||
|
if (thread)
|
||||||
|
{
|
||||||
|
return thread->setProcessorAffinity(cpunum);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// non op right now, needs implementation.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
149
src/OpenThreads/win32/Win32ThreadBarrier.cpp
Normal file
149
src/OpenThreads/win32/Win32ThreadBarrier.cpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Win32Barrier.c++ - C++ Barrier class built on top of POSIX threads.
|
||||||
|
// ~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <OpenThreads/Barrier>
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <OpenThreads/ScopedLock>
|
||||||
|
#include "Win32BarrierPrivateData.h"
|
||||||
|
using namespace OpenThreads;
|
||||||
|
|
||||||
|
// so compiler can place it somewhere
|
||||||
|
Win32BarrierPrivateData::~Win32BarrierPrivateData()
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Constructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Barrier::Barrier(int numThreads) {
|
||||||
|
Win32BarrierPrivateData *pd = new Win32BarrierPrivateData();
|
||||||
|
pd->cnt = 0;
|
||||||
|
pd->phase = 0;
|
||||||
|
pd->maxcnt = numThreads;
|
||||||
|
_valid = true;
|
||||||
|
_prvData = static_cast<void *>(pd);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Destructor
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
Barrier::~Barrier() {
|
||||||
|
Win32BarrierPrivateData *pd =
|
||||||
|
static_cast<Win32BarrierPrivateData*>(_prvData);
|
||||||
|
delete pd;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Reset the barrier to its original state
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
void Barrier::reset() {
|
||||||
|
Win32BarrierPrivateData *pd =
|
||||||
|
static_cast<Win32BarrierPrivateData*>(_prvData);
|
||||||
|
pd->cnt = 0;
|
||||||
|
pd->phase = 0;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Block until numThreads threads have entered the barrier.
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
void Barrier::block(unsigned int numThreads) {
|
||||||
|
|
||||||
|
Win32BarrierPrivateData *pd =
|
||||||
|
static_cast<Win32BarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
if(numThreads != 0) pd->maxcnt = numThreads;
|
||||||
|
int my_phase;
|
||||||
|
|
||||||
|
ScopedLock<Mutex> lock(pd->lock);
|
||||||
|
if( _valid )
|
||||||
|
{
|
||||||
|
my_phase = pd->phase;
|
||||||
|
++pd->cnt;
|
||||||
|
|
||||||
|
if (pd->cnt == pd->maxcnt) { // I am the last one
|
||||||
|
pd->cnt = 0; // reset for next use
|
||||||
|
pd->phase = 1 - my_phase; // toggle phase
|
||||||
|
pd->cond.broadcast();
|
||||||
|
}else{
|
||||||
|
while (pd->phase == my_phase ) {
|
||||||
|
pd->cond.wait(&pd->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Barrier::invalidate()
|
||||||
|
{
|
||||||
|
Win32BarrierPrivateData *pd =
|
||||||
|
static_cast<Win32BarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
pd->lock.lock();
|
||||||
|
_valid = false;
|
||||||
|
pd->lock.unlock();
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Release the barrier, now.
|
||||||
|
//
|
||||||
|
// Use: public.
|
||||||
|
//
|
||||||
|
void Barrier::release() {
|
||||||
|
|
||||||
|
Win32BarrierPrivateData *pd =
|
||||||
|
static_cast<Win32BarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
int my_phase;
|
||||||
|
|
||||||
|
ScopedLock<Mutex> lock(pd->lock);
|
||||||
|
my_phase = pd->phase;
|
||||||
|
|
||||||
|
pd->cnt = 0; // reset for next use
|
||||||
|
pd->phase = 1 - my_phase; // toggle phase
|
||||||
|
pd->cond.broadcast();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Description: Return the number of threads currently blocked in the barrier
|
||||||
|
//
|
||||||
|
// Use: public
|
||||||
|
//
|
||||||
|
int Barrier::numThreadsCurrentlyBlocked() {
|
||||||
|
|
||||||
|
Win32BarrierPrivateData *pd =
|
||||||
|
static_cast<Win32BarrierPrivateData*>(_prvData);
|
||||||
|
|
||||||
|
int numBlocked = -1;
|
||||||
|
ScopedLock<Mutex> lock(pd->lock);
|
||||||
|
numBlocked = pd->cnt;
|
||||||
|
return numBlocked;
|
||||||
|
|
||||||
|
}
|
95
src/OpenThreads/win32/Win32ThreadPrivateData.h
Normal file
95
src/OpenThreads/win32/Win32ThreadPrivateData.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Win32PrivateData.h - Private data structure for Thread
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
#ifndef _Win32PRIVATEDATA_H_
|
||||||
|
#define _Win32PRIVATEDATA_H_
|
||||||
|
|
||||||
|
#ifndef _WINDOWS_
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define _WIN32_WINNT 0x0400
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <OpenThreads/Block>
|
||||||
|
#include "HandleHolder.h"
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
class Win32ThreadPrivateData {
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// We're friendly to Thread, so it can use our data.
|
||||||
|
//
|
||||||
|
friend class Thread;
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// We're friendly to Win32PrivateActions, so it can get at some
|
||||||
|
// variables.
|
||||||
|
//
|
||||||
|
friend class ThreadPrivateActions;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Win32ThreadPrivateData() {};
|
||||||
|
~Win32ThreadPrivateData();
|
||||||
|
|
||||||
|
size_t stackSize;
|
||||||
|
bool isRunning;
|
||||||
|
|
||||||
|
Block threadStartedBlock;
|
||||||
|
|
||||||
|
int cancelMode; // 0 - deffered (default) 1-asynch 2-disabled
|
||||||
|
|
||||||
|
bool detached;
|
||||||
|
|
||||||
|
Thread::ThreadPriority threadPriority;
|
||||||
|
|
||||||
|
Thread::ThreadPolicy threadPolicy;
|
||||||
|
|
||||||
|
HandleHolder tid;
|
||||||
|
|
||||||
|
int uniqueId;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
HandleHolder cancelEvent;
|
||||||
|
|
||||||
|
struct TlsHolder{ // thread local storage slot
|
||||||
|
DWORD ID;
|
||||||
|
TlsHolder(): ID(TlsAlloc()){
|
||||||
|
}
|
||||||
|
~TlsHolder(){
|
||||||
|
TlsFree(ID);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static TlsHolder TLS;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
DWORD cooperativeWait(HANDLE waitHandle, unsigned long timeout);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !_PTHREADPRIVATEDATA_H_
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user