From 0f8a5a86e287864f8382b4474bfda06f0137357e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 26 Sep 2016 19:18:15 +0100 Subject: [PATCH] Introduced OpenThreads::SetProcessorAffinityMaskOfCurrentThread(unsigned long cpumask) and Threads::setProcessorAffinityMask(unsigned long cpumask) to allow finer grained control over the CPU affinity. --- include/OpenThreads/Thread | 41 +++++--- src/OpenThreads/pthreads/PThread.cpp | 94 +++++++++++-------- src/OpenThreads/pthreads/PThreadPrivateData.h | 4 +- 3 files changed, 87 insertions(+), 52 deletions(-) diff --git a/include/OpenThreads/Thread b/include/OpenThreads/Thread index ab835bba3..c525cec8b 100644 --- a/include/OpenThreads/Thread +++ b/include/OpenThreads/Thread @@ -35,12 +35,18 @@ namespace OpenThreads { extern OPENTHREAD_EXPORT_DIRECTIVE int GetNumberOfProcessors(); /** - * Set the processor affinity of current thread. - * - * Note, systems where no support exists no affinity will be set, and -1 will be returned. - * + * Set the processor affinity mask of current thread. If you want to allow thread to run on any processor core use ~0ul for the cpumask */ -extern OPENTHREAD_EXPORT_DIRECTIVE int SetProcessorAffinityOfCurrentThread(unsigned int cpunum); +extern OPENTHREAD_EXPORT_DIRECTIVE int SetProcessorAffinityMaskOfCurrentThread(unsigned long cpumask); + +/** + * Set the processor affinity of current thread. + */ +inline int SetProcessorAffinityOfCurrentThread(unsigned int cpunum) +{ + unsigned long cpumask = 1ul << cpunum; + return SetProcessorAffinityMaskOfCurrentThread(cpumask); +} /** * @class Thread @@ -332,15 +338,28 @@ public: void* getImplementation(){ return _prvData; }; - /** Thread's processor affinity method. This binds a thread to a - * processor whenever possible. This call must be made before + /** Set the Thread's processor affinity to a single CPU. + * This call must be made before * start() or startThread() and has no effect after the thread - * has been running. In the pthreads implementation, this is only - * implemented on sgi, through a pthread extension. On other pthread - * platforms this is ignored. Returns 0 on success, implementation's + * has been running. Returns 0 on success, implementation's * error on failure, or -1 if ignored. */ - int setProcessorAffinity( unsigned int cpunum ); + int setProcessorAffinity( unsigned int cpunum ) + { + unsigned long cpumask = 1ul << cpunum; + return setProcessorAffinityMask(cpumask); + } + + + /** Set the Thread's processor affinity to a one or more CPU's using mask. + * If you want this threadd to run on any processor core then use a cpumask of ~0ul + * This call must be made before + * start() or startThread() and has no effect after the thread + * has been running. Returns 0 on success, implementation's + * error on failure, or -1 if ignored. + */ + int setProcessorAffinityMask( unsigned long cpumask); + /** microSleep method, equivalent to the posix usleep(microsec). * This is not strictly thread API but is used diff --git a/src/OpenThreads/pthreads/PThread.cpp b/src/OpenThreads/pthreads/PThread.cpp index fe0f8f35c..0a72ca168 100644 --- a/src/OpenThreads/pthreads/PThread.cpp +++ b/src/OpenThreads/pthreads/PThread.cpp @@ -108,6 +108,23 @@ void thread_cleanup_handler(void *arg) namespace OpenThreads { +static void setCPUMask(cpu_set_t* cpumask, unsigned long in_cpumask) +{ + CPU_ZERO( cpumask ); + unsigned int numprocessors = OpenThreads::GetNumberOfProcessors(); + unsigned int cpunum=0; + while(in_cpumask!=0 && cpunum>=1; + ++cpunum; + } +} + + class ThreadPrivateActions { @@ -129,13 +146,11 @@ private: PThreadPrivateData *pd = static_cast(thread->_prvData); - - if (pd->cpunum>=0) + if (pd->cpumask>=0) { #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( pd->cpunum, &cpumask ); + setCPUMask( &cpumask, pd->cpumask ); #if defined(HAVE_PTHREAD_SETAFFINITY_NP) pthread_setaffinity_np( pthread_self(), sizeof(cpumask), &cpumask); @@ -533,25 +548,56 @@ size_t Thread::getProcessId() return (size_t)(pd->tid); } +int OpenThreads::SetProcessorAffinityMaskOfCurrentThread(unsigned long in_cpumask) +{ + Thread::Init(); + + Thread* thread = Thread::CurrentThread(); + if (thread) + { + return thread->setProcessorAffinityMask(in_cpumask); + } + else + { +#if defined(HAVE_PTHREAD_SETAFFINITY_NP) || defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY) || defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY) + cpu_set_t cpumask; + setCPUMask(&cpumask, in_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; +} + //----------------------------------------------------------------------------- // // Description: Set the thread's processor affinity // // Use: public // -int Thread::setProcessorAffinity(unsigned int cpunum) +int Thread::setProcessorAffinityMask(unsigned long in_cpumask) { PThreadPrivateData *pd = static_cast (_prvData); - pd->cpunum = cpunum; - if (pd->cpunum<0) return -1; + pd->cpumask = in_cpumask; + if (pd->cpumask==0) return -1; #if 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 ); + setCPUMask(&cpumask, in_cpumask); + #if defined(HAVE_PTHREAD_SETAFFINITY_NP) return pthread_setaffinity_np (pthread_self(), sizeof(cpumask), &cpumask); #elif defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY) @@ -995,33 +1041,3 @@ int OpenThreads::GetNumberOfProcessors() #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; -} diff --git a/src/OpenThreads/pthreads/PThreadPrivateData.h b/src/OpenThreads/pthreads/PThreadPrivateData.h index b6844a49a..6df369bd4 100644 --- a/src/OpenThreads/pthreads/PThreadPrivateData.h +++ b/src/OpenThreads/pthreads/PThreadPrivateData.h @@ -53,7 +53,7 @@ private: nextId++; threadPriority = Thread::THREAD_PRIORITY_DEFAULT; threadPolicy = Thread::THREAD_SCHEDULE_DEFAULT; - cpunum = -1; + cpumask = ~0ul; }; virtual ~PThreadPrivateData() {}; @@ -81,7 +81,7 @@ private: volatile int uniqueId; - volatile int cpunum; + volatile unsigned long cpumask; static int nextId;