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_lispobj(lispobj obj, FILE *file)
36 fwrite(&obj, sizeof(lispobj), 1, file);
40 write_bytes(FILE *file, char *addr, long bytes)
42 long count, here, data;
44 bytes = (bytes+os_vm_page_size-1)&~(os_vm_page_size-1);
46 #ifdef LISP_FEATURE_WIN32
47 /* touch every single page in the space to force it to be mapped. */
48 for (count = 0; count < bytes; count += 0x1000) {
49 volatile int temp = addr[count];
56 data = (ftell(file)+os_vm_page_size-1)&~(os_vm_page_size-1);
60 count = fwrite(addr, 1, bytes, file);
66 perror("error writing to save file");
72 return data/os_vm_page_size - 1;
76 output_space(FILE *file, int id, lispobj *addr, lispobj *end)
78 int words, bytes, data;
79 static char *names[] = {NULL, "dynamic", "static", "read-only"};
81 write_lispobj(id, file);
83 write_lispobj(words, file);
85 bytes = words * sizeof(lispobj);
87 printf("writing %d bytes from the %s space at 0x%08lx\n",
88 bytes, names[id], (unsigned long)addr);
90 data = write_bytes(file, (char *)addr, bytes);
92 write_lispobj(data, file);
93 write_lispobj((long)addr / os_vm_page_size, file);
94 write_lispobj((bytes + os_vm_page_size - 1) / os_vm_page_size, file);
98 open_core_for_saving(char *filename)
100 /* Open the output file. We don't actually need the file yet, but
101 * the fopen() might fail for some reason, and we want to detect
102 * that and back out before we do anything irreversible. */
104 return fopen(filename, "wb");
108 save_to_filehandle(FILE *file, char *filename, lispobj init_function)
112 /* Smash the enclosing state. (Once we do this, there's no good
113 * way to go back, which is a sufficient reason that this ends up
114 * being SAVE-LISP-AND-DIE instead of SAVE-LISP-AND-GO-ON). */
115 printf("[undoing binding stack and other enclosing state... ");
117 for_each_thread(th) { /* XXX really? */
118 unbind_to_here((lispobj *)th->binding_stack_start,th);
119 SetSymbolValue(CURRENT_CATCH_BLOCK, 0,th);
120 SetSymbolValue(CURRENT_UNWIND_PROTECT_BLOCK, 0,th);
125 /* (Now we can actually start copying ourselves into the output file.) */
127 printf("[saving current Lisp image into %s:\n", filename);
130 write_lispobj(CORE_MAGIC, file);
132 write_lispobj(VERSION_CORE_ENTRY_TYPE_CODE, file);
133 write_lispobj(3, file);
134 write_lispobj(SBCL_CORE_VERSION_INTEGER, file);
136 write_lispobj(BUILD_ID_CORE_ENTRY_TYPE_CODE, file);
137 write_lispobj(/* (We're writing the word count of the entry here, and the 2
138 * term is one word for the leading BUILD_ID_CORE_ENTRY_TYPE_CODE
139 * word and one word where we store the count itself.) */
140 2 + strlen((const char *)build_id),
144 for (p = build_id; *p; ++p)
145 write_lispobj(*p, file);
148 write_lispobj(NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE, file);
149 write_lispobj(/* (word count = 3 spaces described by 5 words each, plus the
150 * entry type code, plus this count itself) */
153 READ_ONLY_CORE_SPACE_ID,
154 (lispobj *)READ_ONLY_SPACE_START,
155 (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER,0));
157 STATIC_CORE_SPACE_ID,
158 (lispobj *)STATIC_SPACE_START,
159 (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER,0));
162 DYNAMIC_CORE_SPACE_ID,
163 (lispobj *)current_dynamic_space,
164 dynamic_space_free_pointer);
166 #ifdef LISP_FEATURE_GENCGC
167 /* Flush the current_region, updating the tables. */
168 gc_alloc_update_all_page_tables();
169 update_dynamic_space_free_pointer();
172 DYNAMIC_CORE_SPACE_ID,
173 (lispobj *)DYNAMIC_SPACE_START,
174 (lispobj *)SymbolValue(ALLOCATION_POINTER,0));
177 write_lispobj(INITIAL_FUN_CORE_ENTRY_TYPE_CODE, file);
178 write_lispobj(3, file);
179 write_lispobj(init_function, file);
181 #ifdef LISP_FEATURE_GENCGC
183 size_t size = (last_free_page*sizeof(long)+os_vm_page_size-1)
184 &~(os_vm_page_size-1);
185 long *data = calloc(size, 1);
189 for (i = 0; i < last_free_page; i++) {
190 data[i] = page_table[i].first_object_offset;
192 write_lispobj(PAGE_TABLE_CORE_ENTRY_TYPE_CODE, file);
193 write_lispobj(4, file);
194 write_lispobj(size, file);
195 offset = write_bytes(file, (char *) data, size);
196 write_lispobj(offset, file);
201 write_lispobj(END_CORE_ENTRY_TYPE_CODE, file);
210 save(char *filename, lispobj init_function)
212 FILE *file = open_core_for_saving(filename);
219 return save_to_filehandle(file, filename, init_function);