home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1155 < prev    next >
Text File  |  1990-12-28  |  27KB  |  988 lines

  1. Newsgroups: alt.sys.sun,alt.sources
  2. From: seth@ctr.columbia.edu (Seth Robertson)
  3. Subject: Sun Checkpoint procedure
  4. Message-ID: <1990Apr8.214615.9283@ctr.columbia.edu>
  5. Date: Sun, 8 Apr 90 21:46:15 GMT
  6.  
  7.  
  8. Greetings:
  9.  
  10. Below I have included a beta-test checkpointing program for Sun 3s.
  11.  
  12. Checkpointing, for those of you who do not know, consists of saving the
  13. program state every so often so that if the program crashes you can
  14. restart it from the last checkpoint.
  15.  
  16. Basically, what you have to do is insert a couple lines in your main()
  17. and then select points in your program to do checkpoints (it should be
  18. possible to set up an alarm to do it every hour or so, but I have not
  19. tried this).  You need select these points carefully because the
  20. process of checkpointing does have alot of overhead, so it is
  21. important not to do it too frequently.
  22.  
  23. This checkpointing program is very good for compute-bound programs.
  24. Programs that do I/O have problems because my checkpointing routines
  25. _DO_NOT_DO_ANYTHING_ABOUT_FILES_ If you have open files, you MUST
  26. reopen() them and relseek() them.  Also, programs that use signals
  27. need to be careful.  Basically, if your program reads in data, thinks
  28. about it for a few days, then spits it back out, this is for you.
  29.  
  30. Now for some restrictions.  It is currently working only on Sun 3s.
  31. It compiles fine on Sun4s and (I believe) any Vaxen (Ultrix or BSD)
  32. but the reason that it does not work is because of the Sun4s amd Vaxen
  33. broken setjmp() routines.  On Sun4s, what needs to be done is for
  34. someone to write an assembler routine to save all of the registers.
  35. Especially the stack pointer.  I havn't done too much work on the
  36. Vaxen, but the problem is pretty much the same.
  37.  
  38. I'm setting up a mailing list (which I envision to be very low volume,
  39. but what do I know?) for future enhancements and the like.  The address
  40. is "chkpnt-request@ctr.columbia.edu"
  41.  
  42. I would strongly request people to join the mailing list and report
  43. the experiences they have.  I especially would like to hear from
  44. anyone that gets it working on Sun 4s.
  45.  
  46. Enough of this, here is the code:
  47.  
  48.  
  49. #! /bin/sh
  50. # This is a shell archive.  Remove anything before this line, then unpack
  51. # it by saving it into a file and typing "sh file".  To overwrite existing
  52. # files, type "sh file -c".  You can also feed this as standard input via
  53. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  54. # will see the following message at the end:
  55. #        "End of shell archive."
  56. # Contents:  Makefile README chkpnt.c chkpnt.h main.c
  57. # Wrapped by seth@sirius on Sun Apr  8 17:42:56 1990
  58. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  59. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  60.   echo shar: Will not clobber existing file \"'Makefile'\"
  61. else
  62. echo shar: Extracting \"'Makefile'\" \(1154 characters\)
  63. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  64. X# Makefile attached to demo checkpoint/restore program
  65. X#
  66. X# The CPP Flag TIMEINFO will cause the c/r to print info on how long
  67. X# it took to checkpoint a program.
  68. X#
  69. X# The CPP Flag AOUT will cause the c/r to look in the argv[0] to determine
  70. X# (for a vax) what some exec headers are, and it will also cause the symbol
  71. X# table to be put on the checkpointed program.
  72. X#
  73. XCC = cc
  74. XTARGET_ARCH=
  75. X#LINTFLAGS= -hx
  76. X# For SunOS 4.x
  77. XCFLAGS= -g -Bstatic
  78. XCPPFLAGS= -DSUNOS4 -DTIMEINFO -DAOUT
  79. X# For SunOS 3.x
  80. X#CFLAGS= -g -Bstatic
  81. X#CPPFLAGS= -DTIMEINFO
  82. X# For 4.3 BSD
  83. X#CFLAGS = -g -DBSD43 -DTIMEINFO
  84. X#CPPFLAGS=  -DBSD43 -DTIMEINFO
  85. X# For Ultrix
  86. X#CFLAGS = -g
  87. X#CPPFLAGS= -DULTRIX -DTIMEINFO
  88. X
  89. XCSRC= chkpnt.c main.c
  90. XOBJS= $(CSRC:.c=.o)
  91. X
  92. XFORKS= rforkd rforkt
  93. X
  94. Xpoint:    $(OBJS)
  95. X    $(LINK.c) -o $@ $(OBJS)
  96. X
  97. Xforks: $(FORKS)
  98. X
  99. X# You need to make flip so that the program won't overwrite its own text
  100. Xflip:
  101. X    cp cpnt cpnt-test
  102. X
  103. Xlint:
  104. X    $(LINT.c) $(CSRC)
  105. X
  106. Xclean:
  107. X    rm -f core a.out *~ *.o cpnt*
  108. X
  109. Xrcpout:
  110. X    rcp chkpnt.[ch] main.c sethr@cunixc:check
  111. X    rcp chkpnt.[ch] main.c sethr@cs:check
  112. Xrcpcs:
  113. X    rcp sethr@cs:chkpnt.[ch] .
  114. Xrcpcc:
  115. X    rcp sethr@cunixc:chkpnt.[ch] .
  116. X
  117. Xchkpnt.o: chkpnt.h
  118. Xmain.o: chkpnt.hEND_OF_FILE
  119. if test 1154 -ne `wc -c <'Makefile'`; then
  120.     echo shar: \"'Makefile'\" unpacked with wrong size!
  121. fi
  122. # end of 'Makefile'
  123. fi
  124. if test -f 'README' -a "${1}" != "-c" ; then 
  125.   echo shar: Will not clobber existing file \"'README'\"
  126. else
  127. echo shar: Extracting \"'README'\" \(1412 characters\)
  128. sed "s/^X//" >'README' <<'END_OF_FILE'
  129. X
  130. X
  131. XHello.
  132. X
  133. XThis is a short preliminary document describing the use and restrictions
  134. Xof the checkpoint routines.
  135. X
  136. XThe restrictions are:
  137. X
  138. X1) You have to reopen files manually.
  139. X2) Any funky things like signal handlers and the like can cause the
  140. X   routine to crash and burn or just not be able to be restored
  141. X3) You have to schedule the checkpoints manually.
  142. X
  143. XTo use, you have to include the file chkpnt.h in your program.
  144. X
  145. XYou have to have argc and argv as arguemnts to your main procedure
  146. Xif you select AOUT as a Makefile option.
  147. X
  148. XThe first statement after the main() variable declarations should
  149. Xbe "CheckRestore()" which will restore the program if it has
  150. Xbeen checkpointed.
  151. X
  152. XYou will probably want to change the name the program is saved to in
  153. Xchkpnt.h
  154. X
  155. XIf the program did crash and does need to be restored, you need to
  156. Xmove it to another name (because otherwise the program will dump
  157. Xa new version over the old program text, and that can sometimes be
  158. Xvery very bad...
  159. X
  160. XThe author is not responsible for anything that might happen because
  161. Xof the use/nonuse of this routine.
  162. X
  163. X
  164. XPlease send all questions/bug reports/enhancements to:
  165. XSeth Robertson <seth@ctr.columbia.edu>
  166. X
  167. XOr to the mailing list:
  168. X<chkpnt@ctr.columbia.edu>
  169. X
  170. XTo get added to the mailing list:
  171. X<chkpnt-request@ctr.columbia.edu>
  172. X
  173. X                                        -Seth Robertson
  174. X                                         seth@ctr.columbia.edu
  175. END_OF_FILE
  176. if test 1412 -ne `wc -c <'README'`; then
  177.     echo shar: \"'README'\" unpacked with wrong size!
  178. fi
  179. # end of 'README'
  180. fi
  181. if test -f 'chkpnt.c' -a "${1}" != "-c" ; then 
  182.   echo shar: Will not clobber existing file \"'chkpnt.c'\"
  183. else
  184. echo shar: Extracting \"'chkpnt.c'\" \(16124 characters\)
  185. sed "s/^X//" >'chkpnt.c' <<'END_OF_FILE'
  186. X/*
  187. X**  chkpnt
  188. X**
  189. X**  A routine to that checkpoints and restores a program
  190. X**
  191. X**  Copyright (c) 1989
  192. X**  All rights are currently reserved.
  193. X**
  194. X**  Redistribution and use in source and binary forms are permitted
  195. X**  provided that the above copyright notice and this paragraph are
  196. X**  duplicated in all such forms.
  197. X**
  198. X**  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  199. X**  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  200. X**  WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  201. X**
  202. X**  If you have any enhancements, please send them so that they can
  203. X**  be incorporated into the next version.
  204. X**
  205. X**  This program is quite possibly supported by:
  206. X**    Seth Robertson
  207. X**    seth@ctr.columbia.edu
  208. X**    Columbia University
  209. X**    1220 S.W. Mudd
  210. X**    New York, New York  10027-6699
  211. X**    (212) 854-6475
  212. X**
  213. X**
  214. X**  This has been sucessfully tested on:
  215. X**    Sun 3 running SunOS 4.0.3
  216. X**    Sun 3 running SunOS 4.0
  217. X**    Sun 3 running SunOS 3.4
  218. X**
  219. X**  This has been unsucessfully tested on:
  220. X**    Sun 4 running SunOS 4.0.3c
  221. X**    Vax running Ultrix
  222. X**    Vax running BSD 4.3
  223. X*/
  224. X
  225. X#ifndef lint
  226. Xchar copyright[] =
  227. X"@(#) Copyright (c) 1989 Seth Robertson seth@ctr.columbia.edu\n     \
  228. XAll rights reserved.\n";
  229. Xstatic char ident[] = "@(#)chkpnt.c 0.5 Beta 89/11/25 SMI";
  230. X#endif
  231. X
  232. X/*
  233. X**      The following note applies only to programs which do not
  234. X**      have AOUT defined.  AOUT tells the computer that it can
  235. X**      look at the filename argv[0] to find symbol tables and the
  236. X**      like. (Thus argv must be defined)
  237. X**
  238. X** NOTE:  All programs which use this *MUST* be compiled with static
  239. X**      linking.  This is because any and all symbols are lost when
  240. X**      the program is checkpointed.  For sun, compile with -Bstatic
  241. X*/
  242. X
  243. X#include "chkpnt.h"
  244. X#include <a.out.h>
  245. X#include <errno.h>
  246. X#include <sys/param.h>
  247. X#ifdef BSD43
  248. X#include <sys/fcntl.h>
  249. X#else
  250. X#include <fcntl.h>
  251. X#endif
  252. X#include <sys/dir.h>
  253. X#include <machine/vmparam.h>
  254. X#include <sys/types.h>
  255. X#include <sys/timeb.h>
  256. X#include <setjmp.h>
  257. X#include <signal.h>
  258. X#include <sys/user.h>
  259. X#ifdef SUNOS4
  260. X#include <alloca.h>
  261. X#endif
  262. X
  263. X#ifdef BSD43
  264. Xextern int errno;
  265. X#endif
  266. X
  267. X#ifdef vax
  268. Xextern int etext;
  269. Xstatic u_long ETEXT;
  270. X#endif
  271. X
  272. X#ifdef SUNOS4
  273. Xtypedef void SigType;        /* SunOS 4.0 uses void */
  274. X#else
  275. Xtypdef int SigType;        /* Non 4.0 uses int */
  276. X#endif
  277. X
  278. X#ifdef sun
  279. Xtypedef void *DT;        /* Vaxen apparently don't have *void */
  280. X#else
  281. Xtypedef (char *) DT;
  282. X#endif
  283. X                /* Defines */
  284. Xcaddr_t    brk(), sbrk(), alloca(), calloc(), malloc();
  285. X
  286. Xvoid Dbug();            /* Debug print */
  287. X
  288. X#ifdef AOUT
  289. Xchar *_ProgName = (char *)NULL;    /* argv[0] */
  290. X#endif
  291. X
  292. Xint _ChkPnt = 0;        /* Global (and thus static) checkpoint
  293. X                 * variable.  This is needed to find
  294. X                 * out if the program was checkpointed
  295. X                 * so a restore can be run
  296. X                 */
  297. X
  298. Xint DebugLevel = DEF_DEB_LEV;    /* Setup debugging */
  299. X
  300. X                /* This creates a signal stack that
  301. X                 * the restore will need to use in
  302. X                 * order to work
  303. X                 */
  304. Xstatic char SignalStack[STACKSIZE];
  305. Xstatic caddr_t PSstack;        /* Pointer to saved stack */
  306. Xstatic u_int StackSize;        /* Stack size */
  307. Xstatic jmp_buf svdloc;        /* Non-local goto save */
  308. X
  309. X
  310. X/*
  311. X** Checkpoint
  312. X**
  313. X** Routine that checkpoints the current process at the current point
  314. X** to the files SAVE_NAME and SAVE_STACK_NAME
  315. X*/
  316. Xint
  317. XCheckpoint()
  318. X
  319. X{
  320. X                /* Pointer to the current process's exec
  321. X                 * structure
  322. X                 */
  323. X#ifdef sun
  324. X  struct exec *UsrExec = (struct exec *) USRTEXT;
  325. X#else /* sun */
  326. X# ifdef vax
  327. X  /* NOTHING */
  328. X# else /* vax */
  329. X  THIS IS AN ERROR!!!!  LEAVE ME ALONE
  330. X# endif /* vax */
  331. X#endif /* sun */
  332. X
  333. X
  334. X  struct exec SvdExec;        /* Exec structure that the new checkpointed
  335. X                 * program will have
  336. X                 */
  337. X
  338. X  register int fd;        /* File descripter of output file */
  339. X
  340. X  static caddr_t Btext;        /* Bottom of text */
  341. X  static caddr_t Theap;        /* Top of heap */
  342. X  static caddr_t Tstack;    /* Top (low end) of stack */
  343. X
  344. X  u_long ChkRst = 0xfeedface;    /* Check for correctness */
  345. X
  346. X#ifdef AOUT
  347. X  int aout;            /* argv[0] file */
  348. X#endif
  349. X
  350. X#ifdef TIMEINFO
  351. X  struct timeb first, second;    /* Starting and ending times */
  352. X  int diffs, diffm;        /* Sec and millisec of diff */
  353. X#endif
  354. X
  355. X#ifdef vax
  356. X  ETEXT = PageBrk(&etext);
  357. X#endif vax
  358. X
  359. X#ifdef TIMEINFO
  360. X  ftime(&first);        /* Set starting time */
  361. X#endif
  362. X
  363. X  Theap = sbrk(0);        /* Save top of heap */
  364. X  Tstack = alloca(0);        /* Save top of stack */
  365. X
  366. X  Dbug(DEBUG,"Restore address is 0x%x\n",(DT)&ChkRst,(DT)0,(DT)0,(DT)0);
  367. X
  368. X  if (setjmp(svdloc))
  369. X    {
  370. X      Dbug(DEBUG,"TOS = 0x%x : OTOS = 0x%x\n",(DT)alloca(0),Tstack);
  371. X
  372. X      Dbug(DEBUG,"Restore address is 0x%x\n",(DT)&ChkRst,(DT)0,(DT)0,(DT)0);
  373. X
  374. X      if (ChkRst != 0xfeedface)
  375. X    {
  376. X      Dbug(FATAL,"Restore constant 0x%x is not correct!!!\n",
  377. X           (DT)ChkRst,(DT)0,(DT)0,(DT)0);
  378. X      exit(RET_FAIL);
  379. X    }
  380. X
  381. X      (void)brk(Theap);        /* Set the data segment back (it was at a
  382. X                 * page break, which wastes space
  383. X                 */
  384. X
  385. X      return(RET_RESTORE);    /* Return (unneeded) info that I am restored
  386. X                 * version */
  387. X    }
  388. X
  389. X                /* Compute the stack size */
  390. X  StackSize = (u_int)((u_long)(USRSTACK) - (u_long)(Tstack));
  391. X
  392. X  Dbug(DEBUG,"Stack is %d bytes long, starting from 0x%x\n",
  393. X       (DT)StackSize,(DT)Tstack,(DT)0,(DT)0);
  394. X
  395. X  if ((PSstack = malloc(StackSize)) == NULL)
  396. X    {
  397. X      perror("Chkpnt");
  398. X      Dbug(SERIOUS,"Cannot save stack in memory!!!\n",(DT)0,(DT)0,(DT)0,(DT)0);
  399. X      return(RET_FAIL);
  400. X    }
  401. X
  402. X                /* Copy the stack to the newly created
  403. X                 * memory locations
  404. X                 */
  405. X  bcopy(Tstack,PSstack,(int)StackSize);
  406. X
  407. X  Dbug(DEBUG,"Stack saved in memory to 0x%x\n",(DT)PSstack,(DT)0,(DT)0,(DT)0);
  408. X
  409. X
  410. X  if ((fd = open(SAVE_NAME,O_WRONLY|O_CREAT,SAVE_MODE)) < 0 )
  411. X    {
  412. X      Dbug(SERIOUS,"Cannot open checkpoint text/heap save file %s\n",
  413. X       (DT)SAVE_NAME,(DT)0,(DT)0,(DT)0);
  414. X      return(RET_FAIL);
  415. X    }
  416. X
  417. X  Dbug(DEBUG,"Text/heap save file opened sucessfully\n",
  418. X       (DT)0,(DT)0,(DT)0,(DT)0);
  419. X
  420. X#ifdef AOUT            /* Lets open the argv[0] file */
  421. X  if ((aout = open(_ProgName,O_RDONLY)) < 0 )
  422. X    {
  423. X      Dbug(SERIOUS,"Cannot open argv[0] (%s) for special info.\n",
  424. X       (DT)_ProgName,(DT)0,(DT)0,(DT)0);
  425. X      return(RET_FAIL);
  426. X    }
  427. X
  428. X  Dbug(DEBUG,"argv[0] opened sucessfully\n",
  429. X       (DT)0,(DT)0,(DT)0,(DT)0);
  430. X#endif /* AOUT */
  431. X
  432. X
  433. X  /*
  434. X  ** Create the checkpointed program's exec header
  435. X  **
  436. X  ** Most of the entries are the same, with the exeception of
  437. X  ** the data segment size and the symbol table.
  438. X  **
  439. X  ** The data segment size gets modified to reflect that the
  440. X  ** data segment holds everything that was malloced or created
  441. X  ** during the execution of the program so far as well as anything
  442. X  ** that was there before.
  443. X  **
  444. X  ** The symbol table is set to zero to reflect that it is no longer present
  445. X  */
  446. X
  447. X#ifdef vax
  448. X#ifdef AOUT
  449. X                /* The exec header isn't in memory.  Since
  450. X                 * we will be using argv[0] anyway, we
  451. X                 * might as well use the info.
  452. X                 */
  453. X  if (read(aout, &SvdExec,(size_t)sizeof(struct exec)) != sizeof(struct exec))
  454. X    {
  455. X      Dbug(SERIOUS,"Cannot read exec header\n");
  456. X      return(RET_FAIL);
  457. X    }
  458. X
  459. X  SvdExec.a_magic = ZMAGIC;
  460. X/*  SvdExec.a_text stays the same */
  461. X  SvdExec.a_data = PageBrk(sbrk((int)0)) - (u_long)(ETEXT);
  462. X/*   SvdExec.a_bss stays the same */
  463. X/*  SvdExec.a_syms stays the same */
  464. X/*   SvdExec.a_ent stays the same */
  465. X  SvdExec.a_trsize = 0;
  466. X  SvdExec.a_drsize = 0;
  467. X#else /* AOUT */
  468. X
  469. X                /* Well, the exec header is not apparently
  470. X                 * in memory, so I have to guess.  The only
  471. X                 * real problem is the a_bss, but I am not
  472. X                 * happy about a_text and a_entry
  473. X                 */
  474. X  SvdExec.a_magic = ZMAGIC;
  475. X  SvdExec.a_text = (u_long)ETEXT;
  476. X  SvdExec.a_data = PageBrk(sbrk((int)0)) - (u_long)(ETEXT);
  477. X  SvdExec.a_bss = 0;
  478. X  SvdExec.a_syms = 0;
  479. X  SvdExec.a_entry = USRTEXT;
  480. X  SvdExec.a_trsize = 0;
  481. X  SvdExec.a_drsize = 0;
  482. X#endif /* AOUT */
  483. X#else /* vax */
  484. X#ifdef sun
  485. X#ifdef SUNOS4
  486. X  SvdExec.a_dynamic = UsrExec->a_dynamic;
  487. X  SvdExec.a_toolversion = UsrExec->a_toolversion;
  488. X#endif
  489. X  SvdExec.a_machtype = UsrExec->a_machtype;
  490. X  SvdExec.a_magic = UsrExec->a_magic;
  491. X  SvdExec.a_text = UsrExec->a_text;
  492. X  SvdExec.a_data = PageBrk(sbrk((int)0)) - (N_DATADDR((*UsrExec)));
  493. X  SvdExec.a_bss = UsrExec->a_bss;
  494. X#ifdef AOUT
  495. X  SvdExec.a_syms = UsrExec->a_syms;
  496. X#else
  497. X  SvdExec.a_syms = 0;
  498. X#endif
  499. X  SvdExec.a_entry = UsrExec->a_entry;
  500. X  SvdExec.a_trsize = 0;
  501. X  SvdExec.a_drsize = 0;
  502. X#else
  503. X  THIS IS AN IMPORTANT ERROR!!!
  504. X#endif
  505. X#endif
  506. X                /* Write the new exec header to the
  507. X                 * checkpoint file
  508. X                 */
  509. X
  510. X  if (write(fd, (char *)(&SvdExec), sizeof(SvdExec)) < 0)
  511. X    {
  512. X      Dbug(SERIOUS,"Cannot write exec structure to disk\n",
  513. X       (DT)0,(DT)0,(DT)0,(DT)0);
  514. X      (void)close(fd);
  515. X      return(RET_FAIL);
  516. X    }
  517. X
  518. X  Dbug(DEBUG,"Wrote exec structure successfully\n",(DT)0,(DT)0,(DT)0,(DT)0);
  519. X
  520. X                /* Find beginning of text segment */
  521. X#ifdef sun
  522. X  Btext = (char *)(N_TXTADDR(*UsrExec) + SHSIZE);
  523. X#else /* sun */
  524. X# ifdef vax
  525. X  Btext = USRTEXT;
  526. X# else /* vax */
  527. X  THIS IS AN ERROR!!!!  LEAVE ME ALONE
  528. X# endif /* vax */
  529. X#endif /* sun */
  530. X
  531. X  Dbug(DEBUG,"Text begins at 0x%x\n",(DT)Btext,(DT)0,(DT)0,(DT)0);
  532. X
  533. X                /* Write text segment to disk */
  534. X#ifdef sun
  535. X  if (write(fd, (char *)(Btext), (int)(SvdExec.a_text - SHSIZE)) < 0 && errno != EFAULT)
  536. X#else /* sun */
  537. X# ifdef vax
  538. X                /* For a vax, there might be a zero filled
  539. X                 * page up front
  540. X                 */
  541. X    lseek(fd,N_TXTOFF(SvdExec),0);
  542. X
  543. X  if (write(fd, (char *)(Btext), SvdExec.a_text) < 0 && errno != EFAULT)
  544. X# else /* vax */
  545. X  THIS IS AN ERROR!!!!  LEAVE ME ALONE
  546. X# endif /* vax */
  547. X#endif /* sun */
  548. X
  549. X    {
  550. X      Dbug(SERIOUS,"Cannot write text segment to disk\n",
  551. X       (DT)0,(DT)0,(DT)0,(DT)0);
  552. X      (void)close(fd);
  553. X      return(RET_FAIL);
  554. X    }
  555. X
  556. X  Dbug(DEBUG,"Wrote text segment successfully\n",(DT)0,(DT)0,(DT)0,(DT)0);
  557. X
  558. X
  559. X  _ChkPnt = 1;            /* When/if program is restored, this
  560. X                 * will make it go through restoral
  561. X                 * process
  562. X                 */
  563. X
  564. X#ifdef sun
  565. X  Dbug(DEBUG,"Data begins at 0x%x\n",
  566. X       (DT)(N_DATADDR((*UsrExec))),(DT)0,(DT)0,(DT)0);
  567. X#else /* sun */
  568. X# ifdef vax
  569. X  Dbug(DEBUG,"Data begins at 0x%x\n",(DT)(ETEXT),(DT)0,(DT)0,(DT)0);
  570. X# else /* vax */
  571. X  THIS IS AN ERROR!!!!  LEAVE ME ALONE
  572. X# endif /* vax */
  573. X#endif /* sun */
  574. X
  575. X                /* Write text segment to disk */
  576. X#ifdef sun
  577. X  if (write(fd, (char *)(N_DATADDR((*UsrExec))), (int)SvdExec.a_data) < 0 && errno != EFAULT)
  578. X#else /* sun */
  579. X# ifdef vax
  580. X  if (write(fd, (char *)(ETEXT), SvdExec.a_data) < 0 && errno != EFAULT)
  581. X# else /* vax */
  582. X  THIS IS AN ERROR!!!!  LEAVE ME ALONE
  583. X# endif /* vax */
  584. X#endif /* sun */
  585. X    {
  586. X      Dbug(SERIOUS,"Cannot write data segment to disk\n",
  587. X       (DT)0,(DT)0,(DT)0,(DT)0);
  588. X      (void)close(fd);
  589. X      return(RET_FAIL);
  590. X    }
  591. X
  592. X  _ChkPnt = 0;            /* Reset */
  593. X
  594. X  Dbug(DEBUG,"Wrote data segment successfully\n",(DT)0,(DT)0,(DT)0,(DT)0);
  595. X
  596. X  /* AFTER THIS POINT, SVD_EXEC CAN NO LONGER BE RELIED UPON */
  597. X
  598. X#ifdef AOUT
  599. X  lseek(aout,0,0);        /* Go to beginning of file (there might
  600. X                 * have been i/o before this point)
  601. X                 */
  602. X
  603. X  if (read(aout, &SvdExec,(size_t)sizeof(struct exec)) != sizeof(struct exec))
  604. X    {
  605. X      Dbug(SERIOUS,"Cannot read exec header\n");
  606. X      return(RET_FAIL);
  607. X    }
  608. X
  609. X                /* Go to beginning of sym_table */
  610. X  if (lseek(aout,N_SYMOFF(SvdExec),0) >= 0)
  611. X    {
  612. X      char *symtbl = malloc((size_t)SvdExec.a_syms);
  613. X
  614. X      if (read(aout, symtbl,(size_t)SvdExec.a_syms) != SvdExec.a_syms)
  615. X    {
  616. X      Dbug(SERIOUS,"Cannot read symbol table\n");
  617. X      return(RET_FAIL);
  618. X    }
  619. X
  620. X      if (write(fd, symtbl, (size_t)SvdExec.a_syms) < 0)
  621. X    {
  622. X      Dbug(SERIOUS,"Cannot write Symbol Table to disk\n",
  623. X           (DT)0,(DT)0,(DT)0,(DT)0);
  624. X      (void)close(fd);
  625. X      return(RET_FAIL);
  626. X    }
  627. X
  628. X      free(symtbl);        /* Free up space wasted by symbol table */
  629. X    }
  630. X  else
  631. X    {
  632. X      Dbug(SERIOUS,"Cannot lseek Symbol Table\n",
  633. X       (DT)0,(DT)0,(DT)0,(DT)0);
  634. X      return(RET_FAIL);
  635. X    }
  636. X
  637. X  Dbug(DEBUG,"Symbol Table transfered to save file\n",
  638. X       (DT)0,(DT)0,(DT)0,(DT)0);
  639. X
  640. X                /* Go to beginning of string_table */
  641. X  if (lseek(aout,N_STROFF(SvdExec),0) >= 0)
  642. X    {
  643. X      char *strtbl;
  644. X      u_int strsiz;        /* Size of string table */
  645. X
  646. X      if (read(aout, &strsiz,(size_t)sizeof(int)) != sizeof(int))
  647. X    {
  648. X      Dbug(SERIOUS,"Cannot read string table size\n");
  649. X      return(RET_FAIL);
  650. X    }
  651. X
  652. X                /* Allocate the storage */
  653. X      strtbl = malloc((size_t)strsiz);
  654. X
  655. X                /* Go back to beginning */
  656. X      lseek(aout,N_STROFF(SvdExec),0);
  657. X
  658. X
  659. X      if (read(aout, strtbl,(size_t)strsiz) != strsiz)
  660. X    {
  661. X      Dbug(SERIOUS,"Cannot read string table\n");
  662. X      return(RET_FAIL);
  663. X    }
  664. X
  665. X      if (write(fd, strtbl, (size_t)strsiz) < 0)
  666. X    {
  667. X      Dbug(SERIOUS,"Cannot write String Table to disk\n",
  668. X           (DT)0,(DT)0,(DT)0,(DT)0);
  669. X      (void)close(fd);
  670. X      return(RET_FAIL);
  671. X    }
  672. X
  673. X      free(strtbl);        /* Free up space wasted by symbol table */
  674. X    }
  675. X  else
  676. X    {
  677. X      Dbug(SERIOUS,"Cannot lseek String Table\n",
  678. X       (DT)0,(DT)0,(DT)0,(DT)0);
  679. X      return(RET_FAIL);
  680. X    }
  681. X
  682. X  Dbug(DEBUG,"String Table transfered to save file\n",
  683. X       (DT)0,(DT)0,(DT)0,(DT)0);
  684. X
  685. X  (void)close(aout);        /* Close argv[0] */
  686. X#endif /* AOUT */
  687. X
  688. X  (void)close(fd);        /* Close executable */
  689. X
  690. X  free(PSstack);        /* Free up space wasted by stack */
  691. X
  692. X  Dbug(WARNING,"Checkpoint sucessfully completed\n",(DT)0,(DT)0,(DT)0,(DT)0);
  693. X
  694. X#ifdef TIMEINFO
  695. X  ftime(&second);        /* Set end time */
  696. X
  697. X  diffs = second.time - first.time;
  698. X  diffm = second.millitm - first.millitm;
  699. X
  700. X  if (diffm < 0)
  701. X    {
  702. X      diffm = -diffm;
  703. X      diffs = diffs - 1;
  704. X    }
  705. X
  706. X  (void)fprintf(stderr,"Taking %d.%d of real time\n",diffs,diffm);
  707. X
  708. X#endif
  709. X
  710. X
  711. X  return(RET_SUCCESS);
  712. X}
  713. X
  714. X
  715. X
  716. X/*
  717. X** RestorePoint
  718. X**
  719. X** Procedure to restore the processes at the saved state.
  720. X**
  721. X** It does this by jumping to a signal handler with a private stack
  722. X** this handler routine does the actual restore and then a longjmp
  723. X** to go back to the restored point.
  724. X*/
  725. Xvoid
  726. XRestorePoint()
  727. X{
  728. X  SigType RestSigHndlr();    /* Signal handler */
  729. X
  730. X  struct sigvec SigVec;        /* Signal Vector data */
  731. X  struct sigstack SigStack;    /* Signal Stack data */
  732. X
  733. X  Dbug(DEBUG,"Restore running\n",(DT)0,(DT)0,(DT)0,(DT)0);
  734. X
  735. X                /* Setup info for SigStack */
  736. X  SigStack.ss_sp = &SignalStack[STACKSIZE];
  737. X  SigStack.ss_onstack = 0;
  738. X
  739. X                /* Setup info for SigVec */
  740. X  SigVec.sv_handler = RestSigHndlr;
  741. X  SigVec.sv_mask = 0;
  742. X  SigVec.sv_onstack = 1;
  743. X
  744. X  if (sigvec(SIGUSR2,&SigVec,(struct sigvec *)0) < 0)
  745. X    {
  746. X      Dbug(FATAL,"Could not install Signal Vector Interrupt\n",
  747. X       (DT)0,(DT)0,(DT)0,(DT)0);
  748. X      exit(RET_FAIL);
  749. X    }
  750. X
  751. X  if (sigstack(&SigStack,(struct sigstack *)0) < 0)
  752. X    {
  753. X      Dbug(FATAL,"Could not install Signal Stack\n",
  754. X       (DT)0,(DT)0,(DT)0,(DT)0);
  755. X      exit(RET_FAIL);
  756. X    }
  757. X
  758. X  Dbug(DEBUG,"Restore ready for SIGUSR2\n",(DT)0,(DT)0,(DT)0,(DT)0);
  759. X
  760. X  if (kill(0,SIGUSR2) < 0)
  761. X    {
  762. X      Dbug(FATAL,"SIGUSR2 Kill failed\n",(DT)0,(DT)0,(DT)0,(DT)0);
  763. X      exit(RET_FAIL);
  764. X    }
  765. X
  766. X  sleep(5);            /* Lets wait a sec... */
  767. X
  768. X  Dbug(FATAL,"SIGUSR2 Kill didn't happen!\n",(DT)0,(DT)0,(DT)0,(DT)0);
  769. X  exit(RET_FAIL);
  770. X}
  771. X
  772. X
  773. X/*
  774. X** RestSigHndlr
  775. X**
  776. X** Routine to do the actual physical restoring of the stack and then to
  777. X** do the longjmp
  778. X*/
  779. X
  780. XSigType
  781. XRestSigHndlr()
  782. X
  783. X{
  784. X  signal(SIGUSR2, SIG_IGN);    /* Ignore the signal */
  785. X
  786. X  Dbug(DEBUG,"SIGUSR2 succeeded\n",(DT)0,(DT)0,(DT)0,(DT)0);
  787. X
  788. X  Dbug(WARNING,"Ready to test stack memory access\n",(DT)0,(DT)0,(DT)0,(DT)0);
  789. X
  790. X                /* If this works, then the
  791. X                 * read should work.  This will
  792. X                 * make the kernel set up any
  793. X                 * stuff that is needed, which
  794. X                 * it might not do during a system
  795. X                 * call
  796. X                 */
  797. X  Dbug(DEBUG,"Stack is %d bytes long starting from 0x%x\n",
  798. X       (DT)StackSize,(DT)(USRSTACK-StackSize),(DT)0,(DT)0);
  799. X
  800. X  *(int *) (USRSTACK-StackSize) = 0;
  801. X
  802. X  bcopy(PSstack,(char *)(USRSTACK-StackSize),(int)StackSize);
  803. X
  804. X  Dbug(DEBUG,"Copy of stack succeeded\n",(DT)0,(DT)0,(DT)0,(DT)0);
  805. X
  806. X  Dbug(WARNING,"Ready to longjmp\n",(DT)0,(DT)0,(DT)0,(DT)0);
  807. X
  808. X  /* NOTE!!!  You can return different values!!! */
  809. X
  810. X  longjmp(svdloc,1);        /* Continue Program */
  811. X
  812. X  sleep(5);
  813. X
  814. X  Dbug(FATAL,"What happened to the longjmp???\n",(DT)0,(DT)0,(DT)0,(DT)0);
  815. X  exit(RET_FAIL);
  816. X}
  817. X
  818. X
  819. X/*
  820. X** Debugging procedure
  821. X*/
  822. Xvoid
  823. XDbug(dlevel,string,p1,p2,p3,p4)
  824. X
  825. Xint dlevel;
  826. Xchar *string;
  827. XDT p1, p2, p3, p4;
  828. X
  829. X{
  830. X  if (dlevel <= DebugLevel)
  831. X    {
  832. X/*      if (dlevel <= SERIOUS)
  833. X    perror();*/
  834. X      (void)fprintf(stderr,string,p1,p2,p3,p4);
  835. X    }
  836. X
  837. X  if (dlevel == FATAL)
  838. X    {
  839. X/*      (void)fputs("Bailing Out\n",stderr);*/
  840. X      ;
  841. X    }
  842. X}
  843. END_OF_FILE
  844. if test 16124 -ne `wc -c <'chkpnt.c'`; then
  845.     echo shar: \"'chkpnt.c'\" unpacked with wrong size!
  846. fi
  847. # end of 'chkpnt.c'
  848. fi
  849. if test -f 'chkpnt.h' -a "${1}" != "-c" ; then 
  850.   echo shar: Will not clobber existing file \"'chkpnt.h'\"
  851. else
  852. echo shar: Extracting \"'chkpnt.h'\" \(1495 characters\)
  853. sed "s/^X//" >'chkpnt.h' <<'END_OF_FILE'
  854. X/*
  855. X** All rights are currently reserved.
  856. X** (c) 1989
  857. X*/
  858. X
  859. X/*
  860. X** All programs which have AOUT defined *MUST* have 
  861. X** main(int argc,char **argv)  (argv is needed.  It doesn't matter
  862. X** whether you user **argv or *argv[])
  863. X*/
  864. X
  865. X
  866. X#include <stdio.h>
  867. X
  868. X#define SAVE_NAME "cpnt"
  869. X#define SAVE_STACK_NAME "cpnt.stk"
  870. X#define SAVE_MODE 0755
  871. X#define SAVE_STACK_MODE 0644
  872. X
  873. X#define RET_FAIL -1        /* Failed */
  874. X#define RET_SUCCESS 0        /* Normal exec */
  875. X#define RET_RESTORE 1        /* Program was restore */
  876. X
  877. X#define DEBUG 3            /* Verbose */
  878. X#define WARNING 2        /* Semi-important events */
  879. X#define SERIOUS 1        /* Failure events (but not program exit) */
  880. X#define FATAL 0            /* Panic events (program exit) */
  881. X#define DEF_DEB_LEV 0        /* Default debugging level */
  882. X
  883. X#define STACKSIZE (8*1024)    /* 8 K */
  884. X
  885. X#ifdef sun
  886. X                /* 0x1000 aligned */
  887. X#define PageBrk(address) ((((int)(address) >> 12) + 1) << 12)
  888. X#else /* sun */
  889. X# ifdef vax
  890. X                /* 0x400 aligned */
  891. X#define PageBrk(address) ((((int)(address) >> 10) + 1) << 10)
  892. X# else /* vax */
  893. X  THIS IS AN ERROR!!!!  LEAVE ME ALONE
  894. X# endif /* vax */
  895. X#endif /* sun */
  896. X
  897. X
  898. X#ifdef AOUT
  899. Xextern char *_ProgName;        /* Pointer to argv[0] */
  900. X#define CheckRestore() if (!_ProgName) _ProgName = *argv; if (_ChkPnt != 0) RestorePoint()
  901. X#else
  902. X#define CheckRestore() if (_ChkPnt != 0) RestorePoint()
  903. X#endif
  904. X
  905. Xextern int _ChkPnt;        /* Global checkpoint variable */
  906. Xextern int DebugLevel;        /* Debugging level */
  907. X
  908. Xint Checkpoint();        /* Checkpoint routine */
  909. Xvoid RestorePoint();        /* Restore at point of check */
  910. END_OF_FILE
  911. if test 1495 -ne `wc -c <'chkpnt.h'`; then
  912.     echo shar: \"'chkpnt.h'\" unpacked with wrong size!
  913. fi
  914. # end of 'chkpnt.h'
  915. fi
  916. if test -f 'main.c' -a "${1}" != "-c" ; then 
  917.   echo shar: Will not clobber existing file \"'main.c'\"
  918. else
  919. echo shar: Extracting \"'main.c'\" \(1133 characters\)
  920. sed "s/^X//" >'main.c' <<'END_OF_FILE'
  921. X/*
  922. X** All rights are currently reserved.
  923. X** (c) 1989
  924. X*/
  925. X
  926. X#include <stdio.h>
  927. X#include "chkpnt.h"
  928. X
  929. Xmain(argc,argv)
  930. Xint argc;
  931. Xchar *argv[];
  932. X{
  933. X  int sum = 0;            /* Sum information to be saved */
  934. X  register x;            /* Counter */
  935. X  int testit = 0xfeedface;
  936. X
  937. X  (void)printf("Hello.  This is program %s with %d arguments\n",argv[0],argc);
  938. X
  939. X  if (argc == 2)        /* Set debugging level */
  940. X    DebugLevel = atoi(argv[1]);
  941. X
  942. X  CheckRestore();
  943. X
  944. X  for (x=0;x<10;x++)
  945. X    {
  946. X      register y;
  947. X
  948. X      if ((y = Checkpoint()) < 0)
  949. X    {
  950. X      (void)fprintf(stderr,"Error in checkpoint\n");
  951. X      exit(-1);
  952. X    }
  953. X      if (y>0)
  954. X    {
  955. X      (void)printf("This is program %s with %d arguments\n",argv[0],argc);
  956. X      if (testit != 0xfeedface)
  957. X        {
  958. X          fputs("testit failed on Restore\n",stderr);
  959. X          exit(-1);
  960. X        }
  961. X      else
  962. X        (void)printf("Restored at %d loop %d\n",sum,x);
  963. X    }
  964. X
  965. X                /* Yes, I know sum overflows by some
  966. X                 * gigantic amount, but who cares?
  967. X                 */
  968. X      for(y=0;y<1000000;y++)
  969. X    sum += y;
  970. X    }
  971. X
  972. X  (void)printf("And the sum is %d\n",sum);
  973. X
  974. X  if (sum != 653067456)
  975. X    (void)printf("Which is incorrect\n");
  976. X  else
  977. X    (void)printf("Which is correct\n");
  978. X}
  979. END_OF_FILE
  980. if test 1133 -ne `wc -c <'main.c'`; then
  981.     echo shar: \"'main.c'\" unpacked with wrong size!
  982. fi
  983. # end of 'main.c'
  984. fi
  985. echo shar: End of shell archive.
  986. exit 0
  987.  
  988.