|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)malloc.c 4.1 10/10/80"; ! 4: ! 5: /* ! 6: * Patched up version of malloc to do an integrity check ! 7: * on each allocation or free. ! 8: */ ! 9: ! 10: #ifdef debug ! 11: #define ASSERT(p,t) if(!(p))return(t(TRASHED));else ! 12: #else ! 13: #define ASSERT(p,t) ! 14: #endif ! 15: ! 16: /* avoid break bug */ ! 17: #ifdef pdp11 ! 18: #define GRANULE 64 ! 19: #else ! 20: #define GRANULE 0 ! 21: #endif ! 22: /* C storage allocator ! 23: * circular first-fit strategy ! 24: * works with noncontiguous, but monotonically linked, arena ! 25: * each block is preceded by a ptr to the (pointer of) ! 26: * the next following block ! 27: * blocks are exact number of words long ! 28: * aligned to the data type requirements of ALIGN ! 29: * pointers to blocks must have BUSY bit 0 ! 30: * bit in ptr is 1 for busy, 0 for idle ! 31: * gaps in arena are merely noted as busy blocks ! 32: * last block of arena (pointed to by alloct) is empty and ! 33: * has a pointer to first ! 34: * idle blocks are coalesced during space search ! 35: * ! 36: * a different implementation may need to redefine ! 37: * ALIGN, NALIGN, BLOCK, BUSY, INT ! 38: * where INT is integer type to which a pointer can be cast ! 39: */ ! 40: #define INT int ! 41: #define ALIGN int ! 42: #define NALIGN 1 ! 43: #define WORD sizeof(union store) ! 44: #define BLOCK 1024 /* a multiple of WORD*/ ! 45: #define BUSY 1 ! 46: #define NULL 0 ! 47: #define TRASHED -1 ! 48: #define testbusy(p) ((INT)(p)&BUSY) ! 49: #define setbusy(p) (union store *)((INT)(p)|BUSY) ! 50: #define clearbusy(p) (union store *)((INT)(p)&~BUSY) ! 51: ! 52: union store { union store *ptr; ! 53: ALIGN dummy[NALIGN]; ! 54: int calloc; /*calloc clears an array of integers*/ ! 55: }; ! 56: ! 57: static union store allocs[2]; /*initial arena*/ ! 58: static union store *allocp; /*search ptr*/ ! 59: static union store *alloct; /*arena top*/ ! 60: char *sbrk(); ! 61: ! 62: char * ! 63: malloc(nbytes) ! 64: ! 65: unsigned nbytes; ! 66: { ! 67: register union store *p, *q; ! 68: register nw; ! 69: static temp; /*coroutines assume no auto*/ ! 70: ! 71: if(allocs[0].ptr==0) { /*first time*/ ! 72: allocs[0].ptr = setbusy(&allocs[1]); ! 73: allocs[1].ptr = setbusy(&allocs[0]); ! 74: alloct = &allocs[1]; ! 75: allocp = &allocs[0]; ! 76: } ! 77: nw = (nbytes+WORD+WORD-1)/WORD; ! 78: ASSERT(allocp>=allocs && allocp<=alloct,(char *)); ! 79: ASSERT(allock(),(char *)); ! 80: for(p=allocp; ; ) { ! 81: for(temp=0; ; ) { ! 82: if(!testbusy(p->ptr)) { ! 83: while(!testbusy((q=p->ptr)->ptr)) { ! 84: ASSERT(q>p&&q<alloct,(char *)); ! 85: p->ptr = q->ptr; ! 86: } ! 87: if(q>=p+nw && p+nw>=p) ! 88: goto found; ! 89: } ! 90: q = p; ! 91: p = clearbusy(p->ptr); ! 92: if(p>q) ! 93: ASSERT(p<=alloct,(char *)); ! 94: else if(q!=alloct || p!=allocs) { ! 95: ASSERT(q==alloct&&p==allocs,(char *)); ! 96: return(NULL); ! 97: } else if(++temp>1) ! 98: break; ! 99: } ! 100: temp = ((nw+BLOCK/WORD)/(BLOCK/WORD))*(BLOCK/WORD); ! 101: q = (union store *)sbrk(0); ! 102: if(q+temp+GRANULE < q) { ! 103: return(NULL); ! 104: } ! 105: q = (union store *)sbrk(temp*WORD); ! 106: if((INT)q == -1) { ! 107: return(NULL); ! 108: } ! 109: ASSERT(q>alloct,(char *)); ! 110: alloct->ptr = q; ! 111: if(q!=alloct+1) ! 112: alloct->ptr = setbusy(alloct->ptr); ! 113: alloct = q->ptr = q+temp-1; ! 114: alloct->ptr = setbusy(allocs); ! 115: } ! 116: found: ! 117: allocp = p + nw; ! 118: ASSERT(allocp<=alloct,(char *)); ! 119: if(q>allocp) { ! 120: allocp->ptr = p->ptr; ! 121: } ! 122: p->ptr = setbusy(allocp); ! 123: return((char *)(p+1)); ! 124: } ! 125: ! 126: /* ! 127: * freeing strategy tuned for LIFO allocation ! 128: */ ! 129: ! 130: free(ap) ! 131: ! 132: register char *ap; ! 133: { ! 134: register union store *p = (union store *)ap; ! 135: ! 136: ASSERT(p != 0,(long)); ! 137: ASSERT(p>clearbusy(allocs[1].ptr)&&p<=alloct,(long)); ! 138: ASSERT(allock(),(long)); ! 139: allocp = --p; ! 140: ASSERT(testbusy(p->ptr),(long)); ! 141: p->ptr = clearbusy(p->ptr); ! 142: ASSERT(p->ptr > allocp && p->ptr <= alloct,(long)); ! 143: return(NULL); ! 144: } ! 145: ! 146: #ifdef debug ! 147: allock() ! 148: { ! 149: #ifdef longdebug ! 150: register union store *p; ! 151: int x; ! 152: x = 0; ! 153: for(p= &allocs[0]; clearbusy(p->ptr) > p; p=clearbusy(p->ptr)) { ! 154: if(p==allocp) ! 155: x++; ! 156: } ! 157: ASSERT(p==alloct,(long)); ! 158: return(x==1|p==allocp); ! 159: #else ! 160: return(1); ! 161: #endif ! 162: } ! 163: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.