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