aboutsummaryrefslogtreecommitdiff
path: root/CPP/Windows/System.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/Windows/System.cpp')
-rw-r--r--CPP/Windows/System.cpp128
1 files changed, 111 insertions, 17 deletions
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp
index 5fa87f3..4745785 100644
--- a/CPP/Windows/System.cpp
+++ b/CPP/Windows/System.cpp
@@ -25,6 +25,69 @@ namespace NSystem {
25 25
26#ifdef _WIN32 26#ifdef _WIN32
27 27
28/*
29note: returned value in 32-bit version can be limited by value 32.
30 while 64-bit version returns full value.
31GetMaximumProcessorCount(groupNumber) can return higher value than
32GetActiveProcessorCount(groupNumber) in some cases, because CPUs can be added.
33*/
34// typedef DWORD (WINAPI *Func_GetMaximumProcessorCount)(WORD GroupNumber);
35typedef DWORD (WINAPI *Func_GetActiveProcessorCount)(WORD GroupNumber);
36typedef WORD (WINAPI *Func_GetActiveProcessorGroupCount)(VOID);
37/*
38#if 0 && defined(ALL_PROCESSOR_GROUPS)
39#define MY_ALL_PROCESSOR_GROUPS ALL_PROCESSOR_GROUPS
40#else
41#define MY_ALL_PROCESSOR_GROUPS 0xffff
42#endif
43*/
44
45Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
46
47bool CCpuGroups::Load()
48{
49 NumThreadsTotal = 0;
50 GroupSizes.Clear();
51 const HMODULE hmodule = ::GetModuleHandleA("kernel32.dll");
52 // Is_Win11_Groups = GetProcAddress(hmodule, "SetThreadSelectedCpuSetMasks") != NULL;
53 const
54 Func_GetActiveProcessorGroupCount
55 fn_GetActiveProcessorGroupCount = Z7_GET_PROC_ADDRESS(
56 Func_GetActiveProcessorGroupCount, hmodule,
57 "GetActiveProcessorGroupCount");
58 const
59 Func_GetActiveProcessorCount
60 fn_GetActiveProcessorCount = Z7_GET_PROC_ADDRESS(
61 Func_GetActiveProcessorCount, hmodule,
62 "GetActiveProcessorCount");
63 if (!fn_GetActiveProcessorGroupCount ||
64 !fn_GetActiveProcessorCount)
65 return false;
66
67 const unsigned numGroups = fn_GetActiveProcessorGroupCount();
68 if (numGroups == 0)
69 return false;
70 UInt32 sum = 0;
71 for (unsigned i = 0; i < numGroups; i++)
72 {
73 const UInt32 num = fn_GetActiveProcessorCount((WORD)i);
74 /*
75 if (num == 0)
76 {
77 // it means error
78 // but is it possible that some group is empty by some reason?
79 // GroupSizes.Clear();
80 // return false;
81 }
82 */
83 sum += num;
84 GroupSizes.Add(num);
85 }
86 NumThreadsTotal = sum;
87 // NumThreadsTotal = fn_GetActiveProcessorCount(MY_ALL_PROCESSOR_GROUPS);
88 return true;
89}
90
28UInt32 CountAffinity(DWORD_PTR mask) 91UInt32 CountAffinity(DWORD_PTR mask)
29{ 92{
30 UInt32 num = 0; 93 UInt32 num = 0;
@@ -38,31 +101,62 @@ UInt32 CountAffinity(DWORD_PTR mask)
38 101
39BOOL CProcessAffinity::Get() 102BOOL CProcessAffinity::Get()
40{ 103{
41 #ifndef UNDER_CE 104 IsGroupMode = false;
42 return GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask); 105 Groups.Load();
43 #else 106 // SetThreadAffinityMask(GetCurrentThread(), 1);
44 return FALSE; 107 // SetProcessAffinityMask(GetCurrentProcess(), 1);
45 #endif 108 BOOL res = GetProcessAffinityMask(GetCurrentProcess(),
109 &processAffinityMask, &systemAffinityMask);
110 /* DOCs: On a system with more than 64 processors, if the threads
111 of the calling process are in a single processor group, the
112 function sets the variables pointed to by lpProcessAffinityMask
113 and lpSystemAffinityMask to the process affinity mask and the
114 processor mask of active logical processors for that group.
115 If the calling process contains threads in multiple groups,
116 the function returns zero for both affinity masks
117
118 note: tested in Win10: GetProcessAffinityMask() doesn't return 0
119 in (processAffinityMask) and (systemAffinityMask) masks.
120 We need to test it in Win11: how to get mask==0 from GetProcessAffinityMask()?
121 */
122 if (!res)
123 {
124 processAffinityMask = 0;
125 systemAffinityMask = 0;
126 }
127 if (Groups.GroupSizes.Size() > 1 && Groups.NumThreadsTotal)
128 if (// !res ||
129 processAffinityMask == 0 || // to support case described in DOCs and for (!res) case
130 processAffinityMask == systemAffinityMask) // for default nonchanged affinity
131 {
132 // we set IsGroupMode only if processAffinity is default (not changed).
133 res = TRUE;
134 IsGroupMode = true;
135 }
136 return res;
46} 137}
47 138
48 139
140UInt32 CProcessAffinity::Load_and_GetNumberOfThreads()
141{
142 if (Get())
143 {
144 const UInt32 numProcessors = GetNumProcessThreads();
145 if (numProcessors)
146 return numProcessors;
147 }
148 SYSTEM_INFO systemInfo;
149 GetSystemInfo(&systemInfo);
150 // the number of logical processors in the current group
151 return systemInfo.dwNumberOfProcessors;
152}
153
49UInt32 GetNumberOfProcessors() 154UInt32 GetNumberOfProcessors()
50{ 155{
51 // We need to know how many threads we can use. 156 // We need to know how many threads we can use.
52 // By default the process is assigned to one group. 157 // By default the process is assigned to one group.
53 // So we get the number of logical processors (threads)
54 // assigned to current process in the current group.
55 // Group size can be smaller than total number logical processors, for exammple, 2x36
56
57 CProcessAffinity pa; 158 CProcessAffinity pa;
58 159 return pa.Load_and_GetNumberOfThreads();
59 if (pa.Get() && pa.processAffinityMask != 0)
60 return pa.GetNumProcessThreads();
61
62 SYSTEM_INFO systemInfo;
63 GetSystemInfo(&systemInfo);
64 // the number of logical processors in the current group
65 return (UInt32)systemInfo.dwNumberOfProcessors;
66} 160}
67 161
68#else 162#else