[ruamoko] Plug yet more memory leaks

Some of them, especially in rua_obj, were quite legitimate and even a
problem for thread-safety (rua_cmd is currently not thread-safe, but it
needs a lock, which I don't feel like doing at this stage).
This commit is contained in:
Bill Currie 2023-03-05 17:20:04 +09:00
parent f256ab167d
commit 340127fff2
7 changed files with 116 additions and 38 deletions

View file

@ -58,6 +58,7 @@ typedef struct {
} cmd_resources_t; } cmd_resources_t;
static hashtab_t *bi_cmds; static hashtab_t *bi_cmds;
static hashctx_t *bi_cmd_hashctx;
static int bi_cmds_refs; static int bi_cmds_refs;
static const char * static const char *
@ -129,6 +130,7 @@ bi_cmd_destroy (progs_t *pr, void *data)
{ {
if (!--bi_cmds_refs) { if (!--bi_cmds_refs) {
Hash_DelTable (bi_cmds); Hash_DelTable (bi_cmds);
Hash_DelContext (bi_cmd_hashctx);
} }
free (data); free (data);
} }
@ -173,8 +175,9 @@ RUA_Cmd_Init (progs_t *pr, int secure)
res->cmds = 0; res->cmds = 0;
if (!bi_cmds) { if (!bi_cmds) {
//FIXME not thread-safe
bi_cmds = Hash_NewTable (1021, bi_cmd_get_key, bi_cmd_free, 0, bi_cmds = Hash_NewTable (1021, bi_cmd_get_key, bi_cmd_free, 0,
pr->hashctx); &bi_cmd_hashctx);
} }
bi_cmds_refs++; bi_cmds_refs++;

View file

