/[cmucl]/src/lisp/save.c
ViewVC logotype

Contents of /src/lisp/save.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.29 - (show annotations)
Fri Sep 24 04:08:39 2010 UTC (3 years, 6 months ago) by rtoy
Branch: MAIN
CVS Tags: GIT-CONVERSION, cross-sol-x86-merged, cross-sol-x86-base, snapshot-2010-12, snapshot-2010-11, snapshot-2011-09, snapshot-2011-06, snapshot-2011-07, snapshot-2011-04, snapshot-2011-02, snapshot-2011-03, snapshot-2011-01, cross-sol-x86-2010-12-20, cross-sparc-branch-base, HEAD
Branch point for: cross-sparc-branch, cross-sol-x86-branch
Changes since 1.28: +2 -2 lines
File MIME type: text/plain
Include libgen.h on Darwin/x86 to get rid of a compiler warning about
dirname being undefined.
1 /*
2
3 $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/save.c,v 1.29 2010/09/24 04:08:39 rtoy Rel $
4
5 This code was written as part of the CMU Common Lisp project at
6 Carnegie Mellon University, and has been placed in the public domain.
7
8 */
9
10
11 #include <stdio.h>
12 #include <signal.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "lisp.h"
17 #include "os.h"
18 #include "internals.h"
19 #include "core.h"
20 #include "globals.h"
21 #include "save.h"
22 #include "lispregs.h"
23 #include "validate.h"
24 #include "dynbind.h"
25
26 #ifdef GENCGC
27 #include "gencgc.h"
28 #endif
29
30 #ifdef FEATURE_EXECUTABLE
31 #include "elf.h"
32 #if !(defined(DARWIN) && defined(__ppc__))
33 #include <libgen.h>
34 #endif
35 #endif
36
37 extern int version;
38
39 static long
40 write_bytes(FILE * file, char *addr, long bytes)
41 {
42 long count, here, data;
43
44 bytes = (bytes + CORE_PAGESIZE - 1) & ~(CORE_PAGESIZE - 1);
45
46 fflush(file);
47 here = ftell(file);
48 fseek(file, 0, 2);
49 data = (ftell(file) + CORE_PAGESIZE - 1) & ~(CORE_PAGESIZE - 1);
50 fseek(file, data, 0);
51
52 while (bytes > 0) {
53 count = fwrite(addr, 1, bytes, file);
54 if (count > 0) {
55 bytes -= count;
56 addr += count;
57 } else {
58 perror("Error writing to save file");
59 bytes = 0;
60 }
61 }
62 fflush(file);
63 fseek(file, here, 0);
64 return data / CORE_PAGESIZE - 1;
65 }
66
67 static void
68 output_space(FILE * file, int id, lispobj * addr, lispobj * end)
69 {
70 int words, bytes, data;
71 static char *names[] = { NULL, "Dynamic", "Static", "Read-Only" };
72
73 putw(id, file);
74 words = end - addr;
75 putw(words, file);
76
77 bytes = words * sizeof(lispobj);
78
79 printf("Writing %d bytes from the %s space at 0x%08lX.\n",
80 bytes, names[id], (unsigned long) addr);
81
82 data = write_bytes(file, (char *) addr, bytes);
83
84 putw(data, file);
85 putw((long) addr / CORE_PAGESIZE, file);
86 putw((bytes + CORE_PAGESIZE - 1) / CORE_PAGESIZE, file);
87 }
88
89 #ifdef DEBUG_BAD_HEAP
90 static void
91 dump_region(struct alloc_region *alloc_region)
92 {
93 fprintf(stderr, "free_pointer = %p\n", alloc_region->free_pointer);
94 fprintf(stderr, "end_addr = %p\n", alloc_region->end_addr);
95 fprintf(stderr, "first_page = %d\n", alloc_region->first_page);
96 fprintf(stderr, "last_page = %d\n", alloc_region->last_page);
97 fprintf(stderr, "start_addr = %p\n", alloc_region->start_addr);
98
99 fprintf(stderr, " page_table[%d]\n", alloc_region->first_page);
100 fprintf(stderr, " flags = %x\n", page_table[alloc_region->first_page].flags);
101 fprintf(stderr, " offset = %x\n", page_table[alloc_region->first_page].first_object_offset);
102 fprintf(stderr, " used = %x\n", page_table[alloc_region->first_page].bytes_used);
103 }
104 #endif
105
106 boolean
107 save(char *filename, lispobj init_function, int sse2_mode)
108 {
109 FILE *file;
110
111 #if defined WANT_CGC
112 volatile lispobj *func_ptr = &init_function;
113 char sbuf[128];
114
115 strcpy(sbuf, filename);
116 filename = sbuf;
117 /* Get rid of remnant stuff. This is a MUST so that
118 * the memory manager can get started correctly when
119 * we restart after this save. Purify is going to
120 * maybe move the args so we need to consider them volatile,
121 * especially if the gcc optimizer is working!!
122 */
123 purify(NIL, NIL);
124
125 init_function = *func_ptr;
126 /* Set dynamic space pointer to base value so we don't write out
127 * MBs of just cleared heap.
128 */
129 if (SymbolValue(X86_CGC_ACTIVE_P) != NIL)
130 SetSymbolValue(ALLOCATION_POINTER, DYNAMIC_0_SPACE_START);
131 #endif
132 /* Open the file: */
133 remove(filename);
134 file = fopen(filename, "w");
135 if (file == NULL) {
136 perror(filename);
137 return TRUE;
138 }
139 printf("[Undoing binding stack... ");
140 fflush(stdout);
141 unbind_to_here((lispobj *) BINDING_STACK_START);
142 SetSymbolValue(CURRENT_CATCH_BLOCK, 0);
143 SetSymbolValue(CURRENT_UNWIND_PROTECT_BLOCK, 0);
144 SetSymbolValue(EVAL_STACK_TOP, 0);
145 printf("done]\n");
146 #if defined WANT_CGC && defined X86_CGC_ACTIVE_P
147 SetSymbolValue(X86_CGC_ACTIVE_P, T);
148 #endif
149 printf("[Saving current lisp image into %s:\n", filename);
150
151 putw(CORE_MAGIC, file);
152
153 putw(CORE_VERSION, file);
154 #if defined(i386) && defined(FEATURE_SSE2)
155 putw(4, file);
156 #else
157 putw(3, file);
158 #endif
159 putw(version, file);
160
161 #if defined(i386) && defined(FEATURE_SSE2)
162 if (sse2_mode) {
163 putw(SSE2, file);
164 } else {
165 putw(X87, file);
166 }
167 #endif
168
169 putw(CORE_NDIRECTORY, file);
170 putw((5 * 3) + 2, file);
171
172 output_space(file, READ_ONLY_SPACE_ID, read_only_space,
173 (lispobj *) SymbolValue(READ_ONLY_SPACE_FREE_POINTER));
174 output_space(file, STATIC_SPACE_ID, static_space,
175 (lispobj *) SymbolValue(STATIC_SPACE_FREE_POINTER));
176 #ifdef GENCGC
177 /* Flush the current_region updating the tables. */
178 #ifdef DEBUG_BAD_HEAP
179 fprintf(stderr, "before ALLOC_POINTER = %p\n", (lispobj *) SymbolValue(ALLOCATION_POINTER));
180 dump_region(&boxed_region);
181 #endif
182 gc_alloc_update_page_tables(0, &boxed_region);
183 gc_alloc_update_page_tables(1, &unboxed_region);
184 #ifdef DEBUG_BAD_HEAP
185 fprintf(stderr, "boxed_region after update\n");
186 dump_region(&boxed_region);
187
188 print_ptr((lispobj*) 0x2805a184);
189 #endif
190
191 #ifdef DEBUG_BAD_HEAP
192 /*
193 * For some reason x86 has a heap corruption problem. I (rtoy)
194 * have not been able to figure out how that occurs, but what is
195 * happening is that when a core is loaded, there is some static
196 * object pointing to an object that is on a free page. In normal
197 * usage, at startup there should be 4 objects in static space
198 * pointing to a free page, because these are newly allocated
199 * objects created by the C runtime. However, there is an
200 * additional object.
201 *
202 * I do not know what this object should be or how it got there,
203 * but it will often cause CMUCL to fail to save a new core file.
204 *
205 * Disabling this call to update_dynamic_space_free_pointer is a
206 * work around. What is happening is that u_d_s_f_p is resetting
207 * ALLOCATION_POINTER, but that weird object is in the current
208 * region, but after resetting the pointer, that object isn't
209 * saved to the core file. By not resetting the pointer, the
210 * object (or at least enough of it) gets saved in the core file
211 * that we don't have problems when reloading.
212 *
213 * Note that on sparc and ppc, u_d_s_f_p doesn't actually do
214 * anything because the call to reset ALLOCATION_POINTER is a nop
215 * on sparc and ppc. And sparc and ppc dont' have the heap
216 * corruption issue. That's not conclusive evidence, though.
217 *
218 * This needs more work and investigation.
219 */
220 update_dynamic_space_free_pointer();
221 #endif
222
223 #ifdef DEBUG_BAD_HEAP
224 fprintf(stderr, "after ALLOC_POINTER = %p\n", (lispobj *) SymbolValue(ALLOCATION_POINTER));
225 #endif
226 #endif
227
228 #ifdef reg_ALLOC
229 output_space(file, DYNAMIC_SPACE_ID, current_dynamic_space,
230 current_dynamic_space_free_pointer);
231 #else
232 output_space(file, DYNAMIC_SPACE_ID, current_dynamic_space,
233 (lispobj *) SymbolValue(ALLOCATION_POINTER));
234 #endif
235
236 putw(CORE_INITIAL_FUNCTION, file);
237 putw(3, file);
238 putw(init_function, file);
239
240 putw(CORE_END, file);
241 fclose(file);
242
243 printf("done.]\n");
244
245 exit(0);
246 }
247
248
249 #ifdef FEATURE_EXECUTABLE
250 boolean
251 save_executable(char *filename, lispobj init_function)
252 {
253 char *dir_name;
254
255 #if defined WANT_CGC
256 volatile lispobj *func_ptr = &init_function;
257 char sbuf[128];
258
259 strcpy(sbuf, filename);
260 filename = sbuf;
261 /* Get rid of remnant stuff. This is a MUST so that
262 * the memory manager can get started correctly when
263 * we restart after this save. Purify is going to
264 * maybe move the args so we need to consider them volatile,
265 * especially if the gcc optimizer is working!!
266 */
267 purify(NIL, NIL);
268
269 init_function = *func_ptr;
270 /* Set dynamic space pointer to base value so we don't write out
271 * MBs of just cleared heap.
272 */
273 if(SymbolValue(X86_CGC_ACTIVE_P) != NIL)
274 SetSymbolValue(ALLOCATION_POINTER, DYNAMIC_0_SPACE_START);
275 #endif
276 dir_name = dirname(strdup(filename));
277
278 printf("[Undoing binding stack... ");
279 fflush(stdout);
280 unbind_to_here((lispobj *)BINDING_STACK_START);
281 SetSymbolValue(CURRENT_CATCH_BLOCK, 0);
282 SetSymbolValue(CURRENT_UNWIND_PROTECT_BLOCK, 0);
283 SetSymbolValue(EVAL_STACK_TOP, 0);
284 printf("done]\n");
285 #if defined WANT_CGC && defined X86_CGC_ACTIVE_P
286 SetSymbolValue(X86_CGC_ACTIVE_P, T);
287 #endif
288 printf("[Saving current lisp image as executable into \"%s\":\n", filename);
289
290 printf("\t[Writing core objects\n");
291 fflush(stdout);
292 write_space_object(dir_name, READ_ONLY_SPACE_ID, (os_vm_address_t)read_only_space,
293 (os_vm_address_t)SymbolValue(READ_ONLY_SPACE_FREE_POINTER));
294 write_space_object(dir_name, STATIC_SPACE_ID, (os_vm_address_t)static_space,
295 (os_vm_address_t)SymbolValue(STATIC_SPACE_FREE_POINTER));
296 #ifdef GENCGC
297 /* Flush the current_region updating the tables. */
298 #ifdef DEBUG_BAD_HEAP
299 fprintf(stderr, "before ALLOC_POINTER = %p\n", (lispobj *) SymbolValue(ALLOCATION_POINTER));
300 dump_region(&boxed_region);
301 #endif
302 gc_alloc_update_page_tables(0,&boxed_region);
303 gc_alloc_update_page_tables(1,&unboxed_region);
304 #ifdef DEBUG_BAD_HEAP
305 fprintf(stderr, "boxed_region after update\n");
306 dump_region(&boxed_region);
307
308 print_ptr((lispobj*) 0x2805a184);
309 #endif
310 #ifdef DEBUG_BAD_HEAP
311 /*
312 * For some reason x86 has a heap corruption problem. I (rtoy)
313 * have not been able to figure out how that occurs, but what is
314 * happening is that when a core is loaded, there is some static
315 * object pointing to an object that is on a free page. In normal
316 * usage, at startup there should be 4 objects in static space
317 * pointing to a free page, because these are newly allocated
318 * objects created by the C runtime. However, there is an
319 * additional object.
320 *
321 * I do not know what this object should be or how it got there,
322 * but it will often cause CMUCL to fail to save a new core file.
323 *
324 * Disabling this call to update_dynamic_space_free_pointer is a
325 * work around. What is happening is that u_d_s_f_p is resetting
326 * ALLOCATION_POINTER, but that weird object is in the current
327 * region, but after resetting the pointer, that object isn't
328 * saved to the core file. By not resetting the pointer, the
329 * object (or at least enough of it) gets saved in the core file
330 * that we don't have problems when reloading.
331 *
332 * Note that on sparc and ppc, u_d_s_f_p doesn't actually do
333 * anything because the call to reset ALLOCATION_POINTER is a nop
334 * on sparc and ppc. And sparc and ppc dont' have the heap
335 * corruption issue. That's not conclusive evidence, though.
336 *
337 * This needs more work and investigation.
338 */
339 update_dynamic_space_free_pointer();
340 #endif
341
342 #ifdef DEBUG_BAD_HEAP
343 fprintf(stderr, "after ALLOC_POINTER = %p\n", (lispobj *) SymbolValue(ALLOCATION_POINTER));
344 #endif
345 #endif
346
347 #ifdef reg_ALLOC
348 write_space_object(dir_name, DYNAMIC_SPACE_ID, (os_vm_address_t)current_dynamic_space,
349 (os_vm_address_t)current_dynamic_space_free_pointer);
350 #else
351 write_space_object(dir_name, DYNAMIC_SPACE_ID, (os_vm_address_t)current_dynamic_space,
352 (os_vm_address_t)SymbolValue(ALLOCATION_POINTER));
353 #endif
354
355 printf("\tdone]\n");
356 fflush(stdout);
357
358 printf("Linking executable...\n");
359 fflush(stdout);
360 obj_run_linker(init_function, filename);
361 printf("done.\n");
362 exit(0);
363 }
364 #endif

  ViewVC Help
Powered by ViewVC 1.1.5