MINOR: tools: extend the pointer hashing code to ease manipulations

We'll need to further extend the pointer hashing code to pass extra
parameters and to retrieve the dropped bits, so let's first split the
part that hashes the pointer from the part that reduces the hash to
the desired size.
This commit is contained in:
Willy Tarreau 2026-03-11 16:20:23 +01:00
parent 01457979b6
commit 825e5611ba

View file

@ -1324,6 +1324,50 @@ static inline uint statistical_prng_range(uint range)
return mul32hi(statistical_prng(), range ? range - 1 : 0);
}
/* The functions below are used to hash one or two pointers together and reduce
* the result to fit into a given number of bits. The first part is made of a
* multiplication (and possibly an addition) by one or two prime numbers giving
* a 64-bit number whose center bits are the most distributed, and the second
* part will reuse this value and return a mix of the most variable bits that
* fits in the requested size. The most convenient approach is to directly
* call ptr_hash() / ptr2_hash(), though for some specific use cases where a
* second value could be useful, one may prefer to call the lower level
* operations instead.
*/
/* reduce a 64-bit pointer hash to <bits> bits */
static forceinline uint _ptr_hash_reduce(unsigned long long x, const int bits)
{
if (!bits)
return 0;
if (sizeof(long) == 4)
x ^= x >> 32;
else
x >>= 31 - (bits + 1) / 2;
return x & (~0U >> (-bits & 31));
}
/* single-pointer version, low-level, use ptr_hash() instead */
static forceinline ullong _ptr_hash(const void *p)
{
unsigned long long x = (unsigned long)p;
x *= 0xacd1be85U;
return x;
}
/* two-pointer version, low-level, use ptr2_hash() instead */
static forceinline ullong _ptr2_hash(const void *p1, const void *p2)
{
unsigned long long x = (unsigned long)p1;
unsigned long long y = (unsigned long)p2;
x *= 0xacd1be85U;
y *= 0x9d28e4e9U;
return x ^ y;
}
/* returns a hash on <bits> bits of pointer <p> that is suitable for being used
* to compute statistic buckets, in that it's fast and reasonably distributed
* thanks to mixing the bits via a multiplication by a prime number and using
@ -1337,17 +1381,7 @@ static inline uint statistical_prng_range(uint range)
*/
static forceinline uint ptr_hash(const void *p, const int bits)
{
unsigned long long x = (unsigned long)p;
if (!bits)
return 0;
x *= 0xacd1be85U;
if (sizeof(long) == 4)
x ^= x >> 32;
else
x >>= 31 - (bits + 1) / 2;
return x & (~0U >> (-bits & 31));
return _ptr_hash_reduce(_ptr_hash(p), bits);
}
/* Same as above but works on two pointers. It will return the same values
@ -1355,20 +1389,7 @@ static forceinline uint ptr_hash(const void *p, const int bits)
*/
static forceinline uint ptr2_hash(const void *p1, const void *p2, const int bits)
{
unsigned long long x = (unsigned long)p1;
unsigned long long y = (unsigned long)p2;
if (!bits)
return 0;
x *= 0xacd1be85U;
y *= 0x9d28e4e9U;
x ^= y;
if (sizeof(long) == 4)
x ^= x >> 32;
else
x >>= 33 - bits / 2;
return x & (~0U >> (-bits & 31));
return _ptr_hash_reduce(_ptr2_hash(p1, p2), bits);
}