Merge pull request #730 from bas524/feature

Add setaffinity method to thread implementation and interface class
This commit is contained in:
Aleksandar Fabijanic
2015-03-08 16:10:45 -05:00
13 changed files with 576 additions and 321 deletions

View File

@@ -28,30 +28,34 @@
#endif
#if POCO_OS == POCO_OS_LINUX || POCO_OS == POCO_OS_MAC_OS_X || POCO_OS == POCO_OS_QNX
# include <time.h>
# include <unistd.h>
#endif
#if POCO_OS == POCO_OS_MAC_OS_X
# include <mach/mach.h>
# include <mach/task.h>
# include <mach/thread_policy.h>
#endif
//
// Block SIGPIPE in main thread.
//
#if defined(POCO_OS_FAMILY_UNIX) && !defined(POCO_VXWORKS)
namespace
namespace {
class SignalBlocker
{
class SignalBlocker
public:
SignalBlocker()
{
public:
SignalBlocker()
{
sigset_t sset;
sigemptyset(&sset);
sigaddset(&sset, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &sset, 0);
}
~SignalBlocker()
{
}
};
sigset_t sset;
sigemptyset(&sset);
sigaddset(&sset, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &sset, 0);
}
~SignalBlocker()
{
}
};
static SignalBlocker signalBlocker;
static SignalBlocker signalBlocker;
}
#endif
@@ -59,16 +63,15 @@ namespace
#if defined(POCO_POSIX_DEBUGGER_THREAD_NAMES)
namespace
namespace {
void setThreadName(pthread_t thread, const char* threadName)
{
void setThreadName(pthread_t thread, const char* threadName)
{
# if (POCO_OS == POCO_OS_MAC_OS_X)
pthread_setname_np(threadName); // __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
pthread_setname_np(threadName); // __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
# else
pthread_setname_np(thread, threadName);
pthread_setname_np(thread, threadName);
# endif
}
}
}
@@ -104,7 +107,8 @@ void ThreadImpl::setPriorityImpl(int prio)
_pData->policy = SCHED_OTHER;
if (isRunningImpl())
{
struct sched_param par; struct MyStruct
struct sched_param par;
struct MyStruct
{
};
@@ -168,17 +172,102 @@ void ThreadImpl::setStackSizeImpl(int size)
#if defined(POCO_OS_FAMILY_BSD)
// we must round up to a multiple of the memory page size
const int STACK_PAGE_SIZE = 4096;
size = ((size + STACK_PAGE_SIZE - 1)/STACK_PAGE_SIZE)*STACK_PAGE_SIZE;
size = ((size + STACK_PAGE_SIZE - 1) / STACK_PAGE_SIZE) * STACK_PAGE_SIZE;
#endif
#if !defined(POCO_ANDROID)
if (size < PTHREAD_STACK_MIN)
size = PTHREAD_STACK_MIN;
if (size < PTHREAD_STACK_MIN)
size = PTHREAD_STACK_MIN;
#endif
}
_pData->stackSize = size;
_pData->stackSize = size;
#endif
}
void ThreadImpl::setAffinityImpl(unsigned cpu)
{
#if defined (POCO_OS_FAMILY_UNIX) && POCO_OS != POCO_OS_MAC_OS_X
#ifdef HAVE_PTHREAD_SETAFFINITY_NP
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu, &cpuset);
#ifdef HAVE_THREE_PARAM_SCHED_SETAFFINITY
if (pthread_setaffinity_np(_pData->thread, sizeof(cpuset), &cpuset) != 0)
throw SystemException("Failed to set affinity");
#else
if (pthread_setaffinity_np(_pData->thread, &cpuset) != 0)
throw SystemException("Failed to set affinity");
#endif
#else
throw Poco::NotImplementedException("Thread affinity not supported on this system");
#endif
#endif // defined unix & !defined mac os x
#if POCO_OS == POCO_OS_MAC_OS_X
kern_return_t ret;
thread_affinity_policy policy;
policy.affinity_tag = cpu;
ret = thread_policy_set(pthread_mach_thread_np(_pData->thread),
THREAD_AFFINITY_POLICY,
(thread_policy_t) &policy,
THREAD_AFFINITY_POLICY_COUNT);
if (ret != KERN_SUCCESS)
{
throw SystemException("Failed to set affinity");
}
#endif
yieldImpl();
}
unsigned ThreadImpl::getAffinityImpl() const
{
unsigned cpuSet = 0;
unsigned cpuCount = Environment::processorCount();
#if defined (POCO_OS_FAMILY_UNIX) && POCO_OS != POCO_OS_MAC_OS_X
#ifdef HAVE_PTHREAD_SETAFFINITY_NP
cpu_set_t cpuset;
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", errno);
#else
if (pthread_getaffinity_np(_pData->thread, &cpuset) != 0)
throw SystemException("Failed to get affinity", errno);
#endif
for (unsigned i = 0; i < cpuCount; i++)
{
if (CPU_ISSET(i, &cpuset))
{
cpuSet = i;
break;
}
}
#else
throw Poco::NotImplementedException("Thread affinity not supported on this system");
#endif
#endif // defined unix & !defined mac os x
#if POCO_OS == POCO_OS_MAC_OS_X
kern_return_t ret;
thread_affinity_policy policy;
mach_msg_type_number_t count = THREAD_AFFINITY_POLICY_COUNT;
boolean_t get_default = FALSE;
ret = thread_policy_get(pthread_mach_thread_np(_pData->thread),
THREAD_AFFINITY_POLICY,
(thread_policy_t)&policy,
&count,
&get_default);
if (ret != KERN_SUCCESS)
{
throw SystemException("Failed to get affinity", errno);
}
cpuSet = policy.affinity_tag;
if (cpuSet >= cpuCount)
cpuSet = 0;
#endif
return cpuSet;
}
void ThreadImpl::startImpl(SharedPtr<Runnable> pTarget)
{
@@ -268,19 +357,19 @@ ThreadImpl::TIDImpl ThreadImpl::currentTidImpl()
void ThreadImpl::sleepImpl(long milliseconds)
{
#if defined(__VMS) || defined(__digital__)
// This is specific to DECThreads
struct timespec interval;
interval.tv_sec = milliseconds / 1000;
interval.tv_nsec = (milliseconds % 1000)*1000000;
pthread_delay_np(&interval);
// This is specific to DECThreads
struct timespec interval;
interval.tv_sec = milliseconds / 1000;
interval.tv_nsec = (milliseconds % 1000) * 1000000;
pthread_delay_np(&interval);
#elif POCO_OS == POCO_OS_LINUX || POCO_OS == POCO_OS_MAC_OS_X || POCO_OS == POCO_OS_QNX || POCO_OS == POCO_OS_VXWORKS
Poco::Timespan remainingTime(1000*Poco::Timespan::TimeDiff(milliseconds));
Poco::Timespan remainingTime(1000 * Poco::Timespan::TimeDiff(milliseconds));
int rc;
do
{
struct timespec ts;
ts.tv_sec = (long) remainingTime.totalSeconds();
ts.tv_nsec = (long) remainingTime.useconds()*1000;
ts.tv_nsec = (long) remainingTime.useconds() * 1000;
Poco::Timestamp start;
rc = ::nanosleep(&ts, 0);
if (rc < 0 && errno == EINTR)
@@ -295,8 +384,8 @@ void ThreadImpl::sleepImpl(long milliseconds)
}
while (remainingTime > 0 && rc < 0 && errno == EINTR);
if (rc < 0 && remainingTime > 0) throw Poco::SystemException("Thread::sleep(): nanosleep() failed");
#else
Poco::Timespan remainingTime(1000*Poco::Timespan::TimeDiff(milliseconds));
#else
Poco::Timespan remainingTime(1000 * Poco::Timespan::TimeDiff(milliseconds));
int rc;
do
{
@@ -330,7 +419,7 @@ void* ThreadImpl::runnableEntry(void* pThread)
sigemptyset(&sset);
sigaddset(&sset, SIGQUIT);
sigaddset(&sset, SIGTERM);
sigaddset(&sset, SIGPIPE);
sigaddset(&sset, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &sset, 0);
#endif
@@ -372,11 +461,11 @@ int ThreadImpl::mapPrio(int prio, int policy)
case PRIO_LOWEST_IMPL:
return pmin;
case PRIO_LOW_IMPL:
return pmin + (pmax - pmin)/4;
return pmin + (pmax - pmin) / 4;
case PRIO_NORMAL_IMPL:
return pmin + (pmax - pmin)/2;
return pmin + (pmax - pmin) / 2;
case PRIO_HIGH_IMPL:
return pmin + 3*(pmax - pmin)/4;
return pmin + 3 * (pmax - pmin) / 4;
case PRIO_HIGHEST_IMPL:
return pmax;
default:
@@ -392,7 +481,7 @@ int ThreadImpl::reverseMapPrio(int prio, int policy)
{
int pmin = getMinOSPriorityImpl(policy);
int pmax = getMaxOSPriorityImpl(policy);
int normal = pmin + (pmax - pmin)/2;
int normal = pmin + (pmax - pmin) / 2;
if (prio == pmax)
return PRIO_HIGHEST_IMPL;
if (prio > normal)

View File

@@ -33,7 +33,7 @@ ThreadImpl::ThreadImpl():
{
}
ThreadImpl::~ThreadImpl()
{
}
@@ -93,7 +93,7 @@ void ThreadImpl::startImpl(Runnable& target)
throw SystemException("thread already running");
_pData->pRunnableTarget = &target;
int stackSize = _pData->stackSize == 0 ? DEFAULT_THREAD_STACK_SIZE : _pData->stackSize;
int id = taskSpawn(NULL, _pData->osPrio, VX_FP_TASK, stackSize, reinterpret_cast<FUNCPTR>(runnableEntry), reinterpret_cast<int>(this), 0, 0, 0, 0, 0, 0, 0, 0, 0);
if (id == ERROR)
@@ -143,7 +143,7 @@ ThreadImpl* ThreadImpl::currentImpl()
ThreadImpl::TIDImpl ThreadImpl::currentTidImpl()
{
return taskIdSelf();
return taskIdSelf();
}

View File

@@ -23,40 +23,39 @@
#if defined(POCO_WIN32_DEBUGGER_THREAD_NAMES)
namespace
{
/// See <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>
/// and <http://blogs.msdn.com/b/stevejs/archive/2005/12/19/505815.aspx> for
/// more information on the code below.
namespace {
/// See <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>
/// and <http://blogs.msdn.com/b/stevejs/archive/2005/12/19/505815.aspx> for
/// more information on the code below.
const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
void setThreadName(DWORD dwThreadID, const char* threadName)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
__try
{
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
void setThreadName(DWORD dwThreadID, const char* threadName)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
__try
{
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
}
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
}
}
}
@@ -103,6 +102,20 @@ void ThreadImpl::setOSPriorityImpl(int prio, int /* policy */)
setPriorityImpl(prio);
}
void ThreadImpl::setAffinityImpl(unsigned cpu)
{
DWORD mask = 1;
mask <<= cpu;
if (SetThreadAffinityMask(_thread, mask) == 0)
{
throw SystemException("Failed to set affinity");
}
}
unsigned ThreadImpl::getAffinityImpl() const
{
throw Poco::NotImplementedException("Get thread affinity not supported on this system");
}
void ThreadImpl::startImpl(SharedPtr<Runnable> pTarget)
{

View File

@@ -34,7 +34,7 @@ ThreadImpl::ThreadImpl():
{
}
ThreadImpl::~ThreadImpl()
{
if (_thread) CloseHandle(_thread);
@@ -141,7 +141,7 @@ ThreadImpl* ThreadImpl::currentImpl()
ThreadImpl::TIDImpl ThreadImpl::currentTidImpl()
{
return GetCurrentThreadId();
return GetCurrentThreadId();
}