From 08dd35d9e3c18f669e9da9f91d8a83af644c2ab3 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 3 Jul 2013 12:20:45 -0700 Subject: [PATCH] common: autoselect crc32c based on cpu features If the CPu supposts SSE4.2, use the crc32c instructions. Use the magic incantation from who knows where to do this. __builtin_cpu_supports() is a nicer way to do it, but that is new in gcc 4.8. Avoid static globals; they are bad. Sadly that means we redetect the CPU feature on every call. I assume that is reasonably efficient... Signed-off-by: Sage Weil --- src/Makefile.am | 1 + src/common/crc32c-intel.c | 29 +++++++++-------------------- src/common/sctp_crc32.c | 2 +- src/include/crc32c.h | 13 ++++++++++++- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 7b82e9d23e4e3..c1a7e8020ef3d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1386,6 +1386,7 @@ libcommon_files = \ common/Finisher.cc \ common/environment.cc\ common/sctp_crc32.c\ + common/crc32c-intel.c\ common/assert.cc \ common/run_cmd.cc \ common/WorkQueue.cc \ diff --git a/src/common/crc32c-intel.c b/src/common/crc32c-intel.c index c1fded99fddb5..4c3456466637d 100644 --- a/src/common/crc32c-intel.c +++ b/src/common/crc32c-intel.c @@ -29,8 +29,6 @@ int crc32c_intel_available = 0; #define SCALE_F 4 #endif -static int crc32c_probed; - static uint32_t crc32c_intel_le_hw_byte(uint32_t crc, unsigned char const *data, unsigned length) { @@ -46,11 +44,7 @@ static uint32_t crc32c_intel_le_hw_byte(uint32_t crc, unsigned char const *data, return crc; } -/* - * * Steps through buffer one byte at at time, calculates reflected - * * crc using table. - * */ -uint32_t crc32c_intel(uint32_t crc, unsigned char const *data, unsigned length) +uint32_t ceph_crc32c_le_intel(uint32_t crc, unsigned char const *data, unsigned length) { unsigned int iquotient = length / SCALE_F; unsigned int iremainder = length % SCALE_F; @@ -76,6 +70,7 @@ uint32_t crc32c_intel(uint32_t crc, unsigned char const *data, unsigned length) return crc; } + static void do_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { @@ -92,20 +87,14 @@ static void do_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, : "eax", "ebx", "ecx", "edx"); } -void crc32c_intel_probe(void) +int ceph_have_crc32c_intel(void) { - if (!crc32c_probed) { - unsigned int eax, ebx, ecx, edx; + unsigned int eax, ebx, ecx, edx; - eax = 1; + eax = 1; - do_cpuid(&eax, &ebx, &ecx, &edx); - crc32c_intel_available = (ecx & (1 << 20)) != 0; - crc32c_probed = 1; - } -} - -uint32_t ceph_crc32c_le(uint32_t crc, unsigned char const *data, unsigned length) -{ - return crc32c_intel(crc, data, length); + do_cpuid(&eax, &ebx, &ecx, &edx); + if ((ecx & (1 << 20)) != 0) + return 1; + return 0; } diff --git a/src/common/sctp_crc32.c b/src/common/sctp_crc32.c index 1385834fdff30..b11bb48dd87ff 100644 --- a/src/common/sctp_crc32.c +++ b/src/common/sctp_crc32.c @@ -728,7 +728,7 @@ sctp_csum_finalize(uint32_t crc32c) } #endif -uint32_t ceph_crc32c_le(uint32_t crc, unsigned char const *data, unsigned length) +uint32_t ceph_crc32c_le_generic(uint32_t crc, unsigned char const *data, unsigned length) { return update_crc32(crc, data, length); } diff --git a/src/include/crc32c.h b/src/include/crc32c.h index e3cf8ff27046a..3fd209efb02b3 100644 --- a/src/include/crc32c.h +++ b/src/include/crc32c.h @@ -5,7 +5,18 @@ extern "C" { #endif -uint32_t ceph_crc32c_le(uint32_t crc, unsigned char const *data, unsigned length); +#include + +extern int ceph_have_crc32c_intel(void); +extern uint32_t ceph_crc32c_le_generic(uint32_t crc, unsigned char const *data, unsigned length); +extern uint32_t ceph_crc32c_le_intel(uint32_t crc, unsigned char const *data, unsigned length); + +static inline uint32_t ceph_crc32c_le(uint32_t crc, unsigned char const *data, unsigned length) { + if (ceph_have_crc32c_intel()) //__builtin_cpu_supports("sse4.2")) + return ceph_crc32c_le_intel(crc, data, length); + else + return ceph_crc32c_le_generic(crc, data, length); +} #ifdef __cplusplus } -- 2.39.5