Files
OpenSceneGraph/src/OpenThreads/pthreads/PThread.cpp
Robert Osfield 8e2857905f Fixed warnings generated by clang,
src/osgAnimation/Skeleton.cpp:25:87: warning: addition of default argument on redeclaration makes this constructor a copy constructor [-Wdefault-arg-special-member]
Skeleton::UpdateSkeleton::UpdateSkeleton(const UpdateSkeleton& us, const osg::CopyOp& copyop= osg::CopyOp::SHALLOW_COPY) : osg::Object(us, copyop), osg::NodeCallback(us, copyop)

/src/OpenThreads/pthreads/PThread.cpp:1024:15: warning: comparison of unsigned expression < 0 is always false [-Wtautological-compare]
    if (cpunum<0) return -1;

src/osgDB/ExternalFileWriter.cpp:221:122: warning: expression result unused [-Wunused-value]
    _objects.insert(ObjectsSet::value_type(&obj, ObjectData(absoluteDestinationPath, relativeDestinationPath, written))).first;

src/osgManipulator/Dragger.cpp:175:18: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
        if (*itr = constraint) return;

src/osgManipulator/Dragger.cpp:187:18: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
        if (*itr = constraint)
2011-06-23 19:58:52 +00:00

1052 lines
25 KiB
C++

/* -*-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>
#include <limits.h>
#if defined __linux || defined __sun || defined __APPLE__ || ANDROID
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
#if !defined ANDROID
#include <sys/unistd.h>
#endif
#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
#if defined(ANDROID)
#ifndef PAGE_SIZE
#define PAGE_SIZE 0x400
#endif
#endif
#include <OpenThreads/Thread>
#include "PThreadPrivateData.h"
#include <iostream>
using namespace OpenThreads;
#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()
{
if(!s_isInitialized) Thread::Init();
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)
return pthread_setaffinity_np (pthread_self(), sizeof(cpumask), &cpumask);
#elif defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
return sched_setaffinity( 0, sizeof(cpumask), &cpumask );
#elif defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
return 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);
//-------------------------------------------------------------------------
// Set the stack size if requested, but not less than a platform reasonable
// value.
//
if(pd->stackSize)
{
#ifdef PTHREAD_STACK_MIN
if(pd->stackSize < PTHREAD_STACK_MIN)
pd->stackSize = PTHREAD_STACK_MIN;
#endif
pthread_attr_setstacksize( &thread_attr, pd->stackSize);
if(status != 0)
{
return status;
}
}
//-------------------------------------------------------------------------
// Now get what we actually have...
//
size_t size;
pthread_attr_getstacksize( &thread_attr, &size);
if(status != 0)
{
return status;
}
pd->stackSize = size;
//-------------------------------------------------------------------------
// 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));
if(status == 0)
{
// wait till the thread has actually started.
pd->threadStartedBlock.block();
pd->idSet = true;
}
return status;
}
//-----------------------------------------------------------------------------
//
// Description: Alternate thread start routine.
//
// Use: public
//
int Thread::startThread()
{
if (_prvData) return start();
else return 0;
}
//-----------------------------------------------------------------------------
//
// Description: detach 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()
{
#if defined(HAVE_PTHREAD_TESTCANCEL)
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
if(pthread_self() != pd->tid)
return -1;
pthread_testcancel();
return 0;
#else
return 0;
#endif
}
//-----------------------------------------------------------------------------
//
// Description: Cancel the thread.
//
// Use: public
//
int Thread::cancel()
{
#if defined(HAVE_PTHREAD_CANCEL)
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
if (pd->isRunning)
{
pd->isCanceled = true;
int status = pthread_cancel(pd->tid);
return status;
}
return 0;
#else
return 0;
#endif
}
//-----------------------------------------------------------------------------
//
// Description: Disable cancelibility
//
// Use: public
//
int Thread::setCancelModeDisable()
{
#if defined(HAVE_PTHREAD_SETCANCELSTATE)
return pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, 0 );
#else
return 0;
#endif
}
//-----------------------------------------------------------------------------
//
// Description: set the thread to cancel immediately
//
// Use: public
//
int Thread::setCancelModeAsynchronous() {
#if defined(HAVE_PTHREAD_SETCANCELSTATE)
int status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
if(status != 0) return status;
return pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, 0);
#else
return 0;
#endif
}
//-----------------------------------------------------------------------------
//
// Description: set the thread to cancel at the next convienent point.
//
// Use: public
//
int Thread::setCancelModeDeferred() {
#if defined(HAVE_PTHREAD_SETCANCELSTATE)
int status = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
if(status != 0) return status;
return pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, 0);
#else
return 0;
#endif
}
//-----------------------------------------------------------------------------
//
// 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)
{
#if !defined(ANDROID)
return ::usleep(microsec);
#else
::usleep(microsec);
return 0;
#endif
}
//-----------------------------------------------------------------------------
//
// 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)
{
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);
return 0;
#elif defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
sched_setaffinity( 0, sizeof(cpumask), &cpumask );
return 0;
#elif defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
sched_setaffinity( 0, &cpumask );
return 0;
#endif
#endif
}
return -1;
}