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