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