@@ -371,6 +371,50 @@ inline WindowsAffinity get_process_affinity() {
371371 return affinity;
372372}
373373
374+ // Type machinery used to emulate Cache->GroupCount
375+
376+ template <typename T, typename = void >
377+ struct HasGroupCount : std::false_type {};
378+
379+ template <typename T>
380+ struct HasGroupCount <T, std::void_t <decltype (std::declval<T>().Cache.GroupCount)>>: std::true_type {
381+ };
382+
383+ template <typename T, typename Pred, std::enable_if_t <HasGroupCount<T>::value, bool > = true >
384+ std::set<CpuIndex> readCacheMembers (const T* info, Pred&& is_cpu_allowed) {
385+ std::set<CpuIndex> cpus;
386+ // On Windows 10 this will read a 0 because GroupCount doesn't exist
387+ int groupCount = std::max (info->Cache .GroupCount , WORD (1 ));
388+ for (WORD procGroup = 0 ; procGroup < groupCount; ++procGroup)
389+ {
390+ for (BYTE number = 0 ; number < WIN_PROCESSOR_GROUP_SIZE; ++number)
391+ {
392+ WORD groupNumber = info->Cache .GroupMasks [procGroup].Group ;
393+ const CpuIndex c = static_cast <CpuIndex>(groupNumber) * WIN_PROCESSOR_GROUP_SIZE
394+ + static_cast <CpuIndex>(number);
395+ if (!(info->Cache .GroupMasks [procGroup].Mask & (1ULL << number)) || !is_cpu_allowed (c))
396+ continue ;
397+ cpus.insert (c);
398+ }
399+ }
400+ return cpus;
401+ }
402+
403+ template <typename T, typename Pred, std::enable_if_t <!HasGroupCount<T>::value, bool > = true >
404+ std::set<CpuIndex> readCacheMembers (const T* info, Pred&& is_cpu_allowed) {
405+ std::set<CpuIndex> cpus;
406+ for (BYTE number = 0 ; number < WIN_PROCESSOR_GROUP_SIZE; ++number)
407+ {
408+ WORD groupNumber = info->Cache .GroupMask .Group ;
409+ const CpuIndex c = static_cast <CpuIndex>(groupNumber) * WIN_PROCESSOR_GROUP_SIZE
410+ + static_cast <CpuIndex>(number);
411+ if (!(info->Cache .GroupMask .Mask & (1ULL << number)) || !is_cpu_allowed (c))
412+ continue ;
413+ cpus.insert (c);
414+ }
415+ return cpus;
416+ }
417+
374418#endif
375419
376420#if defined(__linux__) && !defined(__ANDROID__)
@@ -1174,29 +1218,17 @@ class NumaConfig {
11741218 if (info->Relationship == RelationCache && info->Cache .Level == 3 )
11751219 {
11761220 L3Domain domain{};
1177- for (WORD procGroup = 0 ; procGroup < info->Cache .GroupCount ; ++procGroup)
1178- {
1179- for (BYTE number = 0 ; number < WIN_PROCESSOR_GROUP_SIZE; ++number)
1180- {
1181- WORD groupNumber = info->Cache .GroupMasks [procGroup].Group ;
1182- const CpuIndex c =
1183- static_cast <CpuIndex>(groupNumber) * WIN_PROCESSOR_GROUP_SIZE
1184- + static_cast <CpuIndex>(number);
1185- if (!(info->Cache .GroupMasks [procGroup].Mask & (1ULL << number))
1186- || !is_cpu_allowed (c))
1187- continue ;
1188- domain.systemNumaIndex = systemConfig.nodeByCpu .at (c);
1189- domain.cpus .insert (c);
1190- }
1191- }
1221+ domain.cpus = readCacheMembers (info, is_cpu_allowed);
11921222 if (!domain.cpus .empty ())
1223+ {
1224+ domain.systemNumaIndex = systemConfig.nodeByCpu .at (*domain.cpus .begin ());
11931225 l3Domains.push_back (std::move (domain));
1226+ }
11941227 }
11951228 // Variable length data structure, advance to next
11961229 info = reinterpret_cast <PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(
11971230 reinterpret_cast <char *>(info) + info->Size );
11981231 }
1199-
12001232#endif
12011233
12021234 if (!l3Domains.empty ())
0 commit comments