|
|
1.1 ! root 1: /* garbage collecting storage allocator; definition of ! 2: * cell is compatible with malloc, but slightly less portable ! 3: */ ! 4: ! 5: typedef struct dummy { struct dummy *ptr;} cell; ! 6: ! 7: #define GCMAX 5000 ! 8: #define GCMIN 50 ! 9: #define BPW (8*sizeof(*gcmap)) /*bits per word*/ ! 10: #define QBPW >>LOGBPW /* quotient /BPW if BPW not power of 2 */ ! 11: #define RBPW &(BPW-1) /* remainder %BPW if BPW not power of 2 */ ! 12: #define MASK (sizeof(cell)-1) /*assumes cell aligned to power of 2*/ ! 13: #define testbit(b,n) ((b[(n) QBPW]>>((n) RBPW))&1) ! 14: #define setbit(b,n) (b[(n) QBPW]|=1<<((n) RBPW)) ! 15: #define clrbit(b,n) (b[(n) QBPW]&=~(1<<((n) RBPW))) ! 16: #define testbusy(p) (*(int*)((p)-1)&1) ! 17: #define clearbusy(p) (*(int*)((p)-1)&=~1) ! 18: #define setbusy(p) (*(int*)((p)-1)|=1) ! 19: #define endptr(p) (cell*)(*(int*)((p)-1)&~1) ! 20: ! 21: #ifdef pdp11 ! 22: #define STACKTOP (cell*)(-2) ! 23: #define STATICBOT (cell*)2 /*appropriate for cc -i*/ ! 24: #define LOGBPW 4 ! 25: #endif ! 26: #ifdef vax ! 27: #define STACKTOP (cell*)0x7ffffffc ! 28: #define STATICBOT etext ! 29: #define LOGBPW 5 ! 30: #endif ! 31: #ifdef sun ! 32: #define STACKTOP (cell*)0x7ffffffc ! 33: #define STATICBOT etext ! 34: #define LOGBPW 5 ! 35: #endif ! 36: #define STATICTOP end ! 37: ! 38: static unsigned *gcmap; /*bitmap of busy blocks, grows by powers of 2*/ ! 39: static unsigned gcsize; /*number of bits in gcmap*/ ! 40: long gcmax = GCMAX; /*max number of allocations between collections*/ ! 41: long gcmin = GCMIN; /*min number*/ ! 42: extern cell end[]; ! 43: extern cell etext[]; ! 44: ! 45: char * ! 46: galloc(n) ! 47: unsigned n; ! 48: { ! 49: static long count; /*number of allocations since collection*/ ! 50: register cell* q; ! 51: register unsigned d; ! 52: unsigned qd; ! 53: char *malloc(); ! 54: while(++count >= gcmax || ! 55: (q=(cell*)malloc(n)) == 0) { /* at most twice*/ ! 56: if(count <= gcmin) ! 57: return(0); ! 58: garbage(); ! 59: count = 0; ! 60: } ! 61: if(q < STATICTOP) /* probably due to ialloc() */ ! 62: return((char*)q); ! 63: qd = q - STATICTOP; ! 64: if(qd >= gcsize) { ! 65: unsigned *tgmap; ! 66: register unsigned bsize; ! 67: if(BPW != 1<<LOGBPW) ! 68: abort(); ! 69: if(gcsize==0) { ! 70: bsize = 16384 QBPW; ! 71: tgmap = (unsigned*)malloc(bsize*sizeof(*gcmap)); ! 72: } else { ! 73: bsize = (gcsize QBPW)*2; ! 74: tgmap = (unsigned*)realloc((char*)gcmap, ! 75: bsize*sizeof(*gcmap)); ! 76: } ! 77: if(tgmap==0) ! 78: return(0); ! 79: gcmap = tgmap; ! 80: for(d=gcsize QBPW; d<bsize; d++) ! 81: gcmap[d] = 0; ! 82: gcsize = bsize*BPW; ! 83: } ! 84: setbit(gcmap, qd); ! 85: return((char *)q); ! 86: } ! 87: ! 88: /* pointer reversal algorithm ! 89: * gcmap bit is set for first word of each galloc'ed block ! 90: * make all galloc'd blocks appear idle and mark them busy as ! 91: * the garbage collector reaches them ! 92: */ ! 93: garbage() ! 94: { ! 95: cell fence; /* must really be on the stack*/ ! 96: register cell *p, *q; ! 97: register unsigned d; ! 98: register cell *s, *t, *u; /* lots of regs to force full save */ ! 99: register unsigned asize; ! 100: asize = (cell*)sbrk(0) - STATICTOP; ! 101: if(asize > gcsize) ! 102: asize = gcsize; ! 103: for(d=0; d<asize; d++) ! 104: if(testbit(gcmap,d)) ! 105: clearbusy(STATICTOP+d); ! 106: q = 0; ! 107: for(s=STATICBOT; s<STACKTOP; s=(s==STATICTOP-1?&fence:s+1)) { ! 108: p = s->ptr; ! 109: for(;;) { ! 110: while(!((int)p&MASK) && /*is p a cell-aligned address?*/ ! 111: p>=STATICTOP && /* pointing within */ ! 112: (d=p-STATICTOP)<asize && /* bounds of arena? */ ! 113: testbit(gcmap, d) && /*to galloc-ed block?*/ ! 114: !testbusy(p)) { /* not yet visited?*/ ! 115: setbusy(p); ! 116: /* q,p,*p = p,*p,q */ ! 117: t = p; ! 118: p = p->ptr; ! 119: t->ptr = q; ! 120: q = t; ! 121: } ! 122: while(q!=0) { ! 123: for(d=q-STATICTOP; !testbit(gcmap,d); d--) ! 124: continue; ! 125: if(q<endptr(t=STATICTOP+d)-1) ! 126: break; ! 127: /* q,*q,p = *q,p,t */ ! 128: u = q; ! 129: q = q->ptr; ! 130: u->ptr = p; ! 131: p = t; ! 132: } ! 133: if(q==0) ! 134: break; ! 135: /* *q,p,q[1] = p,q[1],*q; q++ */ ! 136: t = q->ptr; ! 137: q->ptr = p; ! 138: q++; ! 139: p = q->ptr; ! 140: q->ptr = t; ! 141: } ! 142: } ! 143: for(d=0; d<asize; d++) { ! 144: if(testbit(gcmap,d)&&!testbusy(STATICTOP+d)) ! 145: clrbit(gcmap,d); ! 146: } ! 147: } ! 148: ! 149: gfree(p) ! 150: cell *p; ! 151: { ! 152: free((char*)p); ! 153: clrbit(gcmap,p-STATICTOP); ! 154: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.