Index: trunk/src/kmk/w32/winchildren.c
===================================================================
--- trunk/src/kmk/w32/winchildren.c	(revision 3616)
+++ trunk/src/kmk/w32/winchildren.c	(revision 3617)
@@ -345,8 +345,14 @@
 /** Array detailing how many active processors there are in each group. */
 static unsigned const      *g_pacProcessorsInGroup = &g_cProcessorGroups;
+/** Info from the GetLogicalProcessorInformationEx call - can be NULL. */
+static GROUP_RELATIONSHIP const *g_pGroupInfo = NULL;
+
 /** Kernel32!GetActiveProcessorGroupCount */
 static WORD (WINAPI        *g_pfnGetActiveProcessorGroupCount)(VOID);
 /** Kernel32!GetActiveProcessorCount */
 static DWORD (WINAPI       *g_pfnGetActiveProcessorCount)(WORD);
+/** Kernel32!GetLogicalProcessorInformationEx */
+static DWORD (WINAPI       *g_pfnGetLogicalProcessorInformationEx)(LOGICAL_PROCESSOR_RELATIONSHIP,
+                                                                   PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD);
 /** Kernel32!SetThreadGroupAffinity */
 static BOOL (WINAPI        *g_pfnSetThreadGroupAffinity)(HANDLE, CONST GROUP_AFFINITY *, GROUP_AFFINITY *);
@@ -460,10 +466,14 @@
     {
         hmod = GetModuleHandleA("KERNEL32.DLL");
-        *(FARPROC *)&g_pfnGetActiveProcessorGroupCount = GetProcAddress(hmod, "GetActiveProcessorGroupCount");
-        *(FARPROC *)&g_pfnGetActiveProcessorCount      = GetProcAddress(hmod, "GetActiveProcessorCount");
-        *(FARPROC *)&g_pfnSetThreadGroupAffinity       = GetProcAddress(hmod, "SetThreadGroupAffinity");
+        *(FARPROC *)&g_pfnGetActiveProcessorGroupCount     = GetProcAddress(hmod, "GetActiveProcessorGroupCount");
+        *(FARPROC *)&g_pfnGetActiveProcessorCount          = GetProcAddress(hmod, "GetActiveProcessorCount");
+        *(FARPROC *)&g_pfnSetThreadGroupAffinity           = GetProcAddress(hmod, "SetThreadGroupAffinity");
+        *(FARPROC *)&g_pfnGetLogicalProcessorInformationEx = GetProcAddress(hmod, "GetLogicalProcessorInformationEx");
+        /*(FARPROC *)&g_pfnGetSystemCpuSetInformation       = GetProcAddress(hmod, "GetSystemCpuSetInformation"); / * W10 */
+        /*(FARPROC *)&g_pfnSetThreadSelectedCpuSetMasks     = GetProcAddress(hmod, "SetThreadSelectedCpuSetMasks"); / * W11 */
         if (   g_pfnSetThreadGroupAffinity
             && g_pfnGetActiveProcessorCount
-            && g_pfnGetActiveProcessorGroupCount)
+            && g_pfnGetActiveProcessorGroupCount
+            && g_pfnGetLogicalProcessorInformationEx)
         {
             unsigned int *pacProcessorsInGroup;
@@ -478,11 +488,36 @@
                 pacProcessorsInGroup[iGroup] = g_pfnGetActiveProcessorCount(iGroup);
 
+            /* Get active process group affinity masks so we can set them correctly. */
+            {
+                DWORD cbNeeded = cbNeeded = offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group)
+                               + offsetof(GROUP_RELATIONSHIP, GroupInfo)
+                               + sizeof(PROCESSOR_GROUP_INFO) * (g_cProcessorGroups + 4);
+                PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX pInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)xcalloc(cbNeeded);
+                BOOL fRet = g_pfnGetLogicalProcessorInformationEx(RelationGroup, pInfo, &cbNeeded);
+                if (!fRet && GetLastError() == ERROR_BUFFER_OVERFLOW)
+                {
+                    free(pInfo);
+                    pInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)xcalloc(cbNeeded);
+                    fRet = g_pfnGetLogicalProcessorInformationEx(RelationGroup, pInfo, &cbNeeded);
+                }
+                if (   fRet
+                    && pInfo->Group.ActiveGroupCount > 0
+                    && pInfo->Group.ActiveGroupCount <= pInfo->Group.MaximumGroupCount)
+                {
+                    g_pGroupInfo = &pInfo->Group; /* leaked */
+                    pInfo = NULL;
+                }
+                else
+                    free(pInfo);
+            }
+
             MkWinChildInitCpuGroupAllocator(&g_ProcessorGroupAllocator);
         }
         else
         {
-            g_pfnSetThreadGroupAffinity       = NULL;
-            g_pfnGetActiveProcessorCount      = NULL;
-            g_pfnGetActiveProcessorGroupCount = NULL;
+            g_pfnSetThreadGroupAffinity           = NULL;
+            g_pfnGetActiveProcessorCount          = NULL;
+            g_pfnGetActiveProcessorGroupCount     = NULL;
+            g_pfnGetLogicalProcessorInformationEx = NULL;
         }
     }
@@ -1343,5 +1378,7 @@
         if (g_cProcessorGroups > 1)
         {
-            GROUP_AFFINITY Affinity = { 0 /* == all active apparently */, pWorker->iProcessorGroup, { 0, 0, 0 } };
+            GROUP_AFFINITY Affinity = { 0, pWorker->iProcessorGroup, { 0, 0, 0 } };
+            if (g_pGroupInfo && pWorker->iProcessorGroup < g_pGroupInfo->ActiveGroupCount)
+                Affinity.Mask = g_pGroupInfo->GroupInfo[pWorker->iProcessorGroup].ActiveProcessorMask;
             fRet = g_pfnSetThreadGroupAffinity(ProcInfo.hThread, &Affinity, NULL);
             assert(fRet);
@@ -2561,6 +2598,10 @@
     if (g_cProcessorGroups > 1)
     {
-        GROUP_AFFINITY Affinity = { 0 /* == all active apparently */, pWorker->iProcessorGroup, { 0, 0, 0 } };
-        BOOL fRet = g_pfnSetThreadGroupAffinity(GetCurrentThread(), &Affinity, NULL);
+        BOOL           fRet;
+        GROUP_AFFINITY Affinity = { 0, pWorker->iProcessorGroup, { 0, 0, 0 } };
+        if (g_pGroupInfo && pWorker->iProcessorGroup < g_pGroupInfo->ActiveGroupCount)
+            Affinity.Mask = g_pGroupInfo->GroupInfo[pWorker->iProcessorGroup].ActiveProcessorMask;
+
+        fRet = g_pfnSetThreadGroupAffinity(GetCurrentThread(), &Affinity, NULL);
         assert(fRet); (void)fRet;
 # ifndef NDEBUG
