diff options
author | Jakub Bogusz <qboosh@pld-linux.org> | 2020-07-10 01:57:23 +0300 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2020-07-10 05:38:55 +0300 |
commit | b2f9f1535bb93ee5fa2ea30ac1c26fa0d676154c (patch) | |
tree | 2e875e49560069cea681049e70f0dc7ec38ca24c /tools | |
parent | f43cb0d672aa8eb09bfdb779de5900c040487d1d (diff) | |
download | linux-b2f9f1535bb93ee5fa2ea30ac1c26fa0d676154c.tar.xz |
libbpf: Fix libbpf hashmap on (I)LP32 architectures
On ILP32, 64-bit result was shifted by value calculated for 32-bit long type
and returned value was much outside hashmap capacity.
As advised by Andrii Nakryiko, this patch uses different hashing variant for
architectures with size_t shorter than long long.
Fixes: e3b924224028 ("libbpf: add resizable non-thread safe internal hashmap")
Signed-off-by: Jakub Bogusz <qboosh@pld-linux.org>
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200709225723.1069937-1-andriin@fb.com
Diffstat (limited to 'tools')
-rw-r--r-- | tools/lib/bpf/hashmap.h | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h index df59fd4fc95b..e0af36b0e5d8 100644 --- a/tools/lib/bpf/hashmap.h +++ b/tools/lib/bpf/hashmap.h @@ -11,14 +11,18 @@ #include <stdbool.h> #include <stddef.h> #include <limits.h> -#ifndef __WORDSIZE -#define __WORDSIZE (__SIZEOF_LONG__ * 8) -#endif static inline size_t hash_bits(size_t h, int bits) { /* shuffle bits and return requested number of upper bits */ - return (h * 11400714819323198485llu) >> (__WORDSIZE - bits); +#if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__) + /* LP64 case */ + return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits); +#elif (__SIZEOF_SIZE_T__ <= __SIZEOF_LONG__) + return (h * 2654435769lu) >> (__SIZEOF_LONG__ * 8 - bits); +#else +# error "Unsupported size_t size" +#endif } typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx); |