8
8
#include <stdlib.h>
9
9
#include <string.h>
10
10
#include <sys/queue.h>
11
+ #include <time.h>
12
+
11
13
#ifdef WIN32
12
14
#include <vc_compat.h>
15
+ #else
16
+ #include <sys/time.h>
17
+ #include <unistd.h>
13
18
#endif
14
19
15
20
#include "lsquic_hash.h"
16
- #include "lsquic_xxhash .h"
21
+ #include "lsquic_rapidhash .h"
17
22
18
23
TAILQ_HEAD (hels_head , lsquic_hash_elem );
19
24
@@ -26,15 +31,47 @@ struct lsquic_hash
26
31
qh_all ;
27
32
struct lsquic_hash_elem * qh_iter_next ;
28
33
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 );
30
35
unsigned qh_count ;
31
36
unsigned qh_nbits ;
37
+ uint64_t qh_hash_seed ;
32
38
};
33
39
34
40
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
+
35
72
struct lsquic_hash *
36
73
lsquic_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 ))
38
75
{
39
76
struct hels_head * buckets ;
40
77
struct lsquic_hash * hash ;
@@ -62,14 +99,26 @@ lsquic_hash_create_ext (int (*cmp)(const void *, const void *, size_t),
62
99
hash -> qh_nbits = nbits ;
63
100
hash -> qh_iter_next = NULL ;
64
101
hash -> qh_count = 0 ;
102
+ hash -> qh_hash_seed = get_seed () ^ (uint64_t )hash
103
+ ^ ((uint64_t )buckets << 32 ) ^ rand ();
65
104
return hash ;
66
105
}
67
106
68
107
69
108
struct lsquic_hash *
70
109
lsquic_hash_create (void )
71
110
{
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 ;
73
122
}
74
123
75
124
@@ -119,7 +168,8 @@ struct lsquic_hash_elem *
119
168
lsquic_hash_insert (struct lsquic_hash * hash , const void * key ,
120
169
unsigned key_sz , void * value , struct lsquic_hash_elem * el )
121
170
{
122
- unsigned buckno , hash_val ;
171
+ uint64_t hash_val ;
172
+ unsigned buckno ;
123
173
124
174
if (el -> qhe_flags & QHE_HASHED )
125
175
return NULL ;
@@ -128,7 +178,7 @@ lsquic_hash_insert (struct lsquic_hash *hash, const void *key,
128
178
0 != lsquic_hash_grow (hash ))
129
179
return NULL ;
130
180
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 );
132
182
buckno = BUCKNO (hash -> qh_nbits , hash_val );
133
183
TAILQ_INSERT_TAIL (& hash -> qh_all , el , qhe_next_all );
134
184
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,
145
195
struct lsquic_hash_elem *
146
196
lsquic_hash_find (struct lsquic_hash * hash , const void * key , unsigned key_sz )
147
197
{
148
- unsigned buckno , hash_val ;
198
+ uint64_t hash_val ;
199
+ unsigned buckno ;
149
200
struct lsquic_hash_elem * el ;
150
201
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 );
152
203
buckno = BUCKNO (hash -> qh_nbits , hash_val );
153
204
TAILQ_FOREACH (el , & hash -> qh_buckets [buckno ], qhe_next_bucket )
154
205
if (hash_val == el -> qhe_hash_val &&
0 commit comments