0.6.12.7.flaky1:
[sbcl.git] / src / runtime / save.c
1 /*
2  * This software is part of the SBCL system. See the README file for
3  * more information.
4  *
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.
10  */
11
12 #include <stdio.h>
13 #include <signal.h>
14 #include <sys/file.h>
15
16 #include "runtime.h"
17 #include "os.h"
18 #include "sbcl.h"
19 #include "core.h"
20 #include "globals.h"
21 #include "save.h"
22 #include "dynbind.h"
23 #include "lispregs.h"
24 #include "validate.h"
25
26 #ifdef GENCGC
27 #include "gencgc.h"
28 #endif
29
30 static long
31 write_bytes(FILE *file, char *addr, long bytes)
32 {
33     long count, here, data;
34
35     bytes = (bytes+os_vm_page_size-1)&~(os_vm_page_size-1);
36
37     fflush(file);
38     here = ftell(file);
39     fseek(file, 0, 2);
40     data = (ftell(file)+os_vm_page_size-1)&~(os_vm_page_size-1);
41     fseek(file, data, 0);
42
43     while (bytes > 0) {
44         count = fwrite(addr, 1, bytes, file);
45         if (count > 0) {
46             bytes -= count;
47             addr += count;
48         }
49         else {
50             perror("error writing to save file");
51             bytes = 0;
52         }
53     }
54     fflush(file);
55     fseek(file, here, 0);
56     return data/os_vm_page_size - 1;
57 }
58
59 static void
60 output_space(FILE *file, int id, lispobj *addr, lispobj *end)
61 {
62     int words, bytes, data;
63     static char *names[] = {NULL, "dynamic", "static", "read-only"};
64
65     putw(id, file);
66     words = end - addr;
67     putw(words, file);
68
69     bytes = words * sizeof(lispobj);
70
71     printf("writing %ld(0x%lx) bytes from the %s(%d) space at 0x%08lx\n",
72            (long)bytes, (long)bytes, names[id], id, (unsigned long)addr);
73
74     data = write_bytes(file, (char *)addr, bytes);
75
76     putw(data, file);
77     putw((long)addr / os_vm_page_size, file);
78     putw((bytes + os_vm_page_size - 1) / os_vm_page_size, file);
79 }
80
81 boolean
82 save(char *filename, lispobj init_function)
83 {
84     FILE *file;
85 #if defined WANT_CGC
86     volatile lispobj*func_ptr = &init_function;
87     char sbuf[128];
88     strcpy(sbuf,filename);
89     filename=sbuf;
90     /* Get rid of remnant stuff. This is a MUST so that the memory
91      * manager can get started correctly when we restart after this
92      * save. Purify is going to maybe move the args so we need to
93      * consider them volatile, especially if the gcc optimizer is
94      * working!! */
95     purify(NIL,NIL);
96
97     init_function = *func_ptr;
98     /* Set dynamic space pointer to base value so we don't write out
99      * MBs of just cleared heap. */
100     if(SymbolValue(X86_CGC_ACTIVE_P) != NIL) {
101         SetSymbolValue(ALLOCATION_POINTER, DYNAMIC_SPACE_START);
102     }
103 #endif
104     /* Open the file: */
105     unlink(filename);
106     file = fopen(filename, "w");
107     if (file == NULL) {
108         perror(filename);
109         return 1;
110     }
111     printf("[undoing binding stack... ");
112     fflush(stdout);
113     unbind_to_here((lispobj *)BINDING_STACK_START);
114     SetSymbolValue(CURRENT_CATCH_BLOCK, 0);
115     SetSymbolValue(CURRENT_UNWIND_PROTECT_BLOCK, 0);
116     SetSymbolValue(EVAL_STACK_TOP, 0);
117     printf("done]\n");
118 #if defined WANT_CGC && defined X86_CGC_ACTIVE_P
119     SetSymbolValue(X86_CGC_ACTIVE_P, T);
120 #endif
121     printf("[saving current Lisp image into %s:\n", filename);
122
123     putw(CORE_MAGIC, file);
124
125     putw(CORE_VERSION, file);
126     putw(3, file);
127     putw(SBCL_CORE_VERSION_INTEGER, file);
128
129     putw(CORE_NDIRECTORY, file);
130     putw((5*3)+2, file); /* 3 5-word space descriptors, plus code and count */
131
132     output_space(file, READ_ONLY_SPACE_ID, (lispobj *)READ_ONLY_SPACE_START,
133                  (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER));
134     output_space(file, STATIC_SPACE_ID, (lispobj *)STATIC_SPACE_START,
135                  (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER));
136 #ifdef reg_ALLOC
137     output_space(file, DYNAMIC_SPACE_ID, (lispobj *)current_dynamic_space,
138                  dynamic_space_free_pointer);
139 #else
140 #ifdef GENCGC
141     /* Flush the current_region updating the tables. */
142     gc_alloc_update_page_tables(0,&boxed_region);
143     gc_alloc_update_page_tables(1,&unboxed_region);
144     update_x86_dynamic_space_free_pointer();
145 #endif
146     output_space(file, DYNAMIC_SPACE_ID, (lispobj *)DYNAMIC_SPACE_START,
147                  (lispobj *)SymbolValue(ALLOCATION_POINTER));
148 #endif
149
150     FSHOW((stderr, "/writing init_function=0x%lx\n", (long)init_function));
151     FSHOW((stderr, "/(SymbolValue(ALLOCATION_POINTER)=0x%lx\n",
152            (long)SymbolValue(ALLOCATION_POINTER)));
153     putw(CORE_INITIAL_FUNCTION, file);
154     putw(3, file);
155     putw(init_function, file);
156
157     putw(CORE_END, file);
158     fclose(file);
159
160     printf("done]\n");
161
162     exit(0);
163 }