From d7826823c05ad82f710da74c3d5d402898187888 Mon Sep 17 00:00:00 2001 From: Salvatore Sanfilippo Date: Thu, 23 Feb 2017 22:38:44 +0800 Subject: [PATCH 1/2] Fix BITPOS unaligned memory access. --- src/bitops.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/bitops.c b/src/bitops.c index 7ab72633..d5b96ce1 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -104,6 +104,7 @@ long redisBitpos(void *s, unsigned long count, int bit) { unsigned long skipval, word = 0, one; long pos = 0; /* Position of bit, to return to the caller. */ unsigned long j; + int found; /* Process whole words first, seeking for first word that is not * all ones or all zeros respectively if we are lookig for zeros @@ -117,21 +118,27 @@ long redisBitpos(void *s, unsigned long count, int bit) { /* Skip initial bits not aligned to sizeof(unsigned long) byte by byte. */ skipval = bit ? 0 : UCHAR_MAX; c = (unsigned char*) s; + found = 0; while((unsigned long)c & (sizeof(*l)-1) && count) { - if (*c != skipval) break; + if (*c != skipval) { + found = 1; + break; + } c++; count--; pos += 8; } /* Skip bits with full word step. */ - skipval = bit ? 0 : ULONG_MAX; l = (unsigned long*) c; - while (count >= sizeof(*l)) { - if (*l != skipval) break; - l++; - count -= sizeof(*l); - pos += sizeof(*l)*8; + if (!found) { + skipval = bit ? 0 : ULONG_MAX; + while (count >= sizeof(*l)) { + if (*l != skipval) break; + l++; + count -= sizeof(*l); + pos += sizeof(*l)*8; + } } /* Load bytes into "word" considering the first byte as the most significant From b3391fd853d55b3da04ede024adcc6bf017c78f1 Mon Sep 17 00:00:00 2001 From: Salvatore Sanfilippo Date: Thu, 23 Feb 2017 22:39:44 +0800 Subject: [PATCH 2/2] Use ARM unaligned accesses ifdefs for SPARC as well. --- src/bitops.c | 2 +- src/config.h | 9 +++++++++ src/hyperloglog.c | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/bitops.c b/src/bitops.c index d5b96ce1..43450fca 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -665,7 +665,7 @@ void bitopCommand(client *c) { * result in GCC compiling the code using multiple-words load/store * operations that are not supported even in ARM >= v6. */ j = 0; - #ifndef __arm__ + #ifndef USE_ALIGNED_ACCESS if (minlen >= sizeof(unsigned long)*4 && numkeys <= 16) { unsigned long *lp[16]; unsigned long *lres = (unsigned long*) res; diff --git a/src/config.h b/src/config.h index 1005dcc2..c23f1c78 100644 --- a/src/config.h +++ b/src/config.h @@ -215,4 +215,13 @@ void setproctitle(const char *fmt, ...); #define __arm64__ #endif +/* Make sure we can test for SPARC just checking for __sparc__. */ +#if defined(__sparc) && !defined(__sparc__) +#define __sparc__ +#endif + +#if defined(__sparc__) || defined(__arm__) +#define USE_ALIGNED_ACCESS +#endif + #endif diff --git a/src/hyperloglog.c b/src/hyperloglog.c index b8a63a73..49516f82 100644 --- a/src/hyperloglog.c +++ b/src/hyperloglog.c @@ -401,7 +401,7 @@ uint64_t MurmurHash64A (const void * key, int len, unsigned int seed) { uint64_t k; #if (BYTE_ORDER == LITTLE_ENDIAN) - #if defined(__arm__) && !defined(__arm64__) + #ifdef USE_ALIGNED_ACCESS memcpy(&k,data,sizeof(uint64_t)); #else k = *((uint64_t*)data);