PageRenderTime 57ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/kits/scc/scinit.c

http://github.com/pablomarx/Thomas
C | 935 lines | 747 code | 66 blank | 122 comment | 127 complexity | 2657f5264969aeb6377c79ae5eed1140 MD5 | raw file
  1. /* SCHEME->C */
  2. /* Copyright 1989 Digital Equipment Corporation
  3. * All Rights Reserved
  4. *
  5. * Permission to use, copy, and modify this software and its documentation is
  6. * hereby granted only under the following terms and conditions. Both the
  7. * above copyright notice and this permission notice must appear in all copies
  8. * of the software, derivative works or modified versions, and any portions
  9. * thereof, and both notices must appear in supporting documentation.
  10. *
  11. * Users of this software agree to the terms and conditions set forth herein,
  12. * and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
  13. * right and license under any changes, enhancements or extensions made to the
  14. * core functions of the software, including but not limited to those affording
  15. * compatibility with other hardware or software environments, but excluding
  16. * applications which incorporate this software. Users further agree to use
  17. * their best efforts to return to Digital any such changes, enhancements or
  18. * extensions that they make and inform Digital of noteworthy uses of this
  19. * software. Correspondence should be provided to Digital at:
  20. *
  21. * Director of Licensing
  22. * Western Research Laboratory
  23. * Digital Equipment Corporation
  24. * 250 University Avenue
  25. * Palo Alto, California 94301
  26. *
  27. * This software may be distributed (but not offered for sale or transferred
  28. * for compensation) to third parties, provided such third parties agree to
  29. * abide by the terms and conditions of this notice.
  30. *
  31. * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  32. * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  33. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  34. * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  35. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  36. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  37. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  38. * SOFTWARE.
  39. */
  40. /* This module defines some basic global objects and initializes those parts
  41. of the SCHEME->C runtime system which are written in C. For
  42. compatibility with other modules, the routines and Scheme globals provided
  43. by these routines appear as members of the module "sc".
  44. */
  45. /* External Definitions */
  46. extern char *sbrk();
  47. extern char *getenv();
  48. extern errno; /* C-library Error flag */
  49. #include <sys/file.h>
  50. #include <sys/types.h>
  51. #include <sys/uio.h>
  52. #include <strings.h>
  53. #include <varargs.h>
  54. /* Definitions for objects within sc */
  55. #include "objects.h"
  56. #include "scinit.h"
  57. #include "heap.h"
  58. #include "apply.h"
  59. #include "callcc.h"
  60. #include "signal.h"
  61. /* Definitions for objects elsewhere in the Scheme system */
  62. extern TSCP scrt1_reverse();
  63. extern TSCP scrt6_error();
  64. extern etext;
  65. #ifdef MIPS
  66. #define ETEXT ((int)&etext) /* First address after text */
  67. #ifdef BIGMIPS
  68. #include <sys/param.h>
  69. #include <sys/immu.h> */
  70. #define STACKBASE (int*)USERSTACK
  71. #else
  72. #include <mips/param.h>
  73. #include <mips/vmparam.h>
  74. #define STACKBASE (int*)USRSTACK
  75. #endif
  76. #endif
  77. #ifdef TITAN
  78. #define ETEXT etext /* First address after text */
  79. #include <sys/mparam.h>
  80. #define STACKBASE (int*)(MAXUSERADDR+1)
  81. #endif
  82. #ifdef VAX
  83. #define ETEXT ((int)&etext) /* First address after text */
  84. #include <vax/param.h>
  85. #include <vax/vmparam.h>
  86. #define STACKBASE (int*)USRSTACK
  87. #endif
  88. /* Global data structure for this module. */
  89. static int emptyvector = VECTORTAG,
  90. emptystring[2] = {STRINGTAG, 0};
  91. FILE *sc_stdin, /* Standard I/O Subroutine FILE pointers */
  92. *sc_stdout,
  93. *sc_stderr;
  94. TSCP sc__2dfile_2a_67475874_v; /* *INITIAL-HEAP-FILE* */
  95. static int expandfailed = 0; /* Expansion failure flag */
  96. static int module_initialized = 0;
  97. /* Command line arguments and environment variables which control the heap are
  98. interpreted by the following functions.
  99. */
  100. static char *heapfilename = NULL; /* Pointer to heap file name */
  101. static int defaultheap = 8, /* Default heap size in megabytes */
  102. minheap = 1, /* Minimum heap size in megabytes */
  103. maxheap = 1000, /* Maximum heap size in megabytes */
  104. defaultlimit = 33, /* Default collection limit */
  105. minlimit = 10, /* Minimum total collection limit */
  106. maxlimit = 45, /* Maximun total collection limit */
  107. scheap, /* Heap size in megabytes */
  108. scmaxheap, /* Heap allowed to grow this big */
  109. sclimit; /* % at which to do total collection */
  110. static char* getargval( argc, argv, cl, env )
  111. int argc;
  112. char *argv[],
  113. *cl, /* Ptr to command line argument name */
  114. *env; /* Ptr to environment variable name */
  115. {
  116. int i;
  117. for (i = 1; i < argc-1; i++) {
  118. if (strcmp( argv[ i ], cl ) == 0) return( argv[ i+1 ] );
  119. }
  120. return( getenv( env ) );
  121. }
  122. static void decodearguments( argc, argv )
  123. int argc;
  124. char *argv[];
  125. {
  126. char *val;
  127. val = getargval( argc, argv, "-sch", "SCHEAP" );
  128. if (val != NULL) {
  129. scheap = atoi( val );
  130. if (scheap < minheap) scheap = minheap;
  131. if (scheap > maxheap) scheap = maxheap;
  132. }
  133. else scheap = defaultheap;
  134. val = getargval( argc, argv, "-scmh", "SCMAXHEAP" );
  135. if (val != NULL) {
  136. scmaxheap = atoi( val );
  137. if (scmaxheap < scheap) scmaxheap = scheap;
  138. if (scmaxheap > maxheap) scmaxheap = maxheap;
  139. }
  140. else scmaxheap = scheap*2;
  141. heapfilename = getargval( argc, argv, "-schf", "SCHEAPFILE" );
  142. val = getargval( argc, argv, "-scgc", "SCGCINFO" );
  143. if (val != NULL) {
  144. sc_gcinfo = atoi( val );
  145. if (sc_gcinfo < 0 || sc_gcinfo > 2) sc_gcinfo = 0;
  146. }
  147. else sc_gcinfo = 0;
  148. val = getargval( argc, argv, "-scl", "SCLIMIT" );
  149. if (val != NULL) {
  150. sclimit = atoi( val );
  151. if (sclimit < minlimit) sclimit = defaultlimit;
  152. if (sclimit > maxlimit) sclimit = defaultlimit;
  153. }
  154. else sclimit = defaultlimit;
  155. }
  156. /* The variables holding the values of the functions defined in this module
  157. are initialized by the following procedure.
  158. */
  159. DEFSTRING( t1030, "MY-RUSAGE", 9 );
  160. DEFSTRING( t1032, "COLLECT-RUSAGE", 14 );
  161. DEFSTRING( t1034, "COLLECT", 7 );
  162. DEFSTRING( t1035, "COLLECT-ALL", 11 );
  163. DEFSTRING( t1036, "CONS", 4 );
  164. DEFSTRING( t1037, "WEAK-CONS", 9 );
  165. DEFSTRING( t1038, "MAKE-STRING", 11 );
  166. DEFSTRING( t1040, "STRING-COPY", 11 );
  167. DEFSTRING( t1044, "MAKE-VECTOR", 11 );
  168. DEFSTRING( t1046, "STRING->SYMBOL", 14 );
  169. DEFSTRING( t1048, "STRING->UNINTERNED-SYMBOL", 25 );
  170. DEFSTRING( t1050, "UNINTERNED-SYMBOL?", 18 );
  171. DEFSTRING( t1052, "CALL-WITH-CURRENT-CONTINUATION", 30 );
  172. DEFSTRING( t1056, "SAVE-HEAP", 9 );
  173. DEFSTRING( t1058, "IMPLEMENTATION-INFORMATION", 26 );
  174. DEFSTRING( t1060, "AFTER-COLLECT", 13 );
  175. DEFSTRING( t1062, "*FROZEN-OBJECTS*", 16 );
  176. DEFSTRING( t2003, "*INITIAL-HEAP-FILE*", 19 );
  177. static init_procs()
  178. {
  179. INITIALIZEVAR( U_TX( ADR( t1030 ) ),
  180. ADR( sc_my_2drusage_v ),
  181. MAKEPROCEDURE( 0,
  182. 0, sc_my_2drusage, EMPTYLIST ) );
  183. INITIALIZEVAR( U_TX( ADR( t1032 ) ),
  184. ADR( sc_collect_2drusage_v ),
  185. MAKEPROCEDURE( 0,
  186. 0,
  187. sc_collect_2drusage, EMPTYLIST ) );
  188. INITIALIZEVAR( U_TX( ADR( t1034 ) ),
  189. ADR( sc_collect_v ),
  190. MAKEPROCEDURE( 0,
  191. 0, sc_collect, EMPTYLIST ) );
  192. INITIALIZEVAR( U_TX( ADR( t1035 ) ),
  193. ADR( sc_collect_2dall_v ),
  194. MAKEPROCEDURE( 0,
  195. 0, sc_collect_2dall, EMPTYLIST ) );
  196. INITIALIZEVAR( U_TX( ADR( t1036 ) ),
  197. ADR( sc_cons_v ),
  198. MAKEPROCEDURE( 2, 0, sc_cons, EMPTYLIST ) );
  199. INITIALIZEVAR( U_TX( ADR( t1037 ) ),
  200. ADR( sc_weak_2dcons_v ),
  201. MAKEPROCEDURE( 2, 0, sc_weak_2dcons, EMPTYLIST ) );
  202. INITIALIZEVAR( U_TX( ADR( t1038 ) ),
  203. ADR( sc_make_2dstring_v ),
  204. MAKEPROCEDURE( 1,
  205. 1,
  206. sc_make_2dstring, EMPTYLIST ) );
  207. INITIALIZEVAR( U_TX( ADR( t1040 ) ),
  208. ADR( sc_string_2dcopy_v ),
  209. MAKEPROCEDURE( 1,
  210. 0,
  211. sc_string_2dcopy, EMPTYLIST ) );
  212. INITIALIZEVAR( U_TX( ADR( t1044 ) ),
  213. ADR( sc_make_2dvector_v ),
  214. MAKEPROCEDURE( 1,
  215. 1,
  216. sc_make_2dvector, EMPTYLIST ) );
  217. INITIALIZEVAR( U_TX( ADR( t1046 ) ),
  218. ADR( sc_string_2d_3esymbol_v ),
  219. MAKEPROCEDURE( 1,
  220. 0,
  221. sc_string_2d_3esymbol, EMPTYLIST ) );
  222. INITIALIZEVAR( U_TX( ADR( t1048 ) ),
  223. ADR( sc_d_2dsymbol_ab4b4447_v ),
  224. MAKEPROCEDURE( 1,
  225. 0,
  226. sc_d_2dsymbol_ab4b4447,
  227. EMPTYLIST ) );
  228. INITIALIZEVAR( U_TX( ADR( t1050 ) ),
  229. ADR( sc_uninterned_2dsymbol_3f_v ),
  230. MAKEPROCEDURE( 1,
  231. 0,
  232. sc_uninterned_2dsymbol_3f,
  233. EMPTYLIST ) );
  234. INITIALIZEVAR( U_TX( ADR( t1052 ) ),
  235. ADR( sc_ntinuation_1af38b9f_v ),
  236. MAKEPROCEDURE( 1,
  237. 0,
  238. sc_ntinuation_1af38b9f,
  239. EMPTYLIST ) );
  240. INITIALIZEVAR( U_TX( ADR( t1056 ) ),
  241. ADR( sc_save_2dheap_v ),
  242. MAKEPROCEDURE( 1,
  243. 1, sc_save_2dheap, EMPTYLIST ) );
  244. INITIALIZEVAR( U_TX( ADR( t1058 ) ),
  245. ADR( sc_implementation_v ),
  246. MAKEPROCEDURE( 0,
  247. 0, sc_implementation, EMPTYLIST ) );
  248. INITIALIZEVAR( U_TX( ADR( t1060 ) ),
  249. ADR( sc_after_2dcollect_v ),
  250. FALSEVALUE );
  251. INITIALIZEVAR( U_TX( ADR( t1062 ) ),
  252. ADR( sc__2afrozen_2dobjects_2a_v ),
  253. EMPTYLIST );
  254. INITIALIZEVAR( U_TX( ADR( t2003 ) ),
  255. ADR( sc__2dfile_2a_67475874_v ),
  256. FALSEVALUE );
  257. MAXDISPLAY( 0 );
  258. return;
  259. }
  260. /* Memory is allocated from the heap by calling the following function
  261. with a byte count. It returns a pointer to the space. Errors occurring
  262. during initialization will cause the program to abort. Later errors will
  263. return -1 as the procedure's value. Storage is allocated on PAGEBYTE
  264. boundaries and counts are rounded up to full pages.
  265. */
  266. static char *getmem( bytes )
  267. int bytes;
  268. {
  269. char *memp;
  270. memp = sbrk( 0 );
  271. if ((int)memp & (PAGEBYTES-1))
  272. sbrk( PAGEBYTES-(int)memp & (PAGEBYTES-1) );
  273. bytes = (bytes+PAGEBYTES-1) & ~(PAGEBYTES-1);
  274. memp = sbrk( bytes );
  275. if ((int)memp == -1) {
  276. memp = NULL;
  277. expandfailed = 1;
  278. if (module_initialized == 0) {
  279. fprintf( stderr, "***** Memory allocation failed: sbrk( %d )\n",
  280. bytes );
  281. exit( 1 );
  282. }
  283. }
  284. if (sc_gcinfo > 1)
  285. fprintf( stderr, "***** Memory %x %x\n", memp, memp+bytes-1 );
  286. return( memp );
  287. }
  288. /* Side tables are allocated by calling the following procedure with the
  289. first and last heap pages, and pointers to the pagegeneration, type,
  290. lock and link tables. An allocation failure will cause the pointers to
  291. be returned as NULL.
  292. */
  293. static char* side_addr; /* Address and size of last side tables. */
  294. static int side_bytes;
  295. static void allocate_sidetables( first, last, pagegen, type, lock, link )
  296. int first, last, /* heap pages */
  297. **pagegen, /* Pointers to pointers to tables */
  298. **type,
  299. **link,
  300. **lock;
  301. {
  302. int bytes;
  303. char* addr;
  304. bytes = ((last-first+1)*sizeof( int )*4+PAGEBYTES-1) & ~(PAGEBYTES-1);
  305. addr = getmem( bytes );
  306. if (addr == NULL) {
  307. *pagegen = *type = *lock = *link = NULL;
  308. return;
  309. }
  310. side_addr = addr;
  311. side_bytes = bytes;
  312. *pagegen = ((int*)side_addr)-first;
  313. *type = *pagegen+last+1-first;
  314. *lock = *type+last+1-first;
  315. *link = *lock+last+1-first;
  316. }
  317. /* The following function is called to initialize the heap from scratch. */
  318. sc_newheap()
  319. {
  320. int i;
  321. char *freebase;
  322. TSCP unknown;
  323. sc_limit = sclimit;
  324. sc_heappages = scheap*(ONEMB/PAGEBYTES);
  325. sc_maxheappages = scmaxheap*(ONEMB/PAGEBYTES);
  326. sc_allocatedheappages = 0;
  327. freebase = getmem( scheap*ONEMB );
  328. sc_firstheappage = ADDRESS_PAGE( freebase );
  329. sc_lastheappage = sc_firstheappage+sc_heappages-1;
  330. sc_freepage = sc_firstheappage;
  331. sc_firstheapp = (int*)freebase;
  332. sc_lastheapp = sc_firstheapp+PAGEWORDS*sc_heappages-1;
  333. sc_current_generation = 3;
  334. sc_next_generation = 3;
  335. sc_genlist = -1;
  336. allocate_sidetables( sc_firstheappage, sc_lastheappage,
  337. &sc_pagegeneration, &sc_pagetype, &sc_pagelock,
  338. &sc_pagelink );
  339. for (i = sc_firstheappage; i <= sc_lastheappage; i++ ) {
  340. sc_pagegeneration[ i ] = 1;
  341. sc_pagelock[ i ] = 0;
  342. }
  343. sc_initiallink = OKTOSET;
  344. sc_conscnt = 0;
  345. sc_extobjwords = 0;
  346. sc_mutex = 0;
  347. sc_pendingsignals = 0;
  348. sc_emptylist = EMPTYLIST;
  349. sc_emptyvector = U_T( &emptyvector, EXTENDEDTAG );
  350. sc_emptystring = U_T( emptystring, EXTENDEDTAG );
  351. sc_falsevalue = FALSEVALUE;
  352. sc_truevalue = TRUEVALUE;
  353. sc_eofobject = EOFOBJECT;
  354. sc_undefined = UNDEFINED;
  355. sc_stdin = stdin;
  356. sc_stdout = stdout;
  357. sc_stderr = stderr;
  358. sc_constants = NULL;
  359. sc_globals = NULL;
  360. sc_stackbase = STACKBASE;
  361. sc_whenfreed = EMPTYLIST;
  362. sc_freed = EMPTYLIST;
  363. sc_clink = EMPTYLIST;
  364. sc_globals = addtoSCPTRS( sc_globals, &sc_clink );
  365. sc_stacktrace = NULL;
  366. sc_obarray = sc_make_2dvector( 1023*4, EMPTYLIST );
  367. sc_initializevar( sc_cstringtostring( "*OBARRAY*" ),
  368. &sc_obarray,
  369. sc_obarray );
  370. init_procs();
  371. unknown = sc_makeprocedure( 0, 0, sc_unknowncall, EMPTYLIST );
  372. TX_U( unknown )->procedure.required = 255;
  373. for (i = 0; i <= 3; i++) {
  374. sc_unknownproc[ i ] = unknown;
  375. sc_globals = addtoSCPTRS( sc_globals, &sc_unknownproc[ i ] );
  376. }
  377. module_initialized = 1;
  378. if (sc_gcinfo)
  379. fprintf( stderr,
  380. "***** SCGCINFO = %d SCHEAP = %d SCMAXHEAP = %d SCLIMIT = %d\n",
  381. sc_gcinfo, scheap, scmaxheap, sclimit );
  382. /* Initialize dynwind as it has redefined call/cc */
  383. dynwind__init();
  384. }
  385. /* A block of storage is added to the heap by the following function. Side
  386. tables are automatically expanded as required.
  387. */
  388. static void addrtoheap( addr, count )
  389. char *addr; /* Address of the block */
  390. int count; /* Size in bytes of the block */
  391. {
  392. int first_addr, /* First page of addr */
  393. last_addr, /* Last page of addr */
  394. i,
  395. first_side, /* First page of current side tables */
  396. last_side, /* Last page of current side tables */
  397. new_first, /* New first page of heap */
  398. new_last, /* New last page of heap */
  399. *new_pagegeneration,
  400. *new_pagetype,
  401. *new_pagelock,
  402. *new_pagelink;
  403. if (addr == NULL) return;
  404. first_addr = ADDRESS_PAGE( addr );
  405. last_addr = ADDRESS_PAGE( addr+count-1 );
  406. if (first_addr >= sc_firstheappage &&
  407. last_addr <= sc_lastheappage) {
  408. /* Block fits in the side table */
  409. if (sc_gcinfo > 1)
  410. fprintf( stderr, "***** To heap %x %x\n", addr, addr+count-1 );
  411. for (i = first_addr; i <= last_addr; i++) {
  412. if (sc_pagegeneration[ i ]) {
  413. fprintf( "***** COLLECT Trying to reallocate page %d\n", i );
  414. abort();
  415. }
  416. sc_pagegeneration[ i ] = 1;
  417. sc_pagelock[ i ] = 0;
  418. }
  419. sc_heappages = sc_heappages+last_addr-first_addr+1;
  420. return;
  421. }
  422. /* Didn't fit, so figure out the new span of pages for the existing
  423. heap, the current side tables, and the new block.
  424. */
  425. first_side = ADDRESS_PAGE( side_addr );
  426. last_side = ADDRESS_PAGE( side_addr+side_bytes-1 );
  427. new_first = sc_firstheappage;
  428. if (first_side < new_first) new_first = first_side;
  429. if (first_addr < new_first) new_first = first_addr;
  430. new_last = sc_lastheappage;
  431. if (last_side > new_last) new_last = last_side;
  432. if (last_addr > new_last) new_last = last_addr;
  433. /* Try to allocate the new side tables */
  434. allocate_sidetables( new_first, new_last, &new_pagegeneration,
  435. &new_pagetype, &new_pagelock, &new_pagelink );
  436. if (new_first == NULL) return;
  437. /* Copy the old side tables */
  438. for (i = new_first; i < sc_firstheappage; i++) {
  439. new_pagegeneration[ i ] = 0;
  440. new_pagelock[ i ] = 0;
  441. }
  442. for (i = sc_firstheappage; i <= sc_lastheappage; i++) {
  443. new_pagegeneration[ i ] = sc_pagegeneration[ i ];
  444. new_pagetype[ i ] = sc_pagetype[ i ];
  445. new_pagelock[ i ] = sc_pagelock[ i ];
  446. new_pagelink[ i ] = sc_pagelink[ i ];
  447. }
  448. for (i = sc_lastheappage+1; i <= new_last; i++) {
  449. new_pagegeneration[ i ] = 0;
  450. new_pagelock[ i ] = 0;
  451. }
  452. /* Flip tables and set new bounds on the heap */
  453. sc_pagegeneration = new_pagegeneration;
  454. sc_pagetype = new_pagetype;
  455. sc_pagelock = new_pagelock;
  456. sc_pagelink = new_pagelink;
  457. sc_firstheappage = new_first;
  458. sc_lastheappage = new_last;
  459. sc_firstheapp = (int*)PAGE_ADDRESS( new_first );
  460. sc_lastheapp = ((int*)PAGE_ADDRESS( new_last+1 ))-1;
  461. /* Add old side tables and storage block to the heap */
  462. addrtoheap( addr, count );
  463. addrtoheap( PAGE_ADDRESS( first_side ),
  464. (last_side-first_side+1)*PAGEBYTES );
  465. }
  466. /* The heap is expanded by calling the following procedure. The boolean result
  467. is true iff the heap was expanded. The amount added to the heap is the
  468. minimum of: the existing heap size, the amount till the maximum, and
  469. 25% of the maximum heap size.
  470. */
  471. int sc_expandheap()
  472. {
  473. int old_pages = sc_heappages, /* Existing heap size */
  474. add_pages = sc_heappages; /* # of pages to add */
  475. char *msgheader;
  476. if ((sc_collecting == 0) || (sc_collecting && sc_gcinfo == 0))
  477. msgheader = "\n***** COLLECT ";
  478. else
  479. msgheader = " ";
  480. if (sc_heappages >= sc_maxheappages || expandfailed != 0) {
  481. if (expandfailed == 0) {
  482. fprintf( stderr, "%scannot further expand heap\n",
  483. msgheader );
  484. expandfailed = 1;
  485. }
  486. return( 0 );
  487. }
  488. if (add_pages > sc_maxheappages-sc_heappages)
  489. add_pages = sc_maxheappages-sc_heappages;
  490. if (add_pages > (sc_maxheappages*25)/100)
  491. add_pages = (sc_maxheappages*25)/100;
  492. if (sc_gcinfo)
  493. fprintf( stderr, "%sheap expanded to ", msgheader );
  494. addrtoheap( getmem( add_pages*PAGEBYTES ), add_pages*PAGEBYTES );
  495. if (sc_gcinfo)
  496. fprintf( stderr, "%d MB\n",
  497. (sc_heappages*PAGEBYTES+ONEMB/2)/ONEMB );
  498. if (expandfailed != 0)
  499. fprintf( stderr, "%sunable to expand the heap\n", msgheader );
  500. return( sc_heappages != old_pages );
  501. }
  502. /* The routines which follow are responsible for saving the heap to disc
  503. and reloading it. Saved heap images have the following header at the
  504. front of the file. Following the header is the sc_constants array, the
  505. sc_globals array, thepagegeneration array, the pagetype array, and all
  506. valid pages of the heap.
  507. */
  508. static struct {
  509. char id[4]; /* S->C */
  510. TSCP procedure; /* Restart procedure */
  511. TSCP correct; /* List of values for constants & globals */
  512. int etext;
  513. int locklist; /* From heap.h */
  514. int lockcnt;
  515. int current_generation;
  516. int next_generation;
  517. int limit;
  518. int heappages;
  519. int firstheappage;
  520. int freepage;
  521. int allocatedheappages;
  522. int *firstheapp;
  523. int conscnt;
  524. SCP consp;
  525. int extobjwords;
  526. int extwaste;
  527. SCP extobjp;
  528. int *sc_stackbase;
  529. TSCP sc_whenfreed;
  530. int sc_constants_limit; /* From objects.h */
  531. int sc_globals_limit;
  532. int sc_maxdisplay;
  533. } save;
  534. /* I/O is done directly with system calls so as to not allocate any data
  535. from the heap when the heap must be restored.
  536. */
  537. static int heapfile; /* File descriptor for the heap file */
  538. static void heapin( address, count )
  539. char *address;
  540. int count;
  541. {
  542. if (read( heapfile, address, count ) != count) {
  543. fprintf( stderr, "***** SAVE-HEAP HEAP FILE read error: %d\n",
  544. errno );
  545. exit( 1 );
  546. }
  547. }
  548. static void heapout( address, count )
  549. char *address;
  550. int count;
  551. {
  552. int error;
  553. if (write( heapfile, address, count ) != count) {
  554. error = errno;
  555. close( heapfile );
  556. sc_error( "SAVE-HEAP", "HEAP FILE fwrite error: ~s", 1,
  557. C_FIXED( error ) );
  558. }
  559. }
  560. /* A Scheme program may call (SAVE-HEAP filename . procedure) to save the
  561. heap in a file named "filename". When the heap is reloaded into a
  562. newly created process, execution will start at the procedure "procedure"
  563. which will be called with the command line argument list. If procedure is
  564. not supplied, then the normal start up procedure will be used.
  565. */
  566. TSCP sc_save_2dheap_v;
  567. TSCP sc_save_2dheap( filename, argl )
  568. TSCP filename, argl;
  569. {
  570. int i, firstpage, pagecount;
  571. TSCP correct, cl, symbol, procedure;
  572. procedure = FALSEVALUE;
  573. if (argl != EMPTYLIST) {
  574. procedure = PAIR_CAR( argl );
  575. if (TSCPTAG( procedure ) != EXTENDEDTAG ||
  576. T_U( procedure )->procedure.tag != PROCEDURETAG)
  577. sc_error( "SAVE-HEAP",
  578. "Restart procedure is not a PROCEDURE: ~s",
  579. 1, procedure );
  580. if (PROCEDURE_REQUIRED( procedure ) > 1 ||
  581. (PROCEDURE_REQUIRED( procedure ) == 0 &&
  582. PROCEDURE_OPTIONAL( procedure ) == 0))
  583. sc_error( "SAVE-HEAP",
  584. "Restart procedure must take 1 argument", 0 );
  585. if (PAIR_CDR( argl ) != EMPTYLIST) {
  586. sc_error( "SAVE-HEAP", "Too many arguments", 0 );
  587. }
  588. }
  589. if (TSCPTAG( filename ) != EXTENDEDTAG ||
  590. T_U( filename )->string.tag != STRINGTAG)
  591. sc_error( "SAVE-HEAP", "File name is not a STRING: ~s", 1,
  592. filename );
  593. heapfile = open( &(T_U( filename )->string.char0),
  594. (O_WRONLY | O_CREAT | O_TRUNC), 0755 );
  595. if (heapfile == -1)
  596. sc_error( "SAVE-HEAP", "Can't open HEAP FILE: ~s", 1,
  597. C_FIXED( errno ) );
  598. sc_collect_2dall();
  599. /* Build the save-heap file header */
  600. correct = EMPTYLIST;
  601. for (i = 0; i < sc_constants->count; i++)
  602. correct = sc_cons( *(sc_constants->ptrs[ i ]), correct );
  603. for (i = 0; i < sc_globals->count; i++)
  604. correct = sc_cons( *(sc_globals->ptrs[ i ]), correct );
  605. strncpy( save.id, "S->C", 4 );
  606. save.procedure = procedure;
  607. save.correct = correct;
  608. save.etext = ETEXT;
  609. save.locklist = sc_locklist;
  610. save.lockcnt = sc_lockcnt;
  611. save.current_generation = sc_current_generation;
  612. save.next_generation = sc_next_generation;
  613. save.limit = sc_limit;
  614. save.heappages = sc_lastheappage-sc_firstheappage+1;
  615. save.firstheappage = sc_firstheappage;
  616. save.freepage = sc_freepage;
  617. save.allocatedheappages = sc_allocatedheappages;
  618. save.firstheapp = sc_firstheapp;
  619. save.conscnt = sc_conscnt;
  620. save.consp = sc_consp;
  621. save.extobjwords = sc_extobjwords;
  622. save.extwaste = sc_extwaste;
  623. save.extobjp = sc_extobjp;
  624. save.sc_stackbase = sc_stackbase;
  625. save.sc_whenfreed = sc_whenfreed;
  626. save.sc_constants_limit = sc_constants->limit;
  627. save.sc_globals_limit = sc_globals->limit;
  628. save.sc_maxdisplay = sc_maxdisplay;
  629. heapout( &save, sizeof( save ) );
  630. heapout( sc_constants, sizeofSCPTRS( sc_constants->limit ) );
  631. heapout( sc_globals, sizeofSCPTRS( sc_globals->limit ) );
  632. heapout( &sc_pagegeneration[ sc_firstheappage ], sc_heappages*4 );
  633. heapout( &sc_pagetype[ sc_firstheappage ], sc_heappages*4 );
  634. pagecount = 0;
  635. for (i = sc_firstheappage; i <= sc_lastheappage; i++) {
  636. if (sc_pagegeneration[ i ] == sc_current_generation ||
  637. (~sc_pagegeneration[ i ] & 1 && sc_pagegeneration[ i ])) {
  638. if (pagecount++ == 0) firstpage = i;
  639. }
  640. else if (pagecount) {
  641. heapout( PAGE_ADDRESS( firstpage ), pagecount*PAGEBYTES );
  642. pagecount = 0;
  643. }
  644. }
  645. if (pagecount)
  646. heapout( PAGE_ADDRESS( firstpage ), pagecount*PAGEBYTES );
  647. close( heapfile );
  648. return( TRUEVALUE );
  649. }
  650. /* The following routine is called from a Scheme main program to determine
  651. how the heap is to be constructed. If the heap is being constructed from
  652. a saved file, then this function will not return. If there is no saved
  653. heap, then sc_newheap will be called to initialize the heap.
  654. */
  655. void sc_restoreheap( desiredheap, argc, argv, mainproc )
  656. int desiredheap;
  657. int argc;
  658. char *argv[];
  659. void (*mainproc)();
  660. {
  661. int i,
  662. pagecount,
  663. firstpage;
  664. char *freebase;
  665. TSCP cl,
  666. *address,
  667. address_value;
  668. if (module_initialized) return;
  669. if (desiredheap) {
  670. defaultheap = desiredheap;
  671. minheap = desiredheap;
  672. }
  673. decodearguments( argc, argv );
  674. if (heapfilename == NULL) {
  675. sc_newheap();
  676. return;
  677. }
  678. /* Saved heap exists, open it and validate the header */
  679. heapfile = open( heapfilename, O_RDONLY );
  680. if (heapfile == -1) {
  681. fprintf( stderr, "***** Can't open heap file: %d\n", errno );
  682. exit( 1 );
  683. }
  684. heapin( &save, sizeof( save ) );
  685. if (strncmp( save.id, "S->C", 4) || save.etext != ETEXT) {
  686. fprintf( stderr, "***** Incompatible heap file image\n" );
  687. exit( 1 );
  688. }
  689. /* Initialize similar to sc__init */
  690. if (scheap < save.heappages/(ONEMB/PAGEBYTES))
  691. scheap = save.heappages/(ONEMB/PAGEBYTES);
  692. if (sclimit < save.limit) sclimit = save.limit;
  693. sc_limit = sclimit;
  694. sc_heappages = scheap*(ONEMB/PAGEBYTES);
  695. if (scmaxheap < scheap) scmaxheap = scheap;
  696. sc_maxheappages = scmaxheap*(ONEMB/PAGEBYTES);
  697. sc_allocatedheappages = save.allocatedheappages;
  698. freebase = getmem( scheap*ONEMB );
  699. sc_firstheappage = ADDRESS_PAGE( freebase );
  700. sc_lastheappage = sc_firstheappage+sc_heappages-1;
  701. sc_firstheapp = (int*)freebase;
  702. sc_lastheapp = sc_firstheapp+PAGEWORDS*sc_heappages-1;
  703. sc_freepage = save.freepage;
  704. allocate_sidetables( sc_firstheappage, sc_lastheappage,
  705. &sc_pagegeneration, &sc_pagetype, &sc_pagelock,
  706. &sc_pagelink );
  707. sc_current_generation = save.current_generation;
  708. sc_next_generation = save.next_generation;
  709. sc_constants =
  710. (struct SCPTRS*)malloc( sizeofSCPTRS( save.sc_constants_limit ) );
  711. heapin( sc_constants, sizeofSCPTRS( save.sc_constants_limit ) );
  712. sc_globals =
  713. (struct SCPTRS*)malloc( sizeofSCPTRS( save.sc_globals_limit ) );
  714. heapin( sc_globals, sizeofSCPTRS( save.sc_globals_limit ) );
  715. heapin( &sc_pagegeneration[ sc_firstheappage ], save.heappages*4 );
  716. for (i = save.firstheappage+save.heappages; i <= sc_lastheappage;
  717. i++ )
  718. sc_pagegeneration[ i ] = 1;
  719. heapin( &sc_pagetype[ sc_firstheappage ], save.heappages*4 );
  720. sc_genlist = -1;
  721. for (i = sc_firstheappage; i <= sc_lastheappage; i++) {
  722. sc_pagelink[ i ] = 0;
  723. sc_pagelock[ i ] = 0;
  724. }
  725. sc_initiallink = OKTOSET;
  726. sc_conscnt = save.conscnt;
  727. sc_consp = save.consp;
  728. sc_extobjwords = save.extobjwords;
  729. sc_extobjp = save.extobjp;
  730. sc_extwaste = save.extwaste;
  731. sc_mutex = 0;
  732. sc_pendingsignals = 0;
  733. sc_emptylist = EMPTYLIST;
  734. sc_emptyvector = U_T( &emptyvector, EXTENDEDTAG );
  735. sc_emptystring = U_T( emptystring, EXTENDEDTAG );
  736. sc_falsevalue = FALSEVALUE;
  737. sc_truevalue = TRUEVALUE;
  738. sc_eofobject = EOFOBJECT;
  739. sc_undefined = UNDEFINED;
  740. sc_stdin = stdin;
  741. sc_stdout = stdout;
  742. sc_stderr = stderr;
  743. sc_maxdisplay = save.sc_maxdisplay;
  744. sc_stackbase = save.sc_stackbase;
  745. sc_whenfreed = save.sc_whenfreed;
  746. sc_freed = EMPTYLIST;
  747. sc_stacktrace = NULL;
  748. /* Reload the heap and correct globals which point into it */
  749. pagecount = 0;
  750. for (i = sc_firstheappage; i < sc_firstheappage+save.heappages;
  751. i++) {
  752. if (sc_pagegeneration[ i ] == sc_current_generation ||
  753. ~sc_pagegeneration[ i ] & 1) {
  754. if (pagecount++ == 0) firstpage = i;
  755. }
  756. else if (pagecount) {
  757. heapin( PAGE_ADDRESS( firstpage ), pagecount*PAGEBYTES );
  758. pagecount = 0;
  759. }
  760. }
  761. if (pagecount)
  762. heapin( PAGE_ADDRESS( firstpage ), pagecount*PAGEBYTES );
  763. cl = save.correct;
  764. for (i = sc_globals->count-1; i >= 0 ; i--) {
  765. *(sc_globals->ptrs[ i ]) = PAIR_CAR( cl );
  766. cl = PAIR_CDR( cl );
  767. }
  768. for (i = sc_constants->count-1; i >= 0; i--) {
  769. *(sc_constants->ptrs[ i ]) = PAIR_CAR( cl );
  770. cl = PAIR_CDR( cl );
  771. }
  772. sc_clink = EMPTYLIST;
  773. close( heapfile );
  774. module_initialized = 1;
  775. sc__2dfile_2a_67475874_v = sc_cstringtostring( heapfilename );
  776. if (sc_gcinfo)
  777. fprintf( stderr,
  778. "***** SCGCINFO = %d SCHEAP = %d SCMAXHEAP = %d SCLIMIT = %d\n",
  779. sc_gcinfo, scheap, scmaxheap, sclimit );
  780. /* Start execution at the appropriate procedure */
  781. if (save.procedure != FALSEVALUE)
  782. sc_apply_2dtwo( save.procedure,
  783. sc_cons( sc_clarguments( argc, argv ), EMPTYLIST ) );
  784. else if (mainproc != NULL)
  785. (*mainproc)( sc_clarguments( argc, argv ) );
  786. else
  787. return;
  788. SCHEMEEXIT();
  789. }
  790. /* This initialization function is provided to allow automatic initialization
  791. from a Modula-2 program.
  792. */
  793. sc__init()
  794. {
  795. sc_restoreheap( 0, 0, NULL, NULL );
  796. }
  797. /* Routines coded in C call the following function to access the Scheme ERROR
  798. function. SYMBOL is a string representing the function name. FORMAT is a
  799. string which is a format descriptor. ARGC is the argument count which is
  800. followed by the arguments.
  801. */
  802. sc_error( va_alist )
  803. va_dcl
  804. {
  805. char *symbol, *format;
  806. int argc;
  807. TSCP argl;
  808. va_list argp;
  809. va_start( argp );
  810. symbol = va_arg( argp, char* );
  811. format = va_arg( argp, char* );
  812. argc = va_arg( argp, int );
  813. argl = sc_emptylist;
  814. while (argc--) argl = sc_cons( va_arg( argp, TSCP ), argl );
  815. scrt6_error( sc_string_2d_3esymbol( sc_cstringtostring( symbol ) ),
  816. sc_cstringtostring( format ),
  817. scrt1_reverse( argl ) );
  818. }
  819. /* The following function returns informations about the implementation. The
  820. form of the function follows a recent proposal on rrrs-authors. The result
  821. is a list of strings or #F's of the form:
  822. (<name> <version> <MACHINE> <CPU> <OS> <FS> . <supports>)
  823. */
  824. TSCP sc_implementation_v;
  825. TSCP sc_implementation()
  826. {
  827. return(
  828. sc_cons(
  829. sc_cstringtostring( "Scheme->C" ),
  830. sc_cons(
  831. sc_cstringtostring( "01nov91jfb+wcdw" ),
  832. sc_cons(
  833. #ifdef MIPS
  834. #ifdef BIGENDIAN
  835. sc_cstringtostring( "Big Endian MIPS" ),
  836. #else
  837. sc_cstringtostring( "DECstation" ),
  838. #endif
  839. #endif
  840. #ifdef TITAN
  841. sc_cstringtostring( "WRL-TITAN" ),
  842. #endif
  843. #ifdef VAX
  844. sc_cstringtostring( "VAX" ),
  845. #endif
  846. sc_cons(
  847. #ifdef MIPS
  848. sc_cstringtostring( "R2000/R3000" ),
  849. #endif
  850. #ifdef TITAN
  851. sc_cstringtostring( "BYTE-ADDRESSED" ),
  852. #endif
  853. #ifdef VAX
  854. sc_cstringtostring( "VAX" ),
  855. #endif
  856. sc_cons(
  857. sc_cstringtostring( "ULTRIX" ),
  858. sc_cons(
  859. FALSEVALUE,
  860. EMPTYLIST
  861. )
  862. )
  863. )
  864. )
  865. )
  866. )
  867. );
  868. }