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>
macos/master
Marc-André Lureau 9 years ago committed by Dave Airlie
parent dcc83cca07
commit a342dc9149
  1. 12
      src/gallium/auxiliary/util/u_hash_table.c
  2. 3
      src/gallium/auxiliary/util/u_hash_table.h
  3. 49
      src/vrend_object.c
  4. 3
      src/vrend_renderer.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);
}

@ -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

@ -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)

@ -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;

Loading…
Cancel
Save