1af69d88dSmrg/* 2af69d88dSmrg * Copyright © 2009,2012 Intel Corporation 3af69d88dSmrg * Copyright © 1988-2004 Keith Packard and Bart Massey. 4af69d88dSmrg * 5af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 6af69d88dSmrg * copy of this software and associated documentation files (the "Software"), 7af69d88dSmrg * to deal in the Software without restriction, including without limitation 8af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the 10af69d88dSmrg * Software is furnished to do so, subject to the following conditions: 11af69d88dSmrg * 12af69d88dSmrg * The above copyright notice and this permission notice (including the next 13af69d88dSmrg * paragraph) shall be included in all copies or substantial portions of the 14af69d88dSmrg * Software. 15af69d88dSmrg * 16af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17af69d88dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20af69d88dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21af69d88dSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22af69d88dSmrg * IN THE SOFTWARE. 23af69d88dSmrg * 24af69d88dSmrg * Except as contained in this notice, the names of the authors 25af69d88dSmrg * or their institutions shall not be used in advertising or 26af69d88dSmrg * otherwise to promote the sale, use or other dealings in this 27af69d88dSmrg * Software without prior written authorization from the 28af69d88dSmrg * authors. 29af69d88dSmrg * 30af69d88dSmrg * Authors: 31af69d88dSmrg * Eric Anholt <eric@anholt.net> 32af69d88dSmrg * Keith Packard <keithp@keithp.com> 33af69d88dSmrg */ 34af69d88dSmrg 35af69d88dSmrg/** 36af69d88dSmrg * Implements an open-addressing, linear-reprobing hash table. 37af69d88dSmrg * 38af69d88dSmrg * For more information, see: 39af69d88dSmrg * 40af69d88dSmrg * http://cgit.freedesktop.org/~anholt/hash_table/tree/README 41af69d88dSmrg */ 42af69d88dSmrg 43af69d88dSmrg#include <stdlib.h> 44af69d88dSmrg#include <string.h> 4501e04c3fSmrg#include <assert.h> 46af69d88dSmrg 47af69d88dSmrg#include "hash_table.h" 48af69d88dSmrg#include "ralloc.h" 49af69d88dSmrg#include "macros.h" 507ec681f3Smrg#include "u_memory.h" 517ec681f3Smrg#include "fast_urem_by_const.h" 527ec681f3Smrg#include "util/u_memory.h" 537ec681f3Smrg 547ec681f3Smrg#define XXH_INLINE_ALL 557ec681f3Smrg#include "xxhash.h" 567ec681f3Smrg 577ec681f3Smrg/** 587ec681f3Smrg * Magic number that gets stored outside of the struct hash_table. 597ec681f3Smrg * 607ec681f3Smrg * The hash table needs a particular pointer to be the marker for a key that 617ec681f3Smrg * was deleted from the table, along with NULL for the "never allocated in the 627ec681f3Smrg * table" marker. Legacy GL allows any GLuint to be used as a GL object name, 637ec681f3Smrg * and we use a 1:1 mapping from GLuints to key pointers, so we need to be 647ec681f3Smrg * able to track a GLuint that happens to match the deleted key outside of 657ec681f3Smrg * struct hash_table. We tell the hash table to use "1" as the deleted key 667ec681f3Smrg * value, so that we test the deleted-key-in-the-table path as best we can. 677ec681f3Smrg */ 687ec681f3Smrg#define DELETED_KEY_VALUE 1 697ec681f3Smrg 707ec681f3Smrgstatic inline void * 717ec681f3Smrguint_key(unsigned id) 727ec681f3Smrg{ 737ec681f3Smrg return (void *)(uintptr_t) id; 747ec681f3Smrg} 75af69d88dSmrg 76af69d88dSmrgstatic const uint32_t deleted_key_value; 77af69d88dSmrg 78af69d88dSmrg/** 79af69d88dSmrg * From Knuth -- a good choice for hash/rehash values is p, p-2 where 80af69d88dSmrg * p and p-2 are both prime. These tables are sized to have an extra 10% 81af69d88dSmrg * free to avoid exponential performance degradation as the hash table fills 82af69d88dSmrg */ 83af69d88dSmrgstatic const struct { 84af69d88dSmrg uint32_t max_entries, size, rehash; 857ec681f3Smrg uint64_t size_magic, rehash_magic; 86af69d88dSmrg} hash_sizes[] = { 877ec681f3Smrg#define ENTRY(max_entries, size, rehash) \ 887ec681f3Smrg { max_entries, size, rehash, \ 897ec681f3Smrg REMAINDER_MAGIC(size), REMAINDER_MAGIC(rehash) } 907ec681f3Smrg 917ec681f3Smrg ENTRY(2, 5, 3 ), 927ec681f3Smrg ENTRY(4, 7, 5 ), 937ec681f3Smrg ENTRY(8, 13, 11 ), 947ec681f3Smrg ENTRY(16, 19, 17 ), 957ec681f3Smrg ENTRY(32, 43, 41 ), 967ec681f3Smrg ENTRY(64, 73, 71 ), 977ec681f3Smrg ENTRY(128, 151, 149 ), 987ec681f3Smrg ENTRY(256, 283, 281 ), 997ec681f3Smrg ENTRY(512, 571, 569 ), 1007ec681f3Smrg ENTRY(1024, 1153, 1151 ), 1017ec681f3Smrg ENTRY(2048, 2269, 2267 ), 1027ec681f3Smrg ENTRY(4096, 4519, 4517 ), 1037ec681f3Smrg ENTRY(8192, 9013, 9011 ), 1047ec681f3Smrg ENTRY(16384, 18043, 18041 ), 1057ec681f3Smrg ENTRY(32768, 36109, 36107 ), 1067ec681f3Smrg ENTRY(65536, 72091, 72089 ), 1077ec681f3Smrg ENTRY(131072, 144409, 144407 ), 1087ec681f3Smrg ENTRY(262144, 288361, 288359 ), 1097ec681f3Smrg ENTRY(524288, 576883, 576881 ), 1107ec681f3Smrg ENTRY(1048576, 1153459, 1153457 ), 1117ec681f3Smrg ENTRY(2097152, 2307163, 2307161 ), 1127ec681f3Smrg ENTRY(4194304, 4613893, 4613891 ), 1137ec681f3Smrg ENTRY(8388608, 9227641, 9227639 ), 1147ec681f3Smrg ENTRY(16777216, 18455029, 18455027 ), 1157ec681f3Smrg ENTRY(33554432, 36911011, 36911009 ), 1167ec681f3Smrg ENTRY(67108864, 73819861, 73819859 ), 1177ec681f3Smrg ENTRY(134217728, 147639589, 147639587 ), 1187ec681f3Smrg ENTRY(268435456, 295279081, 295279079 ), 1197ec681f3Smrg ENTRY(536870912, 590559793, 590559791 ), 1207ec681f3Smrg ENTRY(1073741824, 1181116273, 1181116271 ), 1217ec681f3Smrg ENTRY(2147483648ul, 2362232233ul, 2362232231ul ) 122af69d88dSmrg}; 123af69d88dSmrg 1247ec681f3SmrgASSERTED static inline bool 1257ec681f3Smrgkey_pointer_is_reserved(const struct hash_table *ht, const void *key) 1267ec681f3Smrg{ 1277ec681f3Smrg return key == NULL || key == ht->deleted_key; 1287ec681f3Smrg} 1297ec681f3Smrg 130af69d88dSmrgstatic int 131af69d88dSmrgentry_is_free(const struct hash_entry *entry) 132af69d88dSmrg{ 133af69d88dSmrg return entry->key == NULL; 134af69d88dSmrg} 135af69d88dSmrg 136af69d88dSmrgstatic int 137af69d88dSmrgentry_is_deleted(const struct hash_table *ht, struct hash_entry *entry) 138af69d88dSmrg{ 139af69d88dSmrg return entry->key == ht->deleted_key; 140af69d88dSmrg} 141af69d88dSmrg 142af69d88dSmrgstatic int 143af69d88dSmrgentry_is_present(const struct hash_table *ht, struct hash_entry *entry) 144af69d88dSmrg{ 145af69d88dSmrg return entry->key != NULL && entry->key != ht->deleted_key; 146af69d88dSmrg} 147af69d88dSmrg 1488a1362adSmayabool 1498a1362adSmaya_mesa_hash_table_init(struct hash_table *ht, 1508a1362adSmaya void *mem_ctx, 1518a1362adSmaya uint32_t (*key_hash_function)(const void *key), 1528a1362adSmaya bool (*key_equals_function)(const void *a, 1538a1362adSmaya const void *b)) 1548a1362adSmaya{ 1558a1362adSmaya ht->size_index = 0; 1568a1362adSmaya ht->size = hash_sizes[ht->size_index].size; 1578a1362adSmaya ht->rehash = hash_sizes[ht->size_index].rehash; 1587ec681f3Smrg ht->size_magic = hash_sizes[ht->size_index].size_magic; 1597ec681f3Smrg ht->rehash_magic = hash_sizes[ht->size_index].rehash_magic; 1608a1362adSmaya ht->max_entries = hash_sizes[ht->size_index].max_entries; 1618a1362adSmaya ht->key_hash_function = key_hash_function; 1628a1362adSmaya ht->key_equals_function = key_equals_function; 1638a1362adSmaya ht->table = rzalloc_array(mem_ctx, struct hash_entry, ht->size); 1648a1362adSmaya ht->entries = 0; 1658a1362adSmaya ht->deleted_entries = 0; 1668a1362adSmaya ht->deleted_key = &deleted_key_value; 1678a1362adSmaya 1688a1362adSmaya return ht->table != NULL; 1698a1362adSmaya} 1708a1362adSmaya 171af69d88dSmrgstruct hash_table * 172af69d88dSmrg_mesa_hash_table_create(void *mem_ctx, 17301e04c3fSmrg uint32_t (*key_hash_function)(const void *key), 174af69d88dSmrg bool (*key_equals_function)(const void *a, 175af69d88dSmrg const void *b)) 176af69d88dSmrg{ 177af69d88dSmrg struct hash_table *ht; 178af69d88dSmrg 1798a1362adSmaya /* mem_ctx is used to allocate the hash table, but the hash table is used 1808a1362adSmaya * to allocate all of the suballocations. 1818a1362adSmaya */ 182af69d88dSmrg ht = ralloc(mem_ctx, struct hash_table); 183af69d88dSmrg if (ht == NULL) 184af69d88dSmrg return NULL; 185af69d88dSmrg 1868a1362adSmaya if (!_mesa_hash_table_init(ht, ht, key_hash_function, key_equals_function)) { 187af69d88dSmrg ralloc_free(ht); 188af69d88dSmrg return NULL; 189af69d88dSmrg } 190af69d88dSmrg 191af69d88dSmrg return ht; 192af69d88dSmrg} 193af69d88dSmrg 1947ec681f3Smrgstatic uint32_t 1957ec681f3Smrgkey_u32_hash(const void *key) 1967ec681f3Smrg{ 1977ec681f3Smrg uint32_t u = (uint32_t)(uintptr_t)key; 1987ec681f3Smrg return _mesa_hash_uint(&u); 1997ec681f3Smrg} 2007ec681f3Smrg 2017ec681f3Smrgstatic bool 2027ec681f3Smrgkey_u32_equals(const void *a, const void *b) 2037ec681f3Smrg{ 2047ec681f3Smrg return (uint32_t)(uintptr_t)a == (uint32_t)(uintptr_t)b; 2057ec681f3Smrg} 2067ec681f3Smrg 2077ec681f3Smrg/* key == 0 and key == deleted_key are not allowed */ 2087ec681f3Smrgstruct hash_table * 2097ec681f3Smrg_mesa_hash_table_create_u32_keys(void *mem_ctx) 2107ec681f3Smrg{ 2117ec681f3Smrg return _mesa_hash_table_create(mem_ctx, key_u32_hash, key_u32_equals); 2127ec681f3Smrg} 2137ec681f3Smrg 21401e04c3fSmrgstruct hash_table * 21501e04c3fSmrg_mesa_hash_table_clone(struct hash_table *src, void *dst_mem_ctx) 21601e04c3fSmrg{ 21701e04c3fSmrg struct hash_table *ht; 21801e04c3fSmrg 21901e04c3fSmrg ht = ralloc(dst_mem_ctx, struct hash_table); 22001e04c3fSmrg if (ht == NULL) 22101e04c3fSmrg return NULL; 22201e04c3fSmrg 22301e04c3fSmrg memcpy(ht, src, sizeof(struct hash_table)); 22401e04c3fSmrg 22501e04c3fSmrg ht->table = ralloc_array(ht, struct hash_entry, ht->size); 22601e04c3fSmrg if (ht->table == NULL) { 22701e04c3fSmrg ralloc_free(ht); 22801e04c3fSmrg return NULL; 22901e04c3fSmrg } 23001e04c3fSmrg 23101e04c3fSmrg memcpy(ht->table, src->table, ht->size * sizeof(struct hash_entry)); 23201e04c3fSmrg 23301e04c3fSmrg return ht; 23401e04c3fSmrg} 23501e04c3fSmrg 236af69d88dSmrg/** 237af69d88dSmrg * Frees the given hash table. 238af69d88dSmrg * 239af69d88dSmrg * If delete_function is passed, it gets called on each entry present before 240af69d88dSmrg * freeing. 241af69d88dSmrg */ 242af69d88dSmrgvoid 243af69d88dSmrg_mesa_hash_table_destroy(struct hash_table *ht, 244af69d88dSmrg void (*delete_function)(struct hash_entry *entry)) 245af69d88dSmrg{ 246af69d88dSmrg if (!ht) 247af69d88dSmrg return; 248af69d88dSmrg 249af69d88dSmrg if (delete_function) { 250af69d88dSmrg hash_table_foreach(ht, entry) { 251af69d88dSmrg delete_function(entry); 252af69d88dSmrg } 253af69d88dSmrg } 254af69d88dSmrg ralloc_free(ht); 255af69d88dSmrg} 256af69d88dSmrg 2577ec681f3Smrgstatic void 2587ec681f3Smrghash_table_clear_fast(struct hash_table *ht) 2597ec681f3Smrg{ 2607ec681f3Smrg memset(ht->table, 0, sizeof(struct hash_entry) * hash_sizes[ht->size_index].size); 2617ec681f3Smrg ht->entries = ht->deleted_entries = 0; 2627ec681f3Smrg} 2637ec681f3Smrg 26401e04c3fSmrg/** 26501e04c3fSmrg * Deletes all entries of the given hash table without deleting the table 26601e04c3fSmrg * itself or changing its structure. 26701e04c3fSmrg * 26801e04c3fSmrg * If delete_function is passed, it gets called on each entry present. 26901e04c3fSmrg */ 27001e04c3fSmrgvoid 27101e04c3fSmrg_mesa_hash_table_clear(struct hash_table *ht, 27201e04c3fSmrg void (*delete_function)(struct hash_entry *entry)) 27301e04c3fSmrg{ 2747ec681f3Smrg if (!ht) 2757ec681f3Smrg return; 27601e04c3fSmrg 2777ec681f3Smrg struct hash_entry *entry; 27801e04c3fSmrg 2797ec681f3Smrg if (delete_function) { 2807ec681f3Smrg for (entry = ht->table; entry != ht->table + ht->size; entry++) { 2817ec681f3Smrg if (entry_is_present(ht, entry)) 2827ec681f3Smrg delete_function(entry); 28301e04c3fSmrg 2847ec681f3Smrg entry->key = NULL; 2857ec681f3Smrg } 2867ec681f3Smrg ht->entries = 0; 2877ec681f3Smrg ht->deleted_entries = 0; 2887ec681f3Smrg } else 2897ec681f3Smrg hash_table_clear_fast(ht); 29001e04c3fSmrg} 29101e04c3fSmrg 292af69d88dSmrg/** Sets the value of the key pointer used for deleted entries in the table. 293af69d88dSmrg * 294af69d88dSmrg * The assumption is that usually keys are actual pointers, so we use a 295af69d88dSmrg * default value of a pointer to an arbitrary piece of storage in the library. 296af69d88dSmrg * But in some cases a consumer wants to store some other sort of value in the 297af69d88dSmrg * table, like a uint32_t, in which case that pointer may conflict with one of 298af69d88dSmrg * their valid keys. This lets that user select a safe value. 299af69d88dSmrg * 300af69d88dSmrg * This must be called before any keys are actually deleted from the table. 301af69d88dSmrg */ 302af69d88dSmrgvoid 303af69d88dSmrg_mesa_hash_table_set_deleted_key(struct hash_table *ht, const void *deleted_key) 304af69d88dSmrg{ 305af69d88dSmrg ht->deleted_key = deleted_key; 306af69d88dSmrg} 307af69d88dSmrg 30801e04c3fSmrgstatic struct hash_entry * 30901e04c3fSmrghash_table_search(struct hash_table *ht, uint32_t hash, const void *key) 310af69d88dSmrg{ 3117ec681f3Smrg assert(!key_pointer_is_reserved(ht, key)); 3127ec681f3Smrg 3137ec681f3Smrg uint32_t size = ht->size; 3147ec681f3Smrg uint32_t start_hash_address = util_fast_urem32(hash, size, ht->size_magic); 3157ec681f3Smrg uint32_t double_hash = 1 + util_fast_urem32(hash, ht->rehash, 3167ec681f3Smrg ht->rehash_magic); 317af69d88dSmrg uint32_t hash_address = start_hash_address; 318af69d88dSmrg 319af69d88dSmrg do { 320af69d88dSmrg struct hash_entry *entry = ht->table + hash_address; 321af69d88dSmrg 322af69d88dSmrg if (entry_is_free(entry)) { 323af69d88dSmrg return NULL; 324af69d88dSmrg } else if (entry_is_present(ht, entry) && entry->hash == hash) { 325af69d88dSmrg if (ht->key_equals_function(key, entry->key)) { 326af69d88dSmrg return entry; 327af69d88dSmrg } 328af69d88dSmrg } 329af69d88dSmrg 3307ec681f3Smrg hash_address += double_hash; 3317ec681f3Smrg if (hash_address >= size) 3327ec681f3Smrg hash_address -= size; 333af69d88dSmrg } while (hash_address != start_hash_address); 334af69d88dSmrg 335af69d88dSmrg return NULL; 336af69d88dSmrg} 337af69d88dSmrg 33801e04c3fSmrg/** 33901e04c3fSmrg * Finds a hash table entry with the given key and hash of that key. 34001e04c3fSmrg * 34101e04c3fSmrg * Returns NULL if no entry is found. Note that the data pointer may be 34201e04c3fSmrg * modified by the user. 34301e04c3fSmrg */ 34401e04c3fSmrgstruct hash_entry * 34501e04c3fSmrg_mesa_hash_table_search(struct hash_table *ht, const void *key) 34601e04c3fSmrg{ 34701e04c3fSmrg assert(ht->key_hash_function); 34801e04c3fSmrg return hash_table_search(ht, ht->key_hash_function(key), key); 34901e04c3fSmrg} 35001e04c3fSmrg 35101e04c3fSmrgstruct hash_entry * 35201e04c3fSmrg_mesa_hash_table_search_pre_hashed(struct hash_table *ht, uint32_t hash, 35301e04c3fSmrg const void *key) 35401e04c3fSmrg{ 35501e04c3fSmrg assert(ht->key_hash_function == NULL || hash == ht->key_hash_function(key)); 35601e04c3fSmrg return hash_table_search(ht, hash, key); 35701e04c3fSmrg} 35801e04c3fSmrg 35901e04c3fSmrgstatic struct hash_entry * 36001e04c3fSmrghash_table_insert(struct hash_table *ht, uint32_t hash, 36101e04c3fSmrg const void *key, void *data); 36201e04c3fSmrg 3637ec681f3Smrgstatic void 3647ec681f3Smrghash_table_insert_rehash(struct hash_table *ht, uint32_t hash, 3657ec681f3Smrg const void *key, void *data) 3667ec681f3Smrg{ 3677ec681f3Smrg uint32_t size = ht->size; 3687ec681f3Smrg uint32_t start_hash_address = util_fast_urem32(hash, size, ht->size_magic); 3697ec681f3Smrg uint32_t double_hash = 1 + util_fast_urem32(hash, ht->rehash, 3707ec681f3Smrg ht->rehash_magic); 3717ec681f3Smrg uint32_t hash_address = start_hash_address; 3727ec681f3Smrg do { 3737ec681f3Smrg struct hash_entry *entry = ht->table + hash_address; 3747ec681f3Smrg 3757ec681f3Smrg if (likely(entry->key == NULL)) { 3767ec681f3Smrg entry->hash = hash; 3777ec681f3Smrg entry->key = key; 3787ec681f3Smrg entry->data = data; 3797ec681f3Smrg return; 3807ec681f3Smrg } 3817ec681f3Smrg 3827ec681f3Smrg hash_address += double_hash; 3837ec681f3Smrg if (hash_address >= size) 3847ec681f3Smrg hash_address -= size; 3857ec681f3Smrg } while (true); 3867ec681f3Smrg} 3877ec681f3Smrg 388af69d88dSmrgstatic void 38901e04c3fSmrg_mesa_hash_table_rehash(struct hash_table *ht, unsigned new_size_index) 390af69d88dSmrg{ 391af69d88dSmrg struct hash_table old_ht; 39201e04c3fSmrg struct hash_entry *table; 393af69d88dSmrg 3947ec681f3Smrg if (ht->size_index == new_size_index && ht->deleted_entries == ht->max_entries) { 3957ec681f3Smrg hash_table_clear_fast(ht); 3967ec681f3Smrg assert(!ht->entries); 3977ec681f3Smrg return; 3987ec681f3Smrg } 3997ec681f3Smrg 400af69d88dSmrg if (new_size_index >= ARRAY_SIZE(hash_sizes)) 401af69d88dSmrg return; 402af69d88dSmrg 4038a1362adSmaya table = rzalloc_array(ralloc_parent(ht->table), struct hash_entry, 404af69d88dSmrg hash_sizes[new_size_index].size); 405af69d88dSmrg if (table == NULL) 406af69d88dSmrg return; 407af69d88dSmrg 408af69d88dSmrg old_ht = *ht; 409af69d88dSmrg 410af69d88dSmrg ht->table = table; 411af69d88dSmrg ht->size_index = new_size_index; 412af69d88dSmrg ht->size = hash_sizes[ht->size_index].size; 413af69d88dSmrg ht->rehash = hash_sizes[ht->size_index].rehash; 4147ec681f3Smrg ht->size_magic = hash_sizes[ht->size_index].size_magic; 4157ec681f3Smrg ht->rehash_magic = hash_sizes[ht->size_index].rehash_magic; 416af69d88dSmrg ht->max_entries = hash_sizes[ht->size_index].max_entries; 417af69d88dSmrg ht->entries = 0; 418af69d88dSmrg ht->deleted_entries = 0; 419af69d88dSmrg 420af69d88dSmrg hash_table_foreach(&old_ht, entry) { 4217ec681f3Smrg hash_table_insert_rehash(ht, entry->hash, entry->key, entry->data); 422af69d88dSmrg } 423af69d88dSmrg 4247ec681f3Smrg ht->entries = old_ht.entries; 4257ec681f3Smrg 426af69d88dSmrg ralloc_free(old_ht.table); 427af69d88dSmrg} 428af69d88dSmrg 42901e04c3fSmrgstatic struct hash_entry * 43001e04c3fSmrghash_table_insert(struct hash_table *ht, uint32_t hash, 43101e04c3fSmrg const void *key, void *data) 432af69d88dSmrg{ 43301e04c3fSmrg struct hash_entry *available_entry = NULL; 43401e04c3fSmrg 4357ec681f3Smrg assert(!key_pointer_is_reserved(ht, key)); 436af69d88dSmrg 437af69d88dSmrg if (ht->entries >= ht->max_entries) { 438af69d88dSmrg _mesa_hash_table_rehash(ht, ht->size_index + 1); 439af69d88dSmrg } else if (ht->deleted_entries + ht->entries >= ht->max_entries) { 440af69d88dSmrg _mesa_hash_table_rehash(ht, ht->size_index); 441af69d88dSmrg } 442af69d88dSmrg 4437ec681f3Smrg uint32_t size = ht->size; 4447ec681f3Smrg uint32_t start_hash_address = util_fast_urem32(hash, size, ht->size_magic); 4457ec681f3Smrg uint32_t double_hash = 1 + util_fast_urem32(hash, ht->rehash, 4467ec681f3Smrg ht->rehash_magic); 4477ec681f3Smrg uint32_t hash_address = start_hash_address; 448af69d88dSmrg do { 449af69d88dSmrg struct hash_entry *entry = ht->table + hash_address; 450af69d88dSmrg 451af69d88dSmrg if (!entry_is_present(ht, entry)) { 45201e04c3fSmrg /* Stash the first available entry we find */ 45301e04c3fSmrg if (available_entry == NULL) 45401e04c3fSmrg available_entry = entry; 45501e04c3fSmrg if (entry_is_free(entry)) 45601e04c3fSmrg break; 457af69d88dSmrg } 458af69d88dSmrg 459af69d88dSmrg /* Implement replacement when another insert happens 460af69d88dSmrg * with a matching key. This is a relatively common 461af69d88dSmrg * feature of hash tables, with the alternative 462af69d88dSmrg * generally being "insert the new value as well, and 463af69d88dSmrg * return it first when the key is searched for". 464af69d88dSmrg * 465af69d88dSmrg * Note that the hash table doesn't have a delete 466af69d88dSmrg * callback. If freeing of old data pointers is 467af69d88dSmrg * required to avoid memory leaks, perform a search 468af69d88dSmrg * before inserting. 469af69d88dSmrg */ 47001e04c3fSmrg if (!entry_is_deleted(ht, entry) && 47101e04c3fSmrg entry->hash == hash && 472af69d88dSmrg ht->key_equals_function(key, entry->key)) { 473af69d88dSmrg entry->key = key; 474af69d88dSmrg entry->data = data; 475af69d88dSmrg return entry; 476af69d88dSmrg } 477af69d88dSmrg 4787ec681f3Smrg hash_address += double_hash; 4797ec681f3Smrg if (hash_address >= size) 4807ec681f3Smrg hash_address -= size; 481af69d88dSmrg } while (hash_address != start_hash_address); 482af69d88dSmrg 48301e04c3fSmrg if (available_entry) { 48401e04c3fSmrg if (entry_is_deleted(ht, available_entry)) 48501e04c3fSmrg ht->deleted_entries--; 48601e04c3fSmrg available_entry->hash = hash; 48701e04c3fSmrg available_entry->key = key; 48801e04c3fSmrg available_entry->data = data; 48901e04c3fSmrg ht->entries++; 49001e04c3fSmrg return available_entry; 49101e04c3fSmrg } 49201e04c3fSmrg 493af69d88dSmrg /* We could hit here if a required resize failed. An unchecked-malloc 494af69d88dSmrg * application could ignore this result. 495af69d88dSmrg */ 496af69d88dSmrg return NULL; 497af69d88dSmrg} 498af69d88dSmrg 49901e04c3fSmrg/** 50001e04c3fSmrg * Inserts the key with the given hash into the table. 50101e04c3fSmrg * 50201e04c3fSmrg * Note that insertion may rearrange the table on a resize or rehash, 50301e04c3fSmrg * so previously found hash_entries are no longer valid after this function. 50401e04c3fSmrg */ 50501e04c3fSmrgstruct hash_entry * 50601e04c3fSmrg_mesa_hash_table_insert(struct hash_table *ht, const void *key, void *data) 50701e04c3fSmrg{ 50801e04c3fSmrg assert(ht->key_hash_function); 50901e04c3fSmrg return hash_table_insert(ht, ht->key_hash_function(key), key, data); 51001e04c3fSmrg} 51101e04c3fSmrg 51201e04c3fSmrgstruct hash_entry * 51301e04c3fSmrg_mesa_hash_table_insert_pre_hashed(struct hash_table *ht, uint32_t hash, 51401e04c3fSmrg const void *key, void *data) 51501e04c3fSmrg{ 51601e04c3fSmrg assert(ht->key_hash_function == NULL || hash == ht->key_hash_function(key)); 51701e04c3fSmrg return hash_table_insert(ht, hash, key, data); 51801e04c3fSmrg} 51901e04c3fSmrg 520af69d88dSmrg/** 521af69d88dSmrg * This function deletes the given hash table entry. 522af69d88dSmrg * 523af69d88dSmrg * Note that deletion doesn't otherwise modify the table, so an iteration over 524af69d88dSmrg * the table deleting entries is safe. 525af69d88dSmrg */ 526af69d88dSmrgvoid 527af69d88dSmrg_mesa_hash_table_remove(struct hash_table *ht, 528af69d88dSmrg struct hash_entry *entry) 529af69d88dSmrg{ 530af69d88dSmrg if (!entry) 531af69d88dSmrg return; 532af69d88dSmrg 533af69d88dSmrg entry->key = ht->deleted_key; 534af69d88dSmrg ht->entries--; 535af69d88dSmrg ht->deleted_entries++; 536af69d88dSmrg} 537af69d88dSmrg 53801e04c3fSmrg/** 53901e04c3fSmrg * Removes the entry with the corresponding key, if exists. 54001e04c3fSmrg */ 54101e04c3fSmrgvoid _mesa_hash_table_remove_key(struct hash_table *ht, 54201e04c3fSmrg const void *key) 54301e04c3fSmrg{ 54401e04c3fSmrg _mesa_hash_table_remove(ht, _mesa_hash_table_search(ht, key)); 54501e04c3fSmrg} 54601e04c3fSmrg 5477ec681f3Smrg/** 5487ec681f3Smrg * This function is an iterator over the hash_table when no deleted entries are present. 5497ec681f3Smrg * 5507ec681f3Smrg * Pass in NULL for the first entry, as in the start of a for loop. 5517ec681f3Smrg */ 5527ec681f3Smrgstruct hash_entry * 5537ec681f3Smrg_mesa_hash_table_next_entry_unsafe(const struct hash_table *ht, struct hash_entry *entry) 5547ec681f3Smrg{ 5557ec681f3Smrg assert(!ht->deleted_entries); 5567ec681f3Smrg if (!ht->entries) 5577ec681f3Smrg return NULL; 5587ec681f3Smrg if (entry == NULL) 5597ec681f3Smrg entry = ht->table; 5607ec681f3Smrg else 5617ec681f3Smrg entry = entry + 1; 5627ec681f3Smrg if (entry != ht->table + ht->size) 5637ec681f3Smrg return entry->key ? entry : _mesa_hash_table_next_entry_unsafe(ht, entry); 5647ec681f3Smrg 5657ec681f3Smrg return NULL; 5667ec681f3Smrg} 5677ec681f3Smrg 568af69d88dSmrg/** 569af69d88dSmrg * This function is an iterator over the hash table. 570af69d88dSmrg * 571af69d88dSmrg * Pass in NULL for the first entry, as in the start of a for loop. Note that 572af69d88dSmrg * an iteration over the table is O(table_size) not O(entries). 573af69d88dSmrg */ 574af69d88dSmrgstruct hash_entry * 575af69d88dSmrg_mesa_hash_table_next_entry(struct hash_table *ht, 576af69d88dSmrg struct hash_entry *entry) 577af69d88dSmrg{ 578af69d88dSmrg if (entry == NULL) 579af69d88dSmrg entry = ht->table; 580af69d88dSmrg else 581af69d88dSmrg entry = entry + 1; 582af69d88dSmrg 583af69d88dSmrg for (; entry != ht->table + ht->size; entry++) { 584af69d88dSmrg if (entry_is_present(ht, entry)) { 585af69d88dSmrg return entry; 586af69d88dSmrg } 587af69d88dSmrg } 588af69d88dSmrg 589af69d88dSmrg return NULL; 590af69d88dSmrg} 591af69d88dSmrg 592af69d88dSmrg/** 593af69d88dSmrg * Returns a random entry from the hash table. 594af69d88dSmrg * 595af69d88dSmrg * This may be useful in implementing random replacement (as opposed 596af69d88dSmrg * to just removing everything) in caches based on this hash table 597af69d88dSmrg * implementation. @predicate may be used to filter entries, or may 598af69d88dSmrg * be set to NULL for no filtering. 599af69d88dSmrg */ 600af69d88dSmrgstruct hash_entry * 601af69d88dSmrg_mesa_hash_table_random_entry(struct hash_table *ht, 602af69d88dSmrg bool (*predicate)(struct hash_entry *entry)) 603af69d88dSmrg{ 604af69d88dSmrg struct hash_entry *entry; 605af69d88dSmrg uint32_t i = rand() % ht->size; 606af69d88dSmrg 607af69d88dSmrg if (ht->entries == 0) 608af69d88dSmrg return NULL; 609af69d88dSmrg 610af69d88dSmrg for (entry = ht->table + i; entry != ht->table + ht->size; entry++) { 611af69d88dSmrg if (entry_is_present(ht, entry) && 612af69d88dSmrg (!predicate || predicate(entry))) { 613af69d88dSmrg return entry; 614af69d88dSmrg } 615af69d88dSmrg } 616af69d88dSmrg 617af69d88dSmrg for (entry = ht->table; entry != ht->table + i; entry++) { 618af69d88dSmrg if (entry_is_present(ht, entry) && 619af69d88dSmrg (!predicate || predicate(entry))) { 620af69d88dSmrg return entry; 621af69d88dSmrg } 622af69d88dSmrg } 623af69d88dSmrg 624af69d88dSmrg return NULL; 625af69d88dSmrg} 626af69d88dSmrg 627af69d88dSmrg 628af69d88dSmrguint32_t 629af69d88dSmrg_mesa_hash_data(const void *data, size_t size) 630af69d88dSmrg{ 6317ec681f3Smrg return XXH32(data, size, 0); 6327ec681f3Smrg} 6337ec681f3Smrg 6347ec681f3Smrguint32_t 6357ec681f3Smrg_mesa_hash_data_with_seed(const void *data, size_t size, uint32_t seed) 6367ec681f3Smrg{ 6377ec681f3Smrg return XXH32(data, size, seed); 6387ec681f3Smrg} 6397ec681f3Smrg 6407ec681f3Smrguint32_t 6417ec681f3Smrg_mesa_hash_int(const void *key) 6427ec681f3Smrg{ 6437ec681f3Smrg return XXH32(key, sizeof(int), 0); 6447ec681f3Smrg} 6457ec681f3Smrg 6467ec681f3Smrguint32_t 6477ec681f3Smrg_mesa_hash_uint(const void *key) 6487ec681f3Smrg{ 6497ec681f3Smrg return XXH32(key, sizeof(unsigned), 0); 6507ec681f3Smrg} 6517ec681f3Smrg 6527ec681f3Smrguint32_t 6537ec681f3Smrg_mesa_hash_u32(const void *key) 6547ec681f3Smrg{ 6557ec681f3Smrg return XXH32(key, 4, 0); 656af69d88dSmrg} 657af69d88dSmrg 65801e04c3fSmrg/** FNV-1a string hash implementation */ 659af69d88dSmrguint32_t 66001e04c3fSmrg_mesa_hash_string(const void *_key) 661af69d88dSmrg{ 6627ec681f3Smrg uint32_t hash = 0; 66301e04c3fSmrg const char *key = _key; 6647ec681f3Smrg size_t len = strlen(key); 6657ec681f3Smrg#if defined(_WIN64) || defined(__x86_64__) 6667ec681f3Smrg hash = (uint32_t)XXH64(key, len, hash); 6677ec681f3Smrg#else 6687ec681f3Smrg hash = XXH32(key, len, hash); 6697ec681f3Smrg#endif 6707ec681f3Smrg return hash; 6717ec681f3Smrg} 672af69d88dSmrg 6737ec681f3Smrguint32_t 6747ec681f3Smrg_mesa_hash_pointer(const void *pointer) 6757ec681f3Smrg{ 6767ec681f3Smrg uintptr_t num = (uintptr_t) pointer; 6777ec681f3Smrg return (uint32_t) ((num >> 2) ^ (num >> 6) ^ (num >> 10) ^ (num >> 14)); 6787ec681f3Smrg} 679af69d88dSmrg 6807ec681f3Smrgbool 6817ec681f3Smrg_mesa_key_int_equal(const void *a, const void *b) 6827ec681f3Smrg{ 6837ec681f3Smrg return *((const int *)a) == *((const int *)b); 6847ec681f3Smrg} 6857ec681f3Smrg 6867ec681f3Smrgbool 6877ec681f3Smrg_mesa_key_uint_equal(const void *a, const void *b) 6887ec681f3Smrg{ 6897ec681f3Smrg 6907ec681f3Smrg return *((const unsigned *)a) == *((const unsigned *)b); 6917ec681f3Smrg} 6927ec681f3Smrg 6937ec681f3Smrgbool 6947ec681f3Smrg_mesa_key_u32_equal(const void *a, const void *b) 6957ec681f3Smrg{ 6967ec681f3Smrg return *((const uint32_t *)a) == *((const uint32_t *)b); 697af69d88dSmrg} 698af69d88dSmrg 699af69d88dSmrg/** 700af69d88dSmrg * String compare function for use as the comparison callback in 701af69d88dSmrg * _mesa_hash_table_create(). 702af69d88dSmrg */ 703af69d88dSmrgbool 704af69d88dSmrg_mesa_key_string_equal(const void *a, const void *b) 705af69d88dSmrg{ 706af69d88dSmrg return strcmp(a, b) == 0; 707af69d88dSmrg} 708af69d88dSmrg 709af69d88dSmrgbool 710af69d88dSmrg_mesa_key_pointer_equal(const void *a, const void *b) 711af69d88dSmrg{ 712af69d88dSmrg return a == b; 713af69d88dSmrg} 71401e04c3fSmrg 7158a1362adSmaya/** 7168a1362adSmaya * Helper to create a hash table with pointer keys. 7178a1362adSmaya */ 7188a1362adSmayastruct hash_table * 7198a1362adSmaya_mesa_pointer_hash_table_create(void *mem_ctx) 7208a1362adSmaya{ 7218a1362adSmaya return _mesa_hash_table_create(mem_ctx, _mesa_hash_pointer, 7228a1362adSmaya _mesa_key_pointer_equal); 7238a1362adSmaya} 7248a1362adSmaya 7257ec681f3Smrg 7267ec681f3Smrgbool 7277ec681f3Smrg_mesa_hash_table_reserve(struct hash_table *ht, unsigned size) 7287ec681f3Smrg{ 7297ec681f3Smrg if (size < ht->max_entries) 7307ec681f3Smrg return true; 7317ec681f3Smrg for (unsigned i = ht->size_index + 1; i < ARRAY_SIZE(hash_sizes); i++) { 7327ec681f3Smrg if (hash_sizes[i].max_entries >= size) { 7337ec681f3Smrg _mesa_hash_table_rehash(ht, i); 7347ec681f3Smrg break; 7357ec681f3Smrg } 7367ec681f3Smrg } 7377ec681f3Smrg return ht->max_entries >= size; 7387ec681f3Smrg} 7397ec681f3Smrg 74001e04c3fSmrg/** 74101e04c3fSmrg * Hash table wrapper which supports 64-bit keys. 74201e04c3fSmrg * 74301e04c3fSmrg * TODO: unify all hash table implementations. 74401e04c3fSmrg */ 74501e04c3fSmrg 74601e04c3fSmrgstruct hash_key_u64 { 74701e04c3fSmrg uint64_t value; 74801e04c3fSmrg}; 74901e04c3fSmrg 75001e04c3fSmrgstatic uint32_t 75101e04c3fSmrgkey_u64_hash(const void *key) 75201e04c3fSmrg{ 75301e04c3fSmrg return _mesa_hash_data(key, sizeof(struct hash_key_u64)); 75401e04c3fSmrg} 75501e04c3fSmrg 75601e04c3fSmrgstatic bool 75701e04c3fSmrgkey_u64_equals(const void *a, const void *b) 75801e04c3fSmrg{ 75901e04c3fSmrg const struct hash_key_u64 *aa = a; 76001e04c3fSmrg const struct hash_key_u64 *bb = b; 76101e04c3fSmrg 76201e04c3fSmrg return aa->value == bb->value; 76301e04c3fSmrg} 76401e04c3fSmrg 7657ec681f3Smrg#define FREED_KEY_VALUE 0 7667ec681f3Smrg 76701e04c3fSmrgstruct hash_table_u64 * 76801e04c3fSmrg_mesa_hash_table_u64_create(void *mem_ctx) 76901e04c3fSmrg{ 7707ec681f3Smrg STATIC_ASSERT(FREED_KEY_VALUE != DELETED_KEY_VALUE); 77101e04c3fSmrg struct hash_table_u64 *ht; 77201e04c3fSmrg 77301e04c3fSmrg ht = CALLOC_STRUCT(hash_table_u64); 77401e04c3fSmrg if (!ht) 77501e04c3fSmrg return NULL; 77601e04c3fSmrg 77701e04c3fSmrg if (sizeof(void *) == 8) { 77801e04c3fSmrg ht->table = _mesa_hash_table_create(mem_ctx, _mesa_hash_pointer, 77901e04c3fSmrg _mesa_key_pointer_equal); 78001e04c3fSmrg } else { 78101e04c3fSmrg ht->table = _mesa_hash_table_create(mem_ctx, key_u64_hash, 78201e04c3fSmrg key_u64_equals); 78301e04c3fSmrg } 78401e04c3fSmrg 78501e04c3fSmrg if (ht->table) 78601e04c3fSmrg _mesa_hash_table_set_deleted_key(ht->table, uint_key(DELETED_KEY_VALUE)); 78701e04c3fSmrg 78801e04c3fSmrg return ht; 78901e04c3fSmrg} 79001e04c3fSmrg 7917ec681f3Smrgstatic void 7927ec681f3Smrg_mesa_hash_table_u64_delete_key(struct hash_entry *entry) 7937ec681f3Smrg{ 7947ec681f3Smrg if (sizeof(void *) == 8) 7957ec681f3Smrg return; 7967ec681f3Smrg 7977ec681f3Smrg struct hash_key_u64 *_key = (struct hash_key_u64 *)entry->key; 7987ec681f3Smrg 7997ec681f3Smrg if (_key) 8007ec681f3Smrg free(_key); 8017ec681f3Smrg} 8027ec681f3Smrg 80301e04c3fSmrgvoid 8047ec681f3Smrg_mesa_hash_table_u64_clear(struct hash_table_u64 *ht) 80501e04c3fSmrg{ 80601e04c3fSmrg if (!ht) 80701e04c3fSmrg return; 80801e04c3fSmrg 8097ec681f3Smrg _mesa_hash_table_clear(ht->table, _mesa_hash_table_u64_delete_key); 8107ec681f3Smrg ht->freed_key_data = NULL; 8117ec681f3Smrg ht->deleted_key_data = NULL; 8127ec681f3Smrg} 81301e04c3fSmrg 8147ec681f3Smrgvoid 8157ec681f3Smrg_mesa_hash_table_u64_destroy(struct hash_table_u64 *ht) 8167ec681f3Smrg{ 8177ec681f3Smrg if (!ht) 8187ec681f3Smrg return; 81901e04c3fSmrg 8207ec681f3Smrg _mesa_hash_table_u64_clear(ht); 8217ec681f3Smrg _mesa_hash_table_destroy(ht->table, NULL); 82201e04c3fSmrg free(ht); 82301e04c3fSmrg} 82401e04c3fSmrg 82501e04c3fSmrgvoid 82601e04c3fSmrg_mesa_hash_table_u64_insert(struct hash_table_u64 *ht, uint64_t key, 82701e04c3fSmrg void *data) 82801e04c3fSmrg{ 8297ec681f3Smrg if (key == FREED_KEY_VALUE) { 8307ec681f3Smrg ht->freed_key_data = data; 8317ec681f3Smrg return; 8327ec681f3Smrg } 8337ec681f3Smrg 83401e04c3fSmrg if (key == DELETED_KEY_VALUE) { 83501e04c3fSmrg ht->deleted_key_data = data; 83601e04c3fSmrg return; 83701e04c3fSmrg } 83801e04c3fSmrg 83901e04c3fSmrg if (sizeof(void *) == 8) { 84001e04c3fSmrg _mesa_hash_table_insert(ht->table, (void *)(uintptr_t)key, data); 84101e04c3fSmrg } else { 84201e04c3fSmrg struct hash_key_u64 *_key = CALLOC_STRUCT(hash_key_u64); 84301e04c3fSmrg 84401e04c3fSmrg if (!_key) 84501e04c3fSmrg return; 84601e04c3fSmrg _key->value = key; 84701e04c3fSmrg 84801e04c3fSmrg _mesa_hash_table_insert(ht->table, _key, data); 84901e04c3fSmrg } 85001e04c3fSmrg} 85101e04c3fSmrg 85201e04c3fSmrgstatic struct hash_entry * 85301e04c3fSmrghash_table_u64_search(struct hash_table_u64 *ht, uint64_t key) 85401e04c3fSmrg{ 85501e04c3fSmrg if (sizeof(void *) == 8) { 85601e04c3fSmrg return _mesa_hash_table_search(ht->table, (void *)(uintptr_t)key); 85701e04c3fSmrg } else { 85801e04c3fSmrg struct hash_key_u64 _key = { .value = key }; 85901e04c3fSmrg return _mesa_hash_table_search(ht->table, &_key); 86001e04c3fSmrg } 86101e04c3fSmrg} 86201e04c3fSmrg 86301e04c3fSmrgvoid * 86401e04c3fSmrg_mesa_hash_table_u64_search(struct hash_table_u64 *ht, uint64_t key) 86501e04c3fSmrg{ 86601e04c3fSmrg struct hash_entry *entry; 86701e04c3fSmrg 8687ec681f3Smrg if (key == FREED_KEY_VALUE) 8697ec681f3Smrg return ht->freed_key_data; 8707ec681f3Smrg 87101e04c3fSmrg if (key == DELETED_KEY_VALUE) 87201e04c3fSmrg return ht->deleted_key_data; 87301e04c3fSmrg 87401e04c3fSmrg entry = hash_table_u64_search(ht, key); 87501e04c3fSmrg if (!entry) 87601e04c3fSmrg return NULL; 87701e04c3fSmrg 87801e04c3fSmrg return entry->data; 87901e04c3fSmrg} 88001e04c3fSmrg 88101e04c3fSmrgvoid 88201e04c3fSmrg_mesa_hash_table_u64_remove(struct hash_table_u64 *ht, uint64_t key) 88301e04c3fSmrg{ 88401e04c3fSmrg struct hash_entry *entry; 88501e04c3fSmrg 8867ec681f3Smrg if (key == FREED_KEY_VALUE) { 8877ec681f3Smrg ht->freed_key_data = NULL; 8887ec681f3Smrg return; 8897ec681f3Smrg } 8907ec681f3Smrg 89101e04c3fSmrg if (key == DELETED_KEY_VALUE) { 89201e04c3fSmrg ht->deleted_key_data = NULL; 89301e04c3fSmrg return; 89401e04c3fSmrg } 89501e04c3fSmrg 89601e04c3fSmrg entry = hash_table_u64_search(ht, key); 89701e04c3fSmrg if (!entry) 89801e04c3fSmrg return; 89901e04c3fSmrg 90001e04c3fSmrg if (sizeof(void *) == 8) { 90101e04c3fSmrg _mesa_hash_table_remove(ht->table, entry); 90201e04c3fSmrg } else { 90301e04c3fSmrg struct hash_key *_key = (struct hash_key *)entry->key; 90401e04c3fSmrg 90501e04c3fSmrg _mesa_hash_table_remove(ht->table, entry); 90601e04c3fSmrg free(_key); 90701e04c3fSmrg } 90801e04c3fSmrg} 909