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