Hi Robert,
the long promised patch to implement the sched_setaffinity in a way that
matches the system it is compiled on.
That is there is a cmake configure test to make sure we use the version
available on the system
There are also various improovements to other system specific methods for less
common architectures.
The attached files arebased on rev 7491. The CMakeLists.txt file is the one in
src/OpenThreads/pthreads/CMakeLists.txt
Please apply
thanks
Mathias
--
Dr. Mathias Fröhlich, science + computing ag, Software Solutions
Hagellocher Weg 71-75, D-72070 Tuebingen, Germany
Phone: +49 7071 9457-268, Fax: +49 7071 9457-511
--
Vorstand/Board of Management:
Dr. Bernd Finkbeiner, Dr. Florian Geyer,
Dr. Roland Niemeier, Dr. Arno Steitz, Dr. Ingrid Zech
Vorsitzender des Aufsichtsrats/
Chairman of the Supervisory Board:
Prof. Dr. Hanns Ruder
Sitz/Registered Office: Tuebingen
Registergericht/Registration Court: Stuttgart
Registernummer/Commercial Register No.: HRB 382196
# 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)
/* -*-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)
return pthread_yield();
#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;
}
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org