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 <eric@anholt.net>
32 * Keith Packard <keithp@keithp.com>
33 */
34
35 #include <stdlib.h>
36 #include <assert.h>
37 #include <string.h>
38
39 #include "hash_table.h"
40 #include "macros.h"
41 #include "ralloc.h"
42 #include "set.h"
43 #include "fast_urem_by_const.h"
44
45 /*
46 * From Knuth -- a good choice for hash/rehash values is p, p-2 where
47 * p and p-2 are both prime. These tables are sized to have an extra 10%
48 * free to avoid exponential performance degradation as the hash table fills
49 */
50
51 static const uint32_t deleted_key_value;
52 static const void *deleted_key = &deleted_key_value;
53
54 static const struct {
55 uint32_t max_entries, size, rehash;
56 uint64_t size_magic, rehash_magic;
57 } hash_sizes[] = {
58 #define ENTRY(max_entries, size, rehash) \
59 { max_entries, size, rehash, \
60 REMAINDER_MAGIC(size), REMAINDER_MAGIC(rehash) }
61
62 ENTRY(2, 5, 3 ),
63 ENTRY(4, 7, 5 ),
64 ENTRY(8, 13, 11 ),
65 ENTRY(16, 19, 17 ),
66 ENTRY(32, 43, 41 ),
67 ENTRY(64, 73, 71 ),
68 ENTRY(128, 151, 149 ),
69 ENTRY(256, 283, 281 ),
70 ENTRY(512, 571, 569 ),
71 ENTRY(1024, 1153, 1151 ),
72 ENTRY(2048, 2269, 2267 ),
73 ENTRY(4096, 4519, 4517 ),
74 ENTRY(8192, 9013, 9011 ),
75 ENTRY(16384, 18043, 18041 ),
76 ENTRY(32768, 36109, 36107 ),
77 ENTRY(65536, 72091, 72089 ),
78 ENTRY(131072, 144409, 144407 ),
79 ENTRY(262144, 288361, 288359 ),
80 ENTRY(524288, 576883, 576881 ),
81 ENTRY(1048576, 1153459, 1153457 ),
82 ENTRY(2097152, 2307163, 2307161 ),
83 ENTRY(4194304, 4613893, 4613891 ),
84 ENTRY(8388608, 9227641, 9227639 ),
85 ENTRY(16777216, 18455029, 18455027 ),
86 ENTRY(33554432, 36911011, 36911009 ),
87 ENTRY(67108864, 73819861, 73819859 ),
88 ENTRY(134217728, 147639589, 147639587 ),
89 ENTRY(268435456, 295279081, 295279079 ),
90 ENTRY(536870912, 590559793, 590559791 ),
91 ENTRY(1073741824, 1181116273, 1181116271 ),
92 ENTRY(2147483648ul, 2362232233ul, 2362232231ul )
93 };
94
95 ASSERTED static inline bool
key_pointer_is_reserved(const void * key)96 key_pointer_is_reserved(const void *key)
97 {
98 return key == NULL || key == deleted_key;
99 }
100
101 static int
entry_is_free(struct set_entry * entry)102 entry_is_free(struct set_entry *entry)
103 {
104 return entry->key == NULL;
105 }
106
107 static int
entry_is_deleted(struct set_entry * entry)108 entry_is_deleted(struct set_entry *entry)
109 {
110 return entry->key == deleted_key;
111 }
112
113 static int
entry_is_present(struct set_entry * entry)114 entry_is_present(struct set_entry *entry)
115 {
116 return entry->key != NULL && entry->key != deleted_key;
117 }
118
119 bool
_mesa_set_init(struct set * ht,void * mem_ctx,uint32_t (* key_hash_function)(const void * key),bool (* key_equals_function)(const void * a,const void * b))120 _mesa_set_init(struct set *ht, void *mem_ctx,
121 uint32_t (*key_hash_function)(const void *key),
122 bool (*key_equals_function)(const void *a,
123 const void *b))
124 {
125 ht->size_index = 0;
126 ht->size = hash_sizes[ht->size_index].size;
127 ht->rehash = hash_sizes[ht->size_index].rehash;
128 ht->size_magic = hash_sizes[ht->size_index].size_magic;
129 ht->rehash_magic = hash_sizes[ht->size_index].rehash_magic;
130 ht->max_entries = hash_sizes[ht->size_index].max_entries;
131 ht->key_hash_function = key_hash_function;
132 ht->key_equals_function = key_equals_function;
133 ht->table = rzalloc_array(mem_ctx, struct set_entry, ht->size);
134 ht->entries = 0;
135 ht->deleted_entries = 0;
136
137 return ht->table != NULL;
138 }
139
140 struct set *
_mesa_set_create(void * mem_ctx,uint32_t (* key_hash_function)(const void * key),bool (* key_equals_function)(const void * a,const void * b))141 _mesa_set_create(void *mem_ctx,
142 uint32_t (*key_hash_function)(const void *key),
143 bool (*key_equals_function)(const void *a,
144 const void *b))
145 {
146 struct set *ht;
147
148 ht = ralloc(mem_ctx, struct set);
149 if (ht == NULL)
150 return NULL;
151
152 if (!_mesa_set_init(ht, ht, key_hash_function, key_equals_function)) {
153 ralloc_free(ht);
154 return NULL;
155 }
156
157 return ht;
158 }
159
160 static uint32_t
key_u32_hash(const void * key)161 key_u32_hash(const void *key)
162 {
163 uint32_t u = (uint32_t)(uintptr_t)key;
164 return _mesa_hash_uint(&u);
165 }
166
167 static bool
key_u32_equals(const void * a,const void * b)168 key_u32_equals(const void *a, const void *b)
169 {
170 return (uint32_t)(uintptr_t)a == (uint32_t)(uintptr_t)b;
171 }
172
173 /* key == 0 and key == deleted_key are not allowed */
174 struct set *
_mesa_set_create_u32_keys(void * mem_ctx)175 _mesa_set_create_u32_keys(void *mem_ctx)
176 {
177 return _mesa_set_create(mem_ctx, key_u32_hash, key_u32_equals);
178 }
179
180 struct set *
_mesa_set_clone(struct set * set,void * dst_mem_ctx)181 _mesa_set_clone(struct set *set, void *dst_mem_ctx)
182 {
183 struct set *clone;
184
185 clone = ralloc(dst_mem_ctx, struct set);
186 if (clone == NULL)
187 return NULL;
188
189 memcpy(clone, set, sizeof(struct set));
190
191 clone->table = ralloc_array(clone, struct set_entry, clone->size);
192 if (clone->table == NULL) {
193 ralloc_free(clone);
194 return NULL;
195 }
196
197 memcpy(clone->table, set->table, clone->size * sizeof(struct set_entry));
198
199 return clone;
200 }
201
202 /**
203 * Frees the given set.
204 *
205 * If delete_function is passed, it gets called on each entry present before
206 * freeing.
207 */
208 void
_mesa_set_destroy(struct set * ht,void (* delete_function)(struct set_entry * entry))209 _mesa_set_destroy(struct set *ht, void (*delete_function)(struct set_entry *entry))
210 {
211 if (!ht)
212 return;
213
214 if (delete_function) {
215 set_foreach (ht, entry) {
216 delete_function(entry);
217 }
218 }
219 ralloc_free(ht->table);
220 ralloc_free(ht);
221 }
222
223
224 static void
set_clear_fast(struct set * ht)225 set_clear_fast(struct set *ht)
226 {
227 memset(ht->table, 0, sizeof(struct set_entry) * hash_sizes[ht->size_index].size);
228 ht->entries = ht->deleted_entries = 0;
229 }
230
231 /**
232 * Clears all values from the given set.
233 *
234 * If delete_function is passed, it gets called on each entry present before
235 * the set is cleared.
236 */
237 void
_mesa_set_clear(struct set * set,void (* delete_function)(struct set_entry * entry))238 _mesa_set_clear(struct set *set, void (*delete_function)(struct set_entry *entry))
239 {
240 if (!set)
241 return;
242
243 struct set_entry *entry;
244
245 if (delete_function) {
246 for (entry = set->table; entry != set->table + set->size; entry++) {
247 if (entry_is_present(entry))
248 delete_function(entry);
249
250 entry->key = NULL;
251 }
252 set->entries = 0;
253 set->deleted_entries = 0;
254 } else
255 set_clear_fast(set);
256 }
257
258 /**
259 * Finds a set entry with the given key and hash of that key.
260 *
261 * Returns NULL if no entry is found.
262 */
263 static struct set_entry *
set_search(const struct set * ht,uint32_t hash,const void * key)264 set_search(const struct set *ht, uint32_t hash, const void *key)
265 {
266 assert(!key_pointer_is_reserved(key));
267
268 uint32_t size = ht->size;
269 uint32_t start_address = util_fast_urem32(hash, size, ht->size_magic);
270 uint32_t double_hash = util_fast_urem32(hash, ht->rehash,
271 ht->rehash_magic) + 1;
272 uint32_t hash_address = start_address;
273 do {
274 struct set_entry *entry = ht->table + hash_address;
275
276 if (entry_is_free(entry)) {
277 return NULL;
278 } else if (entry_is_present(entry) && entry->hash == hash) {
279 if (ht->key_equals_function(key, entry->key)) {
280 return entry;
281 }
282 }
283
284 hash_address += double_hash;
285 if (hash_address >= size)
286 hash_address -= size;
287 } while (hash_address != start_address);
288
289 return NULL;
290 }
291
292 struct set_entry *
_mesa_set_search(const struct set * set,const void * key)293 _mesa_set_search(const struct set *set, const void *key)
294 {
295 assert(set->key_hash_function);
296 return set_search(set, set->key_hash_function(key), key);
297 }
298
299 struct set_entry *
_mesa_set_search_pre_hashed(const struct set * set,uint32_t hash,const void * key)300 _mesa_set_search_pre_hashed(const struct set *set, uint32_t hash,
301 const void *key)
302 {
303 assert(set->key_hash_function == NULL ||
304 hash == set->key_hash_function(key));
305 return set_search(set, hash, key);
306 }
307
308 static void
set_add_rehash(struct set * ht,uint32_t hash,const void * key)309 set_add_rehash(struct set *ht, uint32_t hash, const void *key)
310 {
311 uint32_t size = ht->size;
312 uint32_t start_address = util_fast_urem32(hash, size, ht->size_magic);
313 uint32_t double_hash = util_fast_urem32(hash, ht->rehash,
314 ht->rehash_magic) + 1;
315 uint32_t hash_address = start_address;
316 do {
317 struct set_entry *entry = ht->table + hash_address;
318 if (likely(entry->key == NULL)) {
319 entry->hash = hash;
320 entry->key = key;
321 return;
322 }
323
324 hash_address = hash_address + double_hash;
325 if (hash_address >= size)
326 hash_address -= size;
327 } while (true);
328 }
329
330 static void
set_rehash(struct set * ht,unsigned new_size_index)331 set_rehash(struct set *ht, unsigned new_size_index)
332 {
333 struct set old_ht;
334 struct set_entry *table;
335
336 if (ht->size_index == new_size_index && ht->deleted_entries == ht->max_entries) {
337 set_clear_fast(ht);
338 assert(!ht->entries);
339 return;
340 }
341
342 if (new_size_index >= ARRAY_SIZE(hash_sizes))
343 return;
344
345 table = rzalloc_array(ralloc_parent(ht->table), struct set_entry,
346 hash_sizes[new_size_index].size);
347 if (table == NULL)
348 return;
349
350 old_ht = *ht;
351
352 ht->table = table;
353 ht->size_index = new_size_index;
354 ht->size = hash_sizes[ht->size_index].size;
355 ht->rehash = hash_sizes[ht->size_index].rehash;
356 ht->size_magic = hash_sizes[ht->size_index].size_magic;
357 ht->rehash_magic = hash_sizes[ht->size_index].rehash_magic;
358 ht->max_entries = hash_sizes[ht->size_index].max_entries;
359 ht->entries = 0;
360 ht->deleted_entries = 0;
361
362 set_foreach(&old_ht, entry) {
363 set_add_rehash(ht, entry->hash, entry->key);
364 }
365
366 ht->entries = old_ht.entries;
367
368 ralloc_free(old_ht.table);
369 }
370
371 void
_mesa_set_resize(struct set * set,uint32_t entries)372 _mesa_set_resize(struct set *set, uint32_t entries)
373 {
374 /* You can't shrink a set below its number of entries */
375 if (set->entries > entries)
376 entries = set->entries;
377
378 unsigned size_index = 0;
379 while (hash_sizes[size_index].max_entries < entries)
380 size_index++;
381
382 set_rehash(set, size_index);
383 }
384
385 /**
386 * Find a matching entry for the given key, or insert it if it doesn't already
387 * exist.
388 *
389 * Note that insertion may rearrange the table on a resize or rehash,
390 * so previously found hash_entries are no longer valid after this function.
391 */
392 static struct set_entry *
set_search_or_add(struct set * ht,uint32_t hash,const void * key,bool * found)393 set_search_or_add(struct set *ht, uint32_t hash, const void *key, bool *found)
394 {
395 struct set_entry *available_entry = NULL;
396
397 assert(!key_pointer_is_reserved(key));
398
399 if (ht->entries >= ht->max_entries) {
400 set_rehash(ht, ht->size_index + 1);
401 } else if (ht->deleted_entries + ht->entries >= ht->max_entries) {
402 set_rehash(ht, ht->size_index);
403 }
404
405 uint32_t size = ht->size;
406 uint32_t start_address = util_fast_urem32(hash, size, ht->size_magic);
407 uint32_t double_hash = util_fast_urem32(hash, ht->rehash,
408 ht->rehash_magic) + 1;
409 uint32_t hash_address = start_address;
410 do {
411 struct set_entry *entry = ht->table + hash_address;
412
413 if (!entry_is_present(entry)) {
414 /* Stash the first available entry we find */
415 if (available_entry == NULL)
416 available_entry = entry;
417 if (entry_is_free(entry))
418 break;
419 }
420
421 if (!entry_is_deleted(entry) &&
422 entry->hash == hash &&
423 ht->key_equals_function(key, entry->key)) {
424 if (found)
425 *found = true;
426 return entry;
427 }
428
429 hash_address = hash_address + double_hash;
430 if (hash_address >= size)
431 hash_address -= size;
432 } while (hash_address != start_address);
433
434 if (available_entry) {
435 /* There is no matching entry, create it. */
436 if (entry_is_deleted(available_entry))
437 ht->deleted_entries--;
438 available_entry->hash = hash;
439 available_entry->key = key;
440 ht->entries++;
441 if (found)
442 *found = false;
443 return available_entry;
444 }
445
446 /* We could hit here if a required resize failed. An unchecked-malloc
447 * application could ignore this result.
448 */
449 return NULL;
450 }
451
452 /**
453 * Inserts the key with the given hash into the table.
454 *
455 * Note that insertion may rearrange the table on a resize or rehash,
456 * so previously found hash_entries are no longer valid after this function.
457 */
458 static struct set_entry *
set_add(struct set * ht,uint32_t hash,const void * key)459 set_add(struct set *ht, uint32_t hash, const void *key)
460 {
461 struct set_entry *entry = set_search_or_add(ht, hash, key, NULL);
462
463 if (unlikely(!entry))
464 return NULL;
465
466 /* Note: If a matching entry already exists, this will replace it. This is
467 * a relatively common feature of hash tables, with the alternative
468 * generally being "insert the new value as well, and return it first when
469 * the key is searched for".
470 *
471 * Note that the hash table doesn't have a delete callback. If freeing of
472 * old keys is required to avoid memory leaks, use the alternative
473 * _mesa_set_search_or_add function and implement the replacement yourself.
474 */
475 entry->key = key;
476 return entry;
477 }
478
479 struct set_entry *
_mesa_set_add(struct set * set,const void * key)480 _mesa_set_add(struct set *set, const void *key)
481 {
482 assert(set->key_hash_function);
483 return set_add(set, set->key_hash_function(key), key);
484 }
485
486 struct set_entry *
_mesa_set_add_pre_hashed(struct set * set,uint32_t hash,const void * key)487 _mesa_set_add_pre_hashed(struct set *set, uint32_t hash, const void *key)
488 {
489 assert(set->key_hash_function == NULL ||
490 hash == set->key_hash_function(key));
491 return set_add(set, hash, key);
492 }
493
494 struct set_entry *
_mesa_set_search_and_add(struct set * set,const void * key,bool * replaced)495 _mesa_set_search_and_add(struct set *set, const void *key, bool *replaced)
496 {
497 assert(set->key_hash_function);
498 return _mesa_set_search_and_add_pre_hashed(set,
499 set->key_hash_function(key),
500 key, replaced);
501 }
502
503 struct set_entry *
_mesa_set_search_and_add_pre_hashed(struct set * set,uint32_t hash,const void * key,bool * replaced)504 _mesa_set_search_and_add_pre_hashed(struct set *set, uint32_t hash,
505 const void *key, bool *replaced)
506 {
507 assert(set->key_hash_function == NULL ||
508 hash == set->key_hash_function(key));
509 struct set_entry *entry = set_search_or_add(set, hash, key, replaced);
510
511 if (unlikely(!entry))
512 return NULL;
513
514 /* This implements the replacement, same as _mesa_set_add(). The user will
515 * be notified if we're overwriting a found entry.
516 */
517 entry->key = key;
518 return entry;
519 }
520
521 struct set_entry *
_mesa_set_search_or_add(struct set * set,const void * key,bool * found)522 _mesa_set_search_or_add(struct set *set, const void *key, bool *found)
523 {
524 assert(set->key_hash_function);
525 return set_search_or_add(set, set->key_hash_function(key), key, found);
526 }
527
528 struct set_entry *
_mesa_set_search_or_add_pre_hashed(struct set * set,uint32_t hash,const void * key,bool * found)529 _mesa_set_search_or_add_pre_hashed(struct set *set, uint32_t hash,
530 const void *key, bool *found)
531 {
532 assert(set->key_hash_function == NULL ||
533 hash == set->key_hash_function(key));
534 return set_search_or_add(set, hash, key, found);
535 }
536
537 /**
538 * This function deletes the given hash table entry.
539 *
540 * Note that deletion doesn't otherwise modify the table, so an iteration over
541 * the table deleting entries is safe.
542 */
543 void
_mesa_set_remove(struct set * ht,struct set_entry * entry)544 _mesa_set_remove(struct set *ht, struct set_entry *entry)
545 {
546 if (!entry)
547 return;
548
549 entry->key = deleted_key;
550 ht->entries--;
551 ht->deleted_entries++;
552 }
553
554 /**
555 * Removes the entry with the corresponding key, if exists.
556 */
557 void
_mesa_set_remove_key(struct set * set,const void * key)558 _mesa_set_remove_key(struct set *set, const void *key)
559 {
560 _mesa_set_remove(set, _mesa_set_search(set, key));
561 }
562
563 /**
564 * This function is an iterator over the set when no deleted entries are present.
565 *
566 * Pass in NULL for the first entry, as in the start of a for loop.
567 */
568 struct set_entry *
_mesa_set_next_entry_unsafe(const struct set * ht,struct set_entry * entry)569 _mesa_set_next_entry_unsafe(const struct set *ht, struct set_entry *entry)
570 {
571 assert(!ht->deleted_entries);
572 if (!ht->entries)
573 return NULL;
574 if (entry == NULL)
575 entry = ht->table;
576 else
577 entry = entry + 1;
578 if (entry != ht->table + ht->size)
579 return entry->key ? entry : _mesa_set_next_entry_unsafe(ht, entry);
580
581 return NULL;
582 }
583
584 /**
585 * This function is an iterator over the hash table.
586 *
587 * Pass in NULL for the first entry, as in the start of a for loop. Note that
588 * an iteration over the table is O(table_size) not O(entries).
589 */
590 struct set_entry *
_mesa_set_next_entry(const struct set * ht,struct set_entry * entry)591 _mesa_set_next_entry(const struct set *ht, struct set_entry *entry)
592 {
593 if (entry == NULL)
594 entry = ht->table;
595 else
596 entry = entry + 1;
597
598 for (; entry != ht->table + ht->size; entry++) {
599 if (entry_is_present(entry)) {
600 return entry;
601 }
602 }
603
604 return NULL;
605 }
606
607 struct set_entry *
_mesa_set_random_entry(struct set * ht,int (* predicate)(struct set_entry * entry))608 _mesa_set_random_entry(struct set *ht,
609 int (*predicate)(struct set_entry *entry))
610 {
611 struct set_entry *entry;
612 uint32_t i = rand() % ht->size;
613
614 if (ht->entries == 0)
615 return NULL;
616
617 for (entry = ht->table + i; entry != ht->table + ht->size; entry++) {
618 if (entry_is_present(entry) &&
619 (!predicate || predicate(entry))) {
620 return entry;
621 }
622 }
623
624 for (entry = ht->table; entry != ht->table + i; entry++) {
625 if (entry_is_present(entry) &&
626 (!predicate || predicate(entry))) {
627 return entry;
628 }
629 }
630
631 return NULL;
632 }
633
634 /**
635 * Helper to create a set with pointer keys.
636 */
637 struct set *
_mesa_pointer_set_create(void * mem_ctx)638 _mesa_pointer_set_create(void *mem_ctx)
639 {
640 return _mesa_set_create(mem_ctx, _mesa_hash_pointer,
641 _mesa_key_pointer_equal);
642 }
643
644 bool
_mesa_set_intersects(struct set * a,struct set * b)645 _mesa_set_intersects(struct set *a, struct set *b)
646 {
647 assert(a->key_hash_function == b->key_hash_function);
648 assert(a->key_equals_function == b->key_equals_function);
649
650 /* iterate over the set with less entries */
651 if (b->entries < a->entries) {
652 struct set *tmp = a;
653 a = b;
654 b = tmp;
655 }
656
657 set_foreach(a, entry) {
658 if (_mesa_set_search_pre_hashed(b, entry->hash, entry->key))
659 return true;
660 }
661 return false;
662 }
663