[Git][ghc/ghc][master] 3 commits: rts: Teach getNumProcessors to return available processors

Marge Bot gitlab at gitlab.haskell.org
Sat May 30 10:07:41 UTC 2020



 Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC


Commits:
4413828b by Ben Gamari at 2020-05-30T06:07:31-04:00
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.

- - - - -
1449435c by Ben Gamari at 2020-05-30T06:07:31-04:00
users-guide: Note change in getNumProcessors in users guide

- - - - -
3d960169 by Ben Gamari at 2020-05-30T06:07:31-04:00
rts: Drop compatibility shims for Windows Vista

We can now assume that the thread and processor group interfaces are
available.

- - - - -


7 changed files:

- configure.ac
- docs/users_guide/8.12.1-notes.rst
- docs/users_guide/using-concurrent.rst
- hadrian/src/Settings/Packages.hs
- rts/ghc.mk
- rts/posix/OSThreads.c
- rts/win32/OSThreads.c


Changes:

=====================================
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


=====================================
docs/users_guide/8.12.1-notes.rst
=====================================
@@ -17,7 +17,7 @@ Highlights
     digit improvements in runtime for inner loops.
 
     In the mean this improved runtime by about 0.8%. For details
-    see ticket #17823.
+    see ticket :ghc-ticket:`17823`.
 
 Full details
 ------------
@@ -95,7 +95,7 @@ Language
   effectively allows users to choose which variables can or can't be
   instantiated through visible type application. More information can be found
   here: :ref:`Manually-defining-inferred-variables`.
-  
+
 Compiler
 ~~~~~~~~
 
@@ -105,11 +105,18 @@ GHCi
 
 - The ``:script`` command now allows for file names that contain spaces to
   passed as arguments: either by enclosing the file names in double quotes or by
-  escaping spaces in file names with a backslash. (#18027)
+  escaping spaces in file names with a backslash. (:ghc-ticket:`18027`)
 
 Runtime system
 ~~~~~~~~~~~~~~
 
+- :rts-flag:`-N` without a count now tries to respect the number of processors
+  in the process's affinity mask, making GHC's behavior more predictable in
+  containerized settings (:ghc-ticket:`14781`).
+
+- Support for Windows Vista has been dropped. GHC-compiled programs now require
+  Windows 7 or later.
+
 Template Haskell
 ~~~~~~~~~~~~~~~~
 


=====================================
docs/users_guide/using-concurrent.rst
=====================================
@@ -111,6 +111,7 @@ There are two ways to run a program on multiple processors: call
 use the RTS :rts-flag:`-N ⟨x⟩` options.
 
 .. rts-flag:: -N ⟨x⟩
+              -N
               -maxN ⟨x⟩
 
     Use ⟨x⟩ simultaneous threads when running the program.


=====================================
hadrian/src/Settings/Packages.hs
=====================================
@@ -462,4 +462,4 @@ rtsWarnings = mconcat
 -- and also centralizes the versioning.
 -- | Minimum supported Windows version.
 windowsVersion :: String
-windowsVersion = "0x06000100"
+windowsVersion = "0x06010000"


=====================================
rts/ghc.mk
=====================================
@@ -25,7 +25,7 @@ rts_VERSION = 1.0
 # If we're compiling on windows, enforce that we only support Vista SP1+
 # Adding this here means it doesn't have to be done in individual .c files
 # and also centralizes the versioning.
-rts_WINVER = 0x06000100
+rts_WINVER = 0x06010000
 
 # merge GhcLibWays and GhcRTSWays but strip out duplicates
 rts_WAYS = $(GhcLibWays) $(filter-out $(GhcLibWays),$(GhcRTSWays))


=====================================
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


=====================================
rts/win32/OSThreads.c
=====================================
@@ -252,17 +252,6 @@ forkOS_createThread ( HsStablePtr entry )
                            (unsigned*)&pId) == 0);
 }
 
