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());
110#ifdef THREAD_POWER_THROTTLING_CURRENT_VERSION
115 typedef BOOL(WINAPI * SetThreadInformation_t)(
116 HANDLE hThread, THREAD_INFORMATION_CLASS ThreadInformationClass,
117 _In_reads_bytes_(ThreadInformationSize) PVOID ThreadInformation,
118 ULONG ThreadInformationSize);
119 static const auto pfnSetThreadInformation =
120 (SetThreadInformation_t)::GetProcAddress(kernelM,
121 "SetThreadInformation");
122 if (pfnSetThreadInformation) {
123 auto setThreadInformation = [](ULONG ControlMaskAndStateMask) {
124 THREAD_POWER_THROTTLING_STATE state{};
125 state.Version = THREAD_POWER_THROTTLING_CURRENT_VERSION;
126 state.ControlMask = ControlMaskAndStateMask;
127 state.StateMask = ControlMaskAndStateMask;
128 return pfnSetThreadInformation(
129 ::GetCurrentThread(), ThreadPowerThrottling, &state,
sizeof(state));
136 setThreadInformation(Priority == ThreadPriority::Background
137 ? THREAD_POWER_THROTTLING_EXECUTION_SPEED
152 return SetThreadPriority(GetCurrentThread(),
153 Priority != ThreadPriority::Default
154 ? THREAD_MODE_BACKGROUND_BEGIN
155 : THREAD_MODE_BACKGROUND_END)
156 ? SetThreadPriorityResult::SUCCESS
157 : SetThreadPriorityResult::FAILURE;
160struct ProcessorGroup {
163 unsigned UsableThreads;
164 unsigned ThreadsPerCore;
167 unsigned useableCores()
const {
168 return std::max(1U, UsableThreads / ThreadsPerCore);
173static bool IterateProcInfo(LOGICAL_PROCESSOR_RELATIONSHIP Relationship,
F Fn) {
175 BOOL
R = ::GetLogicalProcessorInformationEx(Relationship, NULL, &Len);
176 if (R || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
179 auto *Info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)calloc(1, Len);
180 R = ::GetLogicalProcessorInformationEx(Relationship, Info, &Len);
183 (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((
uint8_t *)Info + Len);
184 for (
auto *Curr = Info; Curr < End;
185 Curr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((
uint8_t *)Curr +
187 if (Curr->Relationship != Relationship)
196static std::optional<std::vector<USHORT>> getActiveGroups() {
198 if (::GetProcessGroupAffinity(GetCurrentProcess(), &Count,
nullptr))
201 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
204 std::vector<USHORT>
Groups;
206 if (!::GetProcessGroupAffinity(GetCurrentProcess(), &Count,
Groups.data()))
213 auto computeGroups = []() {
216 auto HandleGroup = [&](SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *ProcInfo) {
217 GROUP_RELATIONSHIP &El = ProcInfo->Group;
218 for (
unsigned J = 0; J < El.ActiveGroupCount; ++J) {
221 G.AllThreads = El.GroupInfo[J].MaximumProcessorCount;
222 G.UsableThreads = El.GroupInfo[J].ActiveProcessorCount;
224 G.Affinity = El.GroupInfo[J].ActiveProcessorMask;
229 if (!IterateProcInfo(RelationGroup, HandleGroup))
230 return std::vector<ProcessorGroup>();
232 auto HandleProc = [&](SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *ProcInfo) {
233 PROCESSOR_RELATIONSHIP &El = ProcInfo->Processor;
234 assert(El.GroupCount == 1);
235 unsigned NumHyperThreads = 1;
237 if (El.Flags & LTP_PC_SMT)
238 NumHyperThreads = std::bitset<64>(El.GroupMask[0].Mask).count();
239 unsigned I = El.GroupMask[0].Group;
240 Groups[
I].ThreadsPerCore = NumHyperThreads;
243 if (!IterateProcInfo(RelationProcessorCore, HandleProc))
244 return std::vector<ProcessorGroup>();
246 auto ActiveGroups = getActiveGroups();
248 return std::vector<ProcessorGroup>();
253 DWORD_PTR ProcessAffinityMask = 0, SystemAffinityMask = 0;
254 if (::GetProcessAffinityMask(GetCurrentProcess(), &ProcessAffinityMask,
255 &SystemAffinityMask)) {
257 if (ProcessAffinityMask != SystemAffinityMask) {
260 return std::vector<ProcessorGroup>(
Groups.begin(),
Groups.end());
263 assert(ActiveGroups->size() == 1 &&
264 "When an affinity mask is set, the process is expected to be "
265 "assigned to a single processor group!");
267 unsigned CurrentGroupID = (*ActiveGroups)[0];
268 ProcessorGroup NewG{
Groups[CurrentGroupID]};
269 NewG.Affinity = ProcessAffinityMask;
275 return std::vector<ProcessorGroup>(
Groups.begin(),
Groups.end());
277 static auto Groups = computeGroups();
281template <
typename R,
typename UnaryPredicate>
282static unsigned aggregate(R &&
Range, UnaryPredicate
P) {
284 for (
const auto &It :
Range)
290 static unsigned Cores =
291 aggregate(getProcessorGroups(), [](
const ProcessorGroup &
G) {
292 return G.UsableThreads /
G.ThreadsPerCore;
297static int computeHostNumHardwareThreads() {
298 static unsigned Threads =
299 aggregate(getProcessorGroups(),
300 [](
const ProcessorGroup &
G) {
return G.UsableThreads; });
306std::optional<unsigned>
316 unsigned MaxThreadsPerSocket =
322 "The thread index is not within thread strategy's range!");
330 unsigned ThreadPoolNum)
const {
341 GROUP_AFFINITY Affinity{};
342 Affinity.Group =
Groups[*Socket].ID;
343 Affinity.Mask =
Groups[*Socket].Affinity;
344 SetThreadGroupAffinity(GetCurrentThread(), &Affinity,
nullptr);
348 GROUP_AFFINITY Affinity{};
349 GetThreadGroupAffinity(GetCurrentThread(), &Affinity);
351 static unsigned All =
352 aggregate(getProcessorGroups(),
353 [](
const ProcessorGroup &
G) {
return G.AllThreads; });
355 unsigned StartOffset =
356 aggregate(getProcessorGroups(), [&](
const ProcessorGroup &
G) {
357 return G.ID < Affinity.Group ?
G.AllThreads : 0;
362 for (
unsigned I = 0;
I <
sizeof(KAFFINITY) * 8; ++
I) {
363 if ((Affinity.Mask >>
I) & 1)
364 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[]
ArrayRef - 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.
FunctionAddr VTableAddr Count
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.
ArrayRef(const T &OneElt) -> ArrayRef< T >