@@ -106,7 +106,67 @@ void llvm::get_thread_name(SmallVectorImpl<char> &Name) {
106
106
Name.clear ();
107
107
}
108
108
109
+ namespace llvm ::sys::windows {
110
+ HMODULE loadSystemModuleSecure (LPCWSTR lpModuleName) {
111
+ // Ensure we load indeed a module from system32 path.
112
+ // As per GetModuleHandle documentation:
113
+ // "If lpModuleName does not include a path and there is more than one loaded
114
+ // module with the same base name and extension, you cannot predict which
115
+ // module handle will be returned.". This mitigates
116
+ // https://learn.microsoft.com/en-us/security-updates/securityadvisories/2010/2269637
117
+ SmallVector<wchar_t , MAX_PATH> Buf;
118
+ size_t Size = MAX_PATH;
119
+ do {
120
+ Buf.resize_for_overwrite (Size);
121
+ SetLastError (NO_ERROR);
122
+ Size = ::GetSystemDirectoryW (Buf.data (), Buf.size ());
123
+ if (Size == 0 )
124
+ return NULL ;
125
+
126
+ // Try again with larger buffer.
127
+ } while (Size > Buf.size ());
128
+
129
+ Buf.truncate (Size);
130
+ Buf.push_back (L' \\ ' );
131
+ Buf.append (lpModuleName, lpModuleName + std::wcslen (lpModuleName));
132
+ Buf.push_back (0 );
133
+
134
+ return ::GetModuleHandleW (Buf.data ());
135
+ }
136
+ } // namespace llvm::sys::windows
137
+
109
138
SetThreadPriorityResult llvm::set_thread_priority (ThreadPriority Priority) {
139
+ HMODULE kernelM = llvm::sys::windows::loadSystemModuleSecure (L" kernel32.dll" );
140
+ if (kernelM) {
141
+ // SetThreadInformation is only available on Windows 8 and later. Since we
142
+ // still support compilation on Windows 7, we load the function dynamically.
143
+ typedef BOOL (WINAPI * SetThreadInformation_t)(
144
+ HANDLE hThread, THREAD_INFORMATION_CLASS ThreadInformationClass,
145
+ _In_reads_bytes_ (ThreadInformationSize) PVOID ThreadInformation,
146
+ ULONG ThreadInformationSize);
147
+ static const auto pfnSetThreadInformation =
148
+ (SetThreadInformation_t)::GetProcAddress (kernelM,
149
+ " SetThreadInformation" );
150
+ if (pfnSetThreadInformation) {
151
+ auto setThreadInformation = [](ULONG ControlMaskAndStateMask) {
152
+ THREAD_POWER_THROTTLING_STATE state{};
153
+ state.Version = THREAD_POWER_THROTTLING_CURRENT_VERSION;
154
+ state.ControlMask = ControlMaskAndStateMask;
155
+ state.StateMask = ControlMaskAndStateMask;
156
+ return pfnSetThreadInformation (
157
+ ::GetCurrentThread (), ThreadPowerThrottling, &state, sizeof(state));
158
+ };
159
+
160
+ // Use EcoQoS for ThreadPriority::Background available (running on most
161
+ // efficent cores at the most efficient cpu frequency):
162
+ // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadinformation
163
+ // https://learn.microsoft.com/en-us/windows/win32/procthread/quality-of-service
164
+ setThreadInformation (Priority == ThreadPriority::Background
165
+ ? THREAD_POWER_THROTTLING_EXECUTION_SPEED
166
+ : 0 );
167
+ }
168
+ }
169
+
110
170
// https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-setthreadpriority
111
171
// Begin background processing mode. The system lowers the resource scheduling
112
172
// priorities of the thread so that it can perform background work without
0 commit comments