0.8.14.5: Join the foreign legion!
[sbcl.git] / src / code / save.lisp
index 76b7b95..b38cbca 100644 (file)
@@ -17,9 +17,9 @@
 \f
 ;;;; SAVE-LISP-AND-DIE itself
 
-(sb!alien:define-alien-routine "save" (sb!alien:boolean)
-  (file sb!alien:c-string)
-  (initial-fun (sb!alien:unsigned #.sb!vm:n-word-bits)))
+(define-alien-routine "save" (boolean)
+  (file c-string)
+  (initial-fun (unsigned #.sb!vm:n-word-bits)))
 
 ;;; FIXME: When this is run without the PURIFY option,
 ;;; it seems to save memory all the way up to the high-water mark,
                                         (environment-name "auxiliary"))
   #!+sb-doc
   "Save a \"core image\", i.e. enough information to restart a Lisp
-  process later in the same state, in the file of the specified name.
+process later in the same state, in the file of the specified name.
 
-  This implementation is not as polished and painless as you might like: 
-    * It corrupts the current Lisp image enough that the current process
-      needs to be killed afterwards.
-    * It will not work if multiple threads are in use.
-    * There is absolutely no binary compatibility of core images between
-      different runtime support programs. Even runtimes built from the same
-      sources at different times are treated as incompatible for this purpose.
-  This isn't because we like it this way, but just because there don't
-  seem to be good quick fixes for either limitation and no one has been
-  sufficiently motivated to do lengthy fixes.
+This implementation is not as polished and painless as you might
+like:
+  * It corrupts the current Lisp image enough that the current process
+    needs to be killed afterwards. This can be worked around by forking
+    another process that saves the core.
+  * It will not work if multiple threads are in use.
+  * There is absolutely no binary compatibility of core images between
+    different runtime support programs. Even runtimes built from the same
+    sources at different times are treated as incompatible for this
+    purpose.
+This isn't because we like it this way, but just because there don't
+seem to be good quick fixes for either limitation and no one has been
+sufficiently motivated to do lengthy fixes.
 
-  The following &KEY arguments are defined:
-    :TOPLEVEL
-       The function to run when the created core file is resumed.
-       The default function handles command line toplevel option
-       processing and runs the top level read-eval-print loop. This
-       function should not return.
-    :PURIFY
-       If true (the default), do a purifying GC which moves all dynamically
-       allocated objects into static space so that they stay pure. This takes
-       somewhat longer than the normal GC which is otherwise done, but it's
-       only done once, and subsequent GC's will be done less often and will
-       take less time in the resulting core file. See the PURIFY function.
-    :ROOT-STRUCTURES
-       This should be a list of the main entry points in any newly loaded
-       systems. This need not be supplied, but locality and/or GC performance
-       may be better if they are. Meaningless if :PURIFY is NIL. See the
-       PURIFY function.
-    :ENVIRONMENT-NAME
-       This is also passed to the PURIFY function when :PURIFY is T.
-       (rarely used)
+The following &KEY arguments are defined:
+  :TOPLEVEL
+     The function to run when the created core file is resumed. The
+     default function handles command line toplevel option processing
+     and runs the top level read-eval-print loop. This function should
+     not return.
+  :PURIFY
+     If true (the default), do a purifying GC which moves all
+     dynamically allocated objects into static space. This takes
+     somewhat longer than the normal GC which is otherwise done, but
+     it's only done once, and subsequent GC's will be done less often
+     and will take less time in the resulting core file. See the PURIFY
+     function.
+  :ROOT-STRUCTURES
+     This should be a list of the main entry points in any newly loaded
+     systems. This need not be supplied, but locality and/or GC performance
+     may be better if they are. Meaningless if :PURIFY is NIL. See the
+     PURIFY function.
+  :ENVIRONMENT-NAME
+     This is also passed to the PURIFY function when :PURIFY is T.
+     (rarely used)
 
-  The save/load process changes the values of some global variables:
-    *STANDARD-OUTPUT*, *DEBUG-IO*, etc.
-      Everything related to open streams is necessarily changed, since
-      the OS won't let us preserve a stream across save and load.
-    *DEFAULT-PATHNAME-DEFAULTS*
-      This is reinitialized to reflect the working directory where the
-      saved core is loaded."
-
-  (when (fboundp 'cancel-finalization)
-    (cancel-finalization sb!sys:*tty*))
+The save/load process changes the values of some global variables:
+  *STANDARD-OUTPUT*, *DEBUG-IO*, etc.
+    Everything related to open streams is necessarily changed, since
+    the OS won't let us preserve a stream across save and load.
+  *DEFAULT-PATHNAME-DEFAULTS*
+    This is reinitialized to reflect the working directory where the
+    saved core is loaded."
+  (deinit)
   ;; FIXME: Would it be possible to unmix the PURIFY logic from this
   ;; function, and just do a GC :FULL T here? (Then if the user wanted
   ;; a PURIFYed image, he'd just run PURIFY immediately before calling
   (if purify
       (purify :root-structures root-structures
              :environment-name environment-name)
-      #!-gencgc (gc) #!+gencgc (gc :full t))
-  ;; FIXME: Wouldn't it be more correct to go through this list backwards
-  ;; instead of forwards?
-  (dolist (f *before-save-initializations*)
-    (funcall f))
+      #-gencgc (gc) #+gencgc (gc :full t))
   (flet ((restart-lisp ()
            (handling-end-of-the-world
-            (reinit)
-            (dolist (f *after-save-initializations*)
-              (funcall f))
-            (funcall toplevel))))
+           (reinit)
+           (funcall toplevel))))
     ;; FIXME: Perhaps WITHOUT-GCING should be wrapped around the
     ;; LET as well, to avoid the off chance of an interrupt triggering
     ;; GC and making our saved RESTART-LISP address invalid?
     (without-gcing
-      (save (unix-namestring core-file-name nil)
-           (get-lisp-obj-address #'restart-lisp)))))
+     (save (unix-namestring core-file-name nil)
+          (get-lisp-obj-address #'restart-lisp)))))
+
+(defun deinit ()
+  (mapc #'funcall *save-hooks*)
+  (when (fboundp 'cancel-finalization)    
+    (cancel-finalization sb!sys:*tty*))
+  (profile-deinit)
+  (debug-deinit)
+  (foreign-deinit))