|
|
1.1 ! root 1: #include "sam.h" ! 2: /* ! 3: * Garbage-compacting allocator ! 4: * ! 5: * called as: gcalloc(nbytes, where) ! 6: * gcrealloc(p, nbytes) ! 7: * gcfree(p) ! 8: * nbytes is unsigned long ! 9: * where is a pointer to the location which will point to the area ! 10: * (e.g. base in a Bitmap), to be updated when necessary. ! 11: * The return values for the allocators are the new address, ! 12: * but since they update *where, the value isn't too useful. ! 13: * They panic if they fail. ! 14: */ ! 15: ! 16: /* ! 17: * The arena is allocated in longs, to speed up compaction ! 18: * Garbage is compacted towards the bottom (low address end) of the arena. ! 19: * A block has a struct header as its bottom HEADERSIZE longs for use by gcfree. ! 20: * header.pval points to the USER location where the pointer to the block ! 21: * is stored; this cell must be updated after a compaction. ! 22: * Deallocated blocks have header.pval odd. ! 23: */ ! 24: ! 25: #define BRKINCR (16*1024) /* bytes to add to arena each time */ ! 26: #define LBRKINCR (BRKINCR/sizeof(long)) ! 27: #define FREE 1 ! 28: #define HEADERSIZE sizeof(struct header)/sizeof(long) ! 29: ! 30: static long *nextlong; ! 31: static long *startarena; ! 32: static long *endarena; ! 33: static compact(); ! 34: int dontcompact; ! 35: ! 36: extern char *brk(); ! 37: extern char *sbrk(); ! 38: ! 39: struct header{ ! 40: union uuu{ ! 41: long Uival; /* integer value of where */ ! 42: long **Upval; /* where */ ! 43: }u; ! 44: ulong nlongs; /* # of longs in the user's data */ ! 45: }; ! 46: #define ival u.Uival ! 47: #define pval u.Upval ! 48: #define hp ((struct header *)p) ! 49: ! 50: uchar * ! 51: gcalloc(nbytes, where) ! 52: register ulong nbytes; ! 53: long **where; ! 54: { ! 55: register long *p; ! 56: register ulong nl; ! 57: if(nextlong>endarena) ! 58: panic("nextlong>endarena"); ! 59: if((long)where&FREE) /* head off a possible disaster */ ! 60: panic("where&FREE"); ! 61: if(startarena==0){ ! 62: if((int)(startarena=(long *)sbrk(BRKINCR))==-1) ! 63: error(Ealloc); ! 64: endarena=startarena+(BRKINCR/sizeof(long)); ! 65: nextlong=startarena; ! 66: } ! 67: nbytes+=sizeof(long)-1; ! 68: nbytes/=sizeof(long); /* convert bytes to longs */ ! 69: #define Nlongs nbytes ! 70: Nlongs+=HEADERSIZE; ! 71: if(endarena-nextlong < Nlongs){ ! 72: if(!dontcompact) ! 73: compact(); ! 74: if(endarena-nextlong < Nlongs){ ! 75: nl=(nextlong+Nlongs)-startarena; ! 76: /* if !compacting, avoid greed */ ! 77: if(!dontcompact) ! 78: nl=((nl+LBRKINCR-1)/LBRKINCR)*LBRKINCR; ! 79: if(brk((char *)(startarena+nl))!=0) ! 80: error(Ealloc); ! 81: endarena=startarena+nl; ! 82: } ! 83: } ! 84: p=nextlong; ! 85: hp->pval=where; ! 86: hp->nlongs=Nlongs; ! 87: nextlong+=Nlongs; ! 88: return (uchar *)(*(hp->pval)=p+HEADERSIZE); ! 89: } ! 90: uchar * ! 91: gcrealloc(cp, nbytes) ! 92: uchar *cp; ! 93: register ulong nbytes; ! 94: { ! 95: register long *p=(long *)cp, *q; ! 96: register long *newp; ! 97: register long **ptrold; ! 98: register n; ! 99: long *x; ! 100: p-=HEADERSIZE; /* the header */ ! 101: n=hp->nlongs; ! 102: nbytes+=sizeof(long)-1; ! 103: nbytes/=sizeof(long); /* convert bytes to longs; nbytes is now Nlongs */ ! 104: ptrold=hp->pval; /* location that will be updated if compaction occurs */ ! 105: /* we give where==x to gcalloc to avoid collision with old header */ ! 106: newp=(long *)gcalloc((ulong)(Nlongs*sizeof(long)), &x); ! 107: /* now it's safe to have both headers point to the same place */ ! 108: ((struct header *)(newp-HEADERSIZE))->pval=ptrold; ! 109: p= *ptrold; ! 110: q=newp; ! 111: if(n>Nlongs) ! 112: n=Nlongs; ! 113: if(n>0) do ! 114: *q++= *p++; ! 115: while(--n); ! 116: (void)gcfree((uchar *)*ptrold); ! 117: return (uchar *)(*ptrold=newp); ! 118: } ! 119: shiftgcarena(nl) ! 120: ulong nl; ! 121: { ! 122: register long *p; ! 123: if(startarena==0 || dontcompact) ! 124: return; ! 125: if(nl<0) ! 126: panic("shiftgcarena"); ! 127: bcopy((uchar *)startarena, (uchar *)nextlong, (uchar *)(startarena+nl), -1); ! 128: nextlong+=nl; ! 129: startarena+=nl; ! 130: endarena+=nl; ! 131: for(p=startarena; p<nextlong; p+=hp->nlongs){ ! 132: if((hp->ival&FREE)==0) ! 133: *(hp->pval)+=nl; ! 134: } ! 135: } ! 136: gcfree(cp) ! 137: uchar *cp; ! 138: { ! 139: register long *p=(long *)cp; ! 140: if(p==0) ! 141: return; ! 142: p-=HEADERSIZE; ! 143: if(p<startarena || nextlong<=p) ! 144: panic("gcfree"); ! 145: hp->ival|=FREE; ! 146: } ! 147: static ! 148: compact() ! 149: { ! 150: register long *w, *p; ! 151: register ulong n; ! 152: ! 153: w=p=startarena; ! 154: while(p<nextlong){ ! 155: if(hp->ival&FREE){ ! 156: p+=hp->nlongs; ! 157: continue; ! 158: } ! 159: if(w==p){ ! 160: w+=hp->nlongs; ! 161: p+=hp->nlongs; ! 162: continue; ! 163: } ! 164: *(hp->pval)=w+HEADERSIZE; /* update *where */ ! 165: *w++=hp->ival; ! 166: *w++=n=hp->nlongs; ! 167: p+=HEADERSIZE; ! 168: if((n-=HEADERSIZE)>0) do ! 169: *w++ = *p++; ! 170: while(--n); ! 171: } ! 172: nextlong=w; ! 173: } ! 174: gcchk() ! 175: { ! 176: register long *p; ! 177: if(startarena==0) ! 178: return; ! 179: for(p=startarena; p<nextlong; p+=hp->nlongs) ! 180: if((hp->ival&FREE)==0){ ! 181: if(hp->pval==0 || ((long *)hp->pval>=startarena && ((int)(hp->pval)&0x70000000L)==0)) ! 182: panic("gcchk 1"); ! 183: if(p+hp->nlongs>nextlong) ! 184: panic("gcchk 2"); ! 185: } ! 186: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.