/* 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