bpsheap.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. /*
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. %
  4. % File: PXK: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. % Status: Open Source: BSD License
  10. % Mode: Text
  11. % Package:
  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. /*
  40. * There used to be a collection of comments here describing revisions
  41. * made from about 1982 to 1989. I think those are by now of interest
  42. * to archaeologists! So anybody who wants to see them can consult older
  43. * copies of this file in the repositories. It is neverthless proper to
  44. * record the names of those who (in addition to the original author)
  45. * have contributed:
  46. * Julian Padget, Harold Carr, Leigh Stoller
  47. */
  48. /*
  49. * The functions here are (just) called from compiled code. In the
  50. * assembly code for the kernel the code is written with the names
  51. * having a leading underscore. For Linux that underscore remains
  52. * visible here in the C code that is linked to, while under Cygwin
  53. * or on a Macintosh it is not. So here I define functions whose names
  54. * have leading underscores if I am on Linux but not otherwise. This is
  55. * a bit messy and ugly but is still about the neatest I can think of
  56. * at present if I want one body of code to apply everywhere.
  57. */
  58. #if defined __linux__ || defined __CYGWIN__
  59. #define _(x) _ ## x
  60. #else
  61. #define _(x) x
  62. #endif
  63. #include <stdio.h>
  64. #include <stdlib.h>
  65. #include <errno.h>
  66. #include <limits.h> // for PAGESIZE
  67. #include <inttypes.h> // Make newer integer types of known width available
  68. #include <unistd.h>
  69. #include "psl.h"
  70. #ifndef PAGESIZE
  71. #define PAGESIZE 4096
  72. #endif
  73. intptr_t _(unexec)();
  74. /* Use 1 if using compacting collector ($pxnk/compact-gc.sl).
  75. Use 2 if using copying collector ($pnk/copying-gc.sl).
  76. Be sure to update $pxnk/load-psl.sl to include correct collector. */
  77. #define NUMBEROFHEAPS 2
  78. #define MINSIZE 1000 * 1024 * 1024 /* Default total in number of bytes. */
  79. #define MALLOCSIZE 500000 /* Default size for OS support functions. */
  80. #define EXTRABPSSIZE 300000 /* Minimum amount to increase bps by. */
  81. #define MINIMUMHEAPADD 20000 /* Minimum amount to increase heap by */
  82. #ifndef BPSSIZE
  83. #define BPSSIZE 1600000 /* Default bps size in number of bytes */
  84. #endif
  85. extern int Debug;
  86. char * imagefile;
  87. char * abs_imagefile = NULL; /* like imagefile, but as an absolute path */
  88. int64_t max_image_size;
  89. int64_t oldbreakvalue;
  90. intptr_t bpscontrol[2];
  91. extern int64_t alreadysetupbpsandheap;
  92. extern int64_t _(hashtable);
  93. extern char bps[];
  94. extern int64_t symval;
  95. extern int64_t lastbps;
  96. extern int64_t nextbps;
  97. extern int64_t bpslowerbound;
  98. extern int64_t _infbitlength_;
  99. extern int64_t heaplowerbound;
  100. extern int64_t heapupperbound;
  101. extern int64_t heaplast;
  102. extern int64_t heaptrapbound;
  103. extern int64_t oldheaplowerbound;
  104. extern int64_t oldheapupperbound;
  105. extern int64_t oldheaplast;
  106. extern int64_t oldheaptrapbound;
  107. int creloc(int64_t array, long len, int64_t diff, int64_t lowb);
  108. long sizeofsymvectors = 0;
  109. void setupbps();
  110. void getheap(int64_t);
  111. void read_error(char *,int64_t,int64_t);
  112. /*
  113. * On the Macintosh you get messages telling you that sbrk is deprecated.
  114. * If you look up its documentation on Linux that tells you that these
  115. * days you syhould use malloc instead.
  116. * On Windows it is not available. So re-work to remove use of it might
  117. * be in order! But will that interact with the scheme for dumping and
  118. * reloading images?
  119. */
  120. #ifdef __WIN64__
  121. void *sbrk(intptr_t n)
  122. { void *p;
  123. if (n == 0) return (void *)0;
  124. p = (void *)malloc(n);
  125. if (p == NULL) return (void *)(-1);
  126. else return p;
  127. }
  128. /* realpath() is supposed to convert the path s to canonical form. This
  129. * involved traversing any symbolic links and tidying up any sub-strings
  130. * such as "/../". Here I just let it copy the path!
  131. */
  132. char *realpath(const char *s, char *n)
  133. { if (n == NULL) n = (char *)malloc(strlen(s) + 1);
  134. if (n == NULL) return NULL;
  135. strcpy(n, s);
  136. return n;
  137. }
  138. #endif
  139. int setupbpsandheap(int argc,char *argv[])
  140. { int64_t ohl,ohtb,ohub,htb,hlb,hub,diff;
  141. int memset = 0;
  142. FILE * imago;
  143. int64_t headerword [8];
  144. int64_t i, total, bpssize, heapsize, mallocsize;
  145. int64_t current_size_in_bytes, heapsize_in_bytes;
  146. double bpspercent, heappercent;
  147. char *argp, *scanptr, *scanformat;
  148. long hugo;
  149. total = MINSIZE;
  150. mallocsize = MALLOCSIZE;
  151. for (i=1; i<argc-1; i++)
  152. { argp = argv[i];
  153. if (*argp++ == '-')
  154. { scanformat = "";
  155. switch (*argp++)
  156. { case 't': scanptr = (char *)&total;
  157. memset = 1;
  158. switch (*argp)
  159. { case 'x': scanformat = "%x";
  160. break;
  161. case 'd': scanformat = "%d";
  162. break;
  163. }
  164. break;
  165. case 'm': scanptr = (char *)&mallocsize;
  166. switch (*argp)
  167. { case 'x': scanformat = "%lx";
  168. break;
  169. case 'd': scanformat = "%ld";
  170. break;
  171. }
  172. break;
  173. case 'f': imagefile = argv[i+1]; break;
  174. }
  175. if (*scanformat != 0)
  176. sscanf(argv[i+1],scanformat,scanptr);
  177. }
  178. } /* end of for loop -- arg vector searched */
  179. /* insure valid values */
  180. if (total < 1000000) total = total * 1000000;
  181. if (total == 0)
  182. total = MINSIZE;
  183. if (mallocsize <= 0)
  184. mallocsize = MALLOCSIZE;
  185. /* Reserve some space for C's usr of io buffers, etc. By mallocing then
  186. freeing, the memory is sbrk'ed onto the image, but available for future
  187. calls to malloc, which will not need to call sbrk again. */
  188. bpssize = BPSSIZE;
  189. heapsize_in_bytes = total - bpssize;
  190. /* On systems in which the image does not start at address 0, this won't
  191. really allocate the full maximum, but close enough. */
  192. current_size_in_bytes = (((int64_t) sbrk(0))<<5)>>5;
  193. max_image_size = INT64_C(0x1000000000000); /* 1 more than allowable size */
  194. if ((heapsize_in_bytes + current_size_in_bytes) >= max_image_size)
  195. { heapsize_in_bytes = max_image_size - current_size_in_bytes;
  196. total = heapsize_in_bytes + bpssize;
  197. printf("total %" PRIx64 " %" PRIx64 " %" PRIx64 "\n",heapsize_in_bytes, current_size_in_bytes,total);
  198. printf("Size requested will result in pointer values larger than\n");
  199. printf(" PSL items can handle. Will allocate maximum size instead.\n\n");
  200. }
  201. #if (NUMBEROFHEAPS == 2)
  202. heapsize =(heapsize_in_bytes / 8) * 4; /* insure full words */
  203. #else
  204. heapsize =(heapsize_in_bytes / 8) * 8; /* insure full words */
  205. #endif
  206. heappercent = ((float) (total - bpssize) / total) * 100.0;
  207. bpspercent = ((float) bpssize / total) * 100.0;
  208. if (imagefile == NULL)
  209. { printf("Setting heap limit as follows:\n");
  210. if (Debug > 0)
  211. { printf("Total heap & bps space = %" PRId64 " (%" PRIx64 "), bps = %.2f, heap = %.2f\n",
  212. total, total, bpspercent, heappercent);
  213. }
  214. }
  215. setupbps();
  216. if (imagefile != NULL) imago = fopen (imagefile,"r");
  217. /* before getheap */
  218. getheap(heapsize);
  219. if (imagefile == NULL)
  220. printf("bpssize = %" PRId64 " (%" PRIX64 "), heapsize = %" PRId64 " (%" PRIX64 ")\nTotal image size = %" PRId64 " (%" PRIX64 ")\n",
  221. bpssize, bpssize,
  222. heapsize, heapsize,
  223. (int64_t) sbrk(0), (int64_t) sbrk(0));
  224. if (imagefile != NULL)
  225. { ohl = oldheaplowerbound; ohub = oldheapupperbound;
  226. ohl = oldheaplast; ohtb = oldheaptrapbound;
  227. hlb = heaplowerbound; hub = heapupperbound;
  228. htb = heaptrapbound;
  229. /* save the new values around restore of the old ones */
  230. printf("Loading image file: %s \n",imagefile);
  231. if (imago == NULL)
  232. { perror ("error");
  233. exit (-1);
  234. }
  235. if (fread (headerword,8,2,imago) != 2)
  236. printf("fread failed %d %s\n", __LINE__, __FILE__);
  237. _(unexec)(); /* set control vector */
  238. if ((int) bpscontrol[0] != headerword[0]
  239. || bpscontrol[1] != headerword[1])
  240. { printf(" Cannot start the image with this bpsl \n");
  241. printf(" %lx != %" PRIx64 ", %lx != %" PRIx64 "\n", bpscontrol[0], headerword [0], bpscontrol[1], headerword[1]);
  242. exit (-19);
  243. }
  244. if (fread(headerword,8,4,imago) != 4)
  245. printf("fread failed %d %s\n", __LINE__, __FILE__);
  246. #ifdef DEBUG
  247. printf("symbol table: %ld (%lx) bytes\n",headerword[0],headerword[0]);
  248. #endif
  249. hugo = fread (&symval,1,headerword[0],imago);
  250. // printf("neu: %lx => %lx\n",hlb, heaplowerbound);
  251. diff = hlb-heaplowerbound;
  252. if (hlb < heaplowerbound)
  253. { creloc((int64_t) &symval,headerword[0]/8,diff,hlb -1);
  254. }
  255. else
  256. { creloc((int64_t) &symval,headerword[0]/8,diff, heaplowerbound -1);
  257. }
  258. sizeofsymvectors = headerword[0]/8;
  259. if (hugo != headerword[0]) read_error("symbol table",hugo,headerword[0]);
  260. #ifdef DEBUG
  261. printf("heap: %ld (%lx) bytes\n",headerword[1],headerword[1]);
  262. #endif
  263. hugo = fread ((char*)hlb,1,headerword[1],imago);
  264. if (hlb < heaplowerbound)
  265. { creloc(hlb,headerword[1]/8,diff,hlb -1);
  266. }
  267. else
  268. { creloc(hlb,headerword[1]/8,diff, heaplowerbound -1);
  269. }
  270. heaplast += diff;
  271. if (hugo != headerword[1]) read_error("heap",hugo,headerword[1]);
  272. #ifdef DEBUG
  273. printf("hash table: %ld (%lx) bytes\n",headerword[2],headerword[2]);
  274. #endif
  275. hugo = fread (&_(hashtable),1,headerword[2],imago);
  276. if (hugo != headerword[2]) read_error("hash table",hugo,headerword[2]);
  277. #ifdef DEBUG
  278. printf("BPS: %ld (%lx) bytes\n",headerword[3],headerword[3]);
  279. #endif
  280. hugo = fread ((char*)bpslowerbound,1,headerword[3],imago);
  281. if (hugo != headerword[3]) read_error("BPS",hugo,headerword[3]);
  282. fclose (imago);
  283. if (memset)
  284. { oldheaplowerbound = ohl; oldheapupperbound = ohub;
  285. oldheaplast = ohl; oldheaptrapbound = ohtb;
  286. heaplowerbound = hlb; heapupperbound = hub;
  287. heaptrapbound = htb;
  288. }
  289. abs_imagefile = realpath(imagefile,NULL);
  290. return (4711);
  291. }
  292. return (0);
  293. }
  294. void read_error(char * what,int64_t bytesread,int64_t byteswanted)
  295. { printf("File too short while reading %s: bytes read = %" PRId64 " (%" PRIx64 "), bytes expected = %" PRId64 " (%" PRIx64 ")\n",
  296. what,bytesread,bytesread,byteswanted,byteswanted);
  297. exit(-1);
  298. }
  299. /* The current procedure is to convert the starting address of the char
  300. array defined in bps.c to an address and store it in nextbps. A check
  301. is made to make sure that nextbps falls on an even word boundry.
  302. */
  303. #ifdef __WIN64__
  304. #define PROT_READ 1
  305. #define PROT_WRITE 2
  306. #define PROT_EXEC 4
  307. int mprotect(void *address, size_t len, int prot)
  308. {
  309. return 0; /* pretend success */
  310. }
  311. #else
  312. #include <sys/mman.h>
  313. #endif
  314. void setupbps()
  315. { char *p = (char *) bps;
  316. int bpssize;
  317. nextbps = ((int64_t)bps + 7) & ~7; /* Up to a multiple of 8. */
  318. bpslowerbound = nextbps;
  319. lastbps = ((int64_t)bps + BPSSIZE) & ~7; /* Down to a multiple of 8. */
  320. p = (char *)(((int64_t) bpslowerbound -1) & ~(PAGESIZE-1));
  321. bpssize = ((BPSSIZE + PAGESIZE-1) & ~(PAGESIZE-1));
  322. if (mprotect(p, bpssize, PROT_READ | PROT_WRITE | PROT_EXEC))
  323. { perror("Couldn't1 mprotect");
  324. exit(errno);
  325. }
  326. }
  327. /* Allocate alternate bps space. Note: The use of sbrk(), and the fact that
  328. nextbps is now greater than heaplast means that unexec should be not be
  329. tried after this routine is called. The image would be huge.
  330. */
  331. int64_t _(allocatemorebps)()
  332. { int64_t current_size_in_bytes;
  333. long old_nextbps = nextbps;
  334. current_size_in_bytes = (int64_t)sbrk(0);
  335. if ((current_size_in_bytes + EXTRABPSSIZE) >= max_image_size)
  336. return(0);
  337. if (((int64_t)sbrk(0)) % 2) /* force to even word boundary*/
  338. nextbps = (int64_t)sbrk(1);
  339. nextbps = (int64_t)sbrk(EXTRABPSSIZE); /* allocate extra BPS */
  340. if (nextbps == -1)
  341. { nextbps = old_nextbps;
  342. return(0);
  343. }
  344. lastbps = nextbps + EXTRABPSSIZE;
  345. return(EXTRABPSSIZE); /* This will be a parameter later */
  346. }
  347. void getheap(int64_t heapsize)
  348. {
  349. #if (NUMBEROFHEAPS == 1)
  350. heaplowerbound = (int64_t)sbrk(heapsize); /* allocate first heap */;
  351. oldheaplowerbound = -1;
  352. #else
  353. heaplowerbound = (int64_t )malloc(2 * heapsize); /* allocate first heap */;
  354. #endif
  355. if (heaplowerbound == (int64_t) NULL )
  356. { perror("GETHEAP");
  357. exit(-1);
  358. }
  359. heapupperbound = heaplowerbound + heapsize;
  360. heaplast = heaplowerbound;
  361. heaptrapbound = heapupperbound -120;
  362. #if (NUMBEROFHEAPS == 2)
  363. oldheaplowerbound = heapupperbound;
  364. oldheapupperbound = oldheaplowerbound + heapsize;
  365. oldheaplast = oldheaplowerbound;
  366. oldheaptrapbound = oldheapupperbound -120;
  367. #endif
  368. oldbreakvalue = (int64_t )sbrk(0);
  369. }
  370. /* Tag( alterheapsize )
  371. */
  372. int64_t _(alterheapsize)(int increment)
  373. { /*
  374. alters the size of the heap by the specified increment. Returns
  375. the increment if successful, otherwise returns 0. May fail if
  376. the sbrk is unsuccessful or if the user tries to cut the heap back
  377. to nothing or the current break value does not match the old value.
  378. The latter case occurs when a malloc or sbrk has allocated space for
  379. some other software, in which case we cannot allocate any more space
  380. contiguously.
  381. Modifies both the heap and gcarray size.
  382. NOTE: a garbage collection should probably be performed before this
  383. routine is called.
  384. NOTE: only implemented for the one heap version on the 68000.
  385. */
  386. int current_size_in_bytes;
  387. int64_t diff;
  388. #if (NUMBEROFHEAPS == 1)
  389. int heapsize;
  390. int gcarraysize, newbreakvalue;
  391. printf("***** cannot extend heap on this machine\n");
  392. return(0);
  393. if ((int64_t) sbrk(0) != oldbreakvalue) /* Non contiguous memory */
  394. return(0);
  395. newbreakvalue = oldbreakvalue + increment;
  396. /* don't let the user cut his heap back to nothing, taking into account
  397. space for the gcarray. */
  398. if ((increment < 0) &&
  399. ((newbreakvalue - heaplowerbound) <
  400. (((heaplast + MINIMUMHEAPADD - heaplowerbound) * 9) / 8)))
  401. return(0);
  402. current_size_in_bytes = sbrk(0);
  403. if ((current_size_in_bytes + increment) >= max_image_size)
  404. return(0);
  405. if ((int64_t)sbrk(increment) == -1) /* the sbrk failed. */
  406. return(0);
  407. newbreakvalue = (int64_t) sbrk(0);
  408. heapsize = (((newbreakvalue - heaplowerbound) / 4) * 4);
  409. gcarraysize = (((heapsize / 9) / 4) * 4);
  410. heapsize = heapsize - gcarraysize;
  411. heapupperbound = heaplowerbound + heapsize;
  412. heaptrapbound = heapupperbound;
  413. oldbreakvalue = newbreakvalue;
  414. return(increment);
  415. #else
  416. /* assumes the current heap is the 'lower' one */
  417. int newbreakvalue;
  418. void * realo;
  419. if ((int64_t) sbrk(0) != oldbreakvalue) /* Non contiguous memory */
  420. { printf(" unable to allocate %" PRIx64 " %" PRIx64 "\n",(int64_t)sbrk(0),oldbreakvalue);
  421. return(0);
  422. }
  423. current_size_in_bytes = ( (int64_t) sbrk(0) <<5) >>5;
  424. if ((current_size_in_bytes + 2* increment) >= max_image_size)
  425. return(-1);
  426. realo = realloc((void *)heaplowerbound,
  427. oldheapupperbound - heaplowerbound + 2*increment);
  428. if (realo == (void *) NULL)
  429. { if (Debug > 0)
  430. { fprintf(stderr,"realloc returned NULL\n");
  431. }
  432. return (-2);
  433. }
  434. if (Debug > 0)
  435. { fprintf(stderr,"Old heaplowerbound = %" PRId64 " (%" PRIX64 "), new = %" PRId64 " (%" PRIX64 ")\n",heaplowerbound,heaplowerbound,(int64_t)realo,(int64_t)realo);
  436. }
  437. diff = realo - (void *)heaplowerbound;
  438. if (realo < (void *)heaplowerbound)
  439. { creloc((int64_t) &symval,sizeofsymvectors,diff,(int64_t)realo -1);
  440. }
  441. else
  442. { creloc((int64_t) &symval,sizeofsymvectors,diff, heaplowerbound -1);
  443. }
  444. if (realo < (void *)heaplowerbound)
  445. { creloc((int64_t)realo,(heapupperbound - heaplowerbound)/8,diff,(int64_t)realo -1);
  446. }
  447. else
  448. { creloc((int64_t)realo,(heapupperbound - heaplowerbound)/8,diff,
  449. heaplowerbound -1);
  450. }
  451. newbreakvalue = (int64_t) sbrk(0);
  452. heaplowerbound = (uint64_t) realo;
  453. heaplast = heaplast + diff ;
  454. heapupperbound = heapupperbound + diff + increment ;
  455. heaptrapbound = heapupperbound - 120;
  456. oldheaplowerbound = oldheaplowerbound + diff + increment;
  457. oldheapupperbound = oldheapupperbound + diff + 2* increment ;
  458. oldheaplast = oldheaplowerbound + diff ;
  459. oldheaptrapbound = oldheapupperbound -120;
  460. oldbreakvalue = newbreakvalue;
  461. return(increment);
  462. #endif
  463. }
  464. intptr_t _(unexec)()
  465. { bpscontrol[0] = bpslowerbound;
  466. bpscontrol[1] = BPSSIZE;
  467. return (intptr_t)bpscontrol;
  468. }
  469. char *_(get_imagefilepath)()
  470. { return abs_imagefile;
  471. }
  472. /* end of bpsheap.c */