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