Fix util/cpuid hybrid detect

- clang-format applied

Bug: None
Change-Id: If8aec0bbb3d3461886f176a77e029833f5dc197d
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/6805445
Reviewed-by: Wan-Teh Chang <wtc@google.com>
This commit is contained in:
Frank Barchard 2025-08-04 16:14:42 -07:00
parent 48943bb378
commit 5eea781282
2 changed files with 136 additions and 8 deletions

View File

@ -2859,7 +2859,8 @@ TEST_F(LibYUVConvertTest, TestI400LargeSize) {
free_aligned_buffer_page_end(dest_argb); free_aligned_buffer_page_end(dest_argb);
free_aligned_buffer_page_end(orig_i400); free_aligned_buffer_page_end(orig_i400);
} }
#endif // defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) #endif // !defined(DISABLE_SLOW_TESTS) && \
// (defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__))
#endif // !defined(LEAN_TESTS) #endif // !defined(LEAN_TESTS)

View File

@ -8,15 +8,31 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
// For hybrid detect.
#if defined(__linux__) && !defined(_GNU_SOURCE) && \
(defined(__i386__) || defined(__x86_64__))
#define _GNU_SOURCE
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef __linux__ #ifdef __linux__
#include <ctype.h> #include <ctype.h>
#include <pthread.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <unistd.h> // for sysconf #include <unistd.h> // for sysconf
#include <sched.h> // For hybrid detect CPU_ZERO()
#endif #endif
// For hybrid detect
#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || \
defined(_M_X64)
#include <stdbool.h>
#endif // defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || \
// defined(_M_X64)
#if defined(_WIN32) #if defined(_WIN32)
#include <windows.h> // for GetSystemInfo #include <windows.h> // for GetSystemInfo
#endif #endif
@ -26,12 +42,122 @@
#include "libyuv/cpu_id.h" #include "libyuv/cpu_id.h"
#ifdef __cplusplus #if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || \
using namespace libyuv; defined(_M_X64)
#endif // Start of Intel Hybrid Detect
#ifdef __linux__ // test Intel and AMD cpuid flags for hybrid cpu
static void KernelVersion(int* version) { void isHybridCPU(bool* isaHybrid) {
int cpu_info[4];
// Check EDX bit 15 for hybrid design indication
CpuId(7, 0, &cpu_info[0]);
int hybrid = (cpu_info[3] >> 15) & 1;
if (hybrid) {
*isaHybrid = true;
} else {
*isaHybrid = false;
}
}
// tests Intel and AMD cpuid flags for performance core
// 0x40 = performance core, 0x20 = efficient core
bool isPerformanceCore(void) {
int cpu_info[4];
// Check EDX bit 15 for hybrid design indication
CpuId(0x1A, 0, &cpu_info[0]);
// core type from eax 24-31
int core_type = (cpu_info[0] >> 24) & 0xFF;
bool isaPCore = core_type != 0x20;
return isaPCore;
}
// TODO(fbarchard): Use common function to query Nth core
#if defined(__linux__)
void* core_thread(void* arg) {
int core_id = *(int*)arg;
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(core_id, &cpuset);
pthread_t thread = pthread_self();
bool runningCoreThread;
if (pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset) == 0) {
runningCoreThread = true;
} else {
runningCoreThread = false;
}
// confirm affinity
CPU_ZERO(&cpuset);
pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
printf("thread running on cpu: ");
for (int i = 0; i < CPU_SETSIZE; i++) {
if (CPU_ISSET(i, &cpuset)) {
printf("%d ", i);
if (runningCoreThread) {
const bool isaPerformanceCore = isPerformanceCore();
if (isaPerformanceCore) {
printf("Core[%d] - Performance\n", i);
} else {
printf("Core[%d] - Efficient\n", i);
}
}
}
}
return NULL;
}
#endif // defined(__linux__)
// Detect cpuid for Nth core
void detectCoreType(int num_cpus) {
#if defined(_WIN32)
for (int i = 0; i < num_cpus; i++) {
HANDLE hThread = NULL;
DWORD_PTR prevThreadPtr = 0;
DWORD_PTR affinityMask = 0;
hThread = GetCurrentThread();
affinityMask = 1ULL << i; // Select core (0-based index)
prevThreadPtr = SetThreadAffinityMask(hThread, affinityMask);
if (prevThreadPtr != 0) {
const bool isaPerformanceCore = isPerformanceCore();
if (isaPerformanceCore) {
printf("Core[%d] - Performance\n", i);
} else {
printf("Core[%d] - Efficient\n", i);
}
} else {
printf("Core[%d] - Error setting affinity\n", i);
}
}
#elif defined(__linux__)
pthread_t thread_id;
int core_id;
for (int i = 0; i < num_cpus; i++) {
core_id = i;
if (pthread_create(&thread_id, NULL, core_thread, &core_id) != 0) {
printf("WARNING: Error creating thread %d\n", i);
fflush(stdout);
return;
}
if (pthread_join(thread_id, NULL) != 0) {
printf("WARNING: Error joining thread %d\n", i);
fflush(stdout);
return;
}
}
#endif
}
// End of Hybrid Detect
#endif // defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || \
// defined(_M_X64)
#if defined(__linux__)
void KernelVersion(int version[2]) {
struct utsname buffer; struct utsname buffer;
int i = 0; int i = 0;
@ -45,12 +171,11 @@ static void KernelVersion(int* version) {
} }
} }
} }
#endif #endif // defined(__linux__)
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
(void)argc; (void)argc;
(void)argv; (void)argv;
#if defined(__linux__) #if defined(__linux__)
{ {
int kernelversion[2]; int kernelversion[2];
@ -179,6 +304,8 @@ int main(int argc, const char* argv[]) {
cpu_info[3] = 0; cpu_info[3] = 0;
printf("Cpu Vendor: %s\n", (char*)(&cpu_info[0])); printf("Cpu Vendor: %s\n", (char*)(&cpu_info[0]));
detectCoreType(num_cpus);
// CPU Family and Model // CPU Family and Model
// 3:0 - Stepping // 3:0 - Stepping
// 7:4 - Model // 7:4 - Model