1: #include "defs" 2: 3: #define NHISTO 50 4: int histo[NHISTO]; 5: 6: int mem[MEMSIZE]; 7: unsigned int nmemused = 0; 8: unsigned int nmemavail = 0; 9: long int totalloc = 0; 10: long int totfreed = 0; 11: 12: int nexpblocks = 0; 13: ptr expblocks = 0; 14: int nexcblocks = 0; 15: ptr excblocks = 0; 16: ptr chains = 0; 17: 18: ptr alloc(), calloc(), malloc(); 19: 20: ptr intalloc(n) 21: int n; 22: { 23: int *p; 24: 25: /*debug*/ if(n>sizeof(struct genblock)) fatal1("intalloc(%d)", n); 26: if( (p = calloc(1,n)) == NULL) 27: { 28: if(memdump) 29: prmem(); 30: fatal1("Line %d: Cannot allocate memory", yylineno); 31: } 32: 33: return(p); 34: } 35: 36: 37: 38: 39: ptr calloc(m,n) 40: int m, n; 41: { 42: return(alloc(m*n)); 43: } 44: 45: 46: 47: ptr malloc(m) 48: int m; 49: { 50: return(alloc(m)); 51: } 52: 53: 54: 55: /* Very stupid memory allocator. Stores a count word before 56: each block; negative if idle, positive if busy. 57: Looks for a block big enough for current request, and splits it 58: if necessary. Does not coalesce, always starts at bottom of memory. 59: Checks validity of all count words it encounters. 60: */ 61: 62: 63: ptr alloc(k) 64: register int k; 65: { 66: int *p; 67: register int i, j; 68: 69: k = (k + sizeof(int)-1) / sizeof(int); 70: if(k <=0) fprintf(diagfile, "alloc(%d words)\n", k); 71: else if(k >= NHISTO) ++histo[0]; 72: else ++histo[k]; 73: totalloc += k; 74: if(k > 256) fprintf(diagfile, "calloc(%d words)\n", k); 75: 76: /* look for a large enough slot */ 77: if(nmemavail > k) 78: for(i=0 ; i<nmemused ; ) 79: { 80: j = mem[i]; 81: if(j>256) 82: { 83: fprintf(diagfile, "Bad count word %d\n", j); 84: goto die; 85: } 86: if(j>=0 || (j = -j)<k) 87: i += (j+1); 88: else { 89: if(j > 256) 90: { 91: fprintf(diagfile, "Bad count word %d\n", j); 92: goto die; 93: } 94: mem[i] = k; 95: if(j > k) 96: mem[i+k+1] = -(j-k-1); 97: for(j = i+k ; j>i ; --j) 98: mem[j] = 0; 99: nmemavail -= (k+1); 100: return(mem + i+1); 101: } 102: } 103: 104: /* otherwise try to advance the fence */ 105: mem[nmemused] = k; 106: p = mem + nmemused + 1; 107: nmemused += (k+1); 108: if(nmemused >= MEMSIZE) 109: { 110: die: 111: /*debug*/ fprintf(diagfile, "Highwater mark %d words. ", nmemused); 112: /*debug*/ fprintf(diagfile, "%ld words left over\n", totalloc-totfreed); 113: /* prmem(); */ 114: fatal1("Line %d: out of memory", yylineno); 115: } 116: return(p); 117: } 118: 119: 120: 121: cfree(p) 122: ptr p; 123: { 124: if(p==0) 125: fatal("cfree(0)"); 126: free(p); 127: } 128: 129: 130: 131: 132: free(p) 133: register unsigned int *p; 134: { 135: if(p<=mem || p>mem+nmemused) 136: { 137: fprintf(diagfile, "attempt to free an unallocated block, "); 138: goto bad; 139: } 140: if(p[-1]>256 || p[-1]<0) 141: { 142: fprintf(diagfile, "attempted to free a block of length %u\n",p[-1]); 143: bad: fprintf(diagfile, "location %o ", p); 144: fprintf(diagfile, "mem=%o lastused=%o\n", mem, mem+nmemused); 145: /* if(p[-1]>256 || p[-1]<0) */ 146: fatal(""); 147: } 148: totfreed += p[-1]; 149: nmemavail += p[-1]+1; 150: p[-1] = - p[-1]; 151: ; 152: } 153: 154: 155: prhisto() 156: { 157: int i; 158: fprintf(diagfile, "allocation histogram:\n%4d big blocks\n",histo[0]); 159: for(i=1;i<NHISTO;++i) 160: if(histo[i]>0) fprintf(diagfile, "%4d %2d-word blocks\n", histo[i],i); 161: } 162: 163: 164: 165: 166: 167: ptr allexpblock() 168: { 169: ptr p; 170: 171: if(expblocks) 172: { 173: p = expblocks; 174: expblocks = expblocks->leftp; 175: zeroout(p, sizeof(struct exprblock)); 176: --nexpblocks; 177: return(p); 178: } 179: else return( ALLOC(exprblock) ); 180: } 181: 182: 183: 184: 185: frexpblock(p) 186: register ptr p; 187: { 188: if ( p[-1] != sizeof(struct exprblock)/sizeof(int) ) 189: badtag("frexpblock", p->tag); 190: if(nexpblocks < EXPRPOOL) 191: { 192: p->leftp = expblocks; 193: p->tag = 0; 194: expblocks = p; 195: ++nexpblocks; 196: } 197: else cfree(p); 198: } 199: 200: 201: 202: 203: ptr allexcblock() 204: { 205: ptr p; 206: 207: if(excblocks) 208: { 209: p = excblocks; 210: excblocks = excblocks->leftp; 211: zeroout(p, sizeof(struct execblock)); 212: --nexcblocks; 213: return(p); 214: } 215: else return( ALLOC(execblock) ); 216: } 217: 218: 219: 220: 221: frexcblock(p) 222: register ptr p; 223: { 224: if( p[-1] != sizeof(struct execblock)/sizeof(int) ) 225: fatal1("invalid frexcblock block of size %d", p[-1]); 226: if(nexcblocks < EXECPOOL) 227: { 228: p->leftp = excblocks; 229: p->tag = 0; 230: excblocks = p; 231: ++nexcblocks; 232: } 233: else cfree(p); 234: } 235: 236: 237: 238: zeroout(p,n) 239: register int *p; 240: int n; 241: { 242: register int *pn; 243: 244: pn = p + (n + sizeof(int)-1)/sizeof(int); 245: 246: while(p < pn) 247: *p++ = 0; 248: } 249: 250: 251: 252: 253: frchain(p0) 254: register chainp *p0; 255: { 256: register ptr p; 257: 258: if(p0==0 || *p0==0) return; 259: 260: for(p = *p0 ; p->nextp ; p = p->nextp) 261: p->datap = 0; 262: 263: p->datap = 0; 264: p->nextp = chains; 265: chains = *p0; 266: *p0 = 0; 267: } 268: 269: 270: chainp mkchain(p,q) 271: ptr p, q; 272: { 273: register chainp r; 274: 275: if(chains) 276: { 277: r = chains; 278: chains = chains->nextp; 279: } 280: else r = ALLOC(chain); 281: r->datap = p; 282: r->nextp = q; 283: return(r); 284: } 285: 286: 287: 288: 289: prmem() 290: { 291: register int i,j; 292: 293: fprintf(diagfile, "Memory dump:\n"); 294: 295: for(i=0 ; i<nmemused ; ) 296: { 297: j = mem[i]; 298: fprintf(diagfile, "Loc %6o = Word %5d ", mem+i, i); 299: if(j<0) 300: fprintf(diagfile, "Idle block length %4d ", j = -j); 301: else fprintf(diagfile, "Busy block length %4d ", j); 302: fprintf(diagfile, "tag %3d", mem[i+1].tag); 303: if(mem[i+1].tag==TNAME && mem[i+1].sthead!=0) 304: fprintf(diagfile, " varname %s", mem[i+1].sthead->namep); 305: else if(j==2) 306: fprintf(diagfile, " chain %o %o", mem[i+1], mem[i+2]); 307: else if (mem[i+1].tag > TIOSTAT) 308: { 309: char *s, *sn; 310: s = & mem[i+1]; 311: sn = s + 12; 312: fprintf(diagfile, " \""); 313: while(*s!= '\0' && s<sn) 314: putc(*s++, diagfile); 315: } 316: fprintf(diagfile, "\n"); 317: 318: i += j+1; 319: } 320: }