Commit | Line | Data |
---|---|---|
832026c6 C |
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 | } |