0.7.13.5
[sbcl/lichteblau.git] / src / runtime / save.c
blob716001fd69850038f0ac0d5f061b99b2fa81f68a
1 /*
2 * This software is part of the SBCL system. See the README file for
3 * more information.
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.
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <signal.h>
15 #include <sys/file.h>
17 #include "runtime.h"
18 #include "os.h"
19 #include "sbcl.h"
20 #include "core.h"
21 #include "globals.h"
22 #include "save.h"
23 #include "dynbind.h"
24 #include "lispregs.h"
25 #include "validate.h"
26 #include "gc-internal.h"
28 #include "genesis/static-symbols.h"
29 #include "genesis/symbol.h"
31 static long
32 write_bytes(FILE *file, char *addr, long bytes)
34 long count, here, data;
36 bytes = (bytes+os_vm_page_size-1)&~(os_vm_page_size-1);
38 fflush(file);
39 here = ftell(file);
40 fseek(file, 0, 2);
41 data = (ftell(file)+os_vm_page_size-1)&~(os_vm_page_size-1);
42 fseek(file, data, 0);
44 while (bytes > 0) {
45 count = fwrite(addr, 1, bytes, file);
46 if (count > 0) {
47 bytes -= count;
48 addr += count;
50 else {
51 perror("error writing to save file");
52 bytes = 0;
55 fflush(file);
56 fseek(file, here, 0);
57 return data/os_vm_page_size - 1;
60 static void
61 output_space(FILE *file, int id, lispobj *addr, lispobj *end)
63 int words, bytes, data;
64 static char *names[] = {NULL, "dynamic", "static", "read-only"};
66 putw(id, file);
67 words = end - addr;
68 putw(words, file);
70 bytes = words * sizeof(lispobj);
72 printf("writing %d bytes from the %s space at 0x%08lx\n",
73 bytes, names[id], (unsigned long)addr);
75 data = write_bytes(file, (char *)addr, bytes);
77 putw(data, file);
78 putw((long)addr / os_vm_page_size, file);
79 putw((bytes + os_vm_page_size - 1) / os_vm_page_size, file);
82 boolean
83 save(char *filename, lispobj init_function)
85 FILE *file;
87 /* Open the output file. We don't actually need the file yet, but
88 * the fopen() might fail for some reason, and we want to detect
89 * that and back out before we do anything irreversible. */
90 unlink(filename);
91 file = fopen(filename, "w");
92 if (!file) {
93 perror(filename);
94 return 1;
97 /* Smash the enclosing state. (Once we do this, there's no good
98 * way to go back, which is a sufficient reason that this ends up
99 * being SAVE-LISP-AND-DIE instead of SAVE-LISP-AND-GO-ON). */
100 printf("[undoing binding stack and other enclosing state... ");
101 fflush(stdout);
102 unbind_to_here((lispobj *)BINDING_STACK_START);
103 SetSymbolValue(CURRENT_CATCH_BLOCK, 0);
104 SetSymbolValue(CURRENT_UNWIND_PROTECT_BLOCK, 0);
105 printf("done]\n");
106 fflush(stdout);
108 /* (Now we can actually start copying ourselves into the output file.) */
110 printf("[saving current Lisp image into %s:\n", filename);
111 fflush(stdout);
113 putw(CORE_MAGIC, file);
115 putw(VERSION_CORE_ENTRY_TYPE_CODE, file);
116 putw(3, file);
117 putw(SBCL_CORE_VERSION_INTEGER, file);
119 putw(BUILD_ID_CORE_ENTRY_TYPE_CODE, file);
120 putw(/* (We're writing the word count of the entry here, and the 2
121 * term is one word for the leading BUILD_ID_CORE_ENTRY_TYPE_CODE
122 * word and one word where we store the count itself.) */
123 2 + strlen(build_id),
124 file);
126 char *p;
127 for (p = build_id; *p; ++p)
128 putw(*p, file);
131 putw(NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE, file);
132 putw(/* (word count = 3 spaces described by 5 words each, plus the
133 * entry type code, plus this count itself) */
134 (5*3)+2, file);
135 output_space(file,
136 READ_ONLY_CORE_SPACE_ID,
137 (lispobj *)READ_ONLY_SPACE_START,
138 (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER));
139 output_space(file,
140 STATIC_CORE_SPACE_ID,
141 (lispobj *)STATIC_SPACE_START,
142 (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER));
143 #ifdef reg_ALLOC
144 output_space(file,
145 DYNAMIC_CORE_SPACE_ID,
146 (lispobj *)current_dynamic_space,
147 dynamic_space_free_pointer);
148 #else
149 #ifdef LISP_FEATURE_GENCGC
150 /* Flush the current_region, updating the tables. */
151 gc_alloc_update_all_page_tables();
152 update_x86_dynamic_space_free_pointer();
153 #endif
154 output_space(file,
155 DYNAMIC_CORE_SPACE_ID,
156 (lispobj *)DYNAMIC_SPACE_START,
157 (lispobj *)SymbolValue(ALLOCATION_POINTER));
158 #endif
160 putw(INITIAL_FUN_CORE_ENTRY_TYPE_CODE, file);
161 putw(3, file);
162 putw(init_function, file);
164 putw(END_CORE_ENTRY_TYPE_CODE, file);
166 fclose(file);
167 printf("done]\n");
169 exit(0);