aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCaio Marcelo de Oliveira Filho <[email protected]>2019-06-10 12:10:54 -0700
committerCaio Marcelo de Oliveira Filho <[email protected]>2019-06-12 15:57:16 -0700
commiteb41ce1b012f24fc7cba664dcc12129342e26843 (patch)
treef4115acb7fb1da2c84d759bd2919ac2892cd4d0f
parentc129cb38613be79198ff57987d5b419f8b04973d (diff)
util/hash_table: Properly handle the NULL key in hash_table_u64
The hash_table_u64 should support any uint64_t as input. It does special handling for the "deleted" key, storing the data in the table itself; do the same for the "freed" key. Fixes: b38dab101ca "util/hash_table: Assert that keys are not reserved pointers" Reviewed-by: Lionel Landwerlin <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r--src/util/hash_table.c41
-rw-r--r--src/util/hash_table.h1
2 files changed, 37 insertions, 5 deletions
diff --git a/src/util/hash_table.c b/src/util/hash_table.c
index a764fabbf05..58104abd739 100644
--- a/src/util/hash_table.c
+++ b/src/util/hash_table.c
@@ -628,9 +628,12 @@ key_u64_equals(const void *a, const void *b)
return aa->value == bb->value;
}
+#define FREED_KEY_VALUE 0
+
struct hash_table_u64 *
_mesa_hash_table_u64_create(void *mem_ctx)
{
+ STATIC_ASSERT(FREED_KEY_VALUE != DELETED_KEY_VALUE);
struct hash_table_u64 *ht;
ht = CALLOC_STRUCT(hash_table_u64);
@@ -661,18 +664,33 @@ _mesa_hash_table_u64_destroy(struct hash_table_u64 *ht,
if (ht->deleted_key_data) {
if (delete_function) {
struct hash_table *table = ht->table;
- struct hash_entry deleted_entry;
+ struct hash_entry entry;
/* Create a fake entry for the delete function. */
- deleted_entry.hash = table->key_hash_function(table->deleted_key);
- deleted_entry.key = table->deleted_key;
- deleted_entry.data = ht->deleted_key_data;
+ entry.hash = table->key_hash_function(table->deleted_key);
+ entry.key = table->deleted_key;
+ entry.data = ht->deleted_key_data;
- delete_function(&deleted_entry);
+ delete_function(&entry);
}
ht->deleted_key_data = NULL;
}
+ if (ht->freed_key_data) {
+ if (delete_function) {
+ struct hash_table *table = ht->table;
+ struct hash_entry entry;
+
+ /* Create a fake entry for the delete function. */
+ entry.hash = table->key_hash_function(uint_key(FREED_KEY_VALUE));
+ entry.key = uint_key(FREED_KEY_VALUE);
+ entry.data = ht->freed_key_data;
+
+ delete_function(&entry);
+ }
+ ht->freed_key_data = NULL;
+ }
+
_mesa_hash_table_destroy(ht->table, delete_function);
free(ht);
}
@@ -681,6 +699,11 @@ void
_mesa_hash_table_u64_insert(struct hash_table_u64 *ht, uint64_t key,
void *data)
{
+ if (key == FREED_KEY_VALUE) {
+ ht->freed_key_data = data;
+ return;
+ }
+
if (key == DELETED_KEY_VALUE) {
ht->deleted_key_data = data;
return;
@@ -715,6 +738,9 @@ _mesa_hash_table_u64_search(struct hash_table_u64 *ht, uint64_t key)
{
struct hash_entry *entry;
+ if (key == FREED_KEY_VALUE)
+ return ht->freed_key_data;
+
if (key == DELETED_KEY_VALUE)
return ht->deleted_key_data;
@@ -730,6 +756,11 @@ _mesa_hash_table_u64_remove(struct hash_table_u64 *ht, uint64_t key)
{
struct hash_entry *entry;
+ if (key == FREED_KEY_VALUE) {
+ ht->freed_key_data = NULL;
+ return;
+ }
+
if (key == DELETED_KEY_VALUE) {
ht->deleted_key_data = NULL;
return;
diff --git a/src/util/hash_table.h b/src/util/hash_table.h
index c808a06d428..be7b50ff1fe 100644
--- a/src/util/hash_table.h
+++ b/src/util/hash_table.h
@@ -173,6 +173,7 @@ hash_table_call_foreach(struct hash_table *ht,
*/
struct hash_table_u64 {
struct hash_table *table;
+ void *freed_key_data;
void *deleted_key_data;
};