@ -140,13 +140,13 @@ font_new (gui_resources_t *res)
{ {
return PR_RESNEW (res->font_map); return PR_RESNEW (res->font_map);
} }
/*
static void static void
font_free (gui_resources_t *res, rua_font_t *font) font_free (gui_resources_t *res, rua_font_t *font)
{ {
PR_RESFREE (res->font_map, font); PR_RESFREE (res->font_map, font);
} }
*/
static void static void
font_reset (gui_resources_t *res) font_reset (gui_resources_t *res)
{ {
@ -168,16 +168,16 @@ font_index (gui_resources_t *res, rua_font_t *font)
static int static int
alloc_font (gui_resources_t *res, font_t *font) alloc_font (gui_resources_t *res, font_t *font)
{ {
rua_font_t *psg = font_new (res); rua_font_t *fnt = font_new (res);
psg->next = res->fonts; fnt->next = res->fonts;
psg->prev = &res->fonts; fnt->prev = &res->fonts;
if (res->fonts) { if (res->fonts) {
res->fonts->prev = &psg->next; res->fonts->prev = &fnt->next;
} }
res->fonts = psg; res->fonts = fnt;
psg->font = font; fnt->font = font;
return font_index (res, psg); return font_index (res, fnt);
} }
static rua_font_t * __attribute__((pure)) static rua_font_t * __attribute__((pure))
@ -215,6 +215,8 @@ bi_gui_destroy (progs_t *pr, void *_res)
{ {
gui_resources_t *res = _res; gui_resources_t *res = _res;
ECS_DelRegistry (res->reg); ECS_DelRegistry (res->reg);
PR_RESDELMAP (res->passage_map);
PR_RESDELMAP (res->font_map);
free (res); free (res);
} }
@ -231,6 +233,15 @@ bi (Font_Load)
R_INT (pr) = alloc_font (res, font); R_INT (pr) = alloc_font (res, font);
} }
bi (Font_Free)
{
gui_resources_t *res = _res;
rua_font_t *font = get_font (res, P_INT (pr, 0));
Font_Free (font->font);
font_free (res, font);
}
bi (Passage_New) bi (Passage_New)
{ {
gui_resources_t *res = _res; gui_resources_t *res = _res;
@ -361,6 +372,15 @@ bi (Text_Draw)
} }
} }
bi (View_Delete)
{
gui_resources_t *res = _res;
uint32_t viewid = P_UINT (pr, 0);
view_t view = { .id = viewid, .reg = res->reg,
.comp = res->view_base + view_href };
View_Delete (view);
}
bi (View_ChildCount) bi (View_ChildCount)
{ {
gui_resources_t *res = _res; gui_resources_t *res = _res;
@ -427,6 +447,7 @@ bi (View_UpdateHierarchy)
#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), }
static builtin_t builtins[] = { static builtin_t builtins[] = {
bi(Font_Load, 2, p(string), p(int)), bi(Font_Load, 2, p(string), p(int)),
bi(Font_Free, 2, p(int)),
bi(Passage_New, 0), bi(Passage_New, 0),
bi(Passage_ParseText, 2, p(ptr), p(string)), bi(Passage_ParseText, 2, p(ptr), p(string)),
bi(Passage_Delete, 1, p(ptr)), bi(Passage_Delete, 1, p(ptr)),
@ -436,6 +457,7 @@ static builtin_t builtins[] = {
bi(Text_View, 2, p(ptr), p(int)), bi(Text_View, 2, p(ptr), p(int)),
bi(Text_SetScript, 4, p(uint), p(string), p(int), p (int)), bi(Text_SetScript, 4, p(uint), p(string), p(int), p (int)),
bi(View_Delete, 1, p(uint)),
bi(View_ChildCount, 1, p(uint)), bi(View_ChildCount, 1, p(uint)),
bi(View_GetChild, 2, p(uint), p(uint)), bi(View_GetChild, 2, p(uint), p(uint)),
bi(View_SetPos, 3, p(uint), p(int), p(int)), bi(View_SetPos, 3, p(uint), p(int), p(int)),

View file

@ -519,8 +519,7 @@ RUA_Input_Init (progs_t *pr, int secure)
input_resources_t *res = calloc (sizeof (input_resources_t), 1); input_resources_t *res = calloc (sizeof (input_resources_t), 1);
res->cookie_super = new_memsuper (); res->cookie_super = new_memsuper ();
res->cookies = Hash_NewTable (251, 0, rua_in_free_cookie, res, res->cookies = Hash_NewTable (251, 0, rua_in_free_cookie, res, pr->hashctx);
&res->hashctx);
Hash_SetHashCompare (res->cookies, rua_in_hash_cookie, rua_in_cmp_cookies); Hash_SetHashCompare (res->cookies, rua_in_hash_cookie, rua_in_cmp_cookies);
PR_Resources_Register (pr, "input", res, bi_input_clear, bi_input_destroy); PR_Resources_Register (pr, "input", res, bi_input_clear, bi_input_destroy);

View file

@ -106,7 +106,9 @@ bi_rua_model_clear (progs_t *pr, void *_res)
static void static void
bi_rua_model_destroy (progs_t *pr, void *_res) bi_rua_model_destroy (progs_t *pr, void *_res)
{ {
free (_res); rua_model_resources_t *res = _res;
PR_RESDELMAP (res->model_map);
free (res);
} }
static int static int

View file

@ -45,6 +45,7 @@
#include "qfalloca.h" #include "qfalloca.h"
#include "QF/cvar.h" #include "QF/cvar.h"
#include "QF/darray.h"
#include "QF/dstring.h" #include "QF/dstring.h"
#include "QF/hash.h" #include "QF/hash.h"
#include "QF/mathlib.h" #include "QF/mathlib.h"
@ -99,6 +100,8 @@ typedef struct obj_list_s {
void *data; void *data;
} obj_list; } obj_list;
typedef struct listset_s DARRAY_TYPE (obj_list *) listset_t;
typedef struct dtable_s { typedef struct dtable_s {
struct dtable_s *next; struct dtable_s *next;
struct dtable_s **prev; struct dtable_s **prev;
@ -106,6 +109,13 @@ typedef struct dtable_s {
pr_func_t *imp; pr_func_t *imp;
} dtable_t; } dtable_t;
typedef struct class_tree {
pr_class_t *class;
obj_list *subclasses;
} class_tree;
typedef struct treeset_s DARRAY_TYPE (class_tree *) treeset_t;
typedef struct probj_resources_s { typedef struct probj_resources_s {
progs_t *pr; progs_t *pr;
unsigned selector_index; unsigned selector_index;
@ -124,6 +134,7 @@ typedef struct probj_resources_s {
hashtab_t *classes; hashtab_t *classes;
hashtab_t *protocols; hashtab_t *protocols;
hashtab_t *load_methods; hashtab_t *load_methods;
listset_t obj_list_sets;
obj_list *obj_list_free_list; obj_list *obj_list_free_list;
obj_list *unresolved_classes; obj_list *unresolved_classes;
obj_list *unclaimed_categories; obj_list *unclaimed_categories;
@ -131,6 +142,9 @@ typedef struct probj_resources_s {
obj_list *unclaimed_proto_list; obj_list *unclaimed_proto_list;
obj_list *module_list; obj_list *module_list;
obj_list *class_tree_list; obj_list *class_tree_list;
class_tree *class_tree_free_list;
treeset_t class_tree_sets;
} probj_t; } probj_t;
static dtable_t * static dtable_t *
@ -184,8 +198,11 @@ obj_list_new (probj_t *probj)
if (!probj->obj_list_free_list) { if (!probj->obj_list_free_list) {
probj->obj_list_free_list = calloc (128, sizeof (obj_list)); probj->obj_list_free_list = calloc (128, sizeof (obj_list));
for (i = 0; i < 127; i++) for (i = 0; i < 127; i++) {
probj->obj_list_free_list[i].next = &probj->obj_list_free_list[i + 1]; __auto_type next = &probj->obj_list_free_list[i + 1];
probj->obj_list_free_list[i].next = next;
}
DARRAY_APPEND (&probj->obj_list_sets, probj->obj_list_free_list);
} }
l = probj->obj_list_free_list; l = probj->obj_list_free_list;
probj->obj_list_free_list = l->next; probj->obj_list_free_list = l->next;
@ -230,28 +247,22 @@ list_remove (probj_t *probj, obj_list **list)
} }
} }
typedef struct class_tree {
pr_class_t *class;
obj_list *subclasses;
} class_tree;
class_tree *class_tree_free_list;
static class_tree * static class_tree *
class_tree_new (void) class_tree_new (probj_t *probj)
{ {
int i; int i;
class_tree *t; class_tree *t;
if (!class_tree_free_list) { if (!probj->class_tree_free_list) {
class_tree_free_list = calloc (128, sizeof (class_tree)); probj->class_tree_free_list = calloc (128, sizeof (class_tree));
for (i = 0; i < 127; i++) { for (i = 0; i < 127; i++) {
class_tree *x = &class_tree_free_list[i]; class_tree *x = &probj->class_tree_free_list[i];
x->subclasses = (obj_list *) (x + 1); x->subclasses = (obj_list *) (x + 1);
} }
DARRAY_APPEND (&probj->class_tree_sets, probj->class_tree_free_list);
} }
t = class_tree_free_list; t = probj->class_tree_free_list;
class_tree_free_list = (class_tree *) t->subclasses; probj->class_tree_free_list = (class_tree *) t->subclasses;
t->subclasses = 0; t->subclasses = 0;
return t; return t;
} }
@ -282,10 +293,10 @@ create_tree_of_subclasses_inherited_from (probj_t *probj, pr_class_t *bottom,
superclass = bottom->super_class ? Hash_Find (probj->classes, super_class) superclass = bottom->super_class ? Hash_Find (probj->classes, super_class)
: 0; : 0;
tree = prev = class_tree_new (); tree = prev = class_tree_new (probj);
prev->class = bottom; prev->class = bottom;
while (superclass != upper) { while (superclass != upper) {
tree = class_tree_new (); tree = class_tree_new (probj);
tree->class = superclass; tree->class = superclass;
tree->subclasses = list_cons (probj, prev, tree->subclasses); tree->subclasses = list_cons (probj, prev, tree->subclasses);
super_class = PR_GetString (pr, superclass->super_class); super_class = PR_GetString (pr, superclass->super_class);
@ -320,7 +331,7 @@ _obj_tree_insert_class (probj_t *probj, class_tree *tree, pr_class_t *class)
return tree; return tree;
list = list->next; list = list->next;
} }
node = class_tree_new (); node = class_tree_new (probj);
node->class = class; node->class = class;
tree->subclasses = list_cons (probj, node, tree->subclasses); tree->subclasses = list_cons (probj, node, tree->subclasses);
return tree; return tree;
@ -381,8 +392,8 @@ obj_create_classes_tree (probj_t *probj, pr_module_t *module)
static void static void
obj_destroy_class_tree_node (probj_t *probj, class_tree *tree, int level) obj_destroy_class_tree_node (probj_t *probj, class_tree *tree, int level)
{ {
tree->subclasses = (obj_list *) class_tree_free_list; tree->subclasses = (obj_list *) probj->class_tree_free_list;
class_tree_free_list = tree; probj->class_tree_free_list = tree;
} }
static void static void
@ -1414,6 +1425,18 @@ rua_obj_error (progs_t *pr, void *data)
int count = pr->pr_argc - 3; int count = pr->pr_argc - 3;
pr_type_t **args = &pr->pr_params[3]; pr_type_t **args = &pr->pr_params[3];
if (pr->progs->version == PROG_VERSION) {
__auto_type va_list = &P_PACKED (pr, pr_va_list_t, 3);
count = va_list->count;
if (count) {
args = alloca (count * sizeof (pr_type_t *));
for (int i = 0; i < count; i++) {
args[i] = &pr->pr_globals[va_list->list + i * 4];
}
} else {
args = 0;
}
}
obj_verror (probj, object, code, fmt, count, args); obj_verror (probj, object, code, fmt, count, args);
} }
@ -2068,6 +2091,18 @@ rua__i_Object_error_error_ (progs_t *pr, void *data)
int count = pr->pr_argc - 3; int count = pr->pr_argc - 3;
pr_type_t **args = &pr->pr_params[3]; pr_type_t **args = &pr->pr_params[3];
if (pr->progs->version == PROG_VERSION) {
__auto_type va_list = &P_PACKED (pr, pr_va_list_t, 3);
count = va_list->count;
if (count) {
args = alloca (count * sizeof (pr_type_t *));
for (int i = 0; i < count; i++) {
args[i] = &pr->pr_globals[va_list->list + i * 4];
}
} else {
args = 0;
}
}
dsprintf (probj->msg, "error: %s (%s)\n%s", dsprintf (probj->msg, "error: %s (%s)\n%s",
PR_GetString (pr, object_get_class_name (probj, self)), PR_GetString (pr, object_get_class_name (probj, self)),
object_is_instance (probj, self) ? "instance" : "class", fmt); object_is_instance (probj, self) ? "instance" : "class", fmt);
@ -2336,10 +2371,16 @@ rua_obj_destroy (progs_t *pr, void *_res)
free (probj->selector_sels); free (probj->selector_sels);
free (probj->selector_names); free (probj->selector_names);
free (probj->selector_argc); free (probj->selector_argc);
//FIXME free (probj->obj_list_free_list);
//FIXME free (class_tree_free_list); for (size_t i = 0; i < probj->obj_list_sets.size; i++) {
//FIXME class_tree_free_list = 0; free (probj->obj_list_sets.a[i]);
}
DARRAY_CLEAR (&probj->obj_list_sets);
for (size_t i = 0; i < probj->class_tree_sets.size; i++) {
free (probj->class_tree_sets.a[i]);
}
DARRAY_CLEAR (&probj->class_tree_sets);
PR_RESDELMAP (probj->dtables); PR_RESDELMAP (probj->dtables);
@ -2358,9 +2399,11 @@ RUA_Obj_Init (progs_t *pr, int secure)
probj->protocols = Hash_NewTable (1021, protocol_get_key, 0, probj, probj->protocols = Hash_NewTable (1021, protocol_get_key, 0, probj,
pr->hashctx); pr->hashctx);
probj->load_methods = Hash_NewTable (1021, 0, 0, probj, pr->hashctx); probj->load_methods = Hash_NewTable (1021, 0, 0, probj, pr->hashctx);
probj->msg = dstring_newstr();
Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, Hash_SetHashCompare (probj->load_methods, load_methods_get_hash,
load_methods_compare); load_methods_compare);
probj->msg = dstring_newstr();
DARRAY_INIT (&probj->obj_list_sets, 32);
DARRAY_INIT (&probj->class_tree_sets, 32);
PR_Sprintf_SetAtHandler (pr, rua_at_handler, probj); PR_Sprintf_SetAtHandler (pr, rua_at_handler, probj);

View file

@ -657,7 +657,10 @@ bi_scene_clear (progs_t *pr, void *_res)
static void static void
bi_scene_destroy (progs_t *pr, void *_res) bi_scene_destroy (progs_t *pr, void *_res)
{ {
free (_res); rua_scene_resources_t *res = _res;
PR_RESDELMAP (res->scene_map);
PR_RESDELMAP (res->lighting_map);
free (res);
} }
void void

View file

@ -480,6 +480,12 @@ main (int argc, char **argv)
ret = thread_data.a[main_ind]->return_code; ret = thread_data.a[main_ind]->return_code;
} }
for (size_t i = 0; i < thread_data.size; i++) {
qwaq_thread_t *thread = thread_data.a[i];
DARRAY_CLEAR (&thread->args);
free (thread_data.a[i]);
}
DARRAY_CLEAR (&thread_data);
Cbuf_Delete (qwaq_cbuf); Cbuf_Delete (qwaq_cbuf);
Sys_Shutdown (); Sys_Shutdown ();
return ret; return ret;