|
|
1.1 ! root 1: /* ! 2: * area-based allocation built on malloc/free ! 3: */ ! 4: ! 5: static char *RCSid = "$Header"; ! 6: ! 7: #include <stddef.h> ! 8: #include <stdlib.h> ! 9: #include <setjmp.h> ! 10: #include "sh.h" ! 11: ! 12: #define ICELLS 100 /* number of Cells in small Block */ ! 13: ! 14: typedef union Cell Cell; ! 15: typedef struct Block Block; ! 16: ! 17: /* ! 18: * The Cells in a Block are organized as a set of objects. ! 19: * Each object (pointed to by dp) begins with a size in (dp-1)->size, ! 20: * followed with "size" data Cells. Free objects are ! 21: * linked together via dp->next. ! 22: */ ! 23: ! 24: union Cell { ! 25: size_t size; ! 26: Cell *next; ! 27: struct {int _;} junk; /* alignment */ ! 28: }; ! 29: ! 30: struct Block { ! 31: Block *next; /* list of Blocks in Area */ ! 32: Cell *free; /* object free list */ ! 33: Cell *last; /* &b.cell[size] */ ! 34: Cell cell [1]; /* [size] Cells for allocation */ ! 35: }; ! 36: ! 37: Block aempty = {&aempty, aempty.cell, aempty.cell}; ! 38: ! 39: /* create empty Area */ ! 40: Area * ! 41: ainit(ap) ! 42: register Area *ap; ! 43: { ! 44: ap->free = &aempty; ! 45: return ap; ! 46: } ! 47: ! 48: /* free all object in Area */ ! 49: void ! 50: afreeall(ap) ! 51: register Area *ap; ! 52: { ! 53: register Block *bp; ! 54: ! 55: if (ap->free == NULL || ap->free == &aempty) ! 56: return; ! 57: for (bp = ap->free; ; bp = bp->next) { ! 58: free((Void*)bp); ! 59: if (bp->next == ap->free) ! 60: break; ! 61: } ! 62: ap->free = &aempty; ! 63: } ! 64: ! 65: /* allocate object from Area */ ! 66: Void * ! 67: alloc(size, ap) ! 68: size_t size; ! 69: register Area *ap; ! 70: { ! 71: int cells, split; ! 72: register Block *bp; ! 73: register Cell *dp, *fp, *fpp; ! 74: #if 0 ! 75: mypr("alloc: size %d area x%x\n", size, ap); ! 76: #endif ! 77: if (size <= 0) { ! 78: aerror(ap, "allocate bad size"); ! 79: return NULL; ! 80: } ! 81: cells = (unsigned)(size - 1) / sizeof(Cell) + 1; ! 82: ! 83: /* find Cell large enough */ ! 84: for (bp = ap->free; ; bp = bp->next) { ! 85: for (fpp = NULL, fp = bp->free; ! 86: fp != bp->last; fpp = fp, fp = fpp->next) ! 87: if ((fp-1)->size >= cells) ! 88: goto Found; ! 89: ! 90: /* wrapped around Block list, create new Block */ ! 91: if (bp == ap->free) { ! 92: bp = malloc(offsetof(Block, cell[ICELLS + cells])); ! 93: if (bp == NULL) { ! 94: aerror(ap, "cannot allocate"); ! 95: return NULL; ! 96: } ! 97: if (ap->free == &aempty) ! 98: bp->next = bp; ! 99: else { ! 100: bp->next = ap->free->next; ! 101: ap->free->next = bp; ! 102: } ! 103: bp->last = bp->cell + ICELLS + cells; ! 104: fp = bp->free = bp->cell + 1; /* initial free list */ ! 105: (fp-1)->size = ICELLS + cells - 1; ! 106: fp->next = bp->last; ! 107: fpp = NULL; ! 108: break; ! 109: } ! 110: } ! 111: Found: ! 112: ap->free = bp; ! 113: dp = fp; /* allocated object */ ! 114: split = (dp-1)->size - cells; ! 115: if (split < 0) ! 116: aerror(ap, "allocated object too small"); ! 117: if (--split <= 0) { /* allocate all */ ! 118: fp = fp->next; ! 119: } else { /* allocate head, free tail */ ! 120: (fp-1)->size = cells; ! 121: fp += cells + 1; ! 122: (fp-1)->size = split; ! 123: fp->next = dp->next; ! 124: } ! 125: if (fpp == NULL) ! 126: bp->free = fp; ! 127: else ! 128: fpp->next = fp; ! 129: return (Void*) dp; ! 130: } ! 131: ! 132: /* change size of object */ ! 133: /* todo: allow expansion */ ! 134: Void * ! 135: aresize(ptr, size, ap) ! 136: register Void *ptr; ! 137: size_t size; ! 138: register Area *ap; ! 139: { ! 140: int cells, split; ! 141: register Cell *dp = (Cell*)ptr; ! 142: ! 143: #if 0 ! 144: mypr("aresize: size %d area x%x ptr x%x\n", size, ap, ptr); ! 145: #endif ! 146: if (size <= 0) { ! 147: aerror(ap, "allocate bad size"); ! 148: return NULL; ! 149: } ! 150: cells = (unsigned)(size - 1) / sizeof(Cell) + 1; ! 151: ! 152: split = (dp-1)->size - cells; ! 153: if (split < 0) ! 154: aerror(ap, "cannot resize larger"); ! 155: if (--split <= 0) /* cannot split */ ! 156: ; ! 157: else { /* shrink head, free tail */ ! 158: (dp-1)->size = cells; ! 159: dp += cells + 1; ! 160: (dp-1)->size = split; ! 161: afree((Void*)dp, ap); ! 162: } ! 163: ! 164: return (Void*) ptr; ! 165: } ! 166: ! 167: void ! 168: afree(ptr, ap) ! 169: Void *ptr; ! 170: register Area *ap; ! 171: { ! 172: register Block *bp; ! 173: register Cell *fp, *fpp; ! 174: register Cell *dp = (Cell*)ptr; ! 175: ! 176: #if 0 ! 177: mypr("afree: area x%x ptr x%x\n", ap, ptr); ! 178: #endif ! 179: /* find Block containing Cell */ ! 180: for (bp = ap->free; ; bp = bp->next) { ! 181: if (bp->cell <= dp && dp < bp->last) ! 182: break; ! 183: if (bp->next == ap->free) { ! 184: aerror(ap, "freeing with invalid area"); ! 185: return; ! 186: } ! 187: } ! 188: ! 189: /* find position in free list */ ! 190: for (fpp = NULL, fp = bp->free; fp < dp; fpp = fp, fp = fpp->next) ! 191: ; ! 192: ! 193: if (fp == dp) { ! 194: aerror(ap, "freeing free object"); ! 195: return; ! 196: } ! 197: ! 198: /* join object with next */ ! 199: if (dp + (dp-1)->size == fp-1) { /* adjacent */ ! 200: (dp-1)->size += (fp-1)->size + 1; ! 201: dp->next = fp->next; ! 202: } else /* non-adjacent */ ! 203: dp->next = fp; ! 204: ! 205: /* join previous with object */ ! 206: if (fpp == NULL) ! 207: bp->free = dp; ! 208: else if (fpp + (fpp-1)->size == dp-1) { /* adjacent */ ! 209: (fpp-1)->size += (dp-1)->size + 1; ! 210: fpp->next = dp->next; ! 211: } else /* non-adjacent */ ! 212: fpp->next = dp; ! 213: } ! 214: ! 215: ! 216: #if TEST_ALLOC ! 217: ! 218: Area a; ! 219: ! 220: main(argc, argv) ! 221: int argc; ! 222: char **argv; ! 223: { ! 224: int i; ! 225: char *p [9]; ! 226: ! 227: ainit(&a); ! 228: for (i = 0; i < 9; i++) { ! 229: p[i] = alloc(124, &a); ! 230: printf("alloc: %x\n", p[i]); ! 231: } ! 232: for (i = 1; i < argc; i++) ! 233: afree(p[atoi(argv[i])], &a); ! 234: afreeall(&a); ! 235: return 0; ! 236: } ! 237: ! 238: void aerror(ap, msg) ! 239: Area *ap; ! 240: char *msg; ! 241: { ! 242: printf("%r\n", &msg); ! 243: sleep(1); ! 244: abort(); ! 245: } ! 246: ! 247: #endif ! 248:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.