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:
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_
|
||||
Reference in New Issue
Block a user