mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-25 13:51:36 +00:00
[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:
parent
f256ab167d
commit
340127fff2
7 changed files with 116 additions and 38 deletions
|
@ -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++;
|
||||||
|
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue