MINOR: standard: provide htonll() and ntohll()
These are the 64-bit equivalent of htonl() and ntohl(). They're a bit tricky in order to avoid expensive operations. The principle consists in letting the compiler detect we're playing with a union and simplify most or all operations. The asm-optimized htonl() version involving bswap (x86) / rev (arm) / other is a single operation on little endian, or a NOP on big-endian. In both cases, this lets the compiler "see" that we're rebuilding a 64-bit word from two 32-bit quantities that fit into a 32-bit register. In big endian, the whole code is optimized out. In little endian, with a decent compiler, a few bswap and 2 shifts are left, which is the minimum acceptable.
This commit is contained in:
parent
763a5d85f7
commit
5b4dd683cb
|
@ -30,6 +30,7 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <common/chunk.h>
|
#include <common/chunk.h>
|
||||||
#include <common/config.h>
|
#include <common/config.h>
|
||||||
#include <eb32tree.h>
|
#include <eb32tree.h>
|
||||||
|
@ -992,6 +993,34 @@ static inline unsigned char utf8_return_length(unsigned char code)
|
||||||
return code & 0x0f;
|
return code & 0x0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Turns 64-bit value <a> from host byte order to network byte order.
|
||||||
|
* The principle consists in letting the compiler detect we're playing
|
||||||
|
* with a union and simplify most or all operations. The asm-optimized
|
||||||
|
* htonl() version involving bswap (x86) / rev (arm) / other is a single
|
||||||
|
* operation on little endian, or a NOP on big-endian. In both cases,
|
||||||
|
* this lets the compiler "see" that we're rebuilding a 64-bit word from
|
||||||
|
* two 32-bit quantities that fit into a 32-bit register. In big endian,
|
||||||
|
* the whole code is optimized out. In little endian, with a decent compiler,
|
||||||
|
* a few bswap and 2 shifts are left, which is the minimum acceptable.
|
||||||
|
*/
|
||||||
|
static inline unsigned long long htonll(unsigned long long a)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
unsigned int w1;
|
||||||
|
unsigned int w2;
|
||||||
|
} by32;
|
||||||
|
unsigned long long by64;
|
||||||
|
} w = { .by64 = a };
|
||||||
|
return ((unsigned long long)htonl(w.by32.w1) << 32) | htonl(w.by32.w2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Turns 64-bit value <a> from network byte order to host byte order. */
|
||||||
|
static inline unsigned long long ntohll(unsigned long long a)
|
||||||
|
{
|
||||||
|
return htonll(a);
|
||||||
|
}
|
||||||
|
|
||||||
/* returns a 64-bit a timestamp with the finest resolution available. The
|
/* returns a 64-bit a timestamp with the finest resolution available. The
|
||||||
* unit is intentionally not specified. It's mostly used to compare dates.
|
* unit is intentionally not specified. It's mostly used to compare dates.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue