From 8edd2286fdf9df2b9da806bda7ed262492f95921 Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Wed, 24 May 2017 15:00:24 -0700 Subject: [PATCH] MaskCpuFlags return cpuinfo so InitCpuFlags can call it Reduce number of atomic references to cpu_info by making InitCpuFlags call MaskCpuFlags and return the same value. BUG=libyuv:641 TEST=libyuv_unittests pass Change-Id: I5dfff8f7a10671bc8ef3ec0ed6f302791e752faa Reviewed-on: https://chromium-review.googlesource.com/514145 Commit-Queue: Frank Barchard Reviewed-by: Cheng Wang --- include/libyuv/cpu_id.h | 17 ++++++++++------- source/cpu_id.cc | 25 ++++++++++++------------- unit_test/cpu_thread_test.cc | 7 +++++-- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/include/libyuv/cpu_id.h b/include/libyuv/cpu_id.h index 77471fda5..a362052d7 100644 --- a/include/libyuv/cpu_id.h +++ b/include/libyuv/cpu_id.h @@ -46,17 +46,14 @@ static const int kCpuHasMIPS = 0x10000; static const int kCpuHasDSPR2 = 0x20000; static const int kCpuHasMSA = 0x40000; -// Internal function used to auto-init. +// Optional init function. TestCpuFlag does an auto-init. +// Returns cpu_info flags. LIBYUV_API int InitCpuFlags(void); -// Internal function for parsing /proc/cpuinfo. -LIBYUV_API -int ArmCpuCaps(const char* cpuinfo_name); - // Detect CPU has SSE2 etc. // Test_flag parameter should be one of kCpuHas constants above. -// returns non-zero if instruction set is detected +// Returns non-zero if instruction set is detected static __inline int TestCpuFlag(int test_flag) { LIBYUV_API extern int cpu_info_; #ifdef __ATOMIC_RELAXED @@ -67,12 +64,18 @@ static __inline int TestCpuFlag(int test_flag) { return (!cpu_info ? InitCpuFlags() : cpu_info) & test_flag; } +// Internal function for parsing /proc/cpuinfo. +LIBYUV_API +int ArmCpuCaps(const char* cpuinfo_name); + // For testing, allow CPU flags to be disabled. // ie MaskCpuFlags(~kCpuHasSSSE3) to disable SSSE3. // MaskCpuFlags(-1) to enable all cpu specific optimizations. // MaskCpuFlags(1) to disable all cpu specific optimizations. +// MaskCpuFlags(0) to reset state so next call will auto init. +// Returns cpu_info flags. LIBYUV_API -void MaskCpuFlags(int enable_flags); +int MaskCpuFlags(int enable_flags); // Low level cpuid for X86. Returns zeros on other CPUs. // eax is the info type that you want. diff --git a/source/cpu_id.cc b/source/cpu_id.cc index 044039675..b3eef701d 100644 --- a/source/cpu_id.cc +++ b/source/cpu_id.cc @@ -46,6 +46,7 @@ extern "C" { // cpu_info_ variable for SIMD instruction sets detected. LIBYUV_API int cpu_info_ = 0; +// TODO(fbarchard): Consider using int for cpuid so casting is not needed. // Low level cpuid for X86. #if (defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \ defined(__x86_64__)) && \ @@ -55,7 +56,7 @@ void CpuId(uint32 info_eax, uint32 info_ecx, uint32* cpu_info) { #if defined(_MSC_VER) // Visual C version uses intrinsic or inline x86 assembly. #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219) - __cpuidex((int*)(cpu_info), info_eax, info_ecx); + __cpuidex((int*)(cpu_info), info_eax, info_ecx); // NOLINT #elif defined(_M_IX86) __asm { mov eax, info_eax @@ -69,7 +70,7 @@ void CpuId(uint32 info_eax, uint32 info_ecx, uint32* cpu_info) { } #else // Visual C but not x86 if (info_ecx == 0) { - __cpuid((int*)(cpu_info), info_eax); + __cpuid((int*)(cpu_info), info_eax); // NOLINT } else { cpu_info[3] = cpu_info[2] = cpu_info[1] = cpu_info[0] = 0u; } @@ -122,8 +123,9 @@ void CpuId(uint32 eax, uint32 ecx, uint32* cpu_info) { // X86 CPUs have xgetbv to detect OS saves high parts of ymm registers. int GetXCR0() { uint32 xcr0 = 0u; +// VS2010 SP1 required #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219) - xcr0 = (uint32)(_xgetbv(0)); // VS2010 SP1 required. + xcr0 = (uint32)(_xgetbv(0)); // NOLINT #elif defined(__i386__) || defined(__x86_64__) asm(".byte 0x0f, 0x01, 0xd0" : "=a"(xcr0) : "c"(0) : "%edx"); #endif // defined(__i386__) || defined(__x86_64__) @@ -170,7 +172,7 @@ LIBYUV_API SAFEBUFFERS int ArmCpuCaps(const char* cpuinfo_name) { LIBYUV_API SAFEBUFFERS int MipsCpuCaps(const char* cpuinfo_name, const char ase[]) { char cpuinfo_line[512]; - int len = (int)strlen(ase); + int len = (int)strlen(ase); // NOLINT FILE* f = fopen(cpuinfo_name, "r"); if (!f) { // ase enabled if /proc/cpuinfo is unavailable. @@ -325,22 +327,19 @@ static SAFEBUFFERS int GetCpuFlags(void) { // Note that use of this function is not thread safe. LIBYUV_API -void MaskCpuFlags(int enable_flags) { +int MaskCpuFlags(int enable_flags) { + int cpu_info = GetCpuFlags() & enable_flags; #ifdef __ATOMIC_RELAXED - __atomic_store_n(&cpu_info_, GetCpuFlags() & enable_flags, __ATOMIC_RELAXED); + __atomic_store_n(&cpu_info_, cpu_info, __ATOMIC_RELAXED); #else - cpu_info_ = GetCpuFlags() & enable_flags; + cpu_info_ = cpu_info; #endif + return cpu_info; } LIBYUV_API int InitCpuFlags(void) { - MaskCpuFlags(-1); -#ifdef __ATOMIC_RELAXED - return __atomic_load_n(&cpu_info_, __ATOMIC_RELAXED); -#else - return cpu_info_; -#endif + return MaskCpuFlags(-1); } #ifdef __cplusplus diff --git a/unit_test/cpu_thread_test.cc b/unit_test/cpu_thread_test.cc index 185e36348..59061b98e 100644 --- a/unit_test/cpu_thread_test.cc +++ b/unit_test/cpu_thread_test.cc @@ -12,8 +12,11 @@ #include "libyuv/cpu_id.h" -// TODO(fbarchard): Port to other platforms -#if defined(__linux__) +#if defined(__clang__) +#if __has_include() +#define LIBYUV_HAVE_PTHREAD 1 +#endif +#elif defined(__linux__) #define LIBYUV_HAVE_PTHREAD 1 #endif