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>
18+ #endif
19+
20+ #if !(defined(_POSIX_TIMERS ) && _POSIX_TIMERS > 0 ) && defined(__APPLE__ )
21+ #include <mach/mach_time.h>
1322#endif
1423
1524#include "lsquic_hash.h"
16- #include "lsquic_xxhash .h"
25+ #include "lsquic_rapidhash .h"
1726
1827TAILQ_HEAD (hels_head , lsquic_hash_elem );
1928
@@ -26,15 +35,47 @@ struct lsquic_hash
2635 qh_all ;
2736 struct lsquic_hash_elem * qh_iter_next ;
2837 int (* qh_cmp )(const void * , const void * , size_t );
29- unsigned (* qh_hash )(const void * , size_t , unsigned seed );
38+ uint64_t (* qh_hash )(const void * , size_t , uint64_t seed );
3039 unsigned qh_count ;
3140 unsigned qh_nbits ;
41+ uint64_t qh_hash_seed ;
3242};
3343
3444
45+ static uint64_t get_seed ()
46+ {
47+ static uint64_t seed = 0 ;
48+ if (seed == 0 )
49+ {
50+ #if defined(WIN32 )
51+ LARGE_INTEGER counter ;
52+ QueryPerformanceCounter (& counter );
53+ seed = counter .QuadPart ;
54+ #elif defined(_POSIX_TIMERS ) && _POSIX_TIMERS > 0
55+ struct timespec ts ;
56+ (void ) clock_gettime (CLOCK_MONOTONIC , & ts );
57+ seed = ts .tv_sec * 1000000000 + ts .tv_nsec ;
58+ #elif defined(__APPLE__ )
59+ seed = mach_absolute_time ();
60+ #else
61+ struct timeval tv ;
62+ gettimeofday (& tv , NULL );
63+ seed = tv .tv_sec * 1000000000 + tv .tv_usec * 1000 ;
64+ #endif
65+ srand (seed );
66+ for (unsigned i = 0 ; i < (seed & 0xf ) + 1 ; ++ i )
67+ {
68+ seed = (seed << 8 ) | (seed >> 56 );
69+ seed ^= rand ();
70+ }
71+ }
72+ return seed ;
73+ }
74+
75+
3576struct lsquic_hash *
3677lsquic_hash_create_ext (int (* cmp )(const void * , const void * , size_t ),
37- unsigned (* hashf )(const void * , size_t , unsigned seed ))
78+ uint64_t (* hashf )(const void * , size_t , uint64_t seed ))
3879{
3980 struct hels_head * buckets ;
4081 struct lsquic_hash * hash ;
@@ -62,14 +103,26 @@ lsquic_hash_create_ext (int (*cmp)(const void *, const void *, size_t),
62103 hash -> qh_nbits = nbits ;
63104 hash -> qh_iter_next = NULL ;
64105 hash -> qh_count = 0 ;
106+ hash -> qh_hash_seed = get_seed () ^ (uint64_t )hash
107+ ^ ((uint64_t )buckets << 32 ) ^ rand ();
65108 return hash ;
66109}
67110
68111
69112struct lsquic_hash *
70113lsquic_hash_create (void )
71114{
72- return lsquic_hash_create_ext (memcmp , XXH32 );
115+ return lsquic_hash_create_ext (memcmp , rapidhash_withSeed );
116+ }
117+
118+
119+ int
120+ lsquic_hash_set_seed (struct lsquic_hash * hash , uint64_t seed )
121+ {
122+ if (hash -> qh_count > 0 )
123+ return -1 ;
124+ hash -> qh_hash_seed = seed ;
125+ return 0 ;
73126}
74127
75128
@@ -119,7 +172,8 @@ struct lsquic_hash_elem *
119172lsquic_hash_insert (struct lsquic_hash * hash , const void * key ,
120173 unsigned key_sz , void * value , struct lsquic_hash_elem * el )
121174{
122- unsigned buckno , hash_val ;
175+ uint64_t hash_val ;
176+ unsigned buckno ;
123177
124178 if (el -> qhe_flags & QHE_HASHED )
125179 return NULL ;
@@ -128,7 +182,7 @@ lsquic_hash_insert (struct lsquic_hash *hash, const void *key,
128182 0 != lsquic_hash_grow (hash ))
129183 return NULL ;
130184
131- hash_val = hash -> qh_hash (key , key_sz , ( uintptr_t ) hash );
185+ hash_val = hash -> qh_hash (key , key_sz , hash -> qh_hash_seed );
132186 buckno = BUCKNO (hash -> qh_nbits , hash_val );
133187 TAILQ_INSERT_TAIL (& hash -> qh_all , el , qhe_next_all );
134188 TAILQ_INSERT_TAIL (& hash -> qh_buckets [buckno ], el , qhe_next_bucket );
@@ -145,10 +199,11 @@ lsquic_hash_insert (struct lsquic_hash *hash, const void *key,
145199struct lsquic_hash_elem *
146200lsquic_hash_find (struct lsquic_hash * hash , const void * key , unsigned key_sz )
147201{
148- unsigned buckno , hash_val ;
202+ uint64_t hash_val ;
203+ unsigned buckno ;
149204 struct lsquic_hash_elem * el ;
150205
151- hash_val = hash -> qh_hash (key , key_sz , ( uintptr_t ) hash );
206+ hash_val = hash -> qh_hash (key , key_sz , hash -> qh_hash_seed );
152207 buckno = BUCKNO (hash -> qh_nbits , hash_val );
153208 TAILQ_FOREACH (el , & hash -> qh_buckets [buckno ], qhe_next_bucket )
154209 if (hash_val == el -> qhe_hash_val &&
0 commit comments