diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 33ae752d6f..2a9dc4a0be 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #else #ifdef __APPLE__ #define _XOPEN_SOURCE @@ -1823,8 +1824,53 @@ void thread_ctrl::detect_cpu_layout() { g_native_core_layout.store(native_core_arrangement::amd_ccx); } + else if (system_id.find("Intel") != std::string::npos) + { +#ifdef _WIN32 + const LOGICAL_PROCESSOR_RELATIONSHIP relationship = LOGICAL_PROCESSOR_RELATIONSHIP::RelationProcessorCore; + DWORD buffer_size = 0; - // TODO: Detect hyperthreaded intel CPUs + // If buffer size is set to 0 bytes, it will be overwritten with the required size + if (GetLogicalProcessorInformationEx(relationship, nullptr, &buffer_size)) + { + LOG_ERROR(GENERAL, "GetLogicalProcessorInformationEx returned 0 bytes"); + return; + } + DWORD error_code = GetLastError(); + if (error_code != ERROR_INSUFFICIENT_BUFFER) + { + LOG_ERROR(GENERAL, "Unexpected windows error code when detecting CPU layout: %u", error_code); + return; + } + + std::vector buffer(buffer_size); + + if (!GetLogicalProcessorInformationEx(relationship, + reinterpret_cast(buffer.data()), &buffer_size)) + { + LOG_ERROR(GENERAL, "GetLogicalProcessorInformationEx failed (size=%u, error=%u)", buffer_size, GetLastError()); + } + else + { + // Iterate through the buffer until a core with hyperthreading is found + auto ptr = reinterpret_cast(buffer.data()); + const std::uintptr_t end = ptr + buffer_size; + + while (ptr < end) + { + auto info = reinterpret_cast(ptr); + if (info->Relationship == relationship && info->Processor.Flags == LTP_PC_SMT) + { + g_native_core_layout.store(native_core_arrangement::intel_ht); + break; + } + ptr += info->Size; + } + } +#else + LOG_TODO(GENERAL, "Thread scheduler is not implemented for Intel and this OS"); +#endif + } } u16 thread_ctrl::get_affinity_mask(thread_class group)