summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2020-05-09 18:55:25 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-05-30 06:07:31 -0400
commit4413828b7c507872c56719fb8920e1c2322830f8 (patch)
tree32754a94c9fd720fff4023081dcce9169999b062
parentaac19e6caa0c94e159610f124114186ee20bcdd1 (diff)
downloadhaskell-4413828b7c507872c56719fb8920e1c2322830f8.tar.gz
rts: Teach getNumProcessors to return available processors
Previously we would report the number of physical processors, which can be quite wrong in a containerized setting. Now we rather return how many processors are in our affinity mask when possible. I also refactored the code to prefer platform-specific since this will report logical CPUs instead of physical (using `machdep.cpu.thread_count` on Darwin and `cpuset_getaffinity` on FreeBSD). Fixes #14781.
-rw-r--r--configure.ac2
-rw-r--r--rts/posix/OSThreads.c44
2 files changed, 35 insertions, 11 deletions
diff --git a/configure.ac b/configure.ac
index bac2cfde5e..f7b02e8dcf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -978,7 +978,7 @@ FP_CHECK_FUNC([GetModuleFileName],
dnl ** check for more functions
dnl ** The following have been verified to be used in ghc/, but might be used somewhere else, too.
-AC_CHECK_FUNCS([getclock getrusage gettimeofday setitimer siginterrupt sysconf times ctime_r sched_setaffinity setlocale])
+AC_CHECK_FUNCS([getclock getrusage gettimeofday setitimer siginterrupt sysconf times ctime_r sched_setaffinity sched_getaffinity setlocale])
dnl ** On OS X 10.4 (at least), time.h doesn't declare ctime_r if
dnl ** _POSIX_C_SOURCE is defined
diff --git a/rts/posix/OSThreads.c b/rts/posix/OSThreads.c
index 7dcf0eed15..42d72c2e0d 100644
--- a/rts/posix/OSThreads.c
+++ b/rts/posix/OSThreads.c
@@ -240,26 +240,50 @@ forkOS_createThread ( HsStablePtr entry )
void freeThreadingResources (void) { /* nothing */ }
+// Get the number of logical CPU cores available to us. Note that this is
+// different from the number of physical cores (see #14781).
uint32_t
getNumberOfProcessors (void)
{
static uint32_t nproc = 0;
if (nproc == 0) {
-#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
- nproc = sysconf(_SC_NPROCESSORS_ONLN);
-#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
- nproc = sysconf(_SC_NPROCESSORS_CONF);
-#elif defined(darwin_HOST_OS)
+#if defined(HAVE_SCHED_GETAFFINITY)
+ cpu_set_t mask;
+ CPU_ZERO(&mask);
+ if (sched_getaffinity(0, sizeof(mask), &mask) == 0) {
+ for (int i = 0; i < CPU_SETSIZE; i++) {
+ if (CPU_ISSET(i, &mask))
+ nproc++;
+ }
+ return nproc;
+ }
+#endif
+
+#if defined(darwin_HOST_OS)
size_t size = sizeof(uint32_t);
- if(sysctlbyname("hw.logicalcpu",&nproc,&size,NULL,0) != 0) {
+ if (sysctlbyname("machdep.cpu.thread_count",&nproc,&size,NULL,0) != 0) {
+ if (sysctlbyname("hw.logicalcpu",&nproc,&size,NULL,0) != 0) {
+ if (sysctlbyname("hw.ncpu",&nproc,&size,NULL,0) != 0)
+ nproc = 1;
+ }
+ }
+#elif defined(freebsd_HOST_OS)
+ cpuset_t mask;
+ CPU_ZERO(&mask);
+ if(cpuset_getaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, sizeof(mask), &mask) == 0) {
+ return CPU_COUNT(&mask);
+ } else {
+ size_t size = sizeof(uint32_t);
if(sysctlbyname("hw.ncpu",&nproc,&size,NULL,0) != 0)
nproc = 1;
}
-#elif defined(freebsd_HOST_OS)
- size_t size = sizeof(uint32_t);
- if(sysctlbyname("hw.ncpu",&nproc,&size,NULL,0) != 0)
- nproc = 1;
+#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
+ // N.B. This is the number of physical processors.
+ nproc = sysconf(_SC_NPROCESSORS_ONLN);
+#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
+ // N.B. This is the number of physical processors.
+ nproc = sysconf(_SC_NPROCESSORS_CONF);
#else
nproc = 1;
#endif