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:
Robert Osfield
2008-04-01 10:49:53 +00:00
parent 73b87274b0
commit 323ce02f23
51 changed files with 7811 additions and 0 deletions

View 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)

View 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

View 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;
}

View 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;
}

View 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_

View 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 );
}

View 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_

View 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);
}

View 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_

View 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_