1.0.27.46: Fix build on systems with "src" in the path.
[sbcl/tcr.git] / src / runtime / save.c
blob635bf49873497fcb971b7c43c62190a59e30cd4d
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 #ifndef LISP_FEATURE_WIN32
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #endif
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <signal.h>
20 #include <sys/file.h>
22 #include "sbcl.h"
23 #include "runtime.h"
24 #include "os.h"
25 #include "core.h"
26 #include "globals.h"
27 #include "save.h"
28 #include "dynbind.h"
29 #include "lispregs.h"
30 #include "validate.h"
31 #include "gc-internal.h"
32 #include "thread.h"
34 #include "genesis/static-symbols.h"
35 #include "genesis/symbol.h"
37 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
38 #include "genesis/lutex.h"
39 #endif
41 /* write_runtime_options uses a simple serialization scheme that
42 * consists of one word of magic, one word indicating whether options
43 * are actually saved, and one word per struct field. */
44 static void
45 write_runtime_options(FILE *file, struct runtime_options *options)
47 size_t optarray[RUNTIME_OPTIONS_WORDS];
49 memset(&optarray, 0, sizeof(optarray));
50 optarray[0] = RUNTIME_OPTIONS_MAGIC;
52 if (options != NULL) {
53 /* optarray[1] is a flag indicating that options are present */
54 optarray[1] = 1;
55 optarray[2] = options->dynamic_space_size;
56 optarray[3] = options->thread_control_stack_size;
59 if (RUNTIME_OPTIONS_WORDS !=
60 fwrite(optarray, sizeof(size_t), RUNTIME_OPTIONS_WORDS, file)) {
61 perror("Error writing runtime options to file");
65 static void
66 write_lispobj(lispobj obj, FILE *file)
68 if (1 != fwrite(&obj, sizeof(lispobj), 1, file)) {
69 perror("Error writing to file");
73 static long
74 write_bytes(FILE *file, char *addr, long bytes, os_vm_offset_t file_offset)
76 long count, here, data;
78 bytes = (bytes+os_vm_page_size-1)&~(os_vm_page_size-1);
80 #ifdef LISP_FEATURE_WIN32
81 /* touch every single page in the space to force it to be mapped. */
82 for (count = 0; count < bytes; count += 0x1000) {
83 volatile int temp = addr[count];
85 #endif
87 fflush(file);
88 here = ftell(file);
89 fseek(file, 0, SEEK_END);
90 data = (ftell(file)+os_vm_page_size-1)&~(os_vm_page_size-1);
91 fseek(file, data, SEEK_SET);
93 while (bytes > 0) {
94 count = fwrite(addr, 1, bytes, file);
95 if (count > 0) {
96 bytes -= count;
97 addr += count;
99 else {
100 perror("error writing to save file");
101 bytes = 0;
104 fflush(file);
105 fseek(file, here, SEEK_SET);
106 return ((data - file_offset) / os_vm_page_size) - 1;
109 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
110 /* saving lutexes in the core */
111 static void **lutex_addresses;
112 static long n_lutexes = 0;
113 static long max_lutexes = 0;
115 static long
116 default_scan_action(lispobj *obj)
118 return (sizetab[widetag_of(*obj)])(obj);
121 static long
122 lutex_scan_action(lispobj *obj)
124 /* note the address of the lutex */
125 if(n_lutexes >= max_lutexes) {
126 max_lutexes *= 2;
127 lutex_addresses = realloc(lutex_addresses, max_lutexes * sizeof(void *));
128 gc_assert(lutex_addresses);
131 lutex_addresses[n_lutexes++] = obj;
133 return (*sizetab[widetag_of(*obj)])(obj);
136 typedef long (*scan_table[256])(lispobj *obj);
138 static void
139 scan_objects(lispobj *start, long n_words, scan_table table)
141 lispobj *end = start + n_words;
142 lispobj *object_ptr;
143 long n_words_scanned;
144 for (object_ptr = start;
145 object_ptr < end;
146 object_ptr += n_words_scanned) {
147 lispobj obj = *object_ptr;
149 n_words_scanned = (table[widetag_of(obj)])(object_ptr);
153 static void
154 scan_for_lutexes(lispobj *addr, long n_words)
156 static int initialized = 0;
157 static scan_table lutex_scan_table;
159 if (!initialized) {
160 int i;
162 /* allocate a little space to get started */
163 lutex_addresses = malloc(16*sizeof(void *));
164 gc_assert(lutex_addresses);
165 max_lutexes = 16;
167 /* initialize the mapping table */
168 for(i = 0; i < ((sizeof lutex_scan_table)/(sizeof lutex_scan_table[0])); ++i) {
169 lutex_scan_table[i] = default_scan_action;
172 lutex_scan_table[LUTEX_WIDETAG] = lutex_scan_action;
174 initialized = 1;
177 /* do the scan */
178 scan_objects(addr, n_words, lutex_scan_table);
180 #endif
182 static void
183 output_space(FILE *file, int id, lispobj *addr, lispobj *end, os_vm_offset_t file_offset)
185 size_t words, bytes, data;
186 static char *names[] = {NULL, "dynamic", "static", "read-only"};
188 write_lispobj(id, file);
189 words = end - addr;
190 write_lispobj(words, file);
192 bytes = words * sizeof(lispobj);
194 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
195 printf("scanning space for lutexes...\n");
196 scan_for_lutexes((char *)addr, words);
197 #endif
199 printf("writing %lu bytes from the %s space at 0x%08lx\n",
200 (unsigned long)bytes, names[id], (unsigned long)addr);
202 data = write_bytes(file, (char *)addr, bytes, file_offset);
204 write_lispobj(data, file);
205 write_lispobj((long)addr / os_vm_page_size, file);
206 write_lispobj((bytes + os_vm_page_size - 1) / os_vm_page_size, file);
209 FILE *
210 open_core_for_saving(char *filename)
212 /* Open the output file. We don't actually need the file yet, but
213 * the fopen() might fail for some reason, and we want to detect
214 * that and back out before we do anything irreversible. */
215 unlink(filename);
216 return fopen(filename, "wb");
219 boolean
220 save_to_filehandle(FILE *file, char *filename, lispobj init_function,
221 boolean make_executable,
222 boolean save_runtime_options)
224 struct thread *th;
225 os_vm_offset_t core_start_pos;
227 /* Smash the enclosing state. (Once we do this, there's no good
228 * way to go back, which is a sufficient reason that this ends up
229 * being SAVE-LISP-AND-DIE instead of SAVE-LISP-AND-GO-ON). */
230 printf("[undoing binding stack and other enclosing state... ");
231 fflush(stdout);
232 for_each_thread(th) { /* XXX really? */
233 unbind_to_here((lispobj *)th->binding_stack_start,th);
234 SetSymbolValue(CURRENT_CATCH_BLOCK, 0,th);
235 SetSymbolValue(CURRENT_UNWIND_PROTECT_BLOCK, 0,th);
237 printf("done]\n");
238 fflush(stdout);
240 /* (Now we can actually start copying ourselves into the output file.) */
242 printf("[saving current Lisp image into %s:\n", filename);
243 fflush(stdout);
245 core_start_pos = ftell(file);
246 write_lispobj(CORE_MAGIC, file);
248 write_lispobj(VERSION_CORE_ENTRY_TYPE_CODE, file);
249 write_lispobj(3, file);
250 write_lispobj(SBCL_CORE_VERSION_INTEGER, file);
252 write_lispobj(BUILD_ID_CORE_ENTRY_TYPE_CODE, file);
253 write_lispobj(/* (We're writing the word count of the entry here, and the 2
254 * term is one word for the leading BUILD_ID_CORE_ENTRY_TYPE_CODE
255 * word and one word where we store the count itself.) */
256 2 + strlen((const char *)build_id),
257 file);
259 unsigned char *p;
260 for (p = (unsigned char *)build_id; *p; ++p)
261 write_lispobj(*p, file);
264 write_lispobj(NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE, file);
265 write_lispobj(/* (word count = 3 spaces described by 5 words each, plus the
266 * entry type code, plus this count itself) */
267 (5*3)+2, file);
268 output_space(file,
269 READ_ONLY_CORE_SPACE_ID,
270 (lispobj *)READ_ONLY_SPACE_START,
271 (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER,0),
272 core_start_pos);
273 output_space(file,
274 STATIC_CORE_SPACE_ID,
275 (lispobj *)STATIC_SPACE_START,
276 (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER,0),
277 core_start_pos);
278 #ifdef LISP_FEATURE_GENCGC
279 /* Flush the current_region, updating the tables. */
280 gc_alloc_update_all_page_tables();
281 update_dynamic_space_free_pointer();
282 #endif
283 #ifdef reg_ALLOC
284 #ifdef LISP_FEATURE_GENCGC
285 output_space(file,
286 DYNAMIC_CORE_SPACE_ID,
287 (lispobj *)DYNAMIC_SPACE_START,
288 dynamic_space_free_pointer,
289 core_start_pos);
290 #else
291 output_space(file,
292 DYNAMIC_CORE_SPACE_ID,
293 (lispobj *)current_dynamic_space,
294 dynamic_space_free_pointer,
295 core_start_pos);
296 #endif
297 #else
298 output_space(file,
299 DYNAMIC_CORE_SPACE_ID,
300 (lispobj *)DYNAMIC_SPACE_START,
301 (lispobj *)SymbolValue(ALLOCATION_POINTER,0),
302 core_start_pos);
303 #endif
305 write_lispobj(INITIAL_FUN_CORE_ENTRY_TYPE_CODE, file);
306 write_lispobj(3, file);
307 write_lispobj(init_function, file);
309 #ifdef LISP_FEATURE_GENCGC
311 size_t size = (last_free_page*sizeof(long)+os_vm_page_size-1)
312 &~(os_vm_page_size-1);
313 unsigned long *data = calloc(size, 1);
314 if (data) {
315 long offset;
316 int i;
317 for (i = 0; i < last_free_page; i++) {
318 data[i] = page_table[i].region_start_offset;
320 write_lispobj(PAGE_TABLE_CORE_ENTRY_TYPE_CODE, file);
321 write_lispobj(4, file);
322 write_lispobj(size, file);
323 offset = write_bytes(file, (char *) data, size, core_start_pos);
324 write_lispobj(offset, file);
327 #endif
329 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
330 if(n_lutexes > 0) {
331 long offset;
332 printf("writing %ld lutexes to the core...\n", n_lutexes);
333 write_lispobj(LUTEX_TABLE_CORE_ENTRY_TYPE_CODE, file);
334 /* word count of the entry */
335 write_lispobj(4, file);
336 /* indicate how many lutexes we saved */
337 write_lispobj(n_lutexes, file);
338 /* save the lutexes */
339 offset = write_bytes(file, (char *) lutex_addresses,
340 n_lutexes * sizeof(*lutex_addresses),
341 core_start_pos);
343 write_lispobj(offset, file);
345 #endif
347 write_lispobj(END_CORE_ENTRY_TYPE_CODE, file);
349 /* Write a trailing header, ignored when parsing the core normally.
350 * This is used to locate the start of the core when the runtime is
351 * prepended to it. */
352 fseek(file, 0, SEEK_END);
354 /* If NULL runtime options are passed to write_runtime_options,
355 * command-line processing is performed as normal in the SBCL
356 * executable. Otherwise, the saved runtime options are used and
357 * all command-line arguments are available to Lisp in
358 * SB-EXT:*POSIX-ARGV*. */
359 write_runtime_options(file,
360 (save_runtime_options ? runtime_options : NULL));
362 if (1 != fwrite(&core_start_pos, sizeof(os_vm_offset_t), 1, file)) {
363 perror("Error writing core starting position to file");
364 fclose(file);
365 } else {
366 write_lispobj(CORE_MAGIC, file);
367 fclose(file);
370 #ifndef LISP_FEATURE_WIN32
371 if (make_executable)
372 chmod (filename, 0755);
373 #endif
375 printf("done]\n");
376 exit(0);
379 /* Slurp the executable portion of the runtime into a malloced buffer
380 * and return it. Places the size in bytes of the runtime into
381 * 'size_out'. Returns NULL if the runtime cannot be loaded from
382 * 'runtime_path'. */
383 void *
384 load_runtime(char *runtime_path, size_t *size_out)
386 void *buf = NULL;
387 FILE *input = NULL;
388 size_t size, count;
389 os_vm_offset_t core_offset;
391 core_offset = search_for_embedded_core (runtime_path);
392 if ((input = fopen(runtime_path, "rb")) == NULL) {
393 fprintf(stderr, "Unable to open runtime: %s\n", runtime_path);
394 goto lose;
397 fseek(input, 0, SEEK_END);
398 size = (size_t) ftell(input);
399 fseek(input, 0, SEEK_SET);
401 if (core_offset != -1 && size > core_offset)
402 size = core_offset;
404 buf = successful_malloc(size);
405 if ((count = fread(buf, 1, size, input)) != size) {
406 fprintf(stderr, "Premature EOF while reading runtime.\n");
407 goto lose;
410 fclose(input);
411 *size_out = size;
412 return buf;
414 lose:
415 if (input != NULL)
416 fclose(input);
417 if (buf != NULL)
418 free(buf);
419 return NULL;
422 boolean
423 save_runtime_to_filehandle(FILE *output, void *runtime, size_t runtime_size)
425 size_t padding;
426 void *padbytes;
428 if (runtime_size != fwrite(runtime, 1, runtime_size, output)) {
429 perror("Error saving runtime");
430 return 0;
433 padding = (os_vm_page_size - (runtime_size % os_vm_page_size)) & ~os_vm_page_size;
434 if (padding > 0) {
435 padbytes = successful_malloc(padding);
436 memset(padbytes, 0, padding);
437 if (padding != fwrite(padbytes, 1, padding, output)) {
438 perror("Error saving runtime");
439 free(padbytes);
440 return 0;
442 free(padbytes);
445 return 1;
448 FILE *
449 prepare_to_save(char *filename, boolean prepend_runtime, void **runtime_bytes,
450 size_t *runtime_size)
452 FILE *file;
453 char *runtime_path;
455 if (prepend_runtime) {
456 runtime_path = os_get_runtime_executable_path();
458 if (runtime_path == NULL) {
459 fprintf(stderr, "Unable to get default runtime path.\n");
460 return NULL;
463 *runtime_bytes = load_runtime(runtime_path, runtime_size);
464 free(runtime_path);
466 if (*runtime_bytes == NULL)
467 return 0;
470 file = open_core_for_saving(filename);
471 if (file == NULL) {
472 free(*runtime_bytes);
473 perror(filename);
474 return NULL;
477 return file;
480 boolean
481 save(char *filename, lispobj init_function, boolean prepend_runtime,
482 boolean save_runtime_options)
484 FILE *file;
485 void *runtime_bytes = NULL;
486 size_t runtime_size;
488 file = prepare_to_save(filename, prepend_runtime, &runtime_bytes, &runtime_size);
489 if (file == NULL)
490 return 1;
492 if (prepend_runtime)
493 save_runtime_to_filehandle(file, runtime_bytes, runtime_size);
495 return save_to_filehandle(file, filename, init_function, prepend_runtime,
496 save_runtime_options);