g_currentProcessCpuCount = 0;
cpu_set_t cpuSet;
- int st = sched_getaffinity(0, sizeof(cpu_set_t), &cpuSet);
+ int st = sched_getaffinity(getpid(), sizeof(cpu_set_t), &cpuSet);
if (st == 0)
{
#cmakedefine01 HAVE_PTHREAD_GETCPUCLOCKID
#cmakedefine01 HAVE_PTHREAD_SIGQUEUE
#cmakedefine01 HAVE_PTHREAD_GETAFFINITY_NP
+#cmakedefine01 HAVE_PTHREAD_ATTR_SETAFFINITY_NP
#cmakedefine01 HAVE_CPUSET_T
#cmakedefine01 HAVE_SIGRETURN
#cmakedefine01 HAVE__THREAD_SYS_SIGRETURN
check_library_exists(${PTHREAD_LIBRARY} pthread_getcpuclockid "" HAVE_PTHREAD_GETCPUCLOCKID)
check_library_exists(${PTHREAD_LIBRARY} pthread_sigqueue "" HAVE_PTHREAD_SIGQUEUE)
check_library_exists(${PTHREAD_LIBRARY} pthread_getaffinity_np "" HAVE_PTHREAD_GETAFFINITY_NP)
+check_library_exists(${PTHREAD_LIBRARY} pthread_attr_setaffinity_np "" HAVE_PTHREAD_ATTR_SETAFFINITY_NP)
check_function_exists(sigreturn HAVE_SIGRETURN)
check_function_exists(_thread_sys_sigreturn HAVE__THREAD_SYS_SIGRETURN)
#endif
#include "pal/dbgmsg.h"
+#include "pal/process.h"
#include <algorithm>
PALAPI
PAL_GetLogicalCpuCountFromOS()
{
- int nrcpus = 0;
+ static int nrcpus = -1;
+ if (nrcpus == -1)
+ {
#if HAVE_SCHED_GETAFFINITY
- cpu_set_t cpuSet;
- int st = sched_getaffinity(0, sizeof(cpu_set_t), &cpuSet);
- if (st != 0)
- {
- ASSERT("sched_getaffinity failed (%d)\n", errno);
- }
+ cpu_set_t cpuSet;
+ int st = sched_getaffinity(gPID, sizeof(cpu_set_t), &cpuSet);
+ if (st != 0)
+ {
+ ASSERT("sched_getaffinity failed (%d)\n", errno);
+ }
- nrcpus = CPU_COUNT(&cpuSet);
+ nrcpus = CPU_COUNT(&cpuSet);
#else // HAVE_SCHED_GETAFFINITY
- nrcpus = PAL_GetTotalCpuCount();
+ nrcpus = PAL_GetTotalCpuCount();
#endif // HAVE_SCHED_GETAFFINITY
+ }
return nrcpus;
}
#ifdef FEATURE_PAL_SXS
_ASSERT_MSG(pNewThread->IsInPal(), "New threads we're about to spawn should always be in the PAL.\n");
#endif // FEATURE_PAL_SXS
+
+#if HAVE_PTHREAD_ATTR_SETAFFINITY_NP && HAVE_SCHED_GETAFFINITY
+ {
+ // Threads inherit their parent's affinity mask on Linux. This is not desired, so we reset
+ // the current thread's affinity mask to the mask of the current process.
+ cpu_set_t cpuSet;
+ CPU_ZERO(&cpuSet);
+
+ int st = sched_getaffinity(gPID, sizeof(cpu_set_t), &cpuSet);
+ if (st != 0)
+ {
+ ASSERT("sched_getaffinity failed!\n");
+ // the sched_getaffinity should never fail for getting affinity of the current process
+ palError = ERROR_INTERNAL_ERROR;
+ goto EXIT;
+ }
+
+ st = pthread_attr_setaffinity_np(&pthreadAttr, sizeof(cpu_set_t), &cpuSet);
+ if (st != 0)
+ {
+ if (st == ENOMEM)
+ {
+ palError = ERROR_NOT_ENOUGH_MEMORY;
+ }
+ else
+ {
+ ASSERT("pthread_attr_setaffinity_np failed!\n");
+ // The pthread_attr_setaffinity_np should never fail except of OOM when
+ // passed the mask extracted using sched_getaffinity.
+ palError = ERROR_INTERNAL_ERROR;
+ }
+ goto EXIT;
+ }
+ }
+#endif // HAVE_PTHREAD_GETAFFINITY_NP && HAVE_SCHED_GETAFFINITY
+
iError = pthread_create(&pthread, &pthreadAttr, CPalThread::ThreadEntry, pNewThread);
#if PTHREAD_CREATE_MODIFIES_ERRNO