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) {
59 return ::GetThreadId(hThread);
62DWORD llvm_thread_get_current_id_impl() { return ::GetCurrentThreadId(); }
71static void SetThreadName(DWORD Id, LPCSTR Name) {
72 constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
75 struct THREADNAME_INFO {
90 ::RaiseException(MS_VC_EXCEPTION, 0,
sizeof(
info) /
sizeof(ULONG_PTR),
92 } __except (EXCEPTION_EXECUTE_HANDLER) {
100 SmallString<64> Storage;
101 StringRef NameStr =
Name.toNullTerminatedStringRef(Storage);
102 SetThreadName(::GetCurrentThreadId(), NameStr.data());
118#ifdef THREAD_POWER_THROTTLING_CURRENT_VERSION
123 typedef BOOL(WINAPI * SetThreadInformation_t)(
124 HANDLE hThread, THREAD_INFORMATION_CLASS ThreadInformationClass,
125 _In_reads_bytes_(ThreadInformationSize) PVOID ThreadInformation,
126 ULONG ThreadInformationSize);
127 static const auto pfnSetThreadInformation =
128 (SetThreadInformation_t)(
void *)::GetProcAddress(
129 kernelM,
"SetThreadInformation");
130 if (pfnSetThreadInformation) {
131 auto setThreadInformation = [](ULONG ControlMaskAndStateMask) {
132 THREAD_POWER_THROTTLING_STATE state{};
133 state.Version = THREAD_POWER_THROTTLING_CURRENT_VERSION;
134 state.ControlMask = ControlMaskAndStateMask;
135 state.StateMask = ControlMaskAndStateMask;
136 return pfnSetThreadInformation(
137 ::GetCurrentThread(), ThreadPowerThrottling, &state,
sizeof(state));
144 setThreadInformation(Priority == ThreadPriority::Background
145 ? THREAD_POWER_THROTTLING_EXECUTION_SPEED
160 return SetThreadPriority(GetCurrentThread(),
161 Priority != ThreadPriority::Default
162 ? THREAD_MODE_BACKGROUND_BEGIN
163 : THREAD_MODE_BACKGROUND_END)
164 ? SetThreadPriorityResult::SUCCESS
165 : SetThreadPriorityResult::FAILURE;
168struct ProcessorGroup {
171 unsigned UsableThreads;
172 unsigned ThreadsPerCore;
175 unsigned useableCores()
const {
176 return std::max(1U, UsableThreads / ThreadsPerCore);
181static bool IterateProcInfo(LOGICAL_PROCESSOR_RELATIONSHIP Relationship,
F Fn) {
183 BOOL
R = ::GetLogicalProcessorInformationEx(Relationship, NULL, &Len);
184 if (R || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
187 auto *Info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)calloc(1, Len);
188 R = ::GetLogicalProcessorInformationEx(Relationship, Info, &Len);
191 (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((
uint8_t *)Info + Len);
192 for (
auto *Curr = Info; Curr < End;
193 Curr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((
uint8_t *)Curr +
195 if (Curr->Relationship != Relationship)
204static std::optional<std::vector<USHORT>> getActiveGroups() {
206 if (::GetProcessGroupAffinity(GetCurrentProcess(), &Count,
nullptr))
209 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
212 std::vector<USHORT>
Groups;
214 if (!::GetProcessGroupAffinity(GetCurrentProcess(), &Count,
Groups.data()))
221 auto computeGroups = []() {
224 auto HandleGroup = [&](SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *ProcInfo) {
225 GROUP_RELATIONSHIP &El = ProcInfo->Group;
226 for (
unsigned J = 0; J < El.ActiveGroupCount; ++J) {
229 G.AllThreads = El.GroupInfo[J].MaximumProcessorCount;
230 G.UsableThreads = El.GroupInfo[J].ActiveProcessorCount;
232 G.Affinity = El.GroupInfo[J].ActiveProcessorMask;
237 if (!IterateProcInfo(RelationGroup, HandleGroup))
238 return std::vector<ProcessorGroup>();
240 auto HandleProc = [&](SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *ProcInfo) {
241 PROCESSOR_RELATIONSHIP &El = ProcInfo->Processor;
242 assert(El.GroupCount == 1);
243 unsigned NumHyperThreads = 1;
245 if (El.Flags & LTP_PC_SMT)
246 NumHyperThreads = std::bitset<64>(El.GroupMask[0].Mask).count();
247 unsigned I = El.GroupMask[0].Group;
248 Groups[
I].ThreadsPerCore = NumHyperThreads;
251 if (!IterateProcInfo(RelationProcessorCore, HandleProc))
252 return std::vector<ProcessorGroup>();
254 auto ActiveGroups = getActiveGroups();
256 return std::vector<ProcessorGroup>();
261 DWORD_PTR ProcessAffinityMask = 0, SystemAffinityMask = 0;
262 if (::GetProcessAffinityMask(GetCurrentProcess(), &ProcessAffinityMask,
263 &SystemAffinityMask)) {
265 if (ProcessAffinityMask != SystemAffinityMask) {
268 return std::vector<ProcessorGroup>(
Groups.begin(),
Groups.end());
271 assert(ActiveGroups->size() == 1 &&
272 "When an affinity mask is set, the process is expected to be "
273 "assigned to a single processor group!");
275 unsigned CurrentGroupID = (*ActiveGroups)[0];
276 ProcessorGroup NewG{
Groups[CurrentGroupID]};
277 NewG.Affinity = ProcessAffinityMask;
283 return std::vector<ProcessorGroup>(
Groups.begin(),
Groups.end());
285 static auto Groups = computeGroups();
289template <
typename R,
typename UnaryPredicate>
290static unsigned aggregate(R &&
Range, UnaryPredicate
P) {
292 for (
const auto &It :
Range)
298 static unsigned Cores =
299 aggregate(getProcessorGroups(), [](
const ProcessorGroup &
G) {
300 return G.UsableThreads /
G.ThreadsPerCore;
305static int computeHostNumHardwareThreads() {
306 static unsigned Threads =
307 aggregate(getProcessorGroups(),
308 [](
const ProcessorGroup &
G) {
return G.UsableThreads; });
314std::optional<unsigned>
324 unsigned MaxThreadsPerSocket =
330 "The thread index is not within thread strategy's range!");
338 unsigned ThreadPoolNum)
const {
349 GROUP_AFFINITY Affinity{};
350 Affinity.Group =
Groups[*Socket].ID;
351 Affinity.Mask =
Groups[*Socket].Affinity;
352 SetThreadGroupAffinity(GetCurrentThread(), &Affinity,
nullptr);
356 GROUP_AFFINITY Affinity{};
357 GetThreadGroupAffinity(GetCurrentThread(), &Affinity);
359 static unsigned All =
360 aggregate(getProcessorGroups(),
361 [](
const ProcessorGroup &
G) {
return G.AllThreads; });
363 unsigned StartOffset =
364 aggregate(getProcessorGroups(), [&](
const ProcessorGroup &
G) {
365 return G.ID < Affinity.Group ?
G.AllThreads : 0;
370 for (
unsigned I = 0;
I <
sizeof(KAFFINITY) * 8; ++
I) {
371 if ((Affinity.Mask >>
I) & 1)
372 V.set(StartOffset +
I);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file defines the SmallString class.
static const X86InstrFMA3Group Groups[]
Represent a constant reference to an array (0 or more elements consecutively in memory),...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
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.
LLVM_ABI void set_thread_name(const Twine &Name)
Set the name of the current thread.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
ArrayRef(const T &OneElt) -> ArrayRef< T >