summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@redhat.com>2016-01-21 01:18:54 +0100
committerDave Airlie <airlied@redhat.com>2016-02-10 12:39:48 +1000
commita342dc9149b435012a70d51bbeee21fa6e1b158b (patch)
tree7249d1c5ccb26e64baeb401a49e8ce007f657fbd
parentdcc83cca07aee215047775fbb9aadff141a6624a (diff)
renderer: fix leak in hashtable on replace
Some american fuzzy lop tests managed to replace resources, however the old values got leaked (I am not sure if this should be allowed) In all cases, introduce a destroy callback to the hashtable, used when a value is removed, replaced or the table is cleared. This simplifies a bit resource management and help avoid potential errors by using simply refcounts. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
-rw-r--r--src/gallium/auxiliary/util/u_hash_table.c12
-rw-r--r--src/gallium/auxiliary/util/u_hash_table.h3
-rw-r--r--src/vrend_object.c49
-rw-r--r--src/vrend_renderer.c3
4 files changed, 25 insertions, 42 deletions
diff --git a/src/gallium/auxiliary/util/u_hash_table.c b/src/gallium/auxiliary/util/u_hash_table.c
index a505fbc..3b1fa63 100644
--- a/src/gallium/auxiliary/util/u_hash_table.c
+++ b/src/gallium/auxiliary/util/u_hash_table.c
@@ -57,7 +57,8 @@ struct util_hash_table
/** Compare two keys */
int (*compare)(void *key1, void *key2);
- /* TODO: key, value destructors? */
+ /** free value */
+ void (*destroy)(void *value);
};
@@ -77,7 +78,8 @@ util_hash_table_item(struct cso_hash_iter iter)
struct util_hash_table *
util_hash_table_create(unsigned (*hash)(void *key),
- int (*compare)(void *key1, void *key2))
+ int (*compare)(void *key1, void *key2),
+ void (*destroy)(void *value))
{
struct util_hash_table *ht;
@@ -93,6 +95,7 @@ util_hash_table_create(unsigned (*hash)(void *key),
ht->hash = hash;
ht->compare = compare;
+ ht->destroy = destroy;
return ht;
}
@@ -155,7 +158,7 @@ util_hash_table_set(struct util_hash_table *ht,
item = util_hash_table_find_item(ht, key, key_hash);
if(item) {
- /* TODO: key/value destruction? */
+ ht->destroy(item->value);
item->value = value;
return PIPE_OK;
}
@@ -218,6 +221,7 @@ util_hash_table_remove(struct util_hash_table *ht,
item = util_hash_table_item(iter);
assert(item);
+ ht->destroy(item->value);
FREE(item);
cso_hash_erase(ht->cso, iter);
@@ -237,6 +241,7 @@ util_hash_table_clear(struct util_hash_table *ht)
iter = cso_hash_first_node(ht->cso);
while (!cso_hash_iter_is_null(iter)) {
item = (struct util_hash_table_item *)cso_hash_take(ht->cso, cso_hash_iter_key(iter));
+ ht->destroy(item->value);
FREE(item);
iter = cso_hash_first_node(ht->cso);
}
@@ -283,6 +288,7 @@ util_hash_table_destroy(struct util_hash_table *ht)
iter = cso_hash_first_node(ht->cso);
while (!cso_hash_iter_is_null(iter)) {
item = (struct util_hash_table_item *)cso_hash_iter_data(iter);
+ ht->destroy(item->value);
FREE(item);
iter = cso_hash_iter_next(iter);
}
diff --git a/src/gallium/auxiliary/util/u_hash_table.h b/src/gallium/auxiliary/util/u_hash_table.h
index 9431761..b4a887b 100644
--- a/src/gallium/auxiliary/util/u_hash_table.h
+++ b/src/gallium/auxiliary/util/u_hash_table.h
@@ -57,7 +57,8 @@ struct util_hash_table;
*/
struct util_hash_table *
util_hash_table_create(unsigned (*hash)(void *key),
- int (*compare)(void *key1, void *key2));
+ int (*compare)(void *key1, void *key2),
+ void (*destroy)(void *value));
enum pipe_error
diff --git a/src/vrend_object.c b/src/vrend_object.c
index eb1da23..3fcf21a 100644
--- a/src/vrend_object.c
+++ b/src/vrend_object.c
@@ -71,15 +71,10 @@ struct vrend_object {
bool free_data;
};
-struct util_hash_table *vrend_object_init_ctx_table(void)
+static void free_object(void *value)
{
- struct util_hash_table *ctx_hash;
- ctx_hash = util_hash_table_create(hash_func, compare);
- return ctx_hash;
-}
+ struct vrend_object *obj = value;
-static void vrend_object_free(struct vrend_object *obj)
-{
if (obj->free_data) {
if (obj_types[obj->type].unref)
obj_types[obj->type].unref(obj->data);
@@ -91,11 +86,11 @@ static void vrend_object_free(struct vrend_object *obj)
free(obj);
}
-static enum pipe_error free_cb(void *key, void *value, void *data)
+struct util_hash_table *vrend_object_init_ctx_table(void)
{
- struct vrend_object *obj = value;
- vrend_object_free(obj);
- return PIPE_OK;
+ struct util_hash_table *ctx_hash;
+ ctx_hash = util_hash_table_create(hash_func, compare, free_object);
+ return ctx_hash;
}
void vrend_object_fini_ctx_table(struct util_hash_table *ctx_hash)
@@ -103,29 +98,26 @@ void vrend_object_fini_ctx_table(struct util_hash_table *ctx_hash)
if (!ctx_hash)
return;
- util_hash_table_foreach(ctx_hash, free_cb, NULL);
util_hash_table_destroy(ctx_hash);
}
-void
-vrend_object_init_resource_table(void)
-{
- if (!res_hash)
- res_hash = util_hash_table_create(hash_func, compare);
-}
-
-static enum pipe_error free_res_cb(void *key, void *value, void *data)
+static void free_res(void *value)
{
struct vrend_object *obj = value;
(*resource_unref)(obj->data);
free(obj);
- return PIPE_OK;
+}
+
+void
+vrend_object_init_resource_table(void)
+{
+ if (!res_hash)
+ res_hash = util_hash_table_create(hash_func, compare, free_res);
}
void vrend_object_fini_resource_table(void)
{
if (res_hash) {
- util_hash_table_foreach(res_hash, free_res_cb, NULL);
util_hash_table_destroy(res_hash);
}
res_hash = NULL;
@@ -159,15 +151,8 @@ void
vrend_object_remove(struct util_hash_table *handle_hash,
uint32_t handle, enum virgl_object_type type)
{
- struct vrend_object *obj;
-
- obj = util_hash_table_get(handle_hash, intptr_to_pointer(handle));
- if (!obj)
- return;
util_hash_table_remove(handle_hash, intptr_to_pointer(handle));
-
- vrend_object_free(obj);
}
void *vrend_object_lookup(struct util_hash_table *handle_hash,
@@ -204,13 +189,7 @@ int vrend_resource_insert(void *data, uint32_t handle)
void vrend_resource_remove(uint32_t handle)
{
- struct vrend_object *obj;
-
- obj = util_hash_table_get(res_hash, intptr_to_pointer(handle));
- if (!obj)
- return;
util_hash_table_remove(res_hash, intptr_to_pointer(handle));
- free(obj);
}
void *vrend_resource_lookup(uint32_t handle, uint32_t ctx_id)
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index 826feb7..d0ca2e0 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -4258,9 +4258,6 @@ void vrend_renderer_resource_unref(uint32_t res_handle)
}
vrend_resource_remove(res->handle);
- res->handle = 0;
-
- vrend_resource_reference(&res, NULL);
}
static int use_sub_data = 0;