#include "core.h"
#include "misc.h"
+#include "internal.h"
static struct map *ed_map safe;
struct ed_info {
while (ei->mark_free_list) {
struct mark *m = ei->mark_free_list;
ei->mark_free_list = (struct mark*)m->all.next;
- free(m);
+ __mark_free(m);
}
while (ei->store) {
struct store *s = ei->store;
struct ed_info *ei = p ? p->data : NULL;
if (!ei) {
- free(m);
+ __mark_free(m);
return;
}
ASSERT(ei->magic==0x4321765498765432UL);
#include "core.h"
#include "internal.h"
+#include "misc.h"
+
+static MEMPOOL(mark);
/* seq numbers added to the end are given a gap of 128.
* seq numbers at other locations are placed at mean of before and after.
struct point_links *lnk = safe_cast p->mdata;
for (i = 0; i < lnk->size; i++)
tlist_del_init(&lnk->lists[i]);
- free(lnk);
- p->mdata = NULL;
+ unalloc_buf(p->mdata, sizeof(*lnk) + lnk->size * sizeof(lnk->lists[0]),
+ mark);
+}
+
+void __mark_free(struct mark *m)
+{
+ unalloc(m, mark);
}
void mark_free(struct mark *m)
return NULL;
lnk = safe_cast pt->mdata;
- ret = calloc(1, sizeof(*ret));
+ alloc(ret, mark);
dup_mark(pt, ret);
ret->viewnum = view;
{
int i;
struct point_links *old = safe_cast p->mdata;
- struct mark *ret = calloc(1, sizeof(*ret));
- struct point_links *lnk = malloc(sizeof(*lnk) +
- old->size * sizeof(lnk->lists[0]));
+ struct mark *ret;
+ struct point_links *lnk;
+
+ alloc(ret, mark);
+ lnk = alloc_buf(sizeof(*lnk) + old->size * sizeof(lnk->lists[0]),
+ mark);
dup_mark(p, ret);
ret->viewnum = MARK_POINT;
tlist_for_each_entry(p, &d->points, view) {
int i;
struct point_links *old = safe_cast p->mdata;
- struct point_links *new = malloc(sizeof(*new) +
- d->nviews *
- sizeof(new->lists[0]));
+ struct point_links *new = alloc_buf(sizeof(*new) +
+ d->nviews *
+ sizeof(new->lists[0]),
+ mark);
new->pt = p;
new->size = d->nviews;
new->moved = old->moved;
{
struct mark *ret;
- ret = calloc(1, sizeof(*ret));
+ alloc(ret, mark);
dup_mark(m, ret);
ret->viewnum = MARK_UNGROUPED;
INIT_TLIST_HEAD(&ret->view, GRP_MARK);
if (m->viewnum == MARK_POINT)
return point_dup(m);
- ret = calloc(1, sizeof(*ret));
+ alloc(ret, mark);
dup_mark(m, ret);
if (m->viewnum == MARK_POINT) abort();
ret->viewnum = m->viewnum;
/* Erroneous call, or race with document closing down */
return NULL;
}
- ret = calloc(1, sizeof(*ret));
+ alloc(ret, mark);
INIT_HLIST_NODE(&ret->all);
INIT_TLIST_HEAD(&ret->view, GRP_MARK);
ret->viewnum = view;
hlist_add_head(&ret->all, &d->marks);
if (view == MARK_POINT) {
- struct point_links *lnk = malloc(sizeof(*lnk) +
- d->nviews *
- sizeof(lnk->lists[0]));
+ struct point_links *lnk = alloc_buf(sizeof(*lnk) +
+ d->nviews *
+ sizeof(lnk->lists[0]),
+ mark);
int i;
lnk->size = d->nviews;
#include <unistd.h>
#include "safe.h"
-
+#include "list.h"
#include "misc.h"
void buf_init(struct buf *b safe)
static void dump_key_hash(void);
static void dump_count_hash(void);
static void stat_dump(void);
+static void dump_mem(void);
static char *tnames[] = {
[TIME_KEY] = "KEY",
dump_key_hash();
dump_count_hash();
fprintf(dump_file, "\n");
+ dump_mem();
fflush(dump_file);
}
hash_free(khashtab);
stats_enabled = 0;
}
+
+static LIST_HEAD(mem_pools);
+
+void *safe __alloc(struct mempool *pool safe, int size, int zero)
+{
+ void *ret = malloc(size);
+
+ if (zero)
+ memset(ret, 0, size);
+ pool->bytes += size;
+ pool->allocations += 1;
+ if (pool->bytes > pool->max_bytes)
+ pool->max_bytes = pool->bytes;
+ if (list_empty(&pool->linkage))
+ list_add(&pool->linkage, &mem_pools);
+ return ret;
+}
+
+void __unalloc(struct mempool *pool safe, void *obj, int size)
+{
+ if (obj) {
+ pool->bytes -= size;
+ pool->allocations -= 1;
+ free(obj);
+ }
+}
+
+static void dump_mem(void)
+{
+ struct mempool *p;
+
+ fprintf(dump_file, "mem:");
+ list_for_each_entry(p, &mem_pools, linkage)
+ fprintf(dump_file, " %s:%ld(%ld):%ld",
+ p->name, p->bytes, p->max_bytes, p->allocations);
+ fprintf(dump_file, "\n");
+}
struct mark *do_vmark_last(struct doc *d safe, int view, struct pane *owner safe);
struct mark *do_vmark_at_point(struct doc *d safe, struct mark *pt safe, int view, struct pane *owner safe);
struct mark *do_vmark_at_or_before(struct doc *d safe, struct mark *m safe, int view, struct pane *owner);
+void __mark_free(struct mark *m);
void stat_count(char *name safe);
void stat_free(void);
+
+/*
+ * Memory allocation tracking
+ */
+
+struct mempool {
+ char *name;
+ long bytes;
+ long allocations;
+ long max_bytes;
+ struct list_head linkage;
+};
+
+#define MEMPOOL(__name) \
+ struct mempool mem ## __name = { \
+ .name = #__name, \
+ .linkage = LIST_HEAD_INIT(mem ## __name.linkage), \
+ }
+
+void *safe __alloc(struct mempool *pool safe, int size, int zero);
+void __unalloc(struct mempool *pool safe, void *obj, int size);
+
+#define alloc(var, pool) \
+ do { var = __alloc(&mem##pool, sizeof((var)[0]), 1); } while (0)
+
+#define alloc_buf(size, pool) __alloc(&mem##pool, size, 0)
+
+#define unalloc(var, pool) \
+ do { __unalloc(&mem##pool, var, sizeof((var)[0])); (var)=NULL; } while (0)
+
+#define unalloc_buf(var, size, pool) \
+ do { __unalloc(&mem##pool, var, size); (var) = NULL; } while(0)
+