|
|
1.1 ! root 1: #ifdef alloc ! 2: #undef alloc ! 3: #undef free ! 4: #endif ! 5: #ifdef debug ! 6: #define ASSERT(p) if(!(p))botch("p");else ! 7: botch(s) ! 8: char *s; ! 9: { ! 10: printf("assertion botched: %s\n",s); ! 11: abort(); ! 12: } ! 13: #else ! 14: #define ASSERT(p) ! 15: #endif ! 16: ! 17: /* C storage allocator ! 18: * first-fit strategy ! 19: * works with noncontiguous, but monotonically linked, arena ! 20: * each block is preceded by a ptr to the (pointer of) ! 21: * the next following block ! 22: * blocks are exact number of words long ! 23: * aligned to the data type requirements of ALIGN ! 24: * pointers to blocks must have BUSY bit 0 ! 25: * bit in ptr is 1 for busy, 0 for idle ! 26: * gaps in arena are merely noted as busy blocks ! 27: * last block of arena is empty and ! 28: * has a pointer to first ! 29: * idle blocks are coalesced during space search ! 30: * ! 31: * a different implementation may need to redefine ! 32: * ALIGN, NALIGN, BUSY, INT ! 33: * where INT is integer type to which a pointer can be cast ! 34: */ ! 35: #define INT long ! 36: #define ALIGN int ! 37: #define NALIGN 1 ! 38: #define WORD sizeof(union store) ! 39: #define BUSY 1 ! 40: #define NULL 0 ! 41: #define testbusy(p) ((INT)(p)&BUSY) ! 42: #define setbusy(p) (union store *)((INT)(p)|BUSY) ! 43: #define clearbusy(p) (union store *)((INT)(p)&~BUSY) ! 44: ! 45: union store { ! 46: struct { ! 47: union store *Uptr; ! 48: char * Uproc; /* pointer to process of allocating guy */ ! 49: } u; ! 50: union store *ptr; ! 51: ALIGN dummy[NALIGN]; ! 52: int calloc; /*calloc clears an array of integers*/ ! 53: }; ! 54: #define proc u.Uproc ! 55: ! 56: char *allocstartp; /* &end, but passed in because this is in ROM */ ! 57: char *allocendp; /* should adjust according to load */ ! 58: #define START allocstartp ! 59: #define FIRSTWORD ((union store *)(START)) ! 60: #define LASTWORD ((union store *)(allocendp-4)) ! 61: static union store *allocb; /*arena base*/ ! 62: #ifdef REALLOC ! 63: static union store *allocx; /*for benefit of realloc*/ ! 64: #endif ! 65: ! 66: allocinit(s, e) ! 67: int *s, *e; ! 68: { ! 69: allocstartp=(char *)s; ! 70: allocendp=(char *)e; ! 71: FIRSTWORD->ptr = LASTWORD; ! 72: LASTWORD->ptr = (union store *)(START+1); ! 73: allocb = (union store *)START; ! 74: } ! 75: ! 76: char * ! 77: realalloc(nbytes, whichproc) ! 78: unsigned nbytes; ! 79: char *whichproc; ! 80: { ! 81: register union store *p, *q; ! 82: register nw; ! 83: register union store *allocp; ! 84: static int temp; ! 85: ! 86: nw = (nbytes+WORD+WORD-1)/WORD; ! 87: ASSERT(allock(allocb)); ! 88: for(; ; ) { /* done at most twice */ ! 89: p = allocb; ! 90: allocp = allocb; ! 91: for(temp=0; ; ) { ! 92: if(!testbusy(p->ptr)) { ! 93: while(!testbusy((q=p->ptr)->ptr)) { ! 94: ASSERT(q>p); ! 95: p->ptr = q->ptr; ! 96: allocp = p; ! 97: } ! 98: if(q>=p+nw && p+nw>=p) ! 99: goto found; ! 100: } ! 101: q = p; ! 102: p = clearbusy(p->ptr); ! 103: if(p <= q) { ! 104: ASSERT(p==allocb); ! 105: if(p != allocb) ! 106: return(NULL); ! 107: if(++temp > 1) ! 108: break; ! 109: } ! 110: } ! 111: return NULL; /* get more space, someday */ ! 112: } ! 113: found: ! 114: allocp = p + nw; ! 115: if(q>allocp) { ! 116: #ifdef REALLOC ! 117: allocx = allocp->ptr; ! 118: #endif ! 119: allocp->ptr = p->ptr; ! 120: } ! 121: p->ptr = setbusy(allocp); ! 122: /* clear the storage, for jerqs only */ ! 123: for(q=p+1; q<p+nw; q++){ ! 124: q->ptr=0; ! 125: q->proc=0; /* cough */ ! 126: } ! 127: p->proc = whichproc; ! 128: return((char *)(p+1)); ! 129: } ! 130: ! 131: char * ! 132: alloc(nbytes) ! 133: unsigned nbytes; ! 134: { ! 135: return realalloc(nbytes, (char *)0); ! 136: } ! 137: ! 138: /* freeing strategy tuned for LIFO allocation ! 139: */ ! 140: free(ap) ! 141: char *ap; ! 142: { ! 143: register union store *p = (union store *)ap-1; ! 144: ! 145: ASSERT(allock(p)); ! 146: ASSERT(testbusy(p->ptr)); ! 147: p->ptr = clearbusy(p->ptr); ! 148: p->proc = 0; ! 149: ASSERT(p->ptr > p); ! 150: } ! 151: ! 152: /* free all storage associated with the named process ! 153: */ ! 154: freeall(whichproc) ! 155: register char *whichproc; ! 156: { ! 157: register union store *p, *r; ! 158: ! 159: if ((p=allocb)->proc == whichproc) /* first block on chain */ ! 160: free((char *)(p+1)); ! 161: for(p=allocb; (r=clearbusy(p->ptr)) > p; p=r) /* rest of chain... */ ! 162: if((r->proc == whichproc) && (r != LASTWORD)) ! 163: free((char *)(r+1)); /* ...except LASTWORD */ ! 164: gcfreeall(whichproc); ! 165: } ! 166: ! 167: #ifdef REALLOC ! 168: /* realloc(p, nbytes) reallocates a block obtained from alloc() ! 169: * and freed since last call of alloc() ! 170: * to have new size nbytes, and old content ! 171: * returns new location, or 0 on failure ! 172: */ ! 173: ! 174: char * ! 175: realloc(pp, nbytes) ! 176: char *pp; ! 177: unsigned nbytes; ! 178: { ! 179: register union store *q; ! 180: register union store *p = (union store *)pp; ! 181: union store *s, *t; ! 182: register unsigned nw; ! 183: unsigned onw; ! 184: ! 185: ASSERT(allock(p-1)); ! 186: if(testbusy(p[-1].ptr)) ! 187: free((char *)p); ! 188: onw = p[-1].ptr - p; ! 189: q = (union store *)alloc(nbytes); ! 190: if(q==NULL || q==p) ! 191: return((char *)q); ! 192: ASSERT(q<p||q>p[-1].ptr); ! 193: s = p; ! 194: t = q; ! 195: nw = (nbytes+WORD-1)/WORD; ! 196: if(nw<onw) ! 197: onw = nw; ! 198: while(onw--!=0) ! 199: *t++ = *s++; ! 200: ASSERT(clearbusy(q[-1].ptr)-q==nw); ! 201: if(q<p && q+nw>=p) ! 202: (q+(q+nw-p))->ptr = allocx; ! 203: ASSERT(allock(q-1)); ! 204: return((char *)q); ! 205: } ! 206: #endif ! 207: ! 208: #ifdef debug ! 209: allock(q) ! 210: union store *q; ! 211: { ! 212: #ifdef longdebug ! 213: register union store *p, *r; ! 214: int x; ! 215: x = 0; ! 216: p = allocb; ! 217: if(((union store *)START)->ptr==0) ! 218: return(1); ! 219: for( ; (r=clearbusy(p->ptr)) > p; p=r) { ! 220: if(p==q) ! 221: x++; ! 222: } ! 223: return(r==allocb&(x==1|p==q)); ! 224: #else ! 225: return(q>=allocb); ! 226: #endif ! 227: } ! 228: abort(){ ! 229: printf("abort\n"); ! 230: for(;;); ! 231: } ! 232: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.