{Begin SubSec Saving Virtual Memory State} {Title Saving Virtual Memory State} {Text {index *PRIMARY* Virtual memory} {index *PRIMARY* Virtual memory file} Interlisp storage allocation occurs within a virtual memory space that is usually much larger than the physical memory on the computer. The virtual memory is stored as a large file on the computer's hard disk, called the virtual memory file. Interlisp controls the swapping of pages between this file and the real memory, swapping in virtual memory pages as they are accessed, and swapping out pages that have been modified. At any moment, the total state of the Interlisp virtual memory is stored partially in the virtual memory file, and partially in the real physical memory. Interlisp provides facilities for saving the total state of the virtual memory, either on the virtual memory file, or in a file on an arbitrary file device. The function {fn LOGOUT} is used to write all altered (dirty) pages from the real memory to the virtual memory file and stop Interlisp, so that Interlisp can be restarted from the state of the {fn LOGOUT}. {fn SAVEVM} updates the virtual memory file without stopping Interlisp, which puts the virtual memory file into a consistant state (temporarily), so it could be restarted if the system crashes. {fn SYSOUT} and {fn MAKESYS} are used to save a copy of the total virtual memory state on a file, which can be loaded into another machine to restore the Interlisp state. {fn VMEM.PURE.STATE} can be used to "freeze" the current state of the virtual memory, so that Interlisp will come up in that state if it is restarted. {FnDef {Name LOGOUT} {Args FAST} {Text Stops Interlisp, and returns control to the operating system. If Interlisp is restarted, it should come up in the same state as when the {fn LOGOUT} was called. {fn LOGOUT} will not affect the state of open files. {fn LOGOUT} writes out all altered pages from real memory to the virtual memory file. If {arg FAST} is {lisp T}, Interlisp is stopped without updating the virtual memory file. Note that after doing {lisp LOGOUT T)} it will not be possible to restart Interlisp from the point of the {fn LOGOUT}, and it may not be possible to restart it at all. Typing {lisp (LOGOUT T)} is preferable to just booting the machine, because it also does other cleanup operations (closing network connections, etc.). If {arg FAST} is the litatom {lisp ?}, {fn LOGOUT} acts like {arg FLG}={lisp T} if the virtual memory file is consistant, otherwise it acts like {arg FLG}={lisp NIL}. This insures that the virtual memory image can be restarted as of {it some} previous state, not necessarily as of the {fn LOGOUT}. {note BEFORELOGOUTFORMS and AFTERLOGOUTFORMS evaluated before/after logout in Interlisp-D only! foo!} {note document how logout waits for processes with BEFOREEXIT of DON'T} }} {FnDef {Name SAVEVM} {Args {anonarg}} {Text This function is similar to logging out and continuing, but faster. It takes about as long as a logout, which can be as brief as 10 seconds or so if you have already written out most of your dirty pages by virtue of being idle a while. After the {fn SAVEVM}, and until the pagefault handler is next forced to write out a dirty page, your virtual memory image will be continuable (as of the {fn SAVEVM}) should there be a system crash or other disaster. {note the arg RELEASEFLG is only of interest to system people} {note RELEASEFLG actually 'flushes' pages not in use, for diagnostics --lmm} }} If the system has been idle long enough (no keyboard or mouse activity), there are dirty pages to be written, and there are few enough dirty pages left to write that a {fn SAVEVM} would be quick, {fn SAVEVM} is automatically called. When {fn SAVEVM} is called automatically, the cursor is changed to a special {index SAV/ING cursor}cursor:  dʠ.@@ N R P \, stored in the variable {index *PRIMARY* SAVINGCURSOR Var}{var SAVINGCURSOR}. You can control how often {fn SAVEVM} is automatically called by setting the following two global variables: {VarDef {Name SAVEVMWAIT}} {VarDef {Name SAVEVMMAX} {Text The system will call {fn SAVEVM} after being idle for {var SAVEVMWAIT} seconds (initially 300) if there are fewer than {var SAVEVMMAX} pages dirty (initially 600). These values are fairly conservative. If you want to be extremely wary, you can set {var SAVEVMWAIT}=0 and {var SAVEVMMAX}=10000, in which case {fn SAVEVM} will be called the first chance available after the first dirty page has been written. }} The function {fn SYSOUT} saves the current state of the Interlisp virtual memory on a file, known as a "sysout file",{index *PRIMARY* Sysout files} or simply a "sysout". The file package can be used to save particular function definitions and other arbitrary objects on files, but {fn SYSOUT} saves the {it total} state of the system. This capability can be useful in many situations: for creating customized systems for other people to use, or to save a particular system state for debugging purposes. Note that a sysout file can be very large (thousands of pages), and can take a long time to create, so it is not to be done lightly. The file produced by {fn SYSOUT} can be loaded into the Interlisp virtual memory and restarted to restore the virtual memory to the exact state that it had when the sysout file was made. The exact method of loading a sysout depend on the implementation. For more information on loading sysout files, see the users guide for your computer. {FnDef {Name SYSOUT} {Args FILE} {Text Saves the current state of the Interlisp virtual memory on the file {arg FILE}, in a form that can be subsequently restarted. The current state of program execution is saved in the sysout file, so {lisp (PROGN (SYSOUT 'FOO) (PRINT 'HELLO))} will cause {lisp HELLO} to be printed after the sysout file is restarted. {fn SYSOUT} can take a very long time (ten or fifteen minutes), particularly when storing a file on a remote file server. To display some indication that something is happening, the cursor is changed to:{index SYS/OUT cursor} ta$b2\JHJHJHJH1. Also, as the sysout file is being written, the cursor is inverted line by line, to show that activity is taking place, and how much of the sysout has completed. For example, after the {fn SYSOUT} is about two-thirds done, the cursor would look like: `}\m؝͠HJHJHJH1. The {fn SYSOUT} cursor is stored in the variable {index *PRIMARY* SYSOUTCURSOR Var}{var SYSOUTCURSOR}. If {arg FILE} is non-{lisp NIL}, the variable {var SYSOUTFILE}{index SYSOUTFILE Var} is set to the body of {arg FILE}. If {arg FILE} is {lisp NIL}, then the value of {var SYSOUTFILE} instead. Therefore, {lisp (SYSOUT)} will save the current state on the next higher version of a file with the same name as the previous {fn SYSOUT}. Also, if the extension for {arg FILE} is not specified, the value of {var SYSOUT.EXT}{index SYSOUT.EXT Var} is used. {fn SYSOUT} sets {var SYSOUTDATE}{index SYSOUTDATE Var} ({PageRef Var SYSOUTDATE}) to {lisp (DATE)}, the time and date that the {fn SYSOUT} was performed. If {fn SYSOUT} was not able to create the sysout file, because of disk or computer error, or because there was not enough space on the directory, {fn SYSOUT} returns {lisp NIL}. Otherwise it returns the full file name of {arg FILE}. Actually, {fn SYSOUT} "returns" twice; when the sysout file is first created, and when it is subsequently restarted. In the latter case, {fn SYSOUT} returns a list whose {fn CAR} is the full file name of {arg FILE}. For example, {lisp (if (LISTP (SYSOUT 'FOO)) then (PRINT 'HELLO))} will cause {lisp HELLO} to be printed when the sysout file is restarted, but not when {fn SYSOUT} is initially performed. Note: {fn SYSOUT} does not save the state of any open files. {fn WHENCLOSE} ({PageRef Fn WHENCLOSE}) can be used to associate certain operations with open files so that when a {lisp SYSOUT} is started up, these files will be reopened, and file pointers repositioned. }} {fn SYSOUT} evaluates the expressions on {var BEFORESYSOUTFORMS}{index BEFORESYSOUTFORMS Var} before creating the sysout file. This variable initially includes expressions to: (1) Set the variables {var SYSOUTDATE} and {var SYSOUTFILE} as described above; (2) Default the sysout file name {arg FILE} according to the values of the variables {var SYSOUTFILE} and {var SYSOUT.EXT}, as described above; and (3) Perform any necessary operations on open files as specified by calls to {fn WHENCLOSE} ({PageRef Fn WHENCLOSE}). After a sysout file is restarted (but {it not} when it is initially created), {fn SYSOUT} evaluates the expressions on {index AFTERSYSOUTFORMS Var}{var AFTERSYSOUTFORMS}. This initially includes expressions to: (1) Perform any necessary operations on previously-opened files as specified by calls to {fn WHENCLOSE} ({PageRef Fn WHENCLOSE}); (2) Possibly print a message, as determined by the value of {var SYSOUTGAG} (see below); and (3) Call {fn SETINITIALS} to reset the initials used for time-stamping ({PageRef Tag TimeStamps}). {VarDef {Name SYSOUTGAG} {Text The value of {var SYSOUTGAG} determines what is printed when a sysout file is restarted. If the value of {var SYSOUTGAG} is a list, the list is evaluated, and no additional message is printed. This allows the user to print a message. If {var SYSOUTGAG} is non-{lisp NIL} and not a list, no message is printed. Finally, if {var SYSOUTGAG} is {lisp NIL} (its initial value), and the sysout file is being restarted by the same user that made the sysout originally, the user is greeted by printing the value of {var HERALDSTRING} (see below) followed by a greeting message. If the sysout file was made by a different user, a message is printed, warning that the currently-loaded user init file may be incorrect for the current user (see {PageRef Tag Greeting}); }} {FnDef {FnName MAKESYS} {FnArgs FILE NAME} {Text Used to store a new Interlisp system on the "makesys file" {arg FILE}. Similar to {fn SYSOUT}, except that before the file is made, the system is "initialized" by undoing the greet history, and clearing the display. When the system is first started up, a "herald" is printed identifying the system, typically "{lisp Interlisp-{arg XX} {arg DATE} ...}". If {arg NAME} is non-{lisp NIL}, {fn MAKESYS} will use it instead of {lisp Interlisp-{arg XX}} in the herald. {fn MAKESYS} sets {var HERALDSTRING}{index HERALDSTRING Var} to the herald string printed out. {fn MAKESYS} also sets the variable {index MAKESYSDATE Var}{var MAKESYSDATE} ({PageRef Var MAKESYSDATE}) to {lisp (DATE)}, i.e. the time and date the system was made. }} {note MAKESYS evals forms on BEFOREMAKESYSFORMS, which undo greet history, set MAKESYSDATE, and call HAROLD} Interlisp-D contains a routine that writes out dirty pages of the virtual memory during I/O wait, assuming that swapping has caused at least one dirty page to be written back into the virtual memory file (making it non-continuable). The frequency with which this routine runs is determined by: {VarDef {Name BACKGROUNDPAGEFREQ} {Text This variable determines how often the routine that writes out dirty pages is run. The {it higher} {lisp BACKGROUNDPAGEFREQ} is set, the {it greater} the time between running the dirty page writing routine. Initially it is set to 4. The lower {lisp BACKGROUNDPAGEFREQ} is set, the less responsiveness you get at typein, so it may not be desirable to set it all the way down to 1. }} {FnDef {Name VMEM.PURE.STATE} {Args X} {Type Nospread} {Text {fn VMEM.PURE.STATE} modifies the swapper's page replacement algorithm so that dirty pages are only written at the end of the virtual memory backing file. This "freezes" a given virtual memory state, so that Interlisp will come up in that state whenever it is restarted. This can be used to set up a "clean" environment on a pool machine, allowing each user to initialize the system simply by rebooting the computer. The way to use {fn VMEM.PURE.STATE} is to set up the environment as you wish it to be "frozen," evaluate {lisp (VMEM.PURE.STATE T)}, and then call any function that saves the virtual memory state ({fn LOGOUT}, {fn SAVEVM}, {fn SYSOUT}, or {fn MAKESYS}). From that point on, whenever the system is restarted, it will return to the state as of the saving operation. Future {fn LOGOUT}, {fn SAVEVM}, etc. operations will not reset this state. Note: When the system is running in "pure state" mode, it uses a significant amount of the virtual memory backing file to save the "frozen" memory image, so this will reduce the amount of virtual memory space available for use. {lisp (VMEM.PURE.STATE)} returns {lisp T} if the system is running in "pure state" mode, {lisp NIL} otherwise. }} {FnDef {Name REALMEMORYSIZE} {Args} {Text Returns the number of real memory pages in the computer. }} {FnDef {Name VMEMSIZE} {Args} {Text Returns the number of pages in use in the virtual memory. This is the roughly the same as the number of pages required to make a sysout file on the local disk (see {fn SYSOUT}, {PageRef Fn SYSOUT}). }} {indexX {Name LASTVMEMFILEPAGE} {Type Variable} {Text {lisp \LASTVMEMFILEPAGE}} } {VarDef {Name \LASTVMEMFILEPAGE} {Text Value is the total size of the virtual memory backing file. This variable is set when the system is started. It should not be set by the user. }} Note: When the virtual memory expands to the point where the virtual memory backing file is almost full, a break will occur with the warning message {index Your virtual memory backing file is almost full... Error}"Your virtual memory backing file is almost full. Save your work & reload asap." When this happens, it is strongly suggested that you save any important work and reload the system. If you continue working past this point, the system will start slowing down considerably, and it will eventually stop working. }{End SubSec Saving Virtual Memory State} ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8))  $ BMOBJ.GETFN2& BMOBJ.GETFN2& BMOBJ.GETFN26z