]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common: autoselect crc32c based on cpu features 393/head
authorSage Weil <sage@inktank.com>
Wed, 3 Jul 2013 19:20:45 +0000 (12:20 -0700)
committerSage Weil <sage@inktank.com>
Wed, 3 Jul 2013 19:20:51 +0000 (12:20 -0700)
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 <sage@inktank.com>
src/Makefile.am
src/common/crc32c-intel.c
src/common/sctp_crc32.c
src/include/crc32c.h

index 7b82e9d23e4e3b76a11becfdb3c91dc25893406e..c1a7e8020ef3d2b1e81b4bae3105a4b49df12baf 100644 (file)
@@ -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 \
index c1fded99fddb55887fe54652aba627bbcec0bf96..4c3456466637d7ec1c48af70f15ac56ad22f5d11 100644 (file)
@@ -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;
 }
index 1385834fdff308d61b594e80dfb47dbae3509233..b11bb48dd87ff2bf04f9090ec76261b65eaece8c 100644 (file)
@@ -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);
 }
index e3cf8ff27046a94b79ea11021cf47ccd7a0b876b..3fd209efb02b301b2aed6760aac6e2e292c840cc 100644 (file)
@@ -5,7 +5,18 @@
 extern "C" {
 #endif
 
-uint32_t ceph_crc32c_le(uint32_t crc, unsigned char const *data, unsigned length);
+#include <string.h>
+
+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
 }