V9/jtools/src/sam/alloc.c
#include "sam.h"
/*
* Allocator. Manages arena between initial bss and garbage-compacted
* arena. Uses shiftgcarena() when it needs to expand its dominion.
*/
#define BRKINCR 4096
#define LBRKINCR (BRKINCR/sizeof(long))
#define FREE 1
typedef struct hdr{
union{
long *Unext; /* pointer to next object */
long Uinext; /* integer next; odd if deallocated */
}uu;
long nlongs;
}hdr;
#define inext uu.Uinext
#define next uu.Unext
#define hp ((struct hdr *)p)
#define HEADERSIZE (sizeof(struct hdr)/sizeof(long))
static long *basep; /* beginning of arena; only set once */
static long *endp; /* end of arena */
static long *nextp; /* next one to be used */
allocinit(){
basep=(long *)sbrk(0);
if(brk((char *)(basep+LBRKINCR))!=0)
error(Ealloc);
nextp=basep;
endp=basep+LBRKINCR;
}
uchar *
alloc(nbytes)
register ulong nbytes;
{
register long *p, *q;
register ulong nl;
nbytes+=sizeof(long)-1;
nbytes/=sizeof(long); /* convert bytes to longs */
#define Nlongs nbytes
Nlongs+=HEADERSIZE;
/* look for exact match */
for(p=basep; p<nextp; p=(long *)(hp->inext&~FREE))
if((hp->inext&FREE) && hp->nlongs==Nlongs){
hp->inext&=~FREE;
goto Return;
}
/* try off the end */
if(endp-nextp < Nlongs){
nl=(nextp+Nlongs)-basep; /* number we need */
nl=((nl+LBRKINCR-1)/LBRKINCR)*LBRKINCR; /* rounded up */
nl-=(endp-basep); /* minus number we have */
if((int)sbrk((int)(nl*sizeof(long)))==-1)
error(Ealloc);
shiftgcarena(nl);
endp+=nl;
}
p=nextp;
nextp+=Nlongs;
hp->nlongs=Nlongs;
hp->next=nextp;
Return:
for(q=p+HEADERSIZE, Nlongs-=HEADERSIZE; Nlongs-->0; )
*q++=0;
return (uchar *)(p+HEADERSIZE);
}
free(cp)
uchar *cp;
{
register long *p=(long *)cp;
if(p<=basep || nextp<=p)
panic("free");
p-=HEADERSIZE;
hp->inext|=FREE;
}