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