1 /*
2 * Copyright © 2009,2012 Intel Corporation
3 * Copyright © 1988-2004 Keith Packard and Bart Massey.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 *
24 * Except as contained in this notice, the names of the authors
25 * or their institutions shall not be used in advertising or
26 * otherwise to promote the sale, use or other dealings in this
27 * Software without prior written authorization from the
28 * authors.
29 *
30 * Authors:
31 * Eric Anholt <[email protected]>
32 * Keith Packard <[email protected]>
33 */
34
35 /**
36 * Implements an open-addressing, linear-reprobing hash table.
37 *
38 * For more information, see:
39 *
40 * http://cgit.freedesktop.org/~anholt/hash_table/tree/README
41 */
42
43 #include <stdlib.h>
44 #include <string.h>
45 #include <assert.h>
46
47 #include "hash_table.h"
48 #include "ralloc.h"
49 #include "macros.h"
50 #include "u_memory.h"
51 #include "fast_urem_by_const.h"
52 #include "util/u_memory.h"
53
54 #define XXH_INLINE_ALL
55 #include "xxhash.h"
56
57 /**
58 * Magic number that gets stored outside of the struct hash_table.
59 *
60 * The hash table needs a particular pointer to be the marker for a key that
61 * was deleted from the table, along with NULL for the "never allocated in the
62 * table" marker. Legacy GL allows any GLuint to be used as a GL object name,
63 * and we use a 1:1 mapping from GLuints to key pointers, so we need to be
64 * able to track a GLuint that happens to match the deleted key outside of
65 * struct hash_table. We tell the hash table to use "1" as the deleted key
66 * value, so that we test the deleted-key-in-the-table path as best we can.
67 */
68 #define DELETED_KEY_VALUE 1
69
70 static inline void *
uint_key(unsigned id)71 uint_key(unsigned id)
72 {
73 return (void *)(uintptr_t) id;
74 }
75
76 static const uint32_t deleted_key_value;
77
78 /**
79 * From Knuth -- a good choice for hash/rehash values is p, p-2 where
80 * p and p-2 are both prime. These tables are sized to have an extra 10%
81 * free to avoid exponential performance degradation as the hash table fills
82 */
83 static const struct {
84 uint32_t max_entries, size, rehash;
85 uint64_t size_magic, rehash_magic;
86 } hash_sizes[] = {
87 #define ENTRY(max_entries, size, rehash) \
88 { max_entries, size, rehash, \
89 REMAINDER_MAGIC(size), REMAINDER_MAGIC(rehash) }
90
91 ENTRY(2, 5, 3 ),
92 ENTRY(4, 7, 5 ),
93 ENTRY(8, 13, 11 ),
94 ENTRY(16, 19, 17 ),
95 ENTRY(32, 43, 41 ),
96 ENTRY(64, 73, 71 ),
97 ENTRY(128, 151, 149 ),
98 ENTRY(256, 283, 281 ),
99 ENTRY(512, 571, 569 ),
100 ENTRY(1024, 1153, 1151 ),
101 ENTRY(2048, 2269, 2267 ),
102 ENTRY(4096, 4519, 4517 ),
103 ENTRY(8192, 9013, 9011 ),
104 ENTRY(16384, 18043, 18041 ),
105 ENTRY(32768, 36109, 36107 ),
106 ENTRY(65536, 72091, 72089 ),
107 ENTRY(131072, 144409, 144407 ),
108 ENTRY(262144, 288361, 288359 ),
109 ENTRY(524288, 576883, 576881 ),
110 ENTRY(1048576, 1153459, 1153457 ),
111 ENTRY(2097152, 2307163, 2307161 ),
112 ENTRY(4194304, 4613893, 4613891 ),
113 ENTRY(8388608, 9227641, 9227639 ),
114 ENTRY(16777216, 18455029, 18455027 ),
115 ENTRY(33554432, 36911011, 36911009 ),
116 ENTRY(67108864, 73819861, 73819859 ),
117 ENTRY(134217728, 147639589, 147639587 ),
118 ENTRY(268435456, 295279081, 295279079 ),
119 ENTRY(536870912, 590559793, 590559791 ),
120 ENTRY(1073741824, 1181116273, 1181116271 ),
121 ENTRY(2147483648ul, 2362232233ul, 2362232231ul )
122 };
123
124 ASSERTED static inline bool
key_pointer_is_reserved(const struct hash_table * ht,const void * key)125 key_pointer_is_reserved(const struct hash_table *ht, const void *key)
126 {
127 return key == NULL || key == ht->deleted_key;
128 }
129
130 static int
entry_is_free(const struct hash_entry * entry)131 entry_is_free(const struct hash_entry *entry)
132 {
133 return entry->key == NULL;
134 }
135
136 static int
entry_is_deleted(const struct hash_table * ht,struct hash_entry * entry)137 entry_is_deleted(const struct hash_table *ht, struct hash_entry *entry)
138 {
139 return entry->key == ht->deleted_key;
140 }
141
142 static int
entry_is_present(const struct hash_table * ht,struct hash_entry * entry)143 entry_is_present(const struct hash_table *ht, struct hash_entry *entry)
144 {
145 return entry->key != NULL && entry->key != ht->deleted_key;
146 }
147
148 bool
_mesa_hash_table_init(struct hash_table * ht,void * mem_ctx,uint32_t (* key_hash_function)(const void * key),bool (* key_equals_function)(const void * a,const void * b))149 _mesa_hash_table_init(struct hash_table *ht,
150 void *mem_ctx,
151 uint32_t (*key_hash_function)(const void *key),
152 bool (*key_equals_function)(const void *a,
153 const void *b))
154 {
155 ht->size_index = 0;
156 ht->size = hash_sizes[ht->size_index].size;
157 ht->rehash = hash_sizes[ht->size_index].rehash;
158 ht->size_magic = hash_sizes[ht->size_index].size_magic;
159 ht->rehash_magic = hash_sizes[ht->size_index].rehash_magic;
160 ht->max_entries = hash_sizes[ht->size_index].max_entries;
161 ht->key_hash_function = key_hash_function;
162 ht->key_equals_function = key_equals_function;
163 ht->table = rzalloc_array(mem_ctx, struct hash_entry, ht->size);
164 ht->entries = 0;
165 ht->deleted_entries = 0;
166 ht->deleted_key = &deleted_key_value;
167
168 return ht->table != NULL;
169 }
170
171 struct hash_table *
_mesa_hash_table_create(void * mem_ctx,uint32_t (* key_hash_function)(const void * key),bool (* key_equals_function)(const void * a,const void * b))172 _mesa_hash_table_create(void *mem_ctx,
173 uint32_t (*key_hash_function)(const void *key),
174 bool (*key_equals_function)(const void *a,
175 const void *b))
176 {
177 struct hash_table *ht;
178
179 /* mem_ctx is used to allocate the hash table, but the hash table is used
180 * to allocate all of the suballocations.
181 */
182 ht = ralloc(mem_ctx, struct hash_table);
183 if (ht == NULL)
184 return NULL;
185
186 if (!_mesa_hash_table_init(ht, ht, key_hash_function, key_equals_function)) {
187 ralloc_free(ht);
188 return NULL;
189 }
190
191 return ht;
192 }
193
194 static uint32_t
key_u32_hash(const void * key)195 key_u32_hash(const void *key)
196 {
197 uint32_t u = (uint32_t)(uintptr_t)key;
198 return _mesa_hash_uint(&u);
199 }
200
201 static bool
key_u32_equals(const void * a,const void * b)202 key_u32_equals(const void *a, const void *b)
203 {
204 return (uint32_t)(uintptr_t)a == (uint32_t)(uintptr_t)b;
205 }
206
207 /* key == 0 and key == deleted_key are not allowed */
208 struct hash_table *
_mesa_hash_table_create_u32_keys(void * mem_ctx)209 _mesa_hash_table_create_u32_keys(void *mem_ctx)
210 {
211 return _mesa_hash_table_create(mem_ctx, key_u32_hash, key_u32_equals);
212 }
213
214 struct hash_table *
_mesa_hash_table_clone(struct hash_table * src,void * dst_mem_ctx)215 _mesa_hash_table_clone(struct hash_table *src, void *dst_mem_ctx)
216 {
217 struct hash_table *ht;
218
219 ht = ralloc(dst_mem_ctx, struct hash_table);
220 if (ht == NULL)
221 return NULL;
222
223 memcpy(ht, src, sizeof(struct hash_table));
224
225 ht->table = ralloc_array(ht, struct hash_entry, ht->size);
226 if (ht->table == NULL) {
227 ralloc_free(ht);
228 return NULL;
229 }
230
231 memcpy(ht->table, src->table, ht->size * sizeof(struct hash_entry));
232
233 return ht;
234 }
235
236 /**
237 * Frees the given hash table.
238 *
239 * If delete_function is passed, it gets called on each entry present before
240 * freeing.
241 */
242 void
_mesa_hash_table_destroy(struct hash_table * ht,void (* delete_function)(struct hash_entry * entry))243 _mesa_hash_table_destroy(struct hash_table *ht,
244 void (*delete_function)(struct hash_entry *entry))
245 {
246 if (!ht)
247 return;
248
249 if (delete_function) {
250 hash_table_foreach(ht, entry) {
251 delete_function(entry);
252 }
253 }
254 ralloc_free(ht);
255 }
256
257 static void
hash_table_clear_fast(struct hash_table * ht)258 hash_table_clear_fast(struct hash_table *ht)
259 {
260 memset(ht->table, 0, sizeof(struct hash_entry) * hash_sizes[ht->size_index].size);
261 ht->entries = ht->deleted_entries = 0;
262 }
263
264 /**
265 * Deletes all entries of the given hash table without deleting the table
266 * itself or changing its structure.
267 *
268 * If delete_function is passed, it gets called on each entry present.
269 */
270 void
_mesa_hash_table_clear(struct hash_table * ht,void (* delete_function)(struct hash_entry * entry))271 _mesa_hash_table_clear(struct hash_table *ht,
272 void (*delete_function)(struct hash_entry *entry))
273 {
274 if (!ht)
275 return;
276
277 struct hash_entry *entry;
278
279 if (delete_function) {
280 for (entry = ht->table; entry != ht->table + ht->size; entry++) {
281 if (entry_is_present(ht, entry))
282 delete_function(entry);
283
284 entry->key = NULL;
285 }
286 ht->entries = 0;
287 ht->deleted_entries = 0;
288 } else
289 hash_table_clear_fast(ht);
290 }
291
292 /** Sets the value of the key pointer used for deleted entries in the table.
293 *
294 * The assumption is that usually keys are actual pointers, so we use a
295 * default value of a pointer to an arbitrary piece of storage in the library.
296 * But in some cases a consumer wants to store some other sort of value in the
297 * table, like a uint32_t, in which case that pointer may conflict with one of
298 * their valid keys. This lets that user select a safe value.
299 *
300 * This must be called before any keys are actually deleted from the table.
301 */
302 void
_mesa_hash_table_set_deleted_key(struct hash_table * ht,const void * deleted_key)303 _mesa_hash_table_set_deleted_key(struct hash_table *ht, const void *deleted_key)
304 {
305 ht->deleted_key = deleted_key;
306 }
307
308 static struct hash_entry *
hash_table_search(const struct hash_table * ht,uint32_t hash,const void * key)309 hash_table_search(const struct hash_table *ht, uint32_t hash, const void *key)
310 {
311 assert(!key_pointer_is_reserved(ht, key));
312
313 uint32_t size = ht->size;
314 uint32_t start_hash_address = util_fast_urem32(hash, size, ht->size_magic);
315 uint32_t double_hash = 1 + util_fast_urem32(hash, ht->rehash,
316 ht->rehash_magic);
317 uint32_t hash_address = start_hash_address;
318
319 do {
320 struct hash_entry *entry = ht->table + hash_address;
321
322 if (entry_is_free(entry)) {
323 return NULL;
324 } else if (entry_is_present(ht, entry) && entry->hash == hash) {
325 if (ht->key_equals_function(key, entry->key)) {
326 return entry;
327 }
328 }
329
330 hash_address += double_hash;
331 if (hash_address >= size)
332 hash_address -= size;
333 } while (hash_address != start_hash_address);
334
335 return NULL;
336 }
337
338 /**
339 * Finds a hash table entry with the given key and hash of that key.
340 *
341 * Returns NULL if no entry is found. Note that the data pointer may be
342 * modified by the user.
343 */
344 struct hash_entry *
_mesa_hash_table_search(const struct hash_table * ht,const void * key)345 _mesa_hash_table_search(const struct hash_table *ht, const void *key)
346 {
347 assert(ht->key_hash_function);
348 return hash_table_search(ht, ht->key_hash_function(key), key);
349 }
350
351 struct hash_entry *
_mesa_hash_table_search_pre_hashed(struct hash_table * ht,uint32_t hash,const void * key)352 _mesa_hash_table_search_pre_hashed(struct hash_table *ht, uint32_t hash,
353 const void *key)
354 {
355 assert(ht->key_hash_function == NULL || hash == ht->key_hash_function(key));
356 return hash_table_search(ht, hash, key);
357 }
358
359 static struct hash_entry *
360 hash_table_insert(struct hash_table *ht, uint32_t hash,
361 const void *key, void *data);
362
363 static void
hash_table_insert_rehash(struct hash_table * ht,uint32_t hash,const void * key,void * data)364 hash_table_insert_rehash(struct hash_table *ht, uint32_t hash,
365 const void *key, void *data)
366 {
367 uint32_t size = ht->size;
368 uint32_t start_hash_address = util_fast_urem32(hash, size, ht->size_magic);
369 uint32_t double_hash = 1 + util_fast_urem32(hash, ht->rehash,
370 ht->rehash_magic);
371 uint32_t hash_address = start_hash_address;
372 do {
373 struct hash_entry *entry = ht->table + hash_address;
374
375 if (likely(entry->key == NULL)) {
376 entry->hash = hash;
377 entry->key = key;
378 entry->data = data;
379 return;
380 }
381
382 hash_address += double_hash;
383 if (hash_address >= size)
384 hash_address -= size;
385 } while (true);
386 }
387
388 static void
_mesa_hash_table_rehash(struct hash_table * ht,unsigned new_size_index)389 _mesa_hash_table_rehash(struct hash_table *ht, unsigned new_size_index)
390 {
391 struct hash_table old_ht;
392 struct hash_entry *table;
393
394 if (ht->size_index == new_size_index && ht->deleted_entries == ht->max_entries) {
395 hash_table_clear_fast(ht);
396 assert(!ht->entries);
397 return;
398 }
399
400 if (new_size_index >= ARRAY_SIZE(hash_sizes))
401 return;
402
403 table = rzalloc_array(ralloc_parent(ht->table), struct hash_entry,
404 hash_sizes[new_size_index].size);
405 if (table == NULL)
406 return;
407
408 old_ht = *ht;
409
410 ht->table = table;
411 ht->size_index = new_size_index;
412 ht->size = hash_sizes[ht->size_index].size;
413 ht->rehash = hash_sizes[ht->size_index].rehash;
414 ht->size_magic = hash_sizes[ht->size_index].size_magic;
415 ht->rehash_magic = hash_sizes[ht->size_index].rehash_magic;
416 ht->max_entries = hash_sizes[ht->size_index].max_entries;
417 ht->entries = 0;
418 ht->deleted_entries = 0;
419
420 hash_table_foreach(&old_ht, entry) {
421 hash_table_insert_rehash(ht, entry->hash, entry->key, entry->data);
422 }
423
424 ht->entries = old_ht.entries;
425
426 ralloc_free(old_ht.table);
427 }
428
429 static struct hash_entry *
hash_table_get_entry(struct hash_table * ht,uint32_t hash,const void * key)430 hash_table_get_entry(struct hash_table *ht, uint32_t hash, const void *key)
431 {
432 struct hash_entry *available_entry = NULL;
433
434 assert(!key_pointer_is_reserved(ht, key));
435
436 if (ht->entries >= ht->max_entries) {
437 _mesa_hash_table_rehash(ht, ht->size_index + 1);
438 } else if (ht->deleted_entries + ht->entries >= ht->max_entries) {
439 _mesa_hash_table_rehash(ht, ht->size_index);
440 }
441
442 uint32_t size = ht->size;
443 uint32_t start_hash_address = util_fast_urem32(hash, size, ht->size_magic);
444 uint32_t double_hash = 1 + util_fast_urem32(hash, ht->rehash,
445 ht->rehash_magic);
446 uint32_t hash_address = start_hash_address;
447 do {
448 struct hash_entry *entry = ht->table + hash_address;
449
450 if (!entry_is_present(ht, entry)) {
451 /* Stash the first available entry we find */
452 if (available_entry == NULL)
453 available_entry = entry;
454 if (entry_is_free(entry))
455 break;
456 }
457
458 /* Implement replacement when another insert happens
459 * with a matching key. This is a relatively common
460 * feature of hash tables, with the alternative
461 * generally being "insert the new value as well, and
462 * return it first when the key is searched for".
463 *
464 * Note that the hash table doesn't have a delete
465 * callback. If freeing of old data pointers is
466 * required to avoid memory leaks, perform a search
467 * before inserting.
468 */
469 if (!entry_is_deleted(ht, entry) &&
470 entry->hash == hash &&
471 ht->key_equals_function(key, entry->key))
472 return entry;
473
474 hash_address += double_hash;
475 if (hash_address >= size)
476 hash_address -= size;
477 } while (hash_address != start_hash_address);
478
479 if (available_entry) {
480 if (entry_is_deleted(ht, available_entry))
481 ht->deleted_entries--;
482 available_entry->hash = hash;
483 ht->entries++;
484 return available_entry;
485 }
486
487 /* We could hit here if a required resize failed. An unchecked-malloc
488 * application could ignore this result.
489 */
490 return NULL;
491 }
492
493 static struct hash_entry *
hash_table_insert(struct hash_table * ht,uint32_t hash,const void * key,void * data)494 hash_table_insert(struct hash_table *ht, uint32_t hash,
495 const void *key, void *data)
496 {
497 struct hash_entry *entry = hash_table_get_entry(ht, hash, key);
498
499 if (entry) {
500 entry->key = key;
501 entry->data = data;
502 }
503
504 return entry;
505 }
506
507 /**
508 * Inserts the key with the given hash into the table.
509 *
510 * Note that insertion may rearrange the table on a resize or rehash,
511 * so previously found hash_entries are no longer valid after this function.
512 */
513 struct hash_entry *
_mesa_hash_table_insert(struct hash_table * ht,const void * key,void * data)514 _mesa_hash_table_insert(struct hash_table *ht, const void *key, void *data)
515 {
516 assert(ht->key_hash_function);
517 return hash_table_insert(ht, ht->key_hash_function(key), key, data);
518 }
519
520 struct hash_entry *
_mesa_hash_table_insert_pre_hashed(struct hash_table * ht,uint32_t hash,const void * key,void * data)521 _mesa_hash_table_insert_pre_hashed(struct hash_table *ht, uint32_t hash,
522 const void *key, void *data)
523 {
524 assert(ht->key_hash_function == NULL || hash == ht->key_hash_function(key));
525 return hash_table_insert(ht, hash, key, data);
526 }
527
528 /**
529 * This function deletes the given hash table entry.
530 *
531 * Note that deletion doesn't otherwise modify the table, so an iteration over
532 * the table deleting entries is safe.
533 */
534 void
_mesa_hash_table_remove(struct hash_table * ht,struct hash_entry * entry)535 _mesa_hash_table_remove(struct hash_table *ht,
536 struct hash_entry *entry)
537 {
538 if (!entry)
539 return;
540
541 entry->key = ht->deleted_key;
542 ht->entries--;
543 ht->deleted_entries++;
544 }
545
546 /**
547 * Removes the entry with the corresponding key, if exists.
548 */
_mesa_hash_table_remove_key(struct hash_table * ht,const void * key)549 void _mesa_hash_table_remove_key(struct hash_table *ht,
550 const void *key)
551 {
552 _mesa_hash_table_remove(ht, _mesa_hash_table_search(ht, key));
553 }
554
555 /**
556 * This function is an iterator over the hash_table when no deleted entries are present.
557 *
558 * Pass in NULL for the first entry, as in the start of a for loop.
559 */
560 struct hash_entry *
_mesa_hash_table_next_entry_unsafe(const struct hash_table * ht,struct hash_entry * entry)561 _mesa_hash_table_next_entry_unsafe(const struct hash_table *ht, struct hash_entry *entry)
562 {
563 assert(!ht->deleted_entries);
564 if (!ht->entries)
565 return NULL;
566 if (entry == NULL)
567 entry = ht->table;
568 else
569 entry = entry + 1;
570 if (entry != ht->table + ht->size)
571 return entry->key ? entry : _mesa_hash_table_next_entry_unsafe(ht, entry);
572
573 return NULL;
574 }
575
576 /**
577 * This function is an iterator over the hash table.
578 *
579 * Pass in NULL for the first entry, as in the start of a for loop. Note that
580 * an iteration over the table is O(table_size) not O(entries).
581 */
582 struct hash_entry *
_mesa_hash_table_next_entry(struct hash_table * ht,struct hash_entry * entry)583 _mesa_hash_table_next_entry(struct hash_table *ht,
584 struct hash_entry *entry)
585 {
586 if (entry == NULL)
587 entry = ht->table;
588 else
589 entry = entry + 1;
590
591 for (; entry != ht->table + ht->size; entry++) {
592 if (entry_is_present(ht, entry)) {
593 return entry;
594 }
595 }
596
597 return NULL;
598 }
599
600 /**
601 * Returns a random entry from the hash table.
602 *
603 * This may be useful in implementing random replacement (as opposed
604 * to just removing everything) in caches based on this hash table
605 * implementation. @predicate may be used to filter entries, or may
606 * be set to NULL for no filtering.
607 */
608 struct hash_entry *
_mesa_hash_table_random_entry(struct hash_table * ht,bool (* predicate)(struct hash_entry * entry))609 _mesa_hash_table_random_entry(struct hash_table *ht,
610 bool (*predicate)(struct hash_entry *entry))
611 {
612 struct hash_entry *entry;
613 uint32_t i = rand() % ht->size;
614
615 if (ht->entries == 0)
616 return NULL;
617
618 for (entry = ht->table + i; entry != ht->table + ht->size; entry++) {
619 if (entry_is_present(ht, entry) &&
620 (!predicate || predicate(entry))) {
621 return entry;
622 }
623 }
624
625 for (entry = ht->table; entry != ht->table + i; entry++) {
626 if (entry_is_present(ht, entry) &&
627 (!predicate || predicate(entry))) {
628 return entry;
629 }
630 }
631
632 return NULL;
633 }
634
635
636 uint32_t
_mesa_hash_data(const void * data,size_t size)637 _mesa_hash_data(const void *data, size_t size)
638 {
639 return XXH32(data, size, 0);
640 }
641
642 uint32_t
_mesa_hash_data_with_seed(const void * data,size_t size,uint32_t seed)643 _mesa_hash_data_with_seed(const void *data, size_t size, uint32_t seed)
644 {
645 return XXH32(data, size, seed);
646 }
647
648 uint32_t
_mesa_hash_int(const void * key)649 _mesa_hash_int(const void *key)
650 {
651 return XXH32(key, sizeof(int), 0);
652 }
653
654 uint32_t
_mesa_hash_uint(const void * key)655 _mesa_hash_uint(const void *key)
656 {
657 return XXH32(key, sizeof(unsigned), 0);
658 }
659
660 uint32_t
_mesa_hash_u32(const void * key)661 _mesa_hash_u32(const void *key)
662 {
663 return XXH32(key, 4, 0);
664 }
665
666 /** FNV-1a string hash implementation */
667 uint32_t
_mesa_hash_string(const void * _key)668 _mesa_hash_string(const void *_key)
669 {
670 return _mesa_hash_string_with_length(_key, strlen((const char *)_key));
671 }
672
673 uint32_t
_mesa_hash_string_with_length(const void * _key,unsigned length)674 _mesa_hash_string_with_length(const void *_key, unsigned length)
675 {
676 uint32_t hash = 0;
677 const char *key = _key;
678 #if defined(_WIN64) || defined(__x86_64__)
679 hash = (uint32_t)XXH64(key, length, hash);
680 #else
681 hash = XXH32(key, length, hash);
682 #endif
683 return hash;
684 }
685
686 uint32_t
_mesa_hash_pointer(const void * pointer)687 _mesa_hash_pointer(const void *pointer)
688 {
689 uintptr_t num = (uintptr_t) pointer;
690 return (uint32_t) ((num >> 2) ^ (num >> 6) ^ (num >> 10) ^ (num >> 14));
691 }
692
693 bool
_mesa_key_int_equal(const void * a,const void * b)694 _mesa_key_int_equal(const void *a, const void *b)
695 {
696 return *((const int *)a) == *((const int *)b);
697 }
698
699 bool
_mesa_key_uint_equal(const void * a,const void * b)700 _mesa_key_uint_equal(const void *a, const void *b)
701 {
702
703 return *((const unsigned *)a) == *((const unsigned *)b);
704 }
705
706 bool
_mesa_key_u32_equal(const void * a,const void * b)707 _mesa_key_u32_equal(const void *a, const void *b)
708 {
709 return *((const uint32_t *)a) == *((const uint32_t *)b);
710 }
711
712 /**
713 * String compare function for use as the comparison callback in
714 * _mesa_hash_table_create().
715 */
716 bool
_mesa_key_string_equal(const void * a,const void * b)717 _mesa_key_string_equal(const void *a, const void *b)
718 {
719 return strcmp(a, b) == 0;
720 }
721
722 bool
_mesa_key_pointer_equal(const void * a,const void * b)723 _mesa_key_pointer_equal(const void *a, const void *b)
724 {
725 return a == b;
726 }
727
728 /**
729 * Helper to create a hash table with pointer keys.
730 */
731 struct hash_table *
_mesa_pointer_hash_table_create(void * mem_ctx)732 _mesa_pointer_hash_table_create(void *mem_ctx)
733 {
734 return _mesa_hash_table_create(mem_ctx, _mesa_hash_pointer,
735 _mesa_key_pointer_equal);
736 }
737
738
739 bool
_mesa_hash_table_reserve(struct hash_table * ht,unsigned size)740 _mesa_hash_table_reserve(struct hash_table *ht, unsigned size)
741 {
742 if (size < ht->max_entries)
743 return true;
744 for (unsigned i = ht->size_index + 1; i < ARRAY_SIZE(hash_sizes); i++) {
745 if (hash_sizes[i].max_entries >= size) {
746 _mesa_hash_table_rehash(ht, i);
747 break;
748 }
749 }
750 return ht->max_entries >= size;
751 }
752
753 /**
754 * Hash table wrapper which supports 64-bit keys.
755 *
756 * TODO: unify all hash table implementations.
757 */
758
759 struct hash_key_u64 {
760 uint64_t value;
761 };
762
763 static uint32_t
key_u64_hash(const void * key)764 key_u64_hash(const void *key)
765 {
766 return _mesa_hash_data(key, sizeof(struct hash_key_u64));
767 }
768
769 static bool
key_u64_equals(const void * a,const void * b)770 key_u64_equals(const void *a, const void *b)
771 {
772 const struct hash_key_u64 *aa = a;
773 const struct hash_key_u64 *bb = b;
774
775 return aa->value == bb->value;
776 }
777
778 #define FREED_KEY_VALUE 0
779
_mesa_hash_table_u64_delete_keys(void * data)780 static void _mesa_hash_table_u64_delete_keys(void *data)
781 {
782 struct hash_table_u64 *ht = ralloc_parent(data);
783
784 _mesa_hash_table_u64_clear(ht);
785 }
786
787 struct hash_table_u64 *
_mesa_hash_table_u64_create(void * mem_ctx)788 _mesa_hash_table_u64_create(void *mem_ctx)
789 {
790 STATIC_ASSERT(FREED_KEY_VALUE != DELETED_KEY_VALUE);
791 struct hash_table_u64 *ht;
792
793 ht = rzalloc(mem_ctx, struct hash_table_u64);
794 if (!ht)
795 return NULL;
796
797 if (sizeof(void *) == 8) {
798 ht->table = _mesa_hash_table_create(ht, _mesa_hash_pointer,
799 _mesa_key_pointer_equal);
800 } else {
801 ht->table = _mesa_hash_table_create(ht, key_u64_hash,
802 key_u64_equals);
803
804 /* Allocate a ralloc sub-context which takes the u64 hash table
805 * as a parent and attach a destructor to it so we can free the
806 * hash_key_u64 objects that were allocated by
807 * _mesa_hash_table_u64_insert().
808 *
809 * The order of creation of this sub-context is crucial: it needs
810 * to happen after the _mesa_hash_table_create() call to guarantee
811 * that the destructor is called before ht->table and its children
812 * are freed, otherwise the _mesa_hash_table_u64_clear() call in the
813 * destructor leads to a use-after-free situation.
814 */
815 if (ht->table) {
816 void *dummy_ctx = ralloc_context(ht);
817
818 /* If we can't allocate a sub-context, free the hash table
819 * immediately and return NULL to avoid future leaks.
820 */
821 if (!dummy_ctx) {
822 ralloc_free(ht);
823 return NULL;
824 }
825
826 ralloc_set_destructor(dummy_ctx, _mesa_hash_table_u64_delete_keys);
827 }
828 }
829
830 if (ht->table)
831 _mesa_hash_table_set_deleted_key(ht->table, uint_key(DELETED_KEY_VALUE));
832
833 return ht;
834 }
835
836 static void
_mesa_hash_table_u64_delete_key(struct hash_entry * entry)837 _mesa_hash_table_u64_delete_key(struct hash_entry *entry)
838 {
839 if (sizeof(void *) == 8)
840 return;
841
842 struct hash_key_u64 *_key = (struct hash_key_u64 *)entry->key;
843
844 if (_key)
845 FREE(_key);
846 }
847
848 void
_mesa_hash_table_u64_clear(struct hash_table_u64 * ht)849 _mesa_hash_table_u64_clear(struct hash_table_u64 *ht)
850 {
851 if (!ht)
852 return;
853
854 _mesa_hash_table_clear(ht->table, _mesa_hash_table_u64_delete_key);
855 ht->freed_key_data = NULL;
856 ht->deleted_key_data = NULL;
857 }
858
859 void
_mesa_hash_table_u64_destroy(struct hash_table_u64 * ht)860 _mesa_hash_table_u64_destroy(struct hash_table_u64 *ht)
861 {
862 if (!ht)
863 return;
864 ralloc_free(ht);
865 }
866
867 void
_mesa_hash_table_u64_insert(struct hash_table_u64 * ht,uint64_t key,void * data)868 _mesa_hash_table_u64_insert(struct hash_table_u64 *ht, uint64_t key,
869 void *data)
870 {
871 if (key == FREED_KEY_VALUE) {
872 ht->freed_key_data = data;
873 return;
874 }
875
876 if (key == DELETED_KEY_VALUE) {
877 ht->deleted_key_data = data;
878 return;
879 }
880
881 if (sizeof(void *) == 8) {
882 _mesa_hash_table_insert(ht->table, (void *)(uintptr_t)key, data);
883 } else {
884 struct hash_key_u64 *_key = CALLOC_STRUCT(hash_key_u64);
885
886 if (!_key)
887 return;
888 _key->value = key;
889
890 struct hash_entry *entry =
891 hash_table_get_entry(ht->table, key_u64_hash(_key), _key);
892
893 if (!entry) {
894 FREE(_key);
895 return;
896 }
897
898 entry->data = data;
899 if (!entry_is_present(ht->table, entry))
900 entry->key = _key;
901 else
902 FREE(_key);
903 }
904 }
905
906 static struct hash_entry *
hash_table_u64_search(struct hash_table_u64 * ht,uint64_t key)907 hash_table_u64_search(struct hash_table_u64 *ht, uint64_t key)
908 {
909 if (sizeof(void *) == 8) {
910 return _mesa_hash_table_search(ht->table, (void *)(uintptr_t)key);
911 } else {
912 struct hash_key_u64 _key = { .value = key };
913 return _mesa_hash_table_search(ht->table, &_key);
914 }
915 }
916
917 void *
_mesa_hash_table_u64_search(struct hash_table_u64 * ht,uint64_t key)918 _mesa_hash_table_u64_search(struct hash_table_u64 *ht, uint64_t key)
919 {
920 struct hash_entry *entry;
921
922 if (key == FREED_KEY_VALUE)
923 return ht->freed_key_data;
924
925 if (key == DELETED_KEY_VALUE)
926 return ht->deleted_key_data;
927
928 entry = hash_table_u64_search(ht, key);
929 if (!entry)
930 return NULL;
931
932 return entry->data;
933 }
934
935 void
_mesa_hash_table_u64_remove(struct hash_table_u64 * ht,uint64_t key)936 _mesa_hash_table_u64_remove(struct hash_table_u64 *ht, uint64_t key)
937 {
938 struct hash_entry *entry;
939
940 if (key == FREED_KEY_VALUE) {
941 ht->freed_key_data = NULL;
942 return;
943 }
944
945 if (key == DELETED_KEY_VALUE) {
946 ht->deleted_key_data = NULL;
947 return;
948 }
949
950 entry = hash_table_u64_search(ht, key);
951 if (!entry)
952 return;
953
954 if (sizeof(void *) == 8) {
955 _mesa_hash_table_remove(ht->table, entry);
956 } else {
957 struct hash_key *_key = (struct hash_key *)entry->key;
958
959 _mesa_hash_table_remove(ht->table, entry);
960 FREE(_key);
961 }
962 }
963
964
965 /*
966 * Iterates in order ("freed key", "deleted key", regular entries...)
967 */
968 struct hash_entry_u64
_mesa_hash_table_u64_next_entry(struct hash_table_u64 * ht,struct hash_entry_u64 * ent)969 _mesa_hash_table_u64_next_entry(struct hash_table_u64 *ht,
970 struct hash_entry_u64 *ent)
971 {
972 /* First entry: freed key */
973 if (!ent && ht->freed_key_data) {
974 return (struct hash_entry_u64){
975 .key = FREED_KEY_VALUE,
976 .data = ht->freed_key_data,
977 };
978 }
979
980 /* Second entry: deleted key */
981 if ((!ent || ent->key == FREED_KEY_VALUE) && ht->deleted_key_data) {
982 return (struct hash_entry_u64){
983 .key = DELETED_KEY_VALUE,
984 .data = ht->deleted_key_data,
985 };
986 }
987
988 /* All other entries: regular */
989 struct hash_entry *next =
990 _mesa_hash_table_next_entry(ht->table, ent ? ent->_entry : NULL);
991
992 if (!next)
993 return (struct hash_entry_u64){.data = NULL};
994
995 uint64_t key;
996 if (sizeof(void *) == 8) {
997 key = (uintptr_t)next->key;
998 } else {
999 const struct hash_key_u64 *_key = next->key;
1000 key = _key->value;
1001 }
1002
1003 return (struct hash_entry_u64){
1004 .key = key,
1005 .data = next->data,
1006 ._entry = next,
1007 };
1008 }
1009