+/* Things to do before doing a final GC before saving a core (without
+ * purify).
+ *
+ * + Pages in large_object pages aren't moved by the GC, so we need to
+ * unset that flag from all pages.
+ * + The pseudo-static generation isn't normally collected, but it seems
+ * reasonable to collect it at least when saving a core. So move the
+ * pages to a normal generation.
+ */
+static void
+prepare_for_final_gc ()
+{
+ page_index_t i;
+ for (i = 0; i < last_free_page; i++) {
+ page_table[i].large_object = 0;
+ if (page_table[i].gen == PSEUDO_STATIC_GENERATION) {
+ int used = page_table[i].bytes_used;
+ page_table[i].gen = HIGHEST_NORMAL_GENERATION;
+ generations[PSEUDO_STATIC_GENERATION].bytes_allocated -= used;
+ generations[HIGHEST_NORMAL_GENERATION].bytes_allocated += used;
+ }
+ }
+}
+
+
+/* Do a non-conservative GC, and then save a core with the initial
+ * function being set to the value of the static symbol
+ * SB!VM:RESTART-LISP-FUNCTION */
+void
+gc_and_save(char *filename)
+{
+ FILE *file = open_core_for_saving(filename);
+ if (!file) {
+ perror(filename);
+ return;
+ }
+ conservative_stack = 0;
+
+ /* The filename might come from Lisp, and be moved by the now
+ * non-conservative GC. */
+ filename = strdup(filename);
+
+ /* Collect twice: once into relatively high memory, and then back
+ * into low memory. This compacts the retained data into the lower
+ * pages, minimizing the size of the core file.
+ */
+ prepare_for_final_gc();
+ gencgc_alloc_start_page = last_free_page;
+ collect_garbage(HIGHEST_NORMAL_GENERATION+1);
+
+ prepare_for_final_gc();
+ gencgc_alloc_start_page = -1;
+ collect_garbage(HIGHEST_NORMAL_GENERATION+1);
+
+ save_to_filehandle(file, filename, SymbolValue(RESTART_LISP_FUNCTION,0));
+ /* Oops. Save still managed to fail. Since we've mangled the stack
+ * beyond hope, there's not much we can do.
+ * (beyond FUNCALLing RESTART_LISP_FUNCTION, but I suspect that's
+ * going to be rather unsatisfactory too... */
+ lose("Attempt to save core after non-conservative GC failed.");
+}