-#if defined(x86_64_HOST_ARCH)
-/* We still support Windows Vista, so we can't depend on it
-   and must manually resolve these. */
-typedef DWORD(WINAPI *GetItemCountProc)(WORD);
-typedef DWORD(WINAPI *GetGroupCountProc)(void);
-typedef BOOL(WINAPI *SetThreadGroupAffinityProc)(HANDLE, const GROUP_AFFINITY*, PGROUP_AFFINITY);
-#if !defined(ALL_PROCESSOR_GROUPS)
-#define ALL_PROCESSOR_GROUPS 0xffff
-#endif
-#endif
-
 void freeThreadingResources (void)
 {
     if (cpuGroupCache)
@@ -310,13 +299,6 @@ getNumberOfProcessorsGroups (void)
 #if defined(x86_64_HOST_ARCH)
     if (!n_groups)
     {
-        /* We still support Windows Vista. Which means we can't rely
-           on the API being available. So we'll have to resolve manually.  */
-        HMODULE kernel = GetModuleHandleW(L"kernel32");
-
-        GetGroupCountProc GetActiveProcessorGroupCount
-          = (GetGroupCountProc)(void*)
-               GetProcAddress(kernel, "GetActiveProcessorGroupCount");
         n_groups = GetActiveProcessorGroupCount();
 
         IF_DEBUG(scheduler, debugBelch("[*] Number of processor groups detected: %u\n", n_groups));
@@ -346,21 +328,10 @@ getProcessorsDistribution (void)
         cpuGroupDistCache = malloc(n_groups * sizeof(uint8_t));
         memset(cpuGroupDistCache, MAXIMUM_PROCESSORS, n_groups * sizeof(uint8_t));
 
-        /* We still support Windows Vista. Which means we can't rely
-        on the API being available. So we'll have to resolve manually.  */
-        HMODULE kernel = GetModuleHandleW(L"kernel32");
-
-        GetItemCountProc  GetActiveProcessorCount
-          = (GetItemCountProc)(void*)
-               GetProcAddress(kernel, "GetActiveProcessorCount");
-
-        if (GetActiveProcessorCount)
+        for (int i = 0; i < n_groups; i++)
         {
-            for (int i = 0; i < n_groups; i++)
-            {
-                cpuGroupDistCache[i] = GetActiveProcessorCount(i);
-                IF_DEBUG(scheduler, debugBelch("[*] Number of active processors in group %u detected: %u\n", i, cpuGroupDistCache[i]));
-            }
+            cpuGroupDistCache[i] = GetActiveProcessorCount(i);
+            IF_DEBUG(scheduler, debugBelch("[*] Number of active processors in group %u detected: %u\n", i, cpuGroupDistCache[i]));
         }
     }
 
@@ -449,14 +420,7 @@ getNumberOfProcessors (void)
     static uint32_t nproc = 0;
 
 #if defined(x86_64_HOST_ARCH)
-    /* We still support Windows Vista. Which means we can't rely
-       on the API being available. So we'll have to resolve manually.  */
-    HMODULE kernel = GetModuleHandleW(L"kernel32");
-
-    GetItemCountProc GetActiveProcessorCount
-      = (GetItemCountProc)(void*)
-          GetProcAddress(kernel, "GetActiveProcessorCount");
-    if (GetActiveProcessorCount && !nproc)
+    if (!nproc)
     {
         nproc = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
 
@@ -517,21 +481,11 @@ setThreadAffinity (uint32_t n, uint32_t m) // cap N of M
         mask[group] |= 1 << ix;
     }
 
-#if defined(x86_64_HOST_ARCH)
-    /* We still support Windows Vista. Which means we can't rely
-       on the API being available. So we'll have to resolve manually.  */
-    HMODULE kernel = GetModuleHandleW(L"kernel32");
-
-    SetThreadGroupAffinityProc SetThreadGroupAffinity
-      = (SetThreadGroupAffinityProc)(void*)
-          GetProcAddress(kernel, "SetThreadGroupAffinity");
-#endif
-
     for (i = 0; i < n_groups; i++)
     {
 #if defined(x86_64_HOST_ARCH)
         // If we support the new API, use it.
-        if (mask[i] > 0 && SetThreadGroupAffinity)
+        if (mask[i] > 0)
         {
             GROUP_AFFINITY hGroup;
             ZeroMemory(&hGroup, sizeof(hGroup));



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/aac19e6caa0c94e159610f124114186ee20bcdd1...3d96016926cc88506db416f87b6e4b68a3a0d25f

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/aac19e6caa0c94e159610f124114186ee20bcdd1...3d96016926cc88506db416f87b6e4b68a3a0d25f
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20200530/e5cf82c6/attachment-0001.html>


More information about the ghc-commits mailing list