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