diff options
author | David Wragg <david@rabbitmq.com> | 2011-08-17 16:12:28 +0100 |
---|---|---|
committer | David Wragg <david@rabbitmq.com> | 2011-08-17 16:12:28 +0100 |
commit | fed4aebe364bb832de098c45473d1304644cb757 (patch) | |
tree | 2bafe6810078295f7b1ec8d518803ebd3ab1b42b | |
parent | a1116487c0804c2155d3ee0e4217c5721a17d65f (diff) | |
download | rabbitmq-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.ac | 2 | ||||
-rw-r--r-- | 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) |