#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#define nil ((void*)0)
#define datoff ((int)&((Xhdr*)0)->data)
enum
{
Nhole = 128,
Magic = 0xDeadBabe,
};
typedef struct Hole Hole;
typedef struct Xalloc Xalloc;
typedef struct Xhdr Xhdr;
struct Hole
{
ulong addr;
ulong size;
ulong top;
Hole *link;
};
struct Xhdr
{
ulong size;
ulong magix;
char data[1];
};
struct Xalloc
{
Lock;
Hole hole[Nhole];
Hole *flist;
Hole *table;
};
Xalloc xlists;
void
xinit(void)
{
Hole *h, *eh;
eh = &xlists.hole[Nhole-1];
for(h = xlists.hole; h < eh; h++)
h->link = h+1;
xlists.flist = h;
}
void
xhole(ulong addr, ulong size)
{
Hole *h, **l;
lock(&xlists);
l = &xlists.table;
for(h = *l; h; h = h->link) {
if(h->top == addr) {
h->size += size;
h->top = h->addr+h->size;
unlock(&xlists);
return;
}
if(h->addr > addr)
break;
l = &h->link;
}
if(xlists.flist == nil) {
print("xfree: no free holes, leaked %d bytes\n", size);
unlock(&xlists);
return;
}
h = xlists.flist;
xlists.flist = h->link;
h->addr = addr;
h->top = addr+size;
h->size = size;
h->link = *l;
*l = h;
unlock(&xlists);
}
void*
xalloc(ulong size)
{
Hole *h, **l;
Xhdr *p;
size += sizeof(Xhdr);
lock(&xlists);
l = &xlists.table;
for(h = *l; h; h = h->link) {
if(h->size >= size) {
p = (Xhdr*)h->addr;
h->addr += size;
h->size -= size;
if(h->size == 0) {
*l = h->link;
h->link = xlists.flist;
xlists.flist = h;
}
p->magix = Magic;
p->size = size;
unlock(&xlists);
return p->data;
}
l = &h->link;
}
unlock(&xlists);
return nil;
}
void
xfree(void *p)
{
Xhdr *x;
x = (Xhdr*)((ulong)p - datoff);
if(x->magix != Magic)
panic("xfree");
xhole((ulong)x, x->size);
}
void
xsummary(void)
{
int i;
Hole *h;
i = 0;
for(h = xlists.flist; h; h = h->link)
i++;
print("%d holes free\n", i);
i = 0;
for(h = xlists.table; h; h = h->link) {
print("%lux %lux %d\n", h->addr, h->top, h->size);
i += h->size;
}
print("%d bytes free\n", i);
}