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
60long 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
80char *  imagefile ;
81int     max_image_size;
82int     oldbreakvalue;
83
84long bpscontrol[2];
85
86extern int  alreadysetupbpsandheap;
87extern int  hashtable;
88extern char bps[];
89extern int  symval;
90extern int  lastbps;
91extern int  nextbps;
92extern int  bpslowerbound;
93extern int  _infbitlength_;
94
95extern int  heaplowerbound;
96extern int  heapupperbound;
97extern int  heaplast;
98extern int  heaptrapbound;
99
100extern int  oldheaplowerbound;
101extern int  oldheapupperbound;
102extern int  oldheaplast;
103extern int  oldheaptrapbound;
104
105/* Write this ourselves to keep from including half the math library */
106static 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
117setupbpsandheap(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#if (NUMBEROFHEAPS == 2)
208  heapsize =(heapsize_in_bytes / 4) * 2;  /* insure full words */
209#else
210  heapsize =(heapsize_in_bytes / 4) * 4;  /* insure full words */
211#endif
212
213  heappercent = ((float) (total - bpssize) / total) * 100.0;
214  bpspercent  = ((float) bpssize / total) * 100.0;
215
216  if (imagefile == NULL)
217  { printf("Setting heap limit as follows:\n");
218    printf("Total heap & bps space = %d (%X), bps = %.2f, heap = %.2f\n",
219          total, total, bpspercent, heappercent);
220  }
221
222  setupbps();
223  getheap(heapsize);
224
225  free (ii2); free(ii4); free (ii6); free(ii8);
226  free (ii1); free (ii3); free (ii5); free(ii7);
227  free (ii11); free (ii9); free (ii10);
228
229
230  if (imagefile == NULL)
231  printf("bpssize = %d (%X), heapsize = %d (%X)\nTotal image size = %d (%X)\n",
232          bpssize, bpssize,
233          heapsize, heapsize,
234          (int) sbrk(0), (int) sbrk(0));
235
236   if (imagefile != NULL) {
237	ohl = oldheaplowerbound; ohub = oldheapupperbound;
238	ohl =  oldheaplast; ohtb = oldheaptrapbound;
239        hlb = heaplowerbound; hub = heapupperbound;
240        hl =  heaplast; htb = heaptrapbound;
241    /* save the new values around restore of the old ones */
242
243       printf("Loading image file :%s \n",imagefile);
244       imago = fopen (imagefile,"r");
245       if (imago == NULL) { perror ("error"); exit (-1); }
246       fread (headerword,4,2,imago);
247       unexec();      /* set control vector */
248      if ((int) bpscontrol[0] != headerword[0]
249                || bpscontrol[1] != headerword[1])
250		{ printf(" Cannot start the image with this bpsl \n");
251                  printf(" %x != %x, %x != %x\n", bpscontrol[0], headerword [0], bpscontrol[1], headerword[1]);
252		  exit (-19); }
253       fread (headerword,4,4,imago);
254       hugo = fread (&symval,1,headerword[0],imago);
255       if (hugo != headerword[0]) read_error();
256
257       hugo = fread ((char*)heaplowerbound,1,headerword[1],imago);
258       if (hugo != headerword[1]) read_error();
259       hugo = fread (&hashtable,1,headerword[2],imago);
260       if (hugo != headerword[2]) read_error();
261       hugo = fread ((char*)bpslowerbound,1,headerword[3],imago);
262       if (hugo != headerword[3]) read_error();
263       fclose (imago);
264       if (memset) {
265        oldheaplowerbound = ohl; oldheapupperbound = ohub;
266        oldheaplast = ohl; oldheaptrapbound = ohtb;
267        heaplowerbound = hlb; heapupperbound = hub;
268        heaptrapbound = htb;}
269       return (4711);
270     }
271return (0);
272
273}
274
275read_error()
276  {
277    printf("file too short\n");
278    exit(-1);
279  }
280
281
282/* The current procedure is to convert the starting address of the char
283   array defined in bps.c to an address and store it in nextbps. A check
284   is made to make sure that nextbps falls on an even word boundry.
285 */
286setupbps()
287{
288  nextbps  =  ((int)bps + 3) & ~3;        /* Up to a multiple of 4. */
289  bpslowerbound = nextbps;
290  lastbps  =  ((int)bps + BPSSIZE) & ~3;    /* Down to a multiple of 4. */
291}
292
293
294/* Allocate alternate bps space. Note: The use of sbrk(), and the fact that
295   nextbps is now greater than heaplast means that unexec should be not be
296   tried after this routine is called. The image would be huge.
297 */
298allocatemorebps()
299{
300  int current_size_in_bytes;
301  int old_nextbps = nextbps;
302
303  current_size_in_bytes = sbrk(0);
304
305  if ((current_size_in_bytes + EXTRABPSSIZE) >= max_image_size)
306    return(0);
307
308  if (((int)sbrk(0)) % 2)      /* force to even word boundary*/
309     nextbps = (int)sbrk(1);
310
311  nextbps = (int)sbrk(EXTRABPSSIZE);   /* allocate extra BPS */
312  if (nextbps == -1) {
313    nextbps = old_nextbps;
314    return(0);
315  }
316  lastbps = nextbps + EXTRABPSSIZE;
317
318  return(EXTRABPSSIZE);   /* This will be a paramter later */
319}
320
321
322getheap(heapsize)
323     int heapsize;
324{
325
326#if (NUMBEROFHEAPS == 1)
327  heaplowerbound        = (int)sbrk(heapsize);  /* allocate first heap */;
328  oldheaplowerbound     = -1;
329#else
330
331  heaplowerbound        = (int)sbrk(2 * heapsize);  /* allocate first heap */;
332#endif
333  if (heaplowerbound == -1) {
334    perror("GETHEAP");
335    exit(-1);
336  }
337  heapupperbound        = heaplowerbound + heapsize;
338  heaplast              = heaplowerbound;
339  heaptrapbound         = heapupperbound -120;
340
341#if (NUMBEROFHEAPS == 2)
342  oldheaplowerbound     = heapupperbound;
343  oldheapupperbound     = oldheaplowerbound + heapsize;
344  oldheaplast           = oldheaplowerbound;
345  oldheaptrapbound      = oldheapupperbound -120;
346#endif
347  oldbreakvalue = (int)sbrk(0);
348}
349
350/* Tag( alterheapsize )
351 */
352alterheapsize(increment)
353int increment;
354{
355/*
356  alters the size of the heap by the specified increment.  Returns
357  the increment if successful, otherwise returns 0.  May fail if
358  the sbrk is unsuccessful or if the user tries to cut the heap back
359  to nothing or the current break value does not match the old value.
360  The latter case occurs when a malloc or sbrk has allocated space for
361  some other software, in which case we cannot allocate any more space
362  contiguously.
363
364  Modifies both the heap and gcarray size.
365  NOTE: a garbage collection should probably be performed before this
366    routine is called.
367  NOTE: only implemented for the one heap version on the 68000.
368*/
369
370  int heapsize;
371  int current_size_in_bytes;
372
373#if (NUMBEROFHEAPS == 1)
374  int gcarraysize, newbreakvalue;
375
376  printf("***** cannot extend heap on this machine\n");
377  return(0);
378
379  if ((int) sbrk(0) != oldbreakvalue)  /* Non contiguous memory */
380      return(0);
381
382  newbreakvalue = oldbreakvalue + increment;
383
384  /* don't let the user cut his heap back to nothing, taking into account
385     space for the gcarray. */
386  if ((increment < 0) &&
387      ((newbreakvalue - heaplowerbound) <
388       (((heaplast + MINIMUMHEAPADD - heaplowerbound) * 9) / 8)))
389    return(0);
390
391  current_size_in_bytes = sbrk(0);
392
393  if ((current_size_in_bytes +  increment) >= max_image_size)
394    return(0);
395
396  if ((int)sbrk(increment) == -1)     /* the sbrk failed. */
397     return(0);
398
399  newbreakvalue = (int) sbrk(0);
400  heapsize = (((newbreakvalue - heaplowerbound) / 4) * 4);
401
402  gcarraysize = (((heapsize / 9) / 4) * 4);
403  heapsize = heapsize - gcarraysize;
404
405  heapupperbound = heaplowerbound + heapsize;
406  heaptrapbound     = heapupperbound;
407
408  oldbreakvalue    = newbreakvalue;
409  return(increment);
410#else
411  /* assumes the current heap is the 'lower' one */
412  int newbreakvalue;
413
414  if ((int) sbrk(0) != oldbreakvalue)  /* Non contiguous memory */
415      {  printf(" unable to allocate %x %x\n",sbrk(0),oldbreakvalue);
416        return(0); }
417
418  current_size_in_bytes = ( (int) sbrk(0) <<5) >>5;
419
420  if ((current_size_in_bytes + 2* increment) >= max_image_size)
421    return(-1);
422
423  if ((int)sbrk(2 * increment) == -1)       /* the sbrk failed. */
424     return(-2);
425
426  newbreakvalue = (int) sbrk(0);
427
428  heapupperbound        = heapupperbound + increment ;
429  heaptrapbound         = heapupperbound - 120;
430  oldheaplowerbound     = oldheaplowerbound + increment;
431  oldheapupperbound     = oldheapupperbound + 2* increment ;
432  oldheaplast           = oldheaplowerbound;
433  oldheaptrapbound      = oldheapupperbound -120;
434
435
436  oldbreakvalue = newbreakvalue;
437  return(increment);
438#endif
439
440}
441
442long unexec()
443{
444  bpscontrol[0] = bpslowerbound;
445  bpscontrol[1] = BPSSIZE;
446  return((long) bpscontrol);
447}
448
449