/* * Copyright (c) 1984, 1985, 1986 AT&T * All Rights Reserved * THIS IS UNPUBLISHED PROPRIETARY SOURCE * CODE OF AT&T. * The copyright notice above does not * evidence any actual or intended * publication of such source code. */ /* @(#)blok.c 1.1 */ /* * UNIX shell * * S. R. Bourne * Rewritten by David Korn * AT&T Bell Laboratories * */ #include "defs.h" #include "stak.h" #include "brkincr.h" /* * storage allocator * (circular first fit strategy) */ #define BUSY 01 #define busy(x) (Rcheat((x)->word)&BUSY) void addblok(); void free(); char *malloc(); void setbrk(); #ifdef DBUG void chkmem(); extern void p_str(); extern void p_num(); extern void p_flush(); #endif /* DBUG */ /* * equivalent to malloc(3) except that a data area stack is * maintained on top of the heap */ char *malloc(nbytes) unsigned nbytes; { register unsigned rbytes = round(nbytes+BYTESPERWORD,BYTESPERWORD); while(1) { register BLKPTR p = blokp; register BLKPTR q; register int c=0; do { if(!busy(p)) { while(!busy(q = p->word)) p->word = q->word; if(ADR(q)-ADR(p) >= rbytes) { blokp = BLK(ADR(p)+rbytes); if(q > blokp) blokp->word = p->word; p->word=BLK(Rcheat(blokp)|BUSY); return(ADR(p+1)); } } q = p; p = BLK(Rcheat(p->word)&~BUSY); } while(p>q || (c++)==0); addblok(rbytes); } } /* * add more space to the heap and move the stack to the top of the heap */ void addblok(reqd) register unsigned int reqd; { if(stakbot == 0) { setbrk(3*BRKINCR); bloktop = BLK(brkbegin); } if(stakbas!=staktop) { register STKPTR rndstak; register BLKPTR blokstak; pushstak(0); rndstak=(STKPTR) round(staktop,BYTESPERWORD); blokstak=BLK(stakbas)-1; blokstak->word=stakbsy; stakbsy=blokstak; bloktop->word=BLK(Rcheat(rndstak)|BUSY); bloktop=BLK(rndstak); } reqd += BRKINCR; reqd &= ~(BRKINCR-1); blokp=bloktop; bloktop=bloktop->word=BLK(Rcheat(bloktop)+reqd); reqd = 0; while((char*)bloktop+BRKINCR > brkend+reqd) reqd += BRKINCR; if(reqd) setbrk((int)reqd); bloktop->word=BLK(Rcheat(brkbegin)|BUSY); { register STKPTR stakadr=STK(bloktop+2); register STKPTR sp = stakadr; if(reqd = (staktop-stakbot)) { while(reqd-- > 0) *sp++ = *stakbot++; sp--; } staktop = sp; stakbas=stakbot=stakadr; } } /* * mark the block free if address is in the heap */ void free(ap) register char *ap; { register BLKPTR p; if(ap>brkbegin && ap<(char*)bloktop) { p = (BLKPTR)(ap-sizeof(p->word)); p->word = (BLKPTR)(Rcheat(p->word)&~BUSY); } } void setbrk(incr) { register char *a=(char *)(sbrk(incr)); if((int)a == -1) error(nospace); a = (char*)round(a,BYTESPERWORD); if(brkbegin==0) brkbegin = a; brkend=a+incr-8; #ifndef INT16 if(brkend > brkbegin + BRKMAX) { error(nospace); } #endif /* INT16 */ } #ifdef DBUG void chkmem() { register BLKPTR p = (BLKPTR)brkbegin; register BLKPTR q; register int us=0, un=0; while(1) { q = (BLKPTR) (Rcheat(p->word)&~BUSY); if(qbloktop) abort(3); if(p==bloktop) break; if(busy(p)) us += q-p; else un += q-p; if(p>=q) { p_flush(); abort(4); } p=q; } un *= sizeof(*q); us *= sizeof(*q); p_str("free/used/missing",':'); p_num(un,' '); p_num(us,' '); p_num((char*)bloktop - (char*)brkbegin - (un+us),NL); } /* * returns 1 if is on heap and is free * returns 2 if is on heap and not beginning of a block * otherwise returns 0 */ int chkfree(ap) register char *ap; { register BLKPTR p; if(ap>brkbegin && ap<(char*)bloktop) { p = (BLKPTR)(ap-sizeof(p->word)); if(p->wordword>bloktop) return(2); return(!busy(p)); } return(0); } #endif /* DBUG */