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 % Status: Open Source: BSD License
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
65 /* Use 1 if using compacting collector ($pxnk/compact-gc.sl).
66 Use 2 if using copying collector ($pnk/copying-gc.sl).
67 Be sure to update $pxnk/load-psl.sl to include correct collector. */
68
69 #define NUMBEROFHEAPS 1
70
71 #define MINSIZE 16000000 /* Default total in number of bytes. */
72 #define MALLOCSIZE 500000 /* Default size for OS support functions. */
73 #define EXTRABPSSIZE 300000 /* Minimum amount to increase bps by. */
74 #define MINIMUMHEAPADD 20000 /* Minimum amount to increase heap by */
75
76
77 #ifndef BPSSIZE
78 #define BPSSIZE 1600000 /* Default bps size in number of bytes */
79 #endif
80
81 char * imagefile;
82 char * abs_imagefile = NULL; /* like imagefile, but as an absolute path */
83 int max_image_size;
84 int oldbreakvalue;
85
86 long bpscontrol[2];
87
88 extern int alreadysetupbpsandheap;
89 extern int hashtable;
90 extern char bps[];
91 extern int symval;
92 extern int lastbps;
93 extern int nextbps;
94 extern int bpslowerbound;
95 extern int _infbitlength_;
96
97 extern int heaplowerbound;
98 extern int heapupperbound;
99 extern int heaplast;
100 extern int heaptrapbound;
101
102 extern int oldheaplowerbound;
103 extern int oldheapupperbound;
104 extern int oldheaplast;
105 extern int oldheaptrapbound;
106
107 /* Write this ourselves to keep from including half the math library */
power(x,n)108 static power(x, n)
109 int x, n;
110 {
111 int i, p;
112
113 p = 1;
114 for (i = 1; i <= n; ++i)
115 p = p * x;
116 return(p);
117 }
118
setupbpsandheap(argc,argv)119 setupbpsandheap(argc,argv)
120 int argc;
121 char *argv[];
122 { int ohl,ohtb,ohlb,ohub,hl,htb,hlb,hub;
123 int memset = 0;
124 FILE * imago;
125 int headerword [8];
126 int i, total, bpssize, heapsize, mallocsize;
127 int current_size_in_bytes, heapsize_in_bytes;
128 double bpspercent, heappercent;
129 char *argp, *scanptr, *scanformat;
130 int ii1,ii2,ii3,ii4,ii5,ii6,ii7,ii8,ii9,ii10,ii11;
131 long hugo;
132
133 total = MINSIZE;
134 mallocsize = MALLOCSIZE;
135
136 for (i=1; i<argc-1; i++)
137 {
138 argp = argv[i];
139 if (*argp++ == '-')
140 {
141 scanformat = "";
142 switch (*argp++) {
143 case 't': scanptr = (char *)&total;
144 memset = 1;
145 switch (*argp) {
146 case 'x': scanformat = "%x";
147 break;
148 case 'd': scanformat = "%d";
149 break;
150 }
151 break;
152 case 'm': scanptr = (char *)&mallocsize;
153 switch (*argp) {
154 case 'x': scanformat = "%x";
155 break;
156 case 'd': scanformat = "%d";
157 break;
158 }
159 break;
160 case 'f': imagefile = argv[i+1]; break;
161 }
162 if (*scanformat != 0)
163 sscanf(argv[i+1],scanformat,scanptr);
164 }
165 } /* end of for loop -- arg vector searched */
166
167 /* insure valid values */
168 if (total == 0)
169 total = MINSIZE;
170
171 if (mallocsize <= 0)
172 mallocsize = MALLOCSIZE;
173
174 /* Reserve some space for C's usr of io buffers, etc. By mallocing then
175 freeing, the memory is sbrk'ed onto the image, but available for future
176 calls to malloc, which will not need to call sbrk again. */
177
178 ii1=malloc(0x408);
179 ii2=calloc(3,3);
180 ii3=malloc(0x408);
181 ii4=malloc(0x142c);
182 ii5=malloc(0x1008);
183 ii6=malloc(0x17);
184 ii7=malloc(0x3);
185 ii8=malloc(0x1068);
186 ii9=malloc(0x28);
187 ii10=malloc(0xc);
188 ii11=malloc(0x384);
189
190 external_user_homedir_string(); /* This is done by read-init-file */
191 external_anyuser_homedir_string("hugo");
192
193 bpssize = BPSSIZE;
194
195 heapsize_in_bytes = total - bpssize;
196
197 /* On systems in which the image does not start at address 0, this won't
198 really allocate the full maximum, but close enough. */
199 current_size_in_bytes = (((int) sbrk(0))<<5)>>5;
200 max_image_size = power(2, _infbitlength_); /* 1 more than allowable size */
201
202 if ((heapsize_in_bytes + current_size_in_bytes) >= max_image_size) {
203 heapsize_in_bytes = max_image_size - current_size_in_bytes;
204 total = heapsize_in_bytes + bpssize;
205 /* printf("Size requested will result in pointer values larger than\n");
206 printf(" PSL items can handle. Will allocate maximum size instead.\n\n");
207 */
208 }
209
210 #if (NUMBEROFHEAPS == 2)
211 heapsize =(heapsize_in_bytes / 4) * 2; /* insure full words */
212 #else
213 heapsize =(heapsize_in_bytes / 4) * 4; /* insure full words */
214 #endif
215
216 heappercent = ((float) (total - bpssize) / total) * 100.0;
217 bpspercent = ((float) bpssize / total) * 100.0;
218
219 if (imagefile == NULL)
220 { printf("Setting heap limit as follows:\n");
221 printf("Total heap & bps space = %d (%X), bps = %.2f, heap = %.2f\n",
222 total, total, bpspercent, heappercent);
223 }
224
225 setupbps();
226 getheap(heapsize);
227
228 free (ii2); free(ii4); free (ii6); free(ii8);
229 free (ii1); free (ii3); free (ii5); free(ii7);
230 free (ii11); free (ii9); free (ii10);
231
232
233 if (imagefile == NULL)
234 printf("bpssize = %d (%X), heapsize = %d (%X)\nTotal image size = %d (%X)\n",
235 bpssize, bpssize,
236 heapsize, heapsize,
237 (int) sbrk(0), (int) sbrk(0));
238
239 if (imagefile != NULL) {
240 ohl = oldheaplowerbound; ohub = oldheapupperbound;
241 ohl = oldheaplast; ohtb = oldheaptrapbound;
242 hlb = heaplowerbound; hub = heapupperbound;
243 hl = heaplast; htb = heaptrapbound;
244 /* save the new values around restore of the old ones */
245
246 // printf("Loading image file :%s \n",imagefile);
247 imago = fopen (imagefile,"r");
248 if (imago == NULL) {
249 printf("Loading image file :%s \n",imagefile);
250 perror ("error"); exit (-1); }
251 fread (headerword,4,2,imago);
252 unexec(); /* set control vector */
253 if ((int) bpscontrol[0] != headerword[0]
254 || bpscontrol[1] != headerword[1])
255 { printf(" Cannot start the image with this bpsl \n");
256 printf(" %x != %x, %x != %x\n", bpscontrol[0], headerword [0], bpscontrol[1], headerword[1]);
257 exit (-19); }
258 fread (headerword,4,4,imago);
259 hugo = fread (&symval,1,headerword[0],imago);
260 if (hugo != headerword[0]) read_error();
261
262 hugo = fread ((char*)heaplowerbound,1,headerword[1],imago);
263 if (hugo != headerword[1]) read_error();
264 hugo = fread (&hashtable,1,headerword[2],imago);
265 if (hugo != headerword[2]) read_error();
266 hugo = fread ((char*)bpslowerbound,1,headerword[3],imago);
267 if (hugo != headerword[3]) read_error();
268 fclose (imago);
269 if (memset) {
270 oldheaplowerbound = ohl; oldheapupperbound = ohub;
271 oldheaplast = ohl; oldheaptrapbound = ohtb;
272 heaplowerbound = hlb; heapupperbound = hub;
273 heaptrapbound = htb;}
274 abs_imagefile = realpath(imagefile,NULL);
275 return (4711);
276 }
277 return (0);
278
279 }
280
read_error()281 read_error()
282 {
283 printf("file too short\n");
284 exit(-1);
285 }
286
287 #include <sys/mman.h>
288 #include <errno.h>
289 #include <limits.h> /* for PAGESIZE */
290 #ifndef PAGESIZE
291 #define PAGESIZE 4096
292 #endif
293
294
295
296
297 /* The current procedure is to convert the starting address of the char
298 array defined in bps.c to an address and store it in nextbps. A check
299 is made to make sure that nextbps falls on an even word boundry.
300 */
setupbps()301 setupbps()
302 { char *p = (char *) bps;
303 int bpssize;
304 char c;
305
306 // nextbps = malloc (50000000);
307 // bps = nextbps;
308 nextbps = ((int)bps + 3) & ~3; /* Up to a multiple of 4. */
309 bpslowerbound = nextbps;
310 lastbps = ((int)bps + BPSSIZE) & ~3; /* Down to a multiple of 4. */
311 p = (char *)(((int) bpslowerbound -1) & ~(PAGESIZE-1));
312 bpssize = ((BPSSIZE + PAGESIZE-1) & ~(PAGESIZE-1));
313 if (mprotect(p, bpssize, PROT_READ | PROT_WRITE | PROT_EXEC )) {
314 perror("Couldn’t mprotect");
315 exit(errno);
316 }
317 }
318
319
320 /* Allocate alternate bps space. Note: The use of sbrk(), and the fact that
321 nextbps is now greater than heaplast means that unexec should be not be
322 tried after this routine is called. The image would be huge.
323 */
allocatemorebps()324 allocatemorebps()
325 {
326 int current_size_in_bytes;
327 int old_nextbps = nextbps;
328
329 current_size_in_bytes = sbrk(0);
330
331 if ((current_size_in_bytes + EXTRABPSSIZE) >= max_image_size)
332 return(0);
333
334 if (((int)sbrk(0)) % 2) /* force to even word boundary*/
335 nextbps = (int)sbrk(1);
336
337 nextbps = (int)sbrk(EXTRABPSSIZE); /* allocate extra BPS */
338 if (nextbps == -1) {
339 nextbps = old_nextbps;
340 return(0);
341 }
342 lastbps = nextbps + EXTRABPSSIZE;
343
344 return(EXTRABPSSIZE); /* This will be a paramter later */
345 }
346
347
getheap(heapsize)348 getheap(heapsize)
349 int heapsize;
350 {
351
352 #if (NUMBEROFHEAPS == 1)
353 // heaplowerbound = (int)sbrk(heapsize); /* allocate first heap */;
354 // oldheaplowerbound = -1;
355 #else
356
357 heaplowerbound = (int)sbrk(2 * heapsize); /* allocate first heap */;
358 #endif
359 if (heaplowerbound == -1) {
360 perror("GETHEAP");
361 exit(-1);
362 }
363 heapsize = 119000000;
364 heaplowerbound = &bps;
365 heaplowerbound += BPSSIZE;
366 heapupperbound = heaplowerbound + heapsize;
367 heaplast = heaplowerbound;
368 heaptrapbound = heapupperbound -120;
369
370
371 #if (NUMBEROFHEAPS == 2)
372 oldheaplowerbound = heapupperbound;
373 oldheapupperbound = oldheaplowerbound + heapsize;
374 oldheaplast = oldheaplowerbound;
375 oldheaptrapbound = oldheapupperbound -120;
376 #endif
377 oldbreakvalue = (int)sbrk(0);
378 }
379
380 /* Tag( alterheapsize )
381 */
alterheapsize(increment)382 alterheapsize(increment)
383 int increment;
384 {
385 /*
386 alters the size of the heap by the specified increment. Returns
387 the increment if successful, otherwise returns 0. May fail if
388 the sbrk is unsuccessful or if the user tries to cut the heap back
389 to nothing or the current break value does not match the old value.
390 The latter case occurs when a malloc or sbrk has allocated space for
391 some other software, in which case we cannot allocate any more space
392 contiguously.
393
394 Modifies both the heap and gcarray size.
395 NOTE: a garbage collection should probably be performed before this
396 routine is called.
397 NOTE: only implemented for the one heap version on the 68000.
398 */
399
400 int heapsize;
401 int current_size_in_bytes;
402
403 #if (NUMBEROFHEAPS == 1)
404 int gcarraysize, newbreakvalue;
405
406 printf("***** cannot extend heap on this machine\n");
407 return(0);
408
409 if ((int) sbrk(0) != oldbreakvalue) /* Non contiguous memory */
410 return(0);
411
412 newbreakvalue = oldbreakvalue + increment;
413
414 /* don't let the user cut his heap back to nothing, taking into account
415 space for the gcarray. */
416 if ((increment < 0) &&
417 ((newbreakvalue - heaplowerbound) <
418 (((heaplast + MINIMUMHEAPADD - heaplowerbound) * 9) / 8)))
419 return(0);
420
421 current_size_in_bytes = sbrk(0);
422
423 if ((current_size_in_bytes + increment) >= max_image_size)
424 return(0);
425
426 if ((int)sbrk(increment) == -1) /* the sbrk failed. */
427 return(0);
428
429 newbreakvalue = (int) sbrk(0);
430 heapsize = (((newbreakvalue - heaplowerbound) / 4) * 4);
431
432 gcarraysize = (((heapsize / 9) / 4) * 4);
433 heapsize = heapsize - gcarraysize;
434
435 heapupperbound = heaplowerbound + heapsize;
436 heaptrapbound = heapupperbound;
437
438 oldbreakvalue = newbreakvalue;
439 return(increment);
440 #else
441 /* assumes the current heap is the 'lower' one */
442 int newbreakvalue;
443
444 if ((int) sbrk(0) != oldbreakvalue) /* Non contiguous memory */
445 { printf(" unable to allocate %x %x\n",sbrk(0),oldbreakvalue);
446 return(0); }
447
448 current_size_in_bytes = ( (int) sbrk(0) <<5) >>5;
449
450 if ((current_size_in_bytes + 2* increment) >= max_image_size)
451 return(-1);
452
453 if ((int)sbrk(2 * increment) == -1) /* the sbrk failed. */
454 return(-2);
455
456 newbreakvalue = (int) sbrk(0);
457
458 heapupperbound = heapupperbound + increment ;
459 heaptrapbound = heapupperbound - 120;
460 oldheaplowerbound = oldheaplowerbound + increment;
461 oldheapupperbound = oldheapupperbound + 2* increment ;
462 oldheaplast = oldheaplowerbound;
463 oldheaptrapbound = oldheapupperbound -120;
464
465
466 oldbreakvalue = newbreakvalue;
467 return(increment);
468 #endif
469
470 }
471
unexec()472 long unexec()
473 {
474 bpscontrol[0] = bpslowerbound;
475 bpscontrol[1] = BPSSIZE;
476 return((long) bpscontrol);
477 }
478
get_imagefilepath()479 char * get_imagefilepath ()
480 {
481 return abs_imagefile;
482 }
483