29llvm_execute_on_thread_impl(
unsigned(__stdcall *ThreadFunc)(
void *),
void *Arg,
30 std::optional<unsigned> StackSizeInBytes) {
31 HANDLE hThread = (HANDLE)::_beginthreadex(NULL, StackSizeInBytes.value_or(0),
32 ThreadFunc, Arg, 0, NULL);
40void llvm_thread_join_impl(HANDLE hThread) {
41 if (::WaitForSingleObject(hThread, INFINITE) == WAIT_FAILED)
43 if (::CloseHandle(hThread) == FALSE)
47void llvm_thread_detach_impl(HANDLE hThread) {
48 if (::CloseHandle(hThread) == FALSE)
52DWORD llvm_thread_get_id_impl(HANDLE hThread) { return ::GetThreadId(hThread); }
54DWORD llvm_thread_get_current_id_impl() { return ::GetCurrentThreadId(); }
63static void SetThreadName(DWORD Id, LPCSTR Name) {
64 constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
67 struct THREADNAME_INFO {
82 ::RaiseException(MS_VC_EXCEPTION, 0,
sizeof(
info) /
sizeof(ULONG_PTR),
84 } __except (EXCEPTION_EXECUTE_HANDLER) {
92 SmallString<64> Storage;
93 StringRef NameStr =
Name.toNullTerminatedStringRef(Storage);
94 SetThreadName(::GetCurrentThreadId(), NameStr.data());
117 size_t Size = MAX_PATH;
119 Buf.resize_for_overwrite(
Size);
120 SetLastError(NO_ERROR);
121 Size = ::GetSystemDirectoryW(Buf.data(), Buf.size());
126 }
while (
Size > Buf.size());
129 Buf.push_back(L
'\\');
130 Buf.append(lpModuleName, lpModuleName + std::wcslen(lpModuleName));
133 return ::GetModuleHandleW(Buf.data());
138#ifdef THREAD_POWER_THROTTLING_CURRENT_VERSION
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));
164 setThreadInformation(Priority == ThreadPriority::Background
165 ? THREAD_POWER_THROTTLING_EXECUTION_SPEED
180 return SetThreadPriority(GetCurrentThread(),
181 Priority != ThreadPriority::Default
182 ? THREAD_MODE_BACKGROUND_BEGIN
183 : THREAD_MODE_BACKGROUND_END)
184 ? SetThreadPriorityResult::SUCCESS
185 : SetThreadPriorityResult::FAILURE;
188struct ProcessorGroup {
191 unsigned UsableThreads;
192 unsigned ThreadsPerCore;
195 unsigned useableCores()
const {
196 return std::max(1U, UsableThreads / ThreadsPerCore);
201static bool IterateProcInfo(LOGICAL_PROCESSOR_RELATIONSHIP Relationship,
F Fn) {
203 BOOL
R = ::GetLogicalProcessorInformationEx(Relationship, NULL, &Len);
204 if (R || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
207 auto *
Info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)calloc(1, Len);
208 R = ::GetLogicalProcessorInformationEx(Relationship,
Info, &Len);
211 (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((
uint8_t *)
Info + Len);
212 for (
auto *Curr =
Info; Curr < End;
213 Curr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((
uint8_t *)Curr +
215 if (Curr->Relationship != Relationship)
224static std::optional<std::vector<USHORT>> getActiveGroups() {
226 if (::GetProcessGroupAffinity(GetCurrentProcess(), &Count,
nullptr))
229 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
232 std::vector<USHORT>
Groups;
234 if (!::GetProcessGroupAffinity(GetCurrentProcess(), &Count,
Groups.data()))
240static ArrayRef<ProcessorGroup> getProcessorGroups() {
241 auto computeGroups = []() {
242 SmallVector<ProcessorGroup, 4>
Groups;
244 auto HandleGroup = [&](SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *ProcInfo) {
245 GROUP_RELATIONSHIP &El = ProcInfo->Group;
246 for (
unsigned J = 0; J < El.ActiveGroupCount; ++J) {
249 G.AllThreads = El.GroupInfo[J].MaximumProcessorCount;
250 G.UsableThreads = El.GroupInfo[J].ActiveProcessorCount;
252 G.Affinity = El.GroupInfo[J].ActiveProcessorMask;
257 if (!IterateProcInfo(RelationGroup, HandleGroup))
258 return std::vector<ProcessorGroup>();
260 auto HandleProc = [&](SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *ProcInfo) {
261 PROCESSOR_RELATIONSHIP &El = ProcInfo->Processor;
262 assert(El.GroupCount == 1);
263 unsigned NumHyperThreads = 1;
265 if (El.Flags & LTP_PC_SMT)
266 NumHyperThreads = std::bitset<64>(El.GroupMask[0].Mask).count();
267 unsigned I = El.GroupMask[0].Group;
268 Groups[
I].ThreadsPerCore = NumHyperThreads;
271 if (!IterateProcInfo(RelationProcessorCore, HandleProc))
272 return std::vector<ProcessorGroup>();
274 auto ActiveGroups = getActiveGroups();
276 return std::vector<ProcessorGroup>();
281 DWORD_PTR ProcessAffinityMask = 0, SystemAffinityMask = 0;
282 if (::GetProcessAffinityMask(GetCurrentProcess(), &ProcessAffinityMask,
283 &SystemAffinityMask)) {
285 if (ProcessAffinityMask != SystemAffinityMask) {
288 return std::vector<ProcessorGroup>(
Groups.begin(),
Groups.end());
291 assert(ActiveGroups->size() == 1 &&
292 "When an affinity mask is set, the process is expected to be "
293 "assigned to a single processor group!");
295 unsigned CurrentGroupID = (*ActiveGroups)[0];
296 ProcessorGroup NewG{
Groups[CurrentGroupID]};
297 NewG.Affinity = ProcessAffinityMask;
303 return std::vector<ProcessorGroup>(
Groups.begin(),
Groups.end());
305 static auto Groups = computeGroups();
306 return ArrayRef<ProcessorGroup>(
Groups);
309template <
typename R,
typename UnaryPredicate>
310static unsigned aggregate(R &&
Range, UnaryPredicate
P) {
312 for (
const auto &It :
Range)
318 static unsigned Cores =
319 aggregate(getProcessorGroups(), [](
const ProcessorGroup &
G) {
320 return G.UsableThreads /
G.ThreadsPerCore;
325static int computeHostNumHardwareThreads() {
326 static unsigned Threads =
327 aggregate(getProcessorGroups(),
328 [](
const ProcessorGroup &
G) {
return G.UsableThreads; });
334std::optional<unsigned>
344 unsigned MaxThreadsPerSocket =
350 "The thread index is not within thread strategy's range!");
358 unsigned ThreadPoolNum)
const {
369 GROUP_AFFINITY Affinity{};
370 Affinity.Group =
Groups[*Socket].ID;
371 Affinity.Mask =
Groups[*Socket].Affinity;
372 SetThreadGroupAffinity(GetCurrentThread(), &Affinity,
nullptr);
376 GROUP_AFFINITY Affinity{};
377 GetThreadGroupAffinity(GetCurrentThread(), &Affinity);
379 static unsigned All =
380 aggregate(getProcessorGroups(),
381 [](
const ProcessorGroup &
G) {
return G.AllThreads; });
383 unsigned StartOffset =
384 aggregate(getProcessorGroups(), [&](
const ProcessorGroup &
G) {
385 return G.ID < Affinity.Group ?
G.AllThreads : 0;
390 for (
unsigned I = 0;
I <
sizeof(KAFFINITY) * 8; ++
I) {
391 if ((Affinity.Mask >>
I) & 1)
392 V.set(StartOffset +
I);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Analysis containing CSE Info
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file defines the SmallString class.
static const X86InstrFMA3Group Groups[]
LLVM_ABI void apply_thread_strategy(unsigned ThreadPoolNum) const
Assign the current thread to an ideal hardware CPU or NUMA node.
LLVM_ABI std::optional< unsigned > compute_cpu_socket(unsigned ThreadPoolNum) const
Finds the CPU socket where a thread should go.
LLVM_ABI unsigned compute_thread_count() const
Retrieves the max available threads for the current strategy.
LLVM_ABI HMODULE loadSystemModuleSecure(LPCWSTR lpModuleName)
Retrieves the handle to a in-memory system module such as ntdll.dll, while ensuring we're not retriev...
This is an optimization pass for GlobalISel generic memory operations.
void ReportLastErrorFatal(const char *Msg)
LLVM_ABI llvm::BitVector get_thread_affinity_mask()
Returns a mask that represents on which hardware thread, core, CPU, NUMA group, the calling thread ca...
LLVM_ABI uint32_t get_max_thread_name_length()
Get the maximum length of a thread name on this platform.
LLVM_ABI SetThreadPriorityResult set_thread_priority(ThreadPriority Priority)
LLVM_ABI unsigned get_cpus()
Returns how many physical CPUs or NUMA groups the system has.
LLVM_ABI bool RunningWindows11OrGreater()
Determines if the program is running on Windows 11 or Windows Server 2022.
FunctionAddr VTableAddr Count
LLVM_ABI void set_thread_name(const Twine &Name)
Set the name of the current thread.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI void get_thread_name(SmallVectorImpl< char > &Name)
Get the name of the current thread.
LLVM_ABI int get_physical_cores()
Returns how many physical cores (as opposed to logical cores returned from thread::hardware_concurren...
LLVM_ABI uint64_t get_threadid()
Return the current thread id, as used in various OS system calls.
ArrayRef(const T &OneElt) -> ArrayRef< T >
int popcount(T Value) noexcept
Count the number of set bits in a value.