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.cpp169
1 files changed, 138 insertions, 31 deletions
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp
index 03c8988..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
@@ -142,9 +236,9 @@ typedef BOOL (WINAPI *Func_GlobalMemoryStatusEx)(MY_LPMEMORYSTATUSEX lpBuffer);
142#endif // !UNDER_CE 236#endif // !UNDER_CE
143 237
144 238
145bool GetRamSize(UInt64 &size) 239bool GetRamSize(size_t &size)
146{ 240{
147 size = (UInt64)(sizeof(size_t)) << 29; 241 size = (size_t)sizeof(size_t) << 29;
148 242
149 #ifndef UNDER_CE 243 #ifndef UNDER_CE
150 MY_MEMORYSTATUSEX stat; 244 MY_MEMORYSTATUSEX stat;
@@ -167,11 +261,23 @@ bool GetRamSize(UInt64 &size)
167 "GlobalMemoryStatusEx"); 261 "GlobalMemoryStatusEx");
168 if (fn && fn(&stat)) 262 if (fn && fn(&stat))
169 { 263 {
170 size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys); 264 // (MY_MEMORYSTATUSEX::ullTotalVirtual) < 4 GiB in 32-bit mode
265 size_t size2 = (size_t)0 - 1;
266 if (size2 > stat.ullTotalPhys)
267 size2 = (size_t)stat.ullTotalPhys;
268 if (size2 > stat.ullTotalVirtual)
269 size2 = (size_t)stat.ullTotalVirtual;
270 size = size2;
171 return true; 271 return true;
172 } 272 }
173 #endif 273 #endif
174 274
275 // On computers with more than 4 GB of memory:
276 // new docs : GlobalMemoryStatus can report (-1) value to indicate an overflow.
277 // some old docs : GlobalMemoryStatus can report (modulo 4 GiB) value.
278 // (for example, if 5 GB total memory, it could report 1 GB).
279 // We don't want to get (modulo 4 GiB) value.
280 // So we use GlobalMemoryStatusEx() instead.
175 { 281 {
176 MEMORYSTATUS stat2; 282 MEMORYSTATUS stat2;
177 stat2.dwLength = sizeof(stat2); 283 stat2.dwLength = sizeof(stat2);
@@ -187,9 +293,11 @@ bool GetRamSize(UInt64 &size)
187// POSIX 293// POSIX
188// #include <stdio.h> 294// #include <stdio.h>
189 295
190bool GetRamSize(UInt64 &size) 296bool GetRamSize(size_t &size)
191{ 297{
192 size = (UInt64)(sizeof(size_t)) << 29; 298 UInt64 size64;
299 size = (size_t)sizeof(size_t) << 29;
300 size64 = size;
193 301
194#if defined(__APPLE__) || defined(__DragonFly__) || \ 302#if defined(__APPLE__) || defined(__DragonFly__) || \
195 defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) 303 defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
@@ -215,7 +323,7 @@ bool GetRamSize(UInt64 &size)
215 // we use strict check (size_sys == sizeof(val)) for returned value 323 // we use strict check (size_sys == sizeof(val)) for returned value
216 // because big-endian encoding is possible: 324 // because big-endian encoding is possible:
217 if (res == 0 && size_sys == sizeof(val) && val) 325 if (res == 0 && size_sys == sizeof(val) && val)
218 size = val; 326 size64 = val;
219 else 327 else
220 { 328 {
221 uint32_t val32 = 0; 329 uint32_t val32 = 0;
@@ -223,12 +331,12 @@ bool GetRamSize(UInt64 &size)
223 res = sysctl(mib, 2, &val32, &size_sys, NULL, 0); 331 res = sysctl(mib, 2, &val32, &size_sys, NULL, 0);
224 // printf("\n sysctl res=%d val=%llx size_sys = %d, %d\n", res, (long long int)val32, (int)size_sys, errno); 332 // printf("\n sysctl res=%d val=%llx size_sys = %d, %d\n", res, (long long int)val32, (int)size_sys, errno);
225 if (res == 0 && size_sys == sizeof(val32) && val32) 333 if (res == 0 && size_sys == sizeof(val32) && val32)
226 size = val32; 334 size64 = val32;
227 } 335 }
228 336
229 #elif defined(_AIX) 337 #elif defined(_AIX)
230 #if defined(_SC_AIX_REALMEM) // AIX 338 #if defined(_SC_AIX_REALMEM) // AIX
231 size = (UInt64)sysconf(_SC_AIX_REALMEM) * 1024; 339 size64 = (UInt64)sysconf(_SC_AIX_REALMEM) * 1024;
232 #endif 340 #endif
233 #elif 0 || defined(__sun) 341 #elif 0 || defined(__sun)
234 #if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) 342 #if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
@@ -240,7 +348,7 @@ bool GetRamSize(UInt64 &size)
240 // printf("\n_SC_PHYS_PAGES (hex) = %lx", (unsigned long)phys_pages); 348 // printf("\n_SC_PHYS_PAGES (hex) = %lx", (unsigned long)phys_pages);
241 // printf("\n_SC_PAGESIZE = %lu\n", (unsigned long)page_size); 349 // printf("\n_SC_PAGESIZE = %lu\n", (unsigned long)page_size);
242 if (phys_pages != -1 && page_size != -1) 350 if (phys_pages != -1 && page_size != -1)
243 size = (UInt64)(Int64)phys_pages * (UInt64)(Int64)page_size; 351 size64 = (UInt64)(Int64)phys_pages * (UInt64)(Int64)page_size;
244 } 352 }
245 #endif 353 #endif
246 #elif defined(__gnu_hurd__) 354 #elif defined(__gnu_hurd__)
@@ -253,7 +361,7 @@ bool GetRamSize(UInt64 &size)
253 struct sysinfo info; 361 struct sysinfo info;
254 if (::sysinfo(&info) != 0) 362 if (::sysinfo(&info) != 0)
255 return false; 363 return false;
256 size = (UInt64)info.mem_unit * info.totalram; 364 size64 = (UInt64)info.mem_unit * info.totalram;
257 /* 365 /*
258 printf("\n mem_unit = %lld", (UInt64)info.mem_unit); 366 printf("\n mem_unit = %lld", (UInt64)info.mem_unit);
259 printf("\n totalram = %lld", (UInt64)info.totalram); 367 printf("\n totalram = %lld", (UInt64)info.totalram);
@@ -262,10 +370,9 @@ bool GetRamSize(UInt64 &size)
262 370
263 #endif 371 #endif
264 372
265 const UInt64 kLimit = (UInt64)1 << (sizeof(size_t) * 8 - 1); 373 size = (size_t)1 << (sizeof(size_t) * 8 - 1);
266 if (size > kLimit) 374 if (size > size64)
267 size = kLimit; 375 size = (size_t)size64;
268
269 return true; 376 return true;
270} 377}
271 378