mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-30 13:47:10 +01:00
Merge pull request #730 from bas524/feature
Add setaffinity method to thread implementation and interface class
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -33,7 +33,7 @@ ThreadImpl::ThreadImpl():
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
ThreadImpl::~ThreadImpl()
|
||||
{
|
||||
}
|
||||
@@ -93,7 +93,7 @@ void ThreadImpl::startImpl(Runnable& target)
|
||||
throw SystemException("thread already running");
|
||||
|
||||
_pData->pRunnableTarget = ⌖
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user