diff options
| author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2025-07-05 00:00:00 +0000 |
|---|---|---|
| committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2025-07-05 19:27:33 +0500 |
| commit | 395149956d696e6e3099d8b76d797437f94a6942 (patch) | |
| tree | 6ed5013a637078ae2dfdc4acf1ad93bf29cea356 /CPP/Windows/System.cpp | |
| parent | e5431fa6f5505e385c6f9367260717e9c47dc2ee (diff) | |
| download | 7zip-25.00.tar.gz 7zip-25.00.tar.bz2 7zip-25.00.zip | |
25.0025.00
Diffstat (limited to 'CPP/Windows/System.cpp')
| -rw-r--r-- | CPP/Windows/System.cpp | 128 |
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 | /* | ||
| 29 | note: returned value in 32-bit version can be limited by value 32. | ||
| 30 | while 64-bit version returns full value. | ||
| 31 | GetMaximumProcessorCount(groupNumber) can return higher value than | ||
| 32 | GetActiveProcessorCount(groupNumber) in some cases, because CPUs can be added. | ||
| 33 | */ | ||
| 34 | // typedef DWORD (WINAPI *Func_GetMaximumProcessorCount)(WORD GroupNumber); | ||
| 35 | typedef DWORD (WINAPI *Func_GetActiveProcessorCount)(WORD GroupNumber); | ||
| 36 | typedef 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 | |||
| 45 | Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | ||
| 46 | |||
| 47 | bool 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 | |||
| 28 | UInt32 CountAffinity(DWORD_PTR mask) | 91 | UInt32 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 | ||
| 39 | BOOL CProcessAffinity::Get() | 102 | BOOL 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 | ||
| 140 | UInt32 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 | |||
| 49 | UInt32 GetNumberOfProcessors() | 154 | UInt32 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 |
