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 51static const uint32_t deleted_key_value; 52static const void *deleted_key = &deleted_key_value; 53 54static 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 95ASSERTED static inline bool 96key_pointer_is_reserved(const void *key) 97{ 98 return key == NULL || key == deleted_key; 99} 100 101static int 102entry_is_free(struct set_entry *entry) 103{ 104 return entry->key == NULL; 105} 106 107static int 108entry_is_deleted(struct set_entry *entry) 109{ 110 return entry->key == deleted_key; 111} 112 113static int 114entry_is_present(struct set_entry *entry) 115{ 116 return entry->key != NULL && entry->key != deleted_key; 117} 118 119bool 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 140struct set * 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 160static uint32_t 161key_u32_hash(const void *key) 162{ 163 uint32_t u = (uint32_t)(uintptr_t)key; 164 return _mesa_hash_uint(&u); 165} 166 167static bool 168key_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 */ 174struct set * 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 180struct set * 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 */ 208void 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 224static void 225set_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 */ 237void 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 */ 263static struct set_entry * 264set_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 292struct set_entry * 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 299struct set_entry * 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 308static void 309set_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 330static void 331set_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 371void 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 */ 392static struct set_entry * 393set_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 */ 458static struct set_entry * 459set_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 479struct set_entry * 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 486struct set_entry * 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 494struct set_entry * 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 503struct set_entry * 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 521struct set_entry * 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 528struct set_entry * 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 */ 543void 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 */ 557void 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 */ 568struct set_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 */ 590struct set_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 607struct set_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 */ 637struct set * 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 644bool 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