/* nalloc.c */
/* $Id: nalloc.c,v 1.5 1993/07/25 19:06:30 nils Exp $ */
/* Memory allocation routines Written By Lawrence Foard */
#include <stdio.h>
#include "nalloc.h"
#include "db.h"
#include "config.h"
#include "externs.h"
static BIGBLK blks[MAXBLK];
static int inited=0;
static void init()
{
int a;
inited=1;
for(a=0;a<MAXBLK;a++)
{
blks[a].owner=NULL;
blks[a].used=NULL;
blks[a].blk=NULL;
}
}
void na_clear(nalloc)
NALLOC *nalloc;
{
int a;
for(a=0;a<MAXBLK;a++)
if (nalloc==blks[a].owner)
{
blks[a].owner=NULL;
blks[a].used=0;
}
}
void na_close(nalloc)
NALLOC *nalloc;
{
int a;
/* search block list freeing all owned by nalloc */
for(a=0;a<MAXBLK;a++)
if (nalloc==blks[a].owner)
{
blks[a].owner=NULL;
blks[a].used=0;
}
free(nalloc);
}
NALLOC *na_open(size)
int size;
{
NALLOC *na=(NALLOC *)malloc(sizeof(NALLOC));
if (!inited)
init();
na->size=size;
na->offset=0;
na->free=NULL;
na->curblk=0; /* Note this isn't correct but is checked anyways */
return(na);
}
static int get_blk(na)
NALLOC *na;
{
int a;
/* search for a block with no space used */
/* NOTE: owned blocks with no used space are public property!!! */
for(a=0;a<MAXBLK;a++)
if (!blks[a].used)
{
if (!blks[a].blk)
{
char buf[80];
#ifdef MALLOCDEBUG
blks[a].blk=(char *)malloc(SBSIZE);
#else
blks[a].blk=(char *)sbrk(SBSIZE);
#endif
sprintf(buf,"new block %d(#%d) used",a*SBSIZE,a);
log_io(buf);
}
blks[a].owner=na;
return(a);
}
return(-1);
}
/* return a pointer to an area containing size bytes (size<SBSIZE) */
void *na_alloc(na,size)
NALLOC *na;
int size;
{
char *p;
/* make sure we still own the current block and that the data */
/* will fit in it if we do */
size+=sizeof(int);
if ((blks[na->curblk].owner!=na) || (size>(SBSIZE-na->offset)))
{
na->curblk=get_blk(na);
na->offset=0;
}
p=blks[na->curblk].blk+na->offset;
/* force p into integer alignment (yuck) */
/* I'm not going to replace & with a division just because some silly */
/* processor may have non power of two byte integers! */
p=(void *)((((unsigned int)p)+sizeof(int)) & ~(sizeof(int)-1));
na->offset+=size;
blks[na->curblk].used++;
return(p);
}
/* reduces allocation given to last call by amount size */
void na_giveback(na,size)
NALLOC *na;
int size;
{
na->offset-=size;
}
/* get an item out of nalloc free list */
char *na_get(na)
NALLOC *na;
{
if (na->free)
{
/* get next free list pointer */
char *next=(char *)na->free;
na->free= na->free->next;
return(next);
}
return(na_alloc(na,na->size));
}
/* put an item back on the na free list */
void na_free(na,item)
NALLOC *na;
void *item;
{
POINT *tmp=(POINT *)item;
tmp->next=na->free;
na->free=tmp;
}
/* do binary search to find block pointer belongs to */
int findit(argptr)
void *argptr;
{
int b;
char *ptr;
ptr=(char *)argptr;
/* try linear search,eventually replace with binary */
for ( b = 0; b < (MAXBLK - 1); b++ )
if ( blks[b].blk && (blks[b].blk <= ptr) && ((blks[b].blk + SBSIZE) > ptr))
return(b);
log_error("pointer not found");
return -1;
#ifdef fooglewizer
t = MAXBLK;
b = 0;
while ( b < (t-1) ) {
m = (b + t) / 2;
/* see if this is it */
if ((blks[m].blk<=ptr) && ((blks[m+1].blk>ptr) || (blks[m+1].blk))) {
if ( (ptr - blks[m].blk) > SBSIZE ) {
log_error("Pointer not in block");
report();
return -1;
}
return m;
}
if ( blks[m].blk && (blks[m].blk < ptr) )
b=m;
else
t=m;
}
log_error("Pointer out of range");
report();
return(-1);
#endif /* fooglewiezer */
}
void na_unalloc(na,data)
NALLOC *na;
void *data;
{
int a;
/* data-=sizeof(int);
a= *((int*)data); */
if (-1==(a=findit(data)))
{
log_error("Can't find pointer");
report();
return;
}
if ((a<0) || (a>MAXBLK))
{
log_error("Attempt to unalloc messed up block");
report();
return;
}
if (blks[a].owner!=na)
{
report();
log_error("Attempt to unalloc unowned block");
return;
}
if (blks[a].used<=0)
{
report();
log_error("Attempt to unalloc too many strings");
return;
}
blks[a].used--;
/* if (findit(data)!=a)
fprintf(stderr,"search failed\n");*/
}
extern NALLOC *glurp;
char *glurpdup(s)
char *s;
{
char *op;
op = na_alloc(glurp,strlen(s)+1);
strcpy(op,s);
return op;
}
/* routines to deal with big chunks of memory */
char *bigalloc(size)
int size;
{
int a,b;
char *ptr;
log_io(tprintf("bigalloc=%d",size));
/* round size up to nearest block */
size=((size-1)/SBSIZE)+1;
/* assign it block pointers */
for(a=0;(a<(MAXBLK-size)) && (blks[a].blk);a++);
if (a==(MAXBLK-size))
return(NULL);
ptr=(char *)sbrk(SBSIZE*size);
for(b=0;b<size;b++)
{
blks[a+b].owner=(NALLOC *)ptr;
blks[a+b].used=1;
blks[a+b].blk=ptr+SBSIZE*b;
}
return(ptr);
}
void bigfree(ptr)
void *ptr;
{
int a;
for(a=0;a<MAXBLK;a++)
if (blks[a].owner==(NALLOC *)ptr)
{
blks[a].owner=NULL;
blks[a].used=0;
}
}
#ifdef BRAIN_DAMAGE
char toupper(c)
char c;
{
return(((c>='a') && (c<='z')) ? c-'a'+'A' : c);
}
void memcpy(dest,source,amt)
char *dest;
char *source;
int amt;
{
while(amt--)
*dest++= *source++;
}
#endif