|
|
1.1 ! root 1: #include <setup.h> ! 2: ! 3: #define oops(x, s) /*if(x)sstep(s)*/ ! 4: long NLONGS, NAVAIL; ! 5: /* ! 6: * Garbage-collecting allocator ! 7: * ! 8: * called as: gcalloc(nbytes, where) ! 9: * nbytes is unsigned long ! 10: * where is a pointer to the location which will point to the area ! 11: * (e.g. base in a Bitmap), to be updated when necessary ! 12: */ ! 13: ! 14: /* ! 15: * The arena is allocated in longs, to speed up compaction ! 16: * Garbage is compacted towards the top (high address end) of the arena, ! 17: * i.e. away from the regular, non-compacting, allocator. ! 18: * A block has a struct header as its top HEADERSIZE longs, and ! 19: * a pointer to the struct header as its bottom long, for use by gcfree. ! 20: * header.caller points to the allocating process so things can be cleaned ! 21: * up when it exits. ! 22: * header.pval points to the USER location where the pointer to the block ! 23: * is stored; this cell must be updated after a compaction. ! 24: * Deallocated blocks have header.pval odd. ! 25: */ ! 26: extern char *allocendp; /* real allocendp defined in alloc.c */ ! 27: #define STARTAREA (long *)(allocendp) ! 28: long *ENDAREA; ! 29: /*static*/ long *nextlong; ! 30: struct header{ ! 31: union uuu{ ! 32: long Uival; /* integer value of where */ ! 33: long **Upval; /* where */ ! 34: }u; ! 35: long *caller; /* which process allocated */ ! 36: unsigned long nlongs; /* # of longs in the user's data */ ! 37: }; ! 38: #define ival u.Uival ! 39: #define pval u.Upval ! 40: #define HEADERSIZE sizeof(struct header)/sizeof(long) ! 41: #define hp ((struct header *)p) ! 42: ! 43: gcinit() ! 44: { ! 45: ENDAREA= maxaddr[VALMAXADDR]-4; ! 46: nextlong = ENDAREA; /* init; this runs in rom, so .data no good */ ! 47: } ! 48: ! 49: char * ! 50: realgcalloc(nbytes, where, caller) ! 51: register unsigned long nbytes; ! 52: long **where; ! 53: char *caller; /* really a Proc * */ ! 54: { ! 55: register retry = 0; ! 56: register long *p; ! 57: ! 58: if((long)caller&1) /* head off a possible disaster */ ! 59: return 0; ! 60: nbytes+=sizeof(long)-1; ! 61: nbytes>>=2; /* convert bytes to longs */ ! 62: #define Nlongs nbytes ! 63: Nlongs+=HEADERSIZE+1; ! 64: while(nextlong-STARTAREA < Nlongs){ ! 65: NLONGS=Nlongs; ! 66: NAVAIL=nextlong-STARTAREA; ! 67: if(retry++) ! 68: return 0; ! 69: compact(); ! 70: } ! 71: p=nextlong-HEADERSIZE; ! 72: hp->caller=(long *)caller; ! 73: hp->pval=where; ! 74: hp->nlongs=Nlongs-HEADERSIZE-1; ! 75: nextlong-=Nlongs; ! 76: *nextlong=(long)p; /* so we can find the header when we free */ ! 77: return (char *)(*(hp->pval)=nextlong+1); ! 78: } ! 79: char * ! 80: gcalloc(n, w) ! 81: unsigned long n; ! 82: long **w; ! 83: { ! 84: return realgcalloc(n, w, (char *)0); ! 85: } ! 86: gcfree(cp) ! 87: register char *cp; ! 88: { ! 89: #define p ((long *)cp) ! 90: /* nice and safe */ ! 91: oops((p<=nextlong || p>=ENDAREA),"gcfree 1"); ! 92: if(p>nextlong && p<ENDAREA){ ! 93: cp=(char *)(p[-1]); /* pointer to the header */ ! 94: oops(p<=nextlong || p>=ENDAREA, "gcfree 2"); ! 95: if(p>nextlong && p<ENDAREA) ! 96: hp->ival|=1; ! 97: } ! 98: #undef p ! 99: } ! 100: gcfreeall(whichproc) ! 101: char *whichproc; ! 102: { ! 103: register long *p; ! 104: for(p=ENDAREA; p>nextlong; p-=hp->nlongs+1){ ! 105: p-=HEADERSIZE; ! 106: oops(hp->caller > nextlong, "gcfreeall 1"); ! 107: oops(hp->pval > nextlong, "gcfreeall 2"); ! 108: if(hp->caller==(long *)whichproc) ! 109: hp->ival|=1; ! 110: } ! 111: } ! 112: #include <jerq.h> ! 113: static ! 114: compact() ! 115: { ! 116: register long *w, *p; ! 117: register struct header *header; ! 118: register unsigned long n; ! 119: static Rectangle r={0, 0, 50, 50}; ! 120: ! 121: rectf(&display, r, F_XOR); ! 122: w=ENDAREA; ! 123: p=w; ! 124: while(p>nextlong){ ! 125: header=(struct header *)(p-HEADERSIZE); ! 126: /* ! 127: if(w==p || (header->ival&1)){ ! 128: p-= n = header->nlongs+HEADERSIZE+1; ! 129: if((header->ival&1)==0) ! 130: w-=n; ! 131: continue; ! 132: } ! 133: */ ! 134: oops(header->caller > nextlong, "compact 1"); ! 135: oops(header->pval > nextlong, "compact 2"); ! 136: if(header->ival&1){ ! 137: p -= header->nlongs+HEADERSIZE+1; ! 138: continue; ! 139: } ! 140: *--w = n = header->nlongs; ! 141: *--w = (long)header->caller; ! 142: *--w = header->ival; ! 143: p-=HEADERSIZE; ! 144: header = (struct header *)w; ! 145: *(((struct header *)w)->pval)=w-n; /* update *where */ ! 146: if(n>0) do ! 147: *--w = *--p; ! 148: while(--n); ! 149: --p; ! 150: *--w = (long)header; /* back pointer to header */ ! 151: } ! 152: nextlong=w; ! 153: rectf(&display, r, F_XOR); ! 154: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.