summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Wragg <david@rabbitmq.com>2011-08-17 16:12:28 +0100
committerDavid Wragg <david@rabbitmq.com>2011-08-17 16:12:28 +0100
commitfed4aebe364bb832de098c45473d1304644cb757 (patch)
tree2bafe6810078295f7b1ec8d518803ebd3ab1b42b
parenta1116487c0804c2155d3ee0e4217c5721a17d65f (diff)
downloadrabbitmq-c-github-ask-fed4aebe364bb832de098c45473d1304644cb757.tar.gz
Don't rely on unaligned accesses or little-endianness
This uses memcpy to avoid the unaligned accesses. gcc on x86 seems to do a reasonable job of optimizing them away. gcc on ARM leaves some memcpy calls in the generated code. It might be better in terms of the code generated to use an approach based on packaged structs (that's wwhat the Linux kernel does). But that would depend on compiler-specific syntax.
-rw-r--r--configure.ac2
-rw-r--r--librabbitmq/amqp_private.h34
2 files changed, 29 insertions, 7 deletions
diff --git a/configure.ac b/configure.ac
index 2bf9433..e6aac32 100644
--- a/configure.ac
+++ b/configure.ac
@@ -45,6 +45,8 @@ AS_IF([test "x$GCC" = "xyes"], [CFLAGS="$CFLAGS -ansi -pedantic"])
AC_C_INLINE
CFLAGS="$orig_cflags"
+AC_C_BIGENDIAN
+
dnl Decide which API abstraction layer to use
PLATFORM_DIR=unix
if test "x$windows" = xyes ; then
diff --git a/librabbitmq/amqp_private.h b/librabbitmq/amqp_private.h
index c6c87e4..dff12db 100644
--- a/librabbitmq/amqp_private.h
+++ b/librabbitmq/amqp_private.h
@@ -138,19 +138,23 @@ static inline void *amqp_offset(void *data, size_t offset)
return (char *)data + offset;
}
-/* assuming a machine that supports unaligned accesses (for now) */
+/* This macro defines the encoding and decoding functions associated with a
+ simple type. */
#define DECLARE_CODEC_BASE_TYPE(bits, htonx, ntohx) \
\
static inline void amqp_e##bits(void *data, size_t offset, \
uint##bits##_t val) \
-{ \
- *(uint##bits##_t *)amqp_offset(data, offset) = htonx(val); \
+{ \
+ uint##bits##_t res = htonx(val); \
+ memcpy(amqp_offset(data, offset), &res, bits/8); \
} \
\
static inline uint##bits##_t amqp_d##bits(void *data, size_t offset) \
-{ \
- return ntohx(*(uint##bits##_t *)amqp_offset(data, offset)); \
+{ \
+ uint##bits##_t val; \
+ memcpy(&val, amqp_offset(data, offset), bits/8); \
+ return ntohx(val); \
} \
\
static inline int amqp_encode_##bits(amqp_bytes_t encoded, size_t *offset, \
@@ -174,7 +178,6 @@ static inline int amqp_decode_##bits(amqp_bytes_t encoded, size_t *offset, \
size_t o = *offset; \
if ((*offset = o + bits / 8) <= encoded.len) { \
*output = amqp_d##bits(encoded.bytes, o); \
- *output = ntohx(*(uint##bits##_t *)((char *)encoded.bytes + o)); \
return 1; \
} \
else { \
@@ -182,7 +185,7 @@ static inline int amqp_decode_##bits(amqp_bytes_t encoded, size_t *offset, \
} \
}
-/* assuming little endian (for now) */
+#ifndef WORDS_BIGENDIAN
#define DECLARE_XTOXLL(func) \
static inline uint64_t func##ll(uint64_t val) \
@@ -199,6 +202,23 @@ static inline uint64_t func##ll(uint64_t val) \
return u.whole; \
}
+#else
+
+#define DECLARE_XTOXLL(func) \
+static inline uint64_t func##ll(uint64_t val) \
+{ \
+ union { \
+ uint64_t whole; \
+ uint32_t halves[2]; \
+ } u; \
+ u.whole = val; \
+ u.halves[0] = func##l(u.halves[0]); \
+ u.halves[1] = func##l(u.halves[1]); \
+ return u.whole; \
+}
+
+#endif
+
DECLARE_XTOXLL(hton)
DECLARE_XTOXLL(ntoh)