diff options
| author | Michael Biebl <biebl@debian.org> | 2018-05-11 22:08:45 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-05-11 22:08:45 +0200 |
| commit | ee9c73a923909e23a649407be77e25235d769e25 (patch) | |
| tree | e21c923621fa278e737da693df9eb60ea31a6067 /shared/nm-utils/nm-hash-utils.c | |
| parent | f60117b41d5433be1b4a96d82cd11d0c3dce9b63 (diff) | |
New upstream version 1.10.8 upstream/1.10.8
Diffstat (limited to 'shared/nm-utils/nm-hash-utils.c')
| -rw-r--r-- | shared/nm-utils/nm-hash-utils.c | 134 |
1 files changed, 34 insertions, 100 deletions
diff --git a/shared/nm-utils/nm-hash-utils.c b/shared/nm-utils/nm-hash-utils.c index 8d8c21ce..c563140e 100644 --- a/shared/nm-utils/nm-hash-utils.c +++ b/shared/nm-utils/nm-hash-utils.c @@ -28,8 +28,6 @@ #include "nm-shared-utils.h" #include "nm-random-utils.h" -#include "siphash24.c" - /*****************************************************************************/ #define HASH_KEY_SIZE 16u @@ -37,77 +35,33 @@ G_STATIC_ASSERT (sizeof (guint) * HASH_KEY_SIZE_GUINT >= HASH_KEY_SIZE); -static const guint8 *volatile global_seed = NULL; - static const guint8 * -_get_hash_key_init (void) +_get_hash_key (void) { - /* the returned hash is aligned to guin64, hence, it is safe - * to use it as guint* or guint64* pointer. */ - static union { - guint8 v8[HASH_KEY_SIZE]; - } g_arr _nm_alignas (guint64); - static gsize g_lock; + static const guint8 *volatile global_seed = NULL; const guint8 *g; - struct siphash siph_state; - uint64_t h; - guint *p; g = global_seed; - if (G_LIKELY (g != NULL)) { - nm_assert (g == g_arr.v8); - return g; - } - - if (g_once_init_enter (&g_lock)) { - - nm_utils_random_bytes (g_arr.v8, sizeof (g_arr.v8)); - - /* use siphash() of the key-size, to mangle the first guint. Otherwise, - * the first guint has only the entropy that nm_utils_random_bytes() - * generated for the first 4 bytes and relies on a good random generator. */ - siphash24_init (&siph_state, g_arr.v8); - siphash24_compress (g_arr.v8, sizeof (g_arr.v8), &siph_state); - h = siphash24_finalize (&siph_state); - p = (guint *) g_arr.v8; - if (sizeof (guint) < sizeof (h)) - *p = *p ^ ((guint) (h & 0xFFFFFFFFu)) ^ ((guint) (h >> 32)); - else - *p = *p ^ ((guint) (h & 0xFFFFFFFFu)); - - g_atomic_pointer_compare_and_exchange (&global_seed, NULL, g_arr.v8); - g_once_init_leave (&g_lock, 1); + if (G_UNLIKELY (g == NULL)) { + /* the returned hash is aligned to guin64, hence, it is save + * to use it as guint* or guint64* pointer. */ + static union { + guint8 v8[HASH_KEY_SIZE]; + } g_arr _nm_alignas (guint64); + static gsize g_lock; + + if (g_once_init_enter (&g_lock)) { + nm_utils_random_bytes (g_arr.v8, sizeof (g_arr.v8)); + g_atomic_pointer_compare_and_exchange (&global_seed, NULL, g_arr.v8); + g = g_arr.v8; + g_once_init_leave (&g_lock, 1); + } else { + g = global_seed; + nm_assert (g); + } } - nm_assert (global_seed == g_arr.v8); - return g_arr.v8; -} - -#define _get_hash_key() \ - ({ \ - const guint8 *_g; \ - \ - _g = global_seed; \ - if (G_UNLIKELY (_g == NULL)) \ - _g = _get_hash_key_init (); \ - _g; \ - }) - -guint -nm_hash_static (guint static_seed) -{ - /* note that we only xor the static_seed with the key. - * We don't use siphash24(), which would mix the bits better. - * Note that this doesn't matter, because static_seed is not - * supposed to be a value that you are hashing (for that, use - * full siphash24()). - * Instead, different callers may set a different static_seed - * so that nm_hash_str(NULL) != nm_hash_ptr(NULL). - * - * Also, ensure that we don't return zero. - */ - return ((*((const guint *) _get_hash_key ())) ^ static_seed) - ?: static_seed ?: 3679500967u; + return g; } void @@ -129,10 +83,11 @@ nm_hash_str (const char *str) { NMHashState h; - if (!str) - return nm_hash_static (1867854211u); - nm_hash_init (&h, 1867854211u); - nm_hash_update_str (&h, str); + if (str) { + nm_hash_init (&h, 1867854211u); + nm_hash_update_str (&h, str); + } else + nm_hash_init (&h, 842995561u); return nm_hash_complete (&h); } @@ -145,13 +100,16 @@ nm_str_hash (gconstpointer str) guint nm_hash_ptr (gconstpointer ptr) { - NMHashState h; + guint h; - if (!ptr) - return nm_hash_static (2907677551u); - nm_hash_init (&h, 2907677551u); - nm_hash_update (&h, &ptr, sizeof (ptr)); - return nm_hash_complete (&h); + h = ((const guint *) _get_hash_key ())[0]; + + if (sizeof (ptr) <= sizeof (guint)) + h = h ^ ((guint) ((uintptr_t) ptr)); + else + h = h ^ ((guint) (((guint64) (uintptr_t) ptr) >> 32)) ^ ((guint) ((uintptr_t) ptr)); + + return h ?: 2907677551u; } guint @@ -159,27 +117,3 @@ nm_direct_hash (gconstpointer ptr) { return nm_hash_ptr (ptr); } - -/*****************************************************************************/ - -guint -nm_pstr_hash (gconstpointer p) -{ - const char *const*s = p; - - if (!s) - return nm_hash_static (101061439u); - return nm_hash_str (*s); -} - -gboolean -nm_pstr_equal (gconstpointer a, gconstpointer b) -{ - const char *const*s1 = a; - const char *const*s2 = b; - - return (s1 == s2) - || ( s1 - && s2 - && nm_streq0 (*s1, *s2)); -} |