From 6ce58897dabc45b1118c7db85883dfa736b6a8ce Mon Sep 17 00:00:00 2001 From: Nick Terrell <terrelln@fb.com> Date: Thu, 30 Mar 2017 12:11:19 -0700 Subject: [PATCH] Use <asm/unaligned.h> for unaligned memory access --- contrib/linux-kernel/lib/mem.h | 115 +++++++----------------------- contrib/linux-kernel/lib/xxhash.c | 35 +++------ 2 files changed, 33 insertions(+), 117 deletions(-) diff --git a/contrib/linux-kernel/lib/mem.h b/contrib/linux-kernel/lib/mem.h index 1b8098e72..6040aa5c7 100644 --- a/contrib/linux-kernel/lib/mem.h +++ b/contrib/linux-kernel/lib/mem.h @@ -13,6 +13,7 @@ /*-**************************************** * Dependencies ******************************************/ +#include <asm/unaligned.h> #include <linux/types.h> /* size_t, ptrdiff_t */ #include <linux/string.h> /* memcpy */ @@ -47,104 +48,62 @@ typedef uintptr_t uPtrDiff; MEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; } MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; } +#if defined(__LITTLE_ENDIAN) +# define MEM_LITTLE_ENDIAN 1 +#else +# define MEM_LITTLE_ENDIAN 0 +#endif + MEM_STATIC unsigned MEM_isLittleEndian(void) { - const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ - return one.c[0]; + return MEM_LITTLE_ENDIAN; } MEM_STATIC U16 MEM_read16(const void* memPtr) { - U16 val; memcpy(&val, memPtr, sizeof(val)); return val; + return get_unaligned((const U16*)memPtr); } MEM_STATIC U32 MEM_read32(const void* memPtr) { - U32 val; memcpy(&val, memPtr, sizeof(val)); return val; + return get_unaligned((const U32*)memPtr); } MEM_STATIC U64 MEM_read64(const void* memPtr) { - U64 val; memcpy(&val, memPtr, sizeof(val)); return val; + return get_unaligned((const U64*)memPtr); } MEM_STATIC size_t MEM_readST(const void* memPtr) { - size_t val; memcpy(&val, memPtr, sizeof(val)); return val; + return get_unaligned((const size_t*)memPtr); } MEM_STATIC void MEM_write16(void* memPtr, U16 value) { - memcpy(memPtr, &value, sizeof(value)); + put_unaligned(value, (U16*)memPtr); } MEM_STATIC void MEM_write32(void* memPtr, U32 value) { - memcpy(memPtr, &value, sizeof(value)); + put_unaligned(value, (U32*)memPtr); } MEM_STATIC void MEM_write64(void* memPtr, U64 value) { - memcpy(memPtr, &value, sizeof(value)); -} - -MEM_STATIC U32 MEM_swap32(U32 in) -{ -#if defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403) - return __builtin_bswap32(in); -#else - return ((in << 24) & 0xff000000 ) | - ((in << 8) & 0x00ff0000 ) | - ((in >> 8) & 0x0000ff00 ) | - ((in >> 24) & 0x000000ff ); -#endif -} - -MEM_STATIC U64 MEM_swap64(U64 in) -{ -#if defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403) - return __builtin_bswap64(in); -#else - return ((in << 56) & 0xff00000000000000ULL) | - ((in << 40) & 0x00ff000000000000ULL) | - ((in << 24) & 0x0000ff0000000000ULL) | - ((in << 8) & 0x000000ff00000000ULL) | - ((in >> 8) & 0x00000000ff000000ULL) | - ((in >> 24) & 0x0000000000ff0000ULL) | - ((in >> 40) & 0x000000000000ff00ULL) | - ((in >> 56) & 0x00000000000000ffULL); -#endif -} - -MEM_STATIC size_t MEM_swapST(size_t in) -{ - if (MEM_32bits()) - return (size_t)MEM_swap32((U32)in); - else - return (size_t)MEM_swap64((U64)in); + put_unaligned(value, (U64*)memPtr); } /*=== Little endian r/w ===*/ MEM_STATIC U16 MEM_readLE16(const void* memPtr) { - if (MEM_isLittleEndian()) - return MEM_read16(memPtr); - else { - const BYTE* p = (const BYTE*)memPtr; - return (U16)(p[0] + (p[1]<<8)); - } + return get_unaligned_le16(memPtr); } MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val) { - if (MEM_isLittleEndian()) { - MEM_write16(memPtr, val); - } else { - BYTE* p = (BYTE*)memPtr; - p[0] = (BYTE)val; - p[1] = (BYTE)(val>>8); - } + put_unaligned_le16(val, memPtr); } MEM_STATIC U32 MEM_readLE24(const void* memPtr) @@ -160,34 +119,22 @@ MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val) MEM_STATIC U32 MEM_readLE32(const void* memPtr) { - if (MEM_isLittleEndian()) - return MEM_read32(memPtr); - else - return MEM_swap32(MEM_read32(memPtr)); + return get_unaligned_le32(memPtr); } MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32) { - if (MEM_isLittleEndian()) - MEM_write32(memPtr, val32); - else - MEM_write32(memPtr, MEM_swap32(val32)); + put_unaligned_le32(val32, memPtr); } MEM_STATIC U64 MEM_readLE64(const void* memPtr) { - if (MEM_isLittleEndian()) - return MEM_read64(memPtr); - else - return MEM_swap64(MEM_read64(memPtr)); + return get_unaligned_le64(memPtr); } MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64) { - if (MEM_isLittleEndian()) - MEM_write64(memPtr, val64); - else - MEM_write64(memPtr, MEM_swap64(val64)); + put_unaligned_le64(val64, memPtr); } MEM_STATIC size_t MEM_readLEST(const void* memPtr) @@ -210,34 +157,22 @@ MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val) MEM_STATIC U32 MEM_readBE32(const void* memPtr) { - if (MEM_isLittleEndian()) - return MEM_swap32(MEM_read32(memPtr)); - else - return MEM_read32(memPtr); + return get_unaligned_be32(memPtr); } MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32) { - if (MEM_isLittleEndian()) - MEM_write32(memPtr, MEM_swap32(val32)); - else - MEM_write32(memPtr, val32); + put_unaligned_be32(val32, memPtr); } MEM_STATIC U64 MEM_readBE64(const void* memPtr) { - if (MEM_isLittleEndian()) - return MEM_swap64(MEM_read64(memPtr)); - else - return MEM_read64(memPtr); + return get_unaligned_be64(memPtr); } MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64) { - if (MEM_isLittleEndian()) - MEM_write64(memPtr, MEM_swap64(val64)); - else - MEM_write64(memPtr, val64); + put_unaligned_be64(val64, memPtr); } MEM_STATIC size_t MEM_readBEST(const void* memPtr) diff --git a/contrib/linux-kernel/lib/xxhash.c b/contrib/linux-kernel/lib/xxhash.c index dccdc65c9..1918836d7 100644 --- a/contrib/linux-kernel/lib/xxhash.c +++ b/contrib/linux-kernel/lib/xxhash.c @@ -103,16 +103,6 @@ static U64 XXH_read64(const void* memPtr) #define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) #define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r))) -static U32 XXH_swap32 (U32 x) -{ - return MEM_swap32(x); -} -static U64 XXH_swap64 (U64 x) -{ - return MEM_swap64(x); -} - - /* ************************************* * Architecture Macros ***************************************/ @@ -120,8 +110,7 @@ typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; /* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */ #ifndef XXH_CPU_LITTLE_ENDIAN - static const int g_one = 1; -# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&g_one)) +# define XXH_CPU_LITTLE_ENDIAN MEM_LITTLE_ENDIAN #endif @@ -130,12 +119,9 @@ typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; *****************************/ typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; -FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align) +FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess, XXH_alignment) { - if (align==XXH_unaligned) - return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); - else - return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr); + return MEM_readLE32(ptr); } FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian) @@ -145,15 +131,12 @@ FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian) static U32 XXH_readBE32(const void* ptr) { - return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); + return MEM_readBE32(ptr); } FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align) { - if (align==XXH_unaligned) - return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); - else - return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr); + return MEM_readLE64(ptr); } FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian) @@ -163,7 +146,7 @@ FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian) static U64 XXH_readBE64(const void* ptr) { - return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); + return MEM_readBE64(ptr); } @@ -729,15 +712,13 @@ XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in) XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); - memcpy(dst, &hash, sizeof(*dst)); + MEM_writeBE32(dst, hash); } XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); - memcpy(dst, &hash, sizeof(*dst)); + MEM_writeBE64(dst, hash); } XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) -- GitLab