|
|
1.1 ! root 1: /* allocate and free routines ! 2: * all blocks are allocated in multiples of 2 ! 3: * with the first word as the true length ! 4: * the lo order bit is 1 if the block is free. ! 5: * A word of zero marks the end of an arena and points ! 6: * to the start of the next arena. Arenas point in a circle. ! 7: */ ! 8: ! 9: #include <stdio.h> ! 10: #include <malloc.h> ! 11: ! 12: struct mblock *_a_scanp = NULL; /* search starts here */ ! 13: ! 14: static unsigned depth = 0; /* depth of malloc recursion */ ! 15: ! 16: static char msg[] = "Bad pointer in free.\n"; ! 17: ! 18: /* get a new arena from sbrk and hook it to the old */ ! 19: ! 20: static void ! 21: newarea( len) ! 22: register unsigned len; ! 23: { ! 24: register struct mblock *newa, *newb, *prev; ! 25: ! 26: char *passbug = BADSBRK; /* beat large model c bug */ ! 27: ! 28: static struct mblock *_a_topar = NULL; ! 29: ! 30: unsigned cbrk = (unsigned)sbrk( 0); ! 31: ! 32: if( len > 65500L) ! 33: return; ! 34: len += sizeof(struct mblock); ! 35: if( len < 512) ! 36: if( cbrk < 65536L - 511) ! 37: len = 512; ! 38: else ! 39: len = -cbrk; ! 40: #if Z8001 ! 41: else if( (unsigned long)cbrk+len > 65536L) ! 42: newarea( - cbrk - sizeof( struct mblock)); ! 43: #endif ! 44: if( passbug == (newa = sbrk(len))) ! 45: return; ! 46: ! 47: if(_a_topar == NULL) /* first time through */ ! 48: _a_scanp = prev = newa; ! 49: ! 50: else if(_a_topar == newa) { /* new over old */ ! 51: --newa; ! 52: len += sizeof(struct mblock); ! 53: prev = newa->uval.next; ! 54: ! 55: } else { /* discontigous arenas */ ! 56: newb = _a_topar; ! 57: prev = (--newb)->uval.next; /* save old ptr */ ! 58: newb->uval.next = newa; /* old pts to new */ ! 59: } ! 60: newa->blksize = (len - sizeof(struct mblock)) | FREE; ! 61: newb = _a_topar = adr(newa) + len; ! 62: (--newb)->blksize = 0; ! 63: newb->uval.next = prev; ! 64: return; ! 65: } ! 66: ! 67: char * ! 68: malloc( size) ! 69: unsigned size; ! 70: { ! 71: register struct mblock *ptr, *optr; ! 72: register unsigned len, siz; ! 73: ! 74: siz = roundup(size + sizeof(unsigned), POW2); ! 75: if(siz < size) ! 76: return(NULL); ! 77: optr = NULL; ! 78: if((ptr = _a_scanp) != NULL) { ! 79: do { ! 80: if(isfree(len = ptr->blksize)) { /* free block */ ! 81: if(optr != NULL) { /* consolidate free */ ! 82: len = (optr->blksize += realsize(len)); ! 83: ptr = optr; ! 84: } ! 85: optr = ptr; ! 86: if(len > siz) { /* got one big enough */ ! 87: if((len -= siz)<LEASTFREE) /* close enough */ ! 88: ptr->blksize = realsize(ptr->blksize); ! 89: else { ! 90: ptr->blksize = siz; ! 91: _a_scanp = siz + adr(ptr); ! 92: _a_scanp->blksize = len; ! 93: } ! 94: return(ptr->uval.usera); ! 95: } ! 96: } else /* used block or area ptr */ ! 97: optr = NULL; ! 98: ! 99: if(len) ! 100: ptr = realsize(len) + adr(ptr); ! 101: else ! 102: ptr = ptr->uval.next; /* new arena */ ! 103: } while(ptr != _a_scanp); ! 104: } ! 105: ! 106: if(optr != NULL) ! 107: _a_scanp = optr; ! 108: ! 109: /* no room in the arena or first time */ ! 110: if(++depth >= 2) { ! 111: depth--; ! 112: return(NULL); ! 113: } ! 114: newarea(siz); ! 115: ptr = malloc(size); ! 116: depth--; ! 117: return(ptr); ! 118: } ! 119: ! 120: /* free a block */ ! 121: free(cp) ! 122: char *cp; ! 123: { ! 124: register struct mblock *ap; ! 125: ! 126: ap = cp - sizeof(unsigned); ! 127: if(!ap->blksize) { ! 128: write(2, msg, strlen(msg)); ! 129: abort(); ! 130: } ! 131: ap->blksize |= FREE; /* mark free even if free */ ! 132: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.