1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %
4 % File: bpsheap.c
5 % Description: Code to dynamically set up bps and heap structures
6 % Author: RAM, HP/FSD
7 % Created: 9-Mar-84
8 % Modified:
9 % Mode: Text
10 % Package:
11 %
12 % (c) Copyright 1982, University of Utah
13 %
14 % Redistribution and use in source and binary forms, with or without
15 % modification, are permitted provided that the following conditions are met:
16 %
17 % * Redistributions of source code must retain the relevant copyright
18 % notice, this list of conditions and the following disclaimer.
19 % * Redistributions in binary form must reproduce the above copyright
20 % notice, this list of conditions and the following disclaimer in the
21 % documentation and/or other materials provided with the distribution.
22 %
23 % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 % THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 % PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNERS OR
27 % CONTRIBUTORS
28 % BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 % POSSIBILITY OF SUCH DAMAGE.
35 %
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 %
38 % Revisions:
39 %
40 % 11-Aug-88 (Julian Padget)
41 % Added initialization of bpslowerbound in setupbps().
42 % 07-Apr-87 (Harold Carr & Leigh Stoller)
43 % Put in error checking to ensure that the memory pointers will fit in
44 % info field of the lisp item.
45 % 21-Dec-86 (Leigh Stoller)
46 % Added allocatemorebps function, called from try-other-bps-spaces in
47 % allocators.sl.
48 % 18-Dec-86 (Leigh Stoller)
49 % Changed to newer model. Bps is now defined in bps.c so that unexec can
50 % alter the text/data boundry. Took out code that allowed command line
51 % modification of bpssize. (Now set in the Makefile). Added setupbps()
52 % that initialzes nextbps and lastbps.
53 % 20-Sep-86 (Leigh Stoller)
54 % Removed assembler alias statements because they are not portable. Instead,
55 % a sed script will be used to convert the _variables of C to VARIABLES of
56 % PSL.
57 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
58 */
59
60 long unexec();
61
62 #include <stdio.h>
63
64 /* Use 1 if using compacting collector ($pxnk/compact-gc.sl).
65 Use 2 if using copying collector ($pnk/copying-gc.sl).
66 Be sure to update $pxnk/load-psl.sl to include correct collector. */
67
68 #define NUMBEROFHEAPS 1
69
70 #define MINSIZE 5000000 /* Default total in number of bytes. */
71 #define MALLOCSIZE 500000 /* Default size for OS support functions. */
72 #define EXTRABPSSIZE 300000 /* Minimum amount to increase bps by. */
73 #define MINIMUMHEAPADD 20000 /* Minimum amount to increase heap by */
74
75
76 #ifndef BPSSIZE
77 #define BPSSIZE 1600000 /* Default bps size in number of bytes */
78 #endif
79
80 char * imagefile ;
81 int max_image_size;
82 int oldbreakvalue;
83
84 long bpscontrol[2];
85
86 extern int alreadysetupbpsandheap;
87 extern int hashtable;
88 extern char bps[];
89 extern int symval;
90 extern int lastbps;
91 extern int nextbps;
92 extern int bpslowerbound;
93 extern int _infbitlength_;
94
95 extern int heaplowerbound;
96 extern int heapupperbound;
97 extern int heaplast;
98 extern int heaptrapbound;
99
100 extern int oldheaplowerbound;
101 extern int oldheapupperbound;
102 extern int oldheaplast;
103 extern int oldheaptrapbound;
104
105 /* Write this ourselves to keep from including half the math library */
power(x,n)106 static power(x, n)
107 int x, n;
108 {
109 int i, p;
110
111 p = 1;
112 for (i = 1; i <= n; ++i)
113 p = p * x;
114 return(p);
115 }
116
setupbpsandheap(argc,argv)117 setupbpsandheap(argc,argv)
118 int argc;
119 char *argv[];
120 { int ohl,ohtb,ohlb,ohub,hl,htb,hlb,hub;
121 int memset = 0;
122 FILE * imago;
123 int headerword [8];
124 int i, total, bpssize, heapsize, mallocsize;
125 int current_size_in_bytes, heapsize_in_bytes;
126 double bpspercent, heappercent;
127 char *argp, *scanptr, *scanformat;
128 int ii1,ii2,ii3,ii4,ii5,ii6,ii7,ii8,ii9,ii10,ii11;
129 long hugo;
130
131 total = MINSIZE;
132 mallocsize = MALLOCSIZE;
133
134 for (i=1; i<argc-1; i++)
135 {
136 argp = argv[i];
137 if (*argp++ == '-')
138 {
139 scanformat = "";
140 switch (*argp++) {
141 case 't': scanptr = (char *)&total;
142 memset = 1;
143 switch (*argp) {
144 case 'x': scanformat = "%x";
145 break;
146 case 'd': scanformat = "%d";
147 break;
148 }
149 break;
150 case 'm': scanptr = (char *)&mallocsize;
151 switch (*argp) {
152 case 'x': scanformat = "%x";
153 break;
154 case 'd': scanformat = "%d";
155 break;
156 }
157 break;
158 case 'f': imagefile = argv[i+1]; break;
159 }
160 if (*scanformat != 0)
161 sscanf(argv[i+1],scanformat,scanptr);
162 }
163 } /* end of for loop -- arg vector searched */
164
165 /* insure valid values */
166 if (total == 0)
167 total = MINSIZE;
168
169 if (mallocsize <= 0)
170 mallocsize = MALLOCSIZE;
171
172 /* Reserve some space for C's usr of io buffers, etc. By mallocing then
173 freeing, the memory is sbrk'ed onto the image, but available for future
174 calls to malloc, which will not need to call sbrk again. */
175
176 ii1=malloc(0x408);
177 ii2=calloc(3,3);
178 ii3=malloc(0x408);
179 ii4=malloc(0x142c);
180 ii5=malloc(0x1008);
181 ii6=malloc(0x17);
182 ii7=malloc(0x3);
183 ii8=malloc(0x1068);
184 ii9=malloc(0x28);
185 ii10=malloc(0xc);
186 ii11=malloc(0x384);
187
188 external_user_homedir_string(); /* This is done by read-init-file */
189 external_anyuser_homedir_string("hugo");
190
191 bpssize = BPSSIZE;
192
193 heapsize_in_bytes = total - bpssize;
194
195 /* On systems in which the image does not start at address 0, this won't
196 really allocate the full maximum, but close enough. */
197 current_size_in_bytes = (((int) sbrk(0))<<5)>>5;
198 max_image_size = power(2, _infbitlength_); /* 1 more than allowable size */
199
200 if ((heapsize_in_bytes + current_size_in_bytes) >= max_image_size) {
201 heapsize_in_bytes = max_image_size - current_size_in_bytes;
202 total = heapsize_in_bytes + bpssize;
203 /* printf("Size requested will result in pointer values larger than\n");
204 printf(" PSL items can handle. Will allocate maximum size instead.\n\n");
205 */
206 }
207
208 #if (NUMBEROFHEAPS == 2)
209 heapsize =(heapsize_in_bytes / 4) * 2; /* insure full words */
210 #else
211 heapsize =(heapsize_in_bytes / 4) * 4; /* insure full words */
212 #endif
213
214 heappercent = ((float) (total - bpssize) / total) * 100.0;
215 bpspercent = ((float) bpssize / total) * 100.0;
216
217 if (imagefile == NULL)
218 { printf("Setting heap limit as follows:\n");
219 printf("Total heap & bps space = %d (%X), bps = %.2f, heap = %.2f\n",
220 total, total, bpspercent, heappercent);
221 }
222
223 setupbps();
224 getheap(heapsize);
225
226 free (ii2); free(ii4); free (ii6); free(ii8);
227 free (ii1); free (ii3); free (ii5); free(ii7);
228 free (ii11); free (ii9); free (ii10);
229
230
231 if (imagefile == NULL)
232 printf("bpssize = %d (%X), heapsize = %d (%X)\nTotal image size = %d (%X)\n",
233 bpssize, bpssize,
234 heapsize, heapsize,
235 (int) sbrk(0), (int) sbrk(0));
236
237 if (imagefile != NULL) {
238 ohl = oldheaplowerbound; ohub = oldheapupperbound;
239 ohl = oldheaplast; ohtb = oldheaptrapbound;
240 hlb = heaplowerbound; hub = heapupperbound;
241 hl = heaplast; htb = heaptrapbound;
242 /* save the new values around restore of the old ones */
243
244 // printf("Loading image file :%s \n",imagefile);
245 imago = fopen (imagefile,"r");
246 if (imago == NULL) {
247 printf("Loading image file :%s \n",imagefile);
248 perror ("error"); exit (-1); }
249 fread (headerword,4,2,imago);
250 unexec(); /* set control vector */
251 if ((int) bpscontrol[0] != headerword[0]
252 || bpscontrol[1] != headerword[1])
253 { printf(" Cannot start the image with this bpsl \n");
254 printf(" %x != %x, %x != %x\n", bpscontrol[0], headerword [0], bpscontrol[1], headerword[1]);
255 exit (-19); }
256 fread (headerword,4,4,imago);
257 hugo = fread (&symval,1,headerword[0],imago);
258 if (hugo != headerword[0]) read_error();
259
260 hugo = fread ((char*)heaplowerbound,1,headerword[1],imago);
261 if (hugo != headerword[1]) read_error();
262 hugo = fread (&hashtable,1,headerword[2],imago);
263 if (hugo != headerword[2]) read_error();
264 hugo = fread ((char*)bpslowerbound,1,headerword[3],imago);
265 if (hugo != headerword[3]) read_error();
266 fclose (imago);
267 if (memset) {
268 oldheaplowerbound = ohl; oldheapupperbound = ohub;
269 oldheaplast = ohl; oldheaptrapbound = ohtb;
270 heaplowerbound = hlb; heapupperbound = hub;
271 heaptrapbound = htb;}
272 return (4711);
273 }
274 return (0);
275
276 }
277
read_error()278 read_error()
279 {
280 printf("file too short\n");
281 exit(-1);
282 }
283
284 #include <sys/mman.h>
285 #include <errno.h>
286 #include <limits.h> /* for PAGESIZE */
287 #ifndef PAGESIZE
288 #define PAGESIZE 4096
289 #endif
290
291
292
293
294 /* The current procedure is to convert the starting address of the char
295 array defined in bps.c to an address and store it in nextbps. A check
296 is made to make sure that nextbps falls on an even word boundry.
297 */
setupbps()298 setupbps()
299 { char *p = (char *) bps;
300 int bpssize;
301 char c;
302
303 // nextbps = malloc (50000000);
304 // bps = nextbps;
305 nextbps = ((int)bps + 3) & ~3; /* Up to a multiple of 4. */
306 bpslowerbound = nextbps;
307 lastbps = ((int)bps + BPSSIZE) & ~3; /* Down to a multiple of 4. */
308 p = (char *)(((int) bpslowerbound -1) & ~(PAGESIZE-1));
309 bpssize = ((BPSSIZE + PAGESIZE-1) & ~(PAGESIZE-1));
310 if (mprotect(p, bpssize, PROT_READ | PROT_WRITE | PROT_EXEC )) {
311 perror("Couldn’t mprotect");
312 exit(errno);
313 }
314 }
315
316
317 /* Allocate alternate bps space. Note: The use of sbrk(), and the fact that
318 nextbps is now greater than heaplast means that unexec should be not be
319 tried after this routine is called. The image would be huge.
320 */
allocatemorebps()321 allocatemorebps()
322 {
323 int current_size_in_bytes;
324 int old_nextbps = nextbps;
325
326 current_size_in_bytes = sbrk(0);
327
328 if ((current_size_in_bytes + EXTRABPSSIZE) >= max_image_size)
329 return(0);
330
331 if (((int)sbrk(0)) % 2) /* force to even word boundary*/
332 nextbps = (int)sbrk(1);
333
334 nextbps = (int)sbrk(EXTRABPSSIZE); /* allocate extra BPS */
335 if (nextbps == -1) {
336 nextbps = old_nextbps;
337 return(0);
338 }
339 lastbps = nextbps + EXTRABPSSIZE;
340
341 return(EXTRABPSSIZE); /* This will be a paramter later */
342 }
343
344
getheap(heapsize)345 getheap(heapsize)
346 int heapsize;
347 {
348
349 #if (NUMBEROFHEAPS == 1)
350 // heaplowerbound = (int)sbrk(heapsize); /* allocate first heap */;
351 // oldheaplowerbound = -1;
352 #else
353
354 heaplowerbound = (int)sbrk(2 * heapsize); /* allocate first heap */;
355 #endif
356 if (heaplowerbound == -1) {
357 perror("GETHEAP");
358 exit(-1);
359 }
360 heapsize = 119000000;
361 heaplowerbound = &bps;
362 heaplowerbound += BPSSIZE;
363 heapupperbound = heaplowerbound + heapsize;
364 heaplast = heaplowerbound;
365 heaptrapbound = heapupperbound -120;
366
367
368 #if (NUMBEROFHEAPS == 2)
369 oldheaplowerbound = heapupperbound;
370 oldheapupperbound = oldheaplowerbound + heapsize;
371 oldheaplast = oldheaplowerbound;
372 oldheaptrapbound = oldheapupperbound -120;
373 #endif
374 oldbreakvalue = (int)sbrk(0);
375 }
376
377 /* Tag( alterheapsize )
378 */
alterheapsize(increment)379 alterheapsize(increment)
380 int increment;
381 {
382 /*
383 alters the size of the heap by the specified increment. Returns
384 the increment if successful, otherwise returns 0. May fail if
385 the sbrk is unsuccessful or if the user tries to cut the heap back
386 to nothing or the current break value does not match the old value.
387 The latter case occurs when a malloc or sbrk has allocated space for
388 some other software, in which case we cannot allocate any more space
389 contiguously.
390
391 Modifies both the heap and gcarray size.
392 NOTE: a garbage collection should probably be performed before this
393 routine is called.
394 NOTE: only implemented for the one heap version on the 68000.
395 */
396
397 int heapsize;
398 int current_size_in_bytes;
399
400 #if (NUMBEROFHEAPS == 1)
401 int gcarraysize, newbreakvalue;
402
403 printf("***** cannot extend heap on this machine\n");
404 return(0);
405
406 if ((int) sbrk(0) != oldbreakvalue) /* Non contiguous memory */
407 return(0);
408
409 newbreakvalue = oldbreakvalue + increment;
410
411 /* don't let the user cut his heap back to nothing, taking into account
412 space for the gcarray. */
413 if ((increment < 0) &&
414 ((newbreakvalue - heaplowerbound) <
415 (((heaplast + MINIMUMHEAPADD - heaplowerbound) * 9) / 8)))
416 return(0);
417
418 current_size_in_bytes = sbrk(0);
419
420 if ((current_size_in_bytes + increment) >= max_image_size)
421 return(0);
422
423 if ((int)sbrk(increment) == -1) /* the sbrk failed. */
424 return(0);
425
426 newbreakvalue = (int) sbrk(0);
427 heapsize = (((newbreakvalue - heaplowerbound) / 4) * 4);
428
429 gcarraysize = (((heapsize / 9) / 4) * 4);
430 heapsize = heapsize - gcarraysize;
431
432 heapupperbound = heaplowerbound + heapsize;
433 heaptrapbound = heapupperbound;
434
435 oldbreakvalue = newbreakvalue;
436 return(increment);
437 #else
438 /* assumes the current heap is the 'lower' one */
439 int newbreakvalue;
440
441 if ((int) sbrk(0) != oldbreakvalue) /* Non contiguous memory */
442 { printf(" unable to allocate %x %x\n",sbrk(0),oldbreakvalue);
443 return(0); }
444
445 current_size_in_bytes = ( (int) sbrk(0) <<5) >>5;
446
447 if ((current_size_in_bytes + 2* increment) >= max_image_size)
448 return(-1);
449
450 if ((int)sbrk(2 * increment) == -1) /* the sbrk failed. */
451 return(-2);
452
453 newbreakvalue = (int) sbrk(0);
454
455 heapupperbound = heapupperbound + increment ;
456 heaptrapbound = heapupperbound - 120;
457 oldheaplowerbound = oldheaplowerbound + increment;
458 oldheapupperbound = oldheapupperbound + 2* increment ;
459 oldheaplast = oldheaplowerbound;
460 oldheaptrapbound = oldheapupperbound -120;
461
462
463 oldbreakvalue = newbreakvalue;
464 return(increment);
465 #endif
466
467 }
468
unexec()469 long unexec()
470 {
471 bpscontrol[0] = bpslowerbound;
472 bpscontrol[1] = BPSSIZE;
473 return((long) bpscontrol);
474 }
475
476