2 * This software is part of the SBCL system. See the README file for
5 * This software is derived from the CMU CL system, which was
6 * written at Carnegie Mellon University and released into the
7 * public domain. The software is in the public domain and is
8 * provided with absolutely no warranty. See the COPYING and CREDITS
9 * files for more information.
27 #include "gc-internal.h"
30 #include "genesis/static-symbols.h"
31 #include "genesis/symbol.h"
34 write_bytes(FILE *file, char *addr, long bytes)
36 long count, here, data;
38 bytes = (bytes+os_vm_page_size-1)&~(os_vm_page_size-1);
43 data = (ftell(file)+os_vm_page_size-1)&~(os_vm_page_size-1);
47 count = fwrite(addr, 1, bytes, file);
53 perror("error writing to save file");
59 return data/os_vm_page_size - 1;
63 output_space(FILE *file, int id, lispobj *addr, lispobj *end)
65 int words, bytes, data;
66 static char *names[] = {NULL, "dynamic", "static", "read-only"};
72 bytes = words * sizeof(lispobj);
74 printf("writing %d bytes from the %s space at 0x%08lx\n",
75 bytes, names[id], (unsigned long)addr);
77 data = write_bytes(file, (char *)addr, bytes);
80 putw((long)addr / os_vm_page_size, file);
81 putw((bytes + os_vm_page_size - 1) / os_vm_page_size, file);
85 save(char *filename, lispobj init_function)
90 /* Open the output file. We don't actually need the file yet, but
91 * the fopen() might fail for some reason, and we want to detect
92 * that and back out before we do anything irreversible. */
94 file = fopen(filename, "w");
100 /* Smash the enclosing state. (Once we do this, there's no good
101 * way to go back, which is a sufficient reason that this ends up
102 * being SAVE-LISP-AND-DIE instead of SAVE-LISP-AND-GO-ON). */
103 printf("[undoing binding stack and other enclosing state... ");
105 for_each_thread(th) { /* XXX really? */
106 unbind_to_here((lispobj *)th->binding_stack_start,th);
107 SetSymbolValue(CURRENT_CATCH_BLOCK, 0,th);
108 SetSymbolValue(CURRENT_UNWIND_PROTECT_BLOCK, 0,th);
113 /* (Now we can actually start copying ourselves into the output file.) */
115 printf("[saving current Lisp image into %s:\n", filename);
118 putw(CORE_MAGIC, file);
120 putw(VERSION_CORE_ENTRY_TYPE_CODE, file);
122 putw(SBCL_CORE_VERSION_INTEGER, file);
124 putw(BUILD_ID_CORE_ENTRY_TYPE_CODE, file);
125 putw(/* (We're writing the word count of the entry here, and the 2
126 * term is one word for the leading BUILD_ID_CORE_ENTRY_TYPE_CODE
127 * word and one word where we store the count itself.) */
128 2 + strlen(build_id),
132 for (p = build_id; *p; ++p)
136 putw(NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE, file);
137 putw(/* (word count = 3 spaces described by 5 words each, plus the
138 * entry type code, plus this count itself) */
141 READ_ONLY_CORE_SPACE_ID,
142 (lispobj *)READ_ONLY_SPACE_START,
143 (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER,0));
145 STATIC_CORE_SPACE_ID,
146 (lispobj *)STATIC_SPACE_START,
147 (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER,0));
150 DYNAMIC_CORE_SPACE_ID,
151 (lispobj *)current_dynamic_space,
152 dynamic_space_free_pointer);
154 #ifdef LISP_FEATURE_GENCGC
155 /* Flush the current_region, updating the tables. */
156 gc_alloc_update_all_page_tables();
157 update_x86_dynamic_space_free_pointer();
160 DYNAMIC_CORE_SPACE_ID,
161 (lispobj *)DYNAMIC_SPACE_START,
162 (lispobj *)SymbolValue(ALLOCATION_POINTER,0));
165 putw(INITIAL_FUN_CORE_ENTRY_TYPE_CODE, file);
167 putw(init_function, file);
169 putw(END_CORE_ENTRY_TYPE_CODE, file);