|
|
1.1 ! root 1: /* ! 2: * malloc.c ! 3: * Memory allocation routines. ! 4: * The memory arena is a circular linked list rooted at __a_first. ! 5: * Each arena is subdivided into two or more blocks. ! 6: * The first word of each block gives its length, ! 7: * with the low order bit set if the block is free; ! 8: * block lengths are always multiples of 2 to allow free marking. ! 9: * A length word containing 0 marks the end of an arena; ! 10: * in this case the following pointer points to the next arena. ! 11: */ ! 12: ! 13: #include <stdio.h> ! 14: #include <sys/malloc.h> ! 15: ! 16: MBLOCK *__a_scanp = NULL; /* start search here */ ! 17: MBLOCK *__a_first = NULL; /* first arena */ ! 18: unsigned __a_count = 0; /* number of blocks */ ! 19: ! 20: /* ! 21: * Get a new arena from sbrk() and hook it to the old list. ! 22: * Return 1 if there is any chance of malloc succeeding, else 0. ! 23: * Note that this assumes the argument to sbrk() is unsigned; ! 24: * bad news if sbrk() expects int and shrinks the break if negative. ! 25: */ ! 26: static ! 27: int ! 28: newarena(size) unsigned size; ! 29: { ! 30: register MBLOCK *mp, *pmp, *linkmp; ! 31: register unsigned len; ! 32: static MBLOCK *__a_top = NULL; ! 33: static char failed = 0; ! 34: ! 35: if (failed) /* no more room */ ! 36: return 0; ! 37: ! 38: /* Add space for end mblock, round up to 2^ARENASIZE */ ! 39: len = roundup(size + sizeof(MBLOCK), ARENASIZE); ! 40: if (len < size) ! 41: len = size; ! 42: ! 43: __a_scanp = __a_first; /* rescan from the begining */ ! 44: ! 45: /* ! 46: * If there isn't enough space get what we can it may be enough. ! 47: * This means further calls to newarena must fail. ! 48: */ ! 49: while ((mp = (MBLOCK *)sbrk(len)) == BADSBRK) { ! 50: failed = 1; ! 51: if (len <= DECRSIZE) ! 52: return 1; /* even zero may be ok */ ! 53: len -= DECRSIZE; ! 54: if (sizeof(MBLOCK) > len) ! 55: len = sizeof(MBLOCK); ! 56: } ! 57: ! 58: if (__a_top == NULL) { /* first time through */ ! 59: __a_count = 2; ! 60: __a_first = __a_scanp = linkmp = mp; ! 61: } ! 62: else if (__a_top == mp) { /* new arena follows old */ ! 63: /* ! 64: * The following assumes that len + sizeof(MBLOCK) ! 65: * will not be greater than the maximum unsigned value, ! 66: * which will be true if 2^ARENASIZE > sizeof(MBLOCK). ! 67: */ ! 68: --mp; ! 69: len += sizeof(MBLOCK); ! 70: linkmp = mp->uval.next; ! 71: __a_count++; ! 72: } ! 73: else { /* discontigous arenas */ ! 74: pmp = __a_top - 1; ! 75: linkmp = pmp->uval.next; /* save old pointer */ ! 76: pmp->uval.next = mp; /* old points to new */ ! 77: __a_count += 2; ! 78: } ! 79: mp->blksize = (len - sizeof(MBLOCK)) | FREE; ! 80: __a_top = bumpp(mp, len); ! 81: pmp = __a_top - 1; ! 82: pmp->blksize = 0; ! 83: pmp->uval.next = linkmp; ! 84: return 1; ! 85: } ! 86: ! 87: /* ! 88: * Allocate memory. ! 89: * Successive free blocks are consolidated when found. ! 90: */ ! 91: char * ! 92: malloc(size) unsigned size; ! 93: { ! 94: register MBLOCK *mp, *prevmp; ! 95: register unsigned len, needed, counter; ! 96: static char msg[] = "Bad pointer in malloc.\r\n"; ! 97: ! 98: if (size == 0) ! 99: return NULL; ! 100: needed = roundup(size + sizeof(unsigned), BLOCKSIZE); ! 101: if (needed < size) ! 102: return NULL; ! 103: ! 104: do { /* until we find enough or newarena fails */ ! 105: prevmp = NULL; ! 106: mp = __a_scanp; ! 107: for(counter = __a_count; counter--; ) { ! 108: if (!isfree(len = mp->blksize)) /* used block or pointer */ ! 109: prevmp = NULL; ! 110: else { ! 111: if (prevmp != NULL) { /* consolidate free */ ! 112: #if 0 ! 113: /* ! 114: * The following assumes adjacent free blocks can be consolidated without ! 115: * overflow of the size. The overflow test is conditionalized out here, ! 116: * but it may be required on some machines. In i8086 LARGE model, the code ! 117: * works without the test but only barely. When the memory arena gets larger ! 118: * than 64K, sbrk() returns mp pointing to the same memory location as ! 119: * newarena()/__a_top, but with a different segment:offset representation; ! 120: * thus the "if (__a_top == mp)" test in newarena fails (even though they ! 121: * point to the same memory location) and newarena() leaves a 0 end marker ! 122: * between the arenas. ! 123: */ ! 124: if (prevmp->blksize + realsize(len) > len) { ! 125: mp = prevmp; ! 126: len = (mp->blksize += realsize(len)); ! 127: __a_count--; ! 128: } ! 129: #else ! 130: mp = prevmp; ! 131: len = (mp->blksize += realsize(len)); ! 132: __a_count--; ! 133: #endif ! 134: } ! 135: if (len < needed) ! 136: prevmp = mp; ! 137: else { /* got one big enough */ ! 138: if ((len -= needed) < LEASTFREE) { ! 139: /* grab the entire block */ ! 140: mp->blksize=needed=realsize(mp->blksize); ! 141: __a_scanp = bumpp(mp, needed); ! 142: } else { ! 143: /* split into used and free portions */ ! 144: mp->blksize = needed; ! 145: __a_scanp = bumpp(mp, needed); ! 146: __a_scanp->blksize = len; ! 147: __a_count++; ! 148: } ! 149: return mp->uval.usera; ! 150: } ! 151: } ! 152: mp = (len) ? bumpp(mp, realsize(len)) : mp->uval.next; ! 153: } ! 154: ! 155: /* ! 156: * There should have been __a_count blocks bringing us full circle. ! 157: */ ! 158: if (mp != __a_scanp) { ! 159: write(2, msg, sizeof(msg) - 1); ! 160: abort(); ! 161: } ! 162: ! 163: /* Not enough room in the current arena, allocate a new one. */ ! 164: } while (newarena(needed)); ! 165: return NULL; ! 166: } ! 167: ! 168: /* ! 169: * Free a block. ! 170: * Some sanity checking. ! 171: * Adjacent free block consolidation happens in malloc(), not here. ! 172: */ ! 173: void ! 174: free(cp) char *cp; ! 175: { ! 176: register MBLOCK *mp; ! 177: register unsigned len; ! 178: ! 179: if (NULL == cp) /* ansi 4.10.3.2: free(NULL) has no effect */ ! 180: return; ! 181: ! 182: mp = mblockp(cp); ! 183: len = mp->blksize; ! 184: if (len < 2) { /* length of 0 or 1 is wrong */ ! 185: static char msg[] = "Bad pointer in free.\r\n"; ! 186: ! 187: write(2, msg, sizeof(msg) - 1); ! 188: abort(); ! 189: } ! 190: mp->blksize |= FREE; /* mark free */ ! 191: ! 192: /* ! 193: * If freed block precedes scan pointer or scan pointer is not free, ! 194: * reset the scan pointer. ! 195: */ ! 196: if (bumpp(mp, realsize(len)) == __a_scanp ! 197: || !isfree(__a_scanp->blksize)) ! 198: __a_scanp = mp; ! 199: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.