X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Funaligned.h;h=154eb1338f6444461ef7ebc1e1b9b7c530f47b88;hb=003ce655b7116d18c86a74c50391e54990346931;hp=f1aab23adc814b8ac3dd7b29955228548e394405;hpb=6506f45c0818618e96deb858bbabdf2cc90eb2df;p=sliver-openvswitch.git diff --git a/lib/unaligned.h b/lib/unaligned.h index f1aab23ad..154eb1338 100644 --- a/lib/unaligned.h +++ b/lib/unaligned.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011 Nicira Networks. + * Copyright (c) 2010, 2011 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +20,12 @@ #include #include "byte-order.h" #include "openvswitch/types.h" +#include "type-props.h" +#include "util.h" /* Public API. */ static inline uint16_t get_unaligned_u16(const uint16_t *); static inline uint32_t get_unaligned_u32(const uint32_t *); -static inline uint64_t get_unaligned_u64(const uint64_t *); static inline void put_unaligned_u16(uint16_t *, uint16_t); static inline void put_unaligned_u32(uint32_t *, uint32_t); static inline void put_unaligned_u64(uint64_t *, uint64_t); @@ -62,7 +63,7 @@ put_unaligned_##ABBREV(TYPE *p, TYPE x) \ GCC_UNALIGNED_ACCESSORS(uint16_t, u16); GCC_UNALIGNED_ACCESSORS(uint32_t, u32); -GCC_UNALIGNED_ACCESSORS(uint64_t, u64); +GCC_UNALIGNED_ACCESSORS(uint64_t, u64__); /* Special case: see below. */ GCC_UNALIGNED_ACCESSORS(ovs_be16, be16); GCC_UNALIGNED_ACCESSORS(ovs_be32, be32); @@ -102,7 +103,7 @@ static inline void put_unaligned_u32(uint32_t *p_, uint32_t x_) p[3] = x; } -static inline uint64_t get_unaligned_u64(const uint64_t *p_) +static inline uint64_t get_unaligned_u64__(const uint64_t *p_) { const uint8_t *p = (const uint8_t *) p_; return ntohll(((uint64_t) p[0] << 56) @@ -115,7 +116,7 @@ static inline uint64_t get_unaligned_u64(const uint64_t *p_) | p[7]); } -static inline void put_unaligned_u64(uint64_t *p_, uint64_t x_) +static inline void put_unaligned_u64__(uint64_t *p_, uint64_t x_) { uint8_t *p = (uint8_t *) p_; uint64_t x = ntohll(x_); @@ -140,31 +141,102 @@ static inline void put_unaligned_u64(uint64_t *p_, uint64_t x_) #define put_unaligned_be32 put_unaligned_u32 #define put_unaligned_be64 put_unaligned_u64 #endif + +/* uint64_t get_unaligned_u64(uint64_t *p); + * + * Returns the value of the possibly misaligned uint64_t at 'p'. 'p' may + * actually be any type that points to a 64-bit integer. That is, on Unix-like + * 32-bit ABIs, it may point to an "unsigned long long int", and on Unix-like + * 64-bit ABIs, it may point to an "unsigned long int" or an "unsigned long + * long int". + * + * This is special-cased because on some Linux targets, the kernel __u64 is + * unsigned long long int and the userspace uint64_t is unsigned long int, so + * that any single function prototype would fail to accept one or the other. + * + * Below, "sizeof (*(P) % 1)" verifies that *P has an integer type, since + * operands to % must be integers. + */ +#define get_unaligned_u64(P) \ + (BUILD_ASSERT(sizeof *(P) == 8), \ + BUILD_ASSERT_GCCONLY(!TYPE_IS_SIGNED(typeof(*(P)))), \ + (void) sizeof (*(P) % 1), \ + get_unaligned_u64__((const uint64_t *) (P))) + +/* Stores 'x' at possibly misaligned address 'p'. + * + * put_unaligned_u64() could be overloaded in the same way as + * get_unaligned_u64(), but so far it has not proven necessary. + */ +static inline void +put_unaligned_u64(uint64_t *p, uint64_t x) +{ + put_unaligned_u64__(p, x); +} +/* Returns the value in 'x'. */ +static inline uint32_t +get_16aligned_u32(const ovs_16aligned_u32 *x) +{ + return ((uint32_t) x->hi << 16) | x->lo; +} + +/* Stores 'value' in 'x'. */ +static inline void +put_16aligned_u32(ovs_16aligned_u32 *x, uint32_t value) +{ + x->hi = value >> 16; + x->lo = value; +} + /* Returns the value in 'x'. */ static inline uint64_t get_32aligned_u64(const ovs_32aligned_u64 *x) { - return ((uint64_t) x->hi << 32) | x->lo; + return ((uint64_t) x->hi << 32) | x->lo; } /* Stores 'value' in 'x'. */ static inline void put_32aligned_u64(ovs_32aligned_u64 *x, uint64_t value) { - x->hi = value >> 32; - x->lo = value; + x->hi = value >> 32; + x->lo = value; } #ifndef __CHECKER__ +/* Returns the value of 'x'. */ +static inline ovs_be32 +get_16aligned_be32(const ovs_16aligned_be32 *x) +{ +#ifdef WORDS_BIGENDIAN + return ((ovs_be32) x->hi << 16) | x->lo; +#else + return ((ovs_be32) x->lo << 16) | x->hi; +#endif +} + +/* Stores network byte order 'value' into 'x'. */ +static inline void +put_16aligned_be32(ovs_16aligned_be32 *x, ovs_be32 value) +{ +#if WORDS_BIGENDIAN + x->hi = value >> 16; + x->lo = value; +#else + x->hi = value; + x->lo = value >> 16; +#endif +} + /* Returns the value of 'x'. */ static inline ovs_be64 get_32aligned_be64(const ovs_32aligned_be64 *x) { #ifdef WORDS_BIGENDIAN - return ((ovs_be64) x->hi << 32) | x->lo; + return ((ovs_be64) x->hi << 32) | x->lo; #else - return ((ovs_be64) x->lo << 32) | x->hi; + return ((ovs_be64) x->lo << 32) | x->hi; #endif } @@ -173,8 +245,8 @@ static inline void put_32aligned_be64(ovs_32aligned_be64 *x, ovs_be64 value) { #if WORDS_BIGENDIAN - x->hi = value >> 32; - x->lo = value; + x->hi = value >> 32; + x->lo = value; #else x->hi = value; x->lo = value >> 32; @@ -183,6 +255,8 @@ put_32aligned_be64(ovs_32aligned_be64 *x, ovs_be64 value) #else /* __CHECKER__ */ /* Making sparse happy with these functions also makes them unreadable, so * don't bother to show it their implementations. */ +ovs_be32 get_16aligned_be32(const ovs_16aligned_be32 *); +void put_16aligned_be32(ovs_16aligned_be32 *, ovs_be32); ovs_be64 get_32aligned_be64(const ovs_32aligned_be64 *); void put_32aligned_be64(ovs_32aligned_be64 *, ovs_be64); #endif