#include "proj.h"
#include "malloc.h"
struct _malloc_root_ malloc_root_
=
{
{
&malloc_root_.malloc_pool_image_,
&malloc_root_.malloc_pool_image_,
(mallocPool) &malloc_root_.malloc_pool_image_.eldest,
(mallocPool) &malloc_root_.malloc_pool_image_.eldest,
(mallocArea_) &malloc_root_.malloc_pool_image_.first,
(mallocArea_) &malloc_root_.malloc_pool_image_.first,
0,
#if MALLOC_DEBUG
0, 0, 0, 0, 0, 0, 0, { '/' }
#else
{ 0 }
#endif
},
};
static void *malloc_reserve_ = NULL;
#if MALLOC_DEBUG
static const char *const malloc_types_[] =
{"KS", "KSR", "NF", "NFR", "US", "USR"};
#endif
static void malloc_kill_area_ (mallocPool pool, mallocArea_ a);
#if MALLOC_DEBUG
static void malloc_verify_area_ (mallocPool pool, mallocArea_ a);
#endif
#if MALLOC_DEBUG
#define malloc_kill_(ptr,s) do {memset((ptr),127,(s));free((ptr));} while(0)
#else
#define malloc_kill_(ptr,s) free((ptr))
#endif
static void
malloc_kill_area_ (mallocPool pool UNUSED, mallocArea_ a)
{
#if MALLOC_DEBUG
assert (strcmp (a->name, ((char *) (a->where)) + a->size) == 0);
#endif
malloc_kill_ (a->where, a->size);
a->next->previous = a->previous;
a->previous->next = a->next;
#if MALLOC_DEBUG
pool->freed += a->size;
pool->frees++;
#endif
malloc_kill_ (a,
offsetof (struct _malloc_area_, name)
+ strlen (a->name) + 1);
}
#if MALLOC_DEBUG
static void
malloc_verify_area_ (mallocPool pool UNUSED, mallocArea_ a UNUSED)
{
mallocSize s = a->size;
assert (strcmp (a->name, ((char *) (a->where)) + s) == 0);
}
#endif
void
malloc_init ()
{
if (malloc_reserve_ != NULL)
return;
malloc_reserve_ = xmalloc (20 * 1024);
}
void
malloc_pool_display (mallocPool p UNUSED)
{
#if MALLOC_DEBUG
mallocPool q;
mallocArea_ a;
fprintf (dmpout, "Pool \"%s\": bytes allocated=%lu, freed=%lu, old sizes=%lu, new sizes\
=%lu,\n allocations=%lu, frees=%lu, resizes=%lu, uses=%lu\n Subpools:\n",
p->name, p->allocated, p->freed, p->old_sizes, p->new_sizes, p->allocations,
p->frees, p->resizes, p->uses);
for (q = p->eldest; q != (mallocPool) & p->eldest; q = q->next)
fprintf (dmpout, " \"%s\"\n", q->name);
fprintf (dmpout, " Storage areas:\n");
for (a = p->first; a != (mallocArea_) & p->first; a = a->next)
{
fprintf (dmpout, " ");
malloc_display_ (a);
}
#endif
}
void
malloc_pool_kill (mallocPool p)
{
mallocPool q;
mallocArea_ a;
if (--p->uses != 0)
return;
#if 0
malloc_pool_display (p);
#endif
assert (p->next->previous == p);
assert (p->previous->next == p);
while ((q = p->eldest) != (mallocPool) &p->eldest)
{
q->uses = 1;
malloc_pool_kill (q);
}
while ((a = p->first) != (mallocArea_) & p->first)
{
malloc_kill_area_ (p, a);
}
p->next->previous = p->previous;
p->previous->next = p->next;
malloc_kill_ (p,
offsetof (struct _malloc_pool_, name)
+ strlen (p->name) + 1);
}
mallocPool
malloc_pool_new (const char *name, mallocPool parent,
unsigned long chunks UNUSED)
{
mallocPool p;
if (parent == NULL)
parent = malloc_pool_image ();
p = malloc_new_ (offsetof (struct _malloc_pool_, name)
+ (MALLOC_DEBUG ? strlen (name) + 1 : 0));
p->next = (mallocPool) &(parent->eldest);
p->previous = parent->youngest;
parent->youngest->next = p;
parent->youngest = p;
p->eldest = (mallocPool) &(p->eldest);
p->youngest = (mallocPool) &(p->eldest);
p->first = (mallocArea_) &(p->first);
p->last = (mallocArea_) &(p->first);
p->uses = 1;
#if MALLOC_DEBUG
p->allocated = p->freed = p->old_sizes = p->new_sizes = p->allocations
= p->frees = p->resizes = 0;
strcpy (p->name, name);
#endif
return p;
}
mallocPool
malloc_pool_use (mallocPool pool)
{
++pool->uses;
return pool;
}
void
malloc_display_ (mallocArea_ a UNUSED)
{
#if MALLOC_DEBUG
fprintf (dmpout, "At %08lX, size=%" mallocSize_f "u, type=%s, \"%s\"\n",
(unsigned long) a->where, a->size, malloc_types_[a->type], a->name);
#endif
}
mallocArea_
malloc_find_inpool_ (mallocPool pool, void *ptr)
{
mallocArea_ a;
mallocArea_ b = (mallocArea_) &pool->first;
int n = 0;
for (a = pool->first; a != (mallocArea_) &pool->first; a = a->next)
{
assert (("Infinite loop detected" != NULL) && (a != b));
if (a->where == ptr)
return a;
++n;
if (n & 1)
b = b->next;
}
assert ("Couldn't find object in pool!" == NULL);
return NULL;
}
void
malloc_kill_inpool_ (mallocPool pool, mallocType_ type UNUSED,
void *ptr, mallocSize s UNUSED)
{
mallocArea_ a;
if (pool == NULL)
pool = malloc_pool_image ();
#if MALLOC_DEBUG
assert ((pool == malloc_pool_image ())
|| malloc_pool_find_ (pool, malloc_pool_image ()));
#endif
a = malloc_find_inpool_ (pool, ptr);
#if MALLOC_DEBUG
assert (a->type == type);
if ((type != MALLOC_typeUS_) && (type != MALLOC_typeUSR_))
assert (a->size == s);
#endif
malloc_kill_area_ (pool, a);
}
void *
malloc_new_ (mallocSize s)
{
void *ptr;
unsigned ss = s;
#if MALLOC_DEBUG && 0
assert (s == (mallocSize) ss);
#endif
ptr = xmalloc (ss);
#if MALLOC_DEBUG
memset (ptr, 126, ss);
#endif
return ptr;
}
void *
malloc_new_inpool_ (mallocPool pool, mallocType_ type, const char *name, mallocSize s)
{
void *ptr;
mallocArea_ a;
unsigned short i;
if (pool == NULL)
pool = malloc_pool_image ();
#if MALLOC_DEBUG
assert ((pool == malloc_pool_image ())
|| malloc_pool_find_ (pool, malloc_pool_image ()));
#endif
ptr = malloc_new_ (s + (i = (MALLOC_DEBUG ? strlen (name) + 1 : 0)));
#if MALLOC_DEBUG
strcpy (((char *) (ptr)) + s, name);
#endif
a = malloc_new_ (offsetof (struct _malloc_area_, name) + i);
switch (type)
{
case MALLOC_typeKP_:
case MALLOC_typeKPR_:
a->next = (mallocArea_) &pool->first;
break;
default:
a->next = pool->first;
break;
}
a->previous = a->next->previous;
a->next->previous = a;
a->previous->next = a;
a->where = ptr;
#if MALLOC_DEBUG
a->size = s;
a->type = type;
strcpy (a->name, name);
pool->allocated += s;
pool->allocations++;
#endif
return ptr;
}
void *
malloc_new_zinpool_ (mallocPool pool, mallocType_ type, const char *name, mallocSize s,
int z)
{
void *ptr;
ptr = malloc_new_inpool_ (pool, type, name, s);
memset (ptr, z, s);
return ptr;
}
char
malloc_pool_find_ (mallocPool pool, mallocPool parent)
{
mallocPool p;
for (p = parent->eldest; p != (mallocPool) & parent->eldest; p = p->next)
{
if ((p == pool) || malloc_pool_find_ (pool, p))
return 1;
}
return 0;
}
void *
malloc_resize_inpool_ (mallocPool pool, mallocType_ type UNUSED,
void *ptr, mallocSize ns, mallocSize os UNUSED)
{
mallocArea_ a;
if (pool == NULL)
pool = malloc_pool_image ();
#if MALLOC_DEBUG
assert ((pool == malloc_pool_image ())
|| malloc_pool_find_ (pool, malloc_pool_image ()));
#endif
a = malloc_find_inpool_ (pool, ptr);
#if MALLOC_DEBUG
assert (a->type == type);
if ((type == MALLOC_typeKSR_) || (type == MALLOC_typeKPR_))
assert (a->size == os);
assert (strcmp (a->name, ((char *) (ptr)) + os) == 0);
#endif
ptr = malloc_resize_ (ptr, ns + (MALLOC_DEBUG ? strlen (a->name) + 1: 0));
a->where = ptr;
#if MALLOC_DEBUG
a->size = ns;
strcpy (((char *) (ptr)) + ns, a->name);
pool->old_sizes += os;
pool->new_sizes += ns;
pool->resizes++;
#endif
return ptr;
}
void *
malloc_resize_ (void *ptr, mallocSize s)
{
int ss = s;
#if MALLOC_DEBUG && 0
assert (s == (mallocSize) ss);
#endif
ptr = xrealloc (ptr, ss);
return ptr;
}
void
malloc_verify_inpool_ (mallocPool pool UNUSED, mallocType_ type UNUSED,
void *ptr UNUSED, mallocSize s UNUSED)
{
#if MALLOC_DEBUG
mallocArea_ a;
if (pool == NULL)
pool = malloc_pool_image ();
assert ((pool == malloc_pool_image ())
|| malloc_pool_find_ (pool, malloc_pool_image ()));
a = malloc_find_inpool_ (pool, ptr);
assert (a->type == type);
if ((type != MALLOC_typeUS_) && (type != MALLOC_typeUSR_))
assert (a->size == s);
malloc_verify_area_ (pool, a);
#endif
}