From fed4aebe364bb832de098c45473d1304644cb757 Mon Sep 17 00:00:00 2001 From: David Wragg Date: Wed, 17 Aug 2011 16:12:28 +0100 Subject: 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. --- configure.ac | 2 ++ librabbitmq/amqp_private.h | 34 +++++++++++++++++++++++++++------- 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) -- cgit v1.2.1 From 9ad5ead9668d078d6c5c2ab9a24a0d31d60f79d0 Mon Sep 17 00:00:00 2001 From: David Wragg Date: Thu, 18 Aug 2011 17:17:51 +0100 Subject: Comment magical memcpys --- librabbitmq/amqp_private.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/librabbitmq/amqp_private.h b/librabbitmq/amqp_private.h index dff12db..6c15383 100644 --- a/librabbitmq/amqp_private.h +++ b/librabbitmq/amqp_private.h @@ -146,12 +146,16 @@ static inline void *amqp_offset(void *data, size_t offset) static inline void amqp_e##bits(void *data, size_t offset, \ uint##bits##_t val) \ { \ - uint##bits##_t res = htonx(val); \ + /* The AMQP data might be unaligned. So we encode and then copy the \ + result into place. */ \ + 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) \ -{ \ +{ \ + /* The AMQP data might be unaligned. So we copy the source value \ + into a variable and then decode it. */ \ uint##bits##_t val; \ memcpy(&val, amqp_offset(data, offset), bits/8); \ return ntohx(val); \ -- cgit v1.2.1