#include "mmprivate.h"
void
__mmalloc_free (mdp, ptr)
struct mdesc *mdp;
PTR ptr;
{
int type;
size_t block, blocks;
register size_t i;
struct list *prev, *next;
block = BLOCK (ptr);
type = mdp -> heapinfo[block].busy.type;
switch (type)
{
case 0:
mdp -> heapstats.chunks_used--;
mdp -> heapstats.bytes_used -=
mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
mdp -> heapstats.bytes_free +=
mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
i = mdp -> heapindex;
if (i > block)
{
while (i > block)
{
i = mdp -> heapinfo[i].free.prev;
}
}
else
{
do
{
i = mdp -> heapinfo[i].free.next;
}
while ((i != 0) && (i < block));
i = mdp -> heapinfo[i].free.prev;
}
if (block == i + mdp -> heapinfo[i].free.size)
{
mdp -> heapinfo[i].free.size +=
mdp -> heapinfo[block].busy.info.size;
block = i;
}
else
{
mdp -> heapinfo[block].free.size =
mdp -> heapinfo[block].busy.info.size;
mdp -> heapinfo[block].free.next = mdp -> heapinfo[i].free.next;
mdp -> heapinfo[block].free.prev = i;
mdp -> heapinfo[i].free.next = block;
mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
mdp -> heapstats.chunks_free++;
}
if (block + mdp -> heapinfo[block].free.size ==
mdp -> heapinfo[block].free.next)
{
mdp -> heapinfo[block].free.size
+= mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.size;
mdp -> heapinfo[block].free.next
= mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.next;
mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
mdp -> heapstats.chunks_free--;
}
blocks = mdp -> heapinfo[block].free.size;
if (blocks >= FINAL_FREE_BLOCKS && block + blocks == mdp -> heaplimit
&& mdp -> morecore (mdp, 0) == ADDRESS (block + blocks))
{
register size_t bytes = blocks * BLOCKSIZE;
mdp -> heaplimit -= blocks;
mdp -> morecore (mdp, -bytes);
mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
= mdp -> heapinfo[block].free.next;
mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
= mdp -> heapinfo[block].free.prev;
block = mdp -> heapinfo[block].free.prev;
mdp -> heapstats.chunks_free--;
mdp -> heapstats.bytes_free -= bytes;
}
mdp -> heapindex = block;
break;
default:
mdp -> heapstats.chunks_used--;
mdp -> heapstats.bytes_used -= 1 << type;
mdp -> heapstats.chunks_free++;
mdp -> heapstats.bytes_free += 1 << type;
prev = (struct list *)
((char *) ADDRESS(block) +
(mdp -> heapinfo[block].busy.info.frag.first << type));
if (mdp -> heapinfo[block].busy.info.frag.nfree ==
(BLOCKSIZE >> type) - 1)
{
next = prev;
for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
{
next = next -> next;
}
prev -> prev -> next = next;
if (next != NULL)
{
next -> prev = prev -> prev;
}
mdp -> heapinfo[block].busy.type = 0;
mdp -> heapinfo[block].busy.info.size = 1;
mdp -> heapstats.chunks_used++;
mdp -> heapstats.bytes_used += BLOCKSIZE;
mdp -> heapstats.chunks_free -= BLOCKSIZE >> type;
mdp -> heapstats.bytes_free -= BLOCKSIZE;
mfree ((PTR) mdp, (PTR) ADDRESS(block));
}
else if (mdp -> heapinfo[block].busy.info.frag.nfree != 0)
{
next = (struct list *) ptr;
next -> next = prev -> next;
next -> prev = prev;
prev -> next = next;
if (next -> next != NULL)
{
next -> next -> prev = next;
}
++mdp -> heapinfo[block].busy.info.frag.nfree;
}
else
{
prev = (struct list *) ptr;
mdp -> heapinfo[block].busy.info.frag.nfree = 1;
mdp -> heapinfo[block].busy.info.frag.first =
RESIDUAL (ptr, BLOCKSIZE) >> type;
prev -> next = mdp -> fraghead[type].next;
prev -> prev = &mdp -> fraghead[type];
prev -> prev -> next = prev;
if (prev -> next != NULL)
{
prev -> next -> prev = prev;
}
}
break;
}
}
void
mfree (md, ptr)
PTR md;
PTR ptr;
{
struct mdesc *mdp;
register struct alignlist *l;
if (ptr != NULL)
{
mdp = MD_TO_MDP (md);
for (l = mdp -> aligned_blocks; l != NULL; l = l -> next)
{
if (l -> aligned == ptr)
{
l -> aligned = NULL;
ptr = l -> exact;
break;
}
}
if (mdp -> mfree_hook != NULL)
{
(*mdp -> mfree_hook) (mdp, ptr);
}
else
{
__mmalloc_free (mdp, ptr);
}
}
}
#if REPLACE_SYSMALLOC
void
free (ptr)
PTR ptr;
{
mfree ((PTR) NULL, ptr);
}
#endif