diff --git a/Foundation/CMakeLists.txt b/Foundation/CMakeLists.txt index 779d38136..beb3498cd 100644 --- a/Foundation/CMakeLists.txt +++ b/Foundation/CMakeLists.txt @@ -108,7 +108,7 @@ endif (${CMAKE_CXX_COMPILER_ID} MATCHES "SunPro") add_definitions( -DPCRE_STATIC) # For SetAffinity -if(UNIX) +if(UNIX AND NOT APPLE) INCLUDE (CheckFunctionExists) INCLUDE (CheckCXXSourceCompiles) CHECK_FUNCTION_EXISTS(pthread_setaffinity_np HAVE_PTHREAD_SETAFFINITY_NP) @@ -143,7 +143,7 @@ if(UNIX) endif(HAVE_THREE_PARAM_SCHED_SETAFFINITY) endif(HAVE_PTHREAD_SETAFFINITY_NP) -endif(UNIX) +endif(UNIX AND NOT APPLE) add_library( "${LIBNAME}" ${LIB_MODE} ${SRCS}) add_library( "${POCO_LIBNAME}" ALIAS "${LIBNAME}") diff --git a/Foundation/include/Poco/Thread.h b/Foundation/include/Poco/Thread.h index 44369039b..a455cfa84 100644 --- a/Foundation/include/Poco/Thread.h +++ b/Foundation/include/Poco/Thread.h @@ -135,11 +135,14 @@ public: /// Typically, the real stack size is rounded up to the nearest /// page size multiple. - void setAffinity(unsigned int cpu); + void setAffinity(unsigned int cpu); /// Limit specified thread to run only on the processors "cpu" /// cpu - processor (core) number /// Method would Throw SystemException if affinity did not setted + unsigned getAffinity() const; + /// Returns using cpu (core) number + int getStackSize() const; /// Returns the thread's stack size in bytes. /// If the default stack size is used, 0 is returned. @@ -355,10 +358,16 @@ inline void Thread::setStackSize(int size) setStackSizeImpl(size); } -inline void Thread::setAffinity(unsigned int cpu) { +inline void Thread::setAffinity(unsigned int cpu) +{ setAffinityImpl(cpu); } +inline unsigned Thread::getAffinity() const +{ + return getAffinityImpl(); +} + inline int Thread::getStackSize() const { return getStackSizeImpl(); diff --git a/Foundation/src/Thread_POSIX.cpp b/Foundation/src/Thread_POSIX.cpp index 75a7c2742..049114463 100644 --- a/Foundation/src/Thread_POSIX.cpp +++ b/Foundation/src/Thread_POSIX.cpp @@ -199,7 +199,7 @@ void ThreadImpl::setAffinityImpl(unsigned cpu) throw SystemException("Failed to set affinity"); #endif #else - poco_bugcheck_msg("Thread affinity not supported on this system"); + throw Poco::NotImplementedException("Thread affinity not supported on this system"); #endif #endif // defined unix & !defined mac os x @@ -229,10 +229,10 @@ unsigned cpuCount = Environment::processorCount(); CPU_ZERO(&cpuset); #ifdef HAVE_THREE_PARAM_SCHED_SETAFFINITY if (pthread_getaffinity_np(_pData->thread, sizeof(cpuset), &cpuset) != 0) - throw SystemException("Failed to get affinity"); + throw SystemException("Failed to get affinity", errno); #else if (pthread_getaffinity_np(_pData->thread, &cpuset) != 0) - throw SystemException("Failed to get affinity"); + throw SystemException("Failed to get affinity", errno); #endif for (unsigned i = 0; i < cpuCount; i++) { if (CPU_ISSET(i, &cpuset)) { @@ -256,9 +256,9 @@ unsigned cpuCount = Environment::processorCount(); &count, &get_default); if (ret != KERN_SUCCESS) { - throw SystemException("Failed to get affinity"); + throw SystemException("Failed to get affinity", errno); } - cpuSet = policy.affinity_tag - 1; + cpuSet = policy.affinity_tag; if (cpuSet >= cpuCount) cpuSet = 0; diff --git a/Foundation/testsuite/src/ThreadTest.cpp b/Foundation/testsuite/src/ThreadTest.cpp index e9fa73072..e6afdd395 100644 --- a/Foundation/testsuite/src/ThreadTest.cpp +++ b/Foundation/testsuite/src/ThreadTest.cpp @@ -19,12 +19,14 @@ #include "Poco/Event.h" #include "Poco/Timestamp.h" #include "Poco/Timespan.h" +#include "Poco/Environment.h" //#include #if defined(__sun) && defined(__SVR4) && !defined(__EXTENSIONS__) #define __EXTENSIONS__ #endif #include - +#include +#include using Poco::Thread; using Poco::Runnable; @@ -449,6 +451,67 @@ void ThreadTest::testSleep() assert (elapsed.totalMilliseconds() >= 190 && elapsed.totalMilliseconds() < 250); } +void ThreadTest::testAffinity() +{ + std::stringstream ss; + unsigned cpuCount = Poco::Environment::processorCount(); + unsigned usedCpu = 0; + bool notImplemented = false; + std::vector threadList; + Thread *thread = NULL; + std::vector runnableList; + MyRunnable *runbl = NULL; + + for (unsigned i = 0; i < cpuCount; i++) + { + ss.str(""); + ss << "Thread" << i; + thread = new Thread(ss.str()); + threadList.push_back(thread); + runbl = new MyRunnable(); + runnableList.push_back(runbl); + } + + for (int i = 0; i < cpuCount; i++) + { + assert (!threadList[i]->isRunning()); + } + + for (int i = 0; i < cpuCount; i++) + { + threadList[i]->start(*runnableList[i]); + try + { + threadList[i]->setAffinity(i); + } + catch (Poco::NotImplementedException &niex) + { + notImplemented = true; + } + Thread::sleep(100); + try + { + usedCpu = threadList[i]->getAffinity(); + } + catch (Poco::NotImplementedException &niex) + { + notImplemented = true; + } + if (!notImplemented) + { + assert (usedCpu == i); + } + } + + for (int i = 0; i < cpuCount; i++) + { + runnableList[i]->notify(); + threadList[i]->join(); + delete runnableList[i]; + delete threadList[i]; + } +} + void ThreadTest::setUp() { @@ -478,6 +541,7 @@ CppUnit::Test* ThreadTest::suite() CppUnit_addTest(pSuite, ThreadTest, testThreadFunctor); CppUnit_addTest(pSuite, ThreadTest, testThreadStackSize); CppUnit_addTest(pSuite, ThreadTest, testSleep); + CppUnit_addTest(pSuite, ThreadTest, testAffinity); return pSuite; } diff --git a/Foundation/testsuite/src/ThreadTest.h b/Foundation/testsuite/src/ThreadTest.h index 3e9f50dae..9c1a9ea6f 100644 --- a/Foundation/testsuite/src/ThreadTest.h +++ b/Foundation/testsuite/src/ThreadTest.h @@ -40,6 +40,7 @@ public: void testThreadFunctor(); void testThreadStackSize(); void testSleep(); + void testAffinity(); void setUp(); void tearDown();