88#include <stdlib.h>
99#include <string.h>
1010#include <sys/queue.h>
11+ #include <time.h>
12+
1113#ifdef WIN32
1214#include <vc_compat.h>
15+ #else
16+ #include <sys/time.h>
17+ #include <unistd.h>
1318#endif
1419
1520#include "lsquic_hash.h"
16- #include "lsquic_xxhash .h"
21+ #include "lsquic_rapidhash .h"
1722
1823TAILQ_HEAD (hels_head , lsquic_hash_elem );
1924
@@ -26,15 +31,47 @@ struct lsquic_hash
2631 qh_all ;
2732 struct lsquic_hash_elem * qh_iter_next ;
2833 int (* qh_cmp )(const void * , const void * , size_t );
29- unsigned (* qh_hash )(const void * , size_t , unsigned seed );
34+ uint64_t (* qh_hash )(const void * , size_t , uint64_t seed );
3035 unsigned qh_count ;
3136 unsigned qh_nbits ;
37+ uint64_t qh_hash_seed ;
3238};
3339
3440
41+ static uint64_t get_seed ()
42+ {
43+ static uint64_t seed = 0 ;
44+ if (seed == 0 )
45+ {
46+ #if defined(WIN32 )
47+ LARGE_INTEGER counter ;
48+ QueryPerformanceCounter (& counter );
49+ seed = counter .QuadPart ;
50+ #elif defined(_POSIX_TIMERS ) && _POSIX_TIMERS > 0
51+ struct timespec ts ;
52+ (void ) clock_gettime (CLOCK_MONOTONIC , & ts );
53+ seed = ts .tv_sec * 1000000000 + ts .tv_nsec ;
54+ #elif defined(__APPLE__ )
55+ seed = mach_absolute_time ();
56+ #else
57+ struct timeval tv ;
58+ gettimeofday (& tv , NULL );
59+ seed = tv .tv_sec * 1000000000 + tv .tv_usec * 1000 ;
60+ #endif
61+ srand (seed );
62+ for (unsigned i = 0 ; i < (seed & 0xf ) + 1 ; ++ i )
63+ {
64+ seed = (seed << 8 ) | (seed >> 56 );
65+ seed ^= rand ();
66+ }
67+ }
68+ return seed ;
69+ }
70+
71+
3572struct lsquic_hash *
3673lsquic_hash_create_ext (int (* cmp )(const void * , const void * , size_t ),
37- unsigned (* hashf )(const void * , size_t , unsigned seed ))
74+ uint64_t (* hashf )(const void * , size_t , uint64_t seed ))
3875{
3976 struct hels_head * buckets ;
4077 struct lsquic_hash * hash ;
@@ -62,14 +99,26 @@ lsquic_hash_create_ext (int (*cmp)(const void *, const void *, size_t),
6299 hash -> qh_nbits = nbits ;
63100 hash -> qh_iter_next = NULL ;
64101 hash -> qh_count = 0 ;
102+ hash -> qh_hash_seed = get_seed () ^ (uint64_t )hash
103+ ^ ((uint64_t )buckets << 32 ) ^ rand ();
65104 return hash ;
66105}
67106
68107
69108struct lsquic_hash *
70109lsquic_hash_create (void )
71110{
72- return lsquic_hash_create_ext (memcmp , XXH32 );
111+ return lsquic_hash_create_ext (memcmp , rapidhash_withSeed );
112+ }
113+
114+
115+ int
116+ lsquic_hash_set_seed (struct lsquic_hash * hash , uint64_t seed )
117+ {
118+ if (hash -> qh_count > 0 )
119+ return -1 ;
120+ hash -> qh_hash_seed = seed ;
121+ return 0 ;
73122}
74123
75124
@@ -119,7 +168,8 @@ struct lsquic_hash_elem *
119168lsquic_hash_insert (struct lsquic_hash * hash , const void * key ,
120169 unsigned key_sz , void * value , struct lsquic_hash_elem * el )
121170{
122- unsigned buckno , hash_val ;
171+ uint64_t hash_val ;
172+ unsigned buckno ;
123173
124174 if (el -> qhe_flags & QHE_HASHED )
125175 return NULL ;
@@ -128,7 +178,7 @@ lsquic_hash_insert (struct lsquic_hash *hash, const void *key,
128178 0 != lsquic_hash_grow (hash ))
129179 return NULL ;
130180
131- hash_val = hash -> qh_hash (key , key_sz , ( uintptr_t ) hash );
181+ hash_val = hash -> qh_hash (key , key_sz , hash -> qh_hash_seed );
132182 buckno = BUCKNO (hash -> qh_nbits , hash_val );
133183 TAILQ_INSERT_TAIL (& hash -> qh_all , el , qhe_next_all );
134184 TAILQ_INSERT_TAIL (& hash -> qh_buckets [buckno ], el , qhe_next_bucket );
@@ -145,10 +195,11 @@ lsquic_hash_insert (struct lsquic_hash *hash, const void *key,
145195struct lsquic_hash_elem *
146196lsquic_hash_find (struct lsquic_hash * hash , const void * key , unsigned key_sz )
147197{
148- unsigned buckno , hash_val ;
198+ uint64_t hash_val ;
199+ unsigned buckno ;
149200 struct lsquic_hash_elem * el ;
150201
151- hash_val = hash -> qh_hash (key , key_sz , ( uintptr_t ) hash );
202+ hash_val = hash -> qh_hash (key , key_sz , hash -> qh_hash_seed );
152203 buckno = BUCKNO (hash -> qh_nbits , hash_val );
153204 TAILQ_FOREACH (el , & hash -> qh_buckets [buckno ], qhe_next_bucket )
154205 if (hash_val == el -> qhe_hash_val &&
0 commit comments