Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#include <stdio.h>
#include <signal.h>
#include <sys/file.h>
#include "lisp.h"
#include "os.h"
#include "internals.h"
#include "core.h"
#include "globals.h"
#include "lispregs.h"
#include "interrupt.h"
#include "save.h"
#include "validate.h"
extern int version;
extern void restore_state(char *stack_ptr, int result);
extern int save_state(int fn(char *stack_ptr, FILE *file), FILE *file);
static long write_bytes(FILE *file, char *addr, long bytes)
{
long count, here, data;
fflush(file);
here = ftell(file);
fseek(file, 0, 2);
data = (ftell(file)+CORE_PAGESIZE-1)&~(CORE_PAGESIZE-1);
fseek(file, data, 0);
while (bytes > 0) {
count = fwrite(addr, 1, bytes, file);
if (count > 0) {
bytes -= count;
addr += count;
}
else {
perror("Error writing to save file");
bytes = 0;
}
}
fflush(file);
fseek(file, here, 0);
return data/CORE_PAGESIZE - 1;
}
static void output_space(FILE *file, int id, lispobj *addr, lispobj *end)
{
int words, bytes, data;
static char *names[] = {NULL, "Dynamic", "Static", "Read-Only"};
putw(id, file);
words = end - addr;
putw(words, file);
bytes = words * sizeof(lispobj);
printf("Writing %d bytes from the %s space at 0x%08X.\n",
bytes, names[id], (unsigned long)addr);
data = write_bytes(file, (char *)addr, bytes);
putw(data, file);
putw((os_vm_address_t)((long)addr / CORE_PAGESIZE), file);
putw((bytes + CORE_PAGESIZE - 1) / CORE_PAGESIZE, file);
}
static long write_stack(FILE *file, char *name, char *start, char *end)
{
long len;
start = (char *)os_trunc_to_page((os_vm_address_t)start);
end = (char *)os_round_up_to_page((os_vm_address_t)end);
len = end-start;
printf("Writing %d bytes from the %s stack at 0x%08X.\n", len, name,
(unsigned long)start);
return write_bytes(file, start, len);
}
static int do_save(char *stack_ptr, FILE *file)
{
struct machine_state ms;
putw(CORE_MAGIC, file);
putw(CORE_VERSION, file);
putw(3, file);
putw(version, file);
putw(CORE_NDIRECTORY, file);
putw((5*3)+2, file);
output_space(file, READ_ONLY_SPACE_ID, read_only_space,
(lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER));
output_space(file, STATIC_SPACE_ID, static_space,
(lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER));
#ifdef reg_ALLOC
output_space(file, DYNAMIC_SPACE_ID, current_dynamic_space,
current_dynamic_space_free_pointer);
#else
output_space(file, DYNAMIC_SPACE_ID, current_dynamic_space,
(lispobj *)SymbolValue(ALLOCATION_POINTER));
#endif
putw(CORE_MACHINE_STATE, file);
putw(2 + sizeof(ms)/sizeof(long), file);
ms.csp = current_control_stack_pointer;
ms.cfp = current_control_frame_pointer;
ms.control_stack_page = write_stack(file, "Control",
(char *)control_stack,
(char *)current_control_stack_pointer);
#ifdef reg_BSP
ms.bsp = current_binding_stack_pointer;
ms.binding_stack_page = write_stack(file, "Binding",
(char *)binding_stack,
(char *)current_binding_stack_pointer);
#else
ms.binding_stack_page = write_stack(file, "Binding",
(char *)binding_stack,
(char *)SymbolValue(BINDING_STACK_POINTER));
#endif
ms.nsp = stack_ptr;
#ifdef NUMBER_STACK_GROWS_UP
ms.number_stack_page = write_stack(file, "Number",
(char *)NUMBER_STACK_START,
stack_ptr);
#else
ms.number_stack_page = write_stack(file, "Number", stack_ptr,
(char *)(NUMBER_STACK_START+NUMBER_STACK_SIZE));
#endif
fwrite((void *)&ms, sizeof(ms), 1, file);
putw(CORE_END, file);
fclose(file);
printf("done.]\n");
return 1;
}
int save(char *filename)
{
FILE *file;
/* Open the file: */
unlink(filename);
file = fopen(filename, "w");
if (file == NULL) {
perror(filename);
return TRUE;
}
printf("[Saving current lisp image into %s:\n", filename);
return save_state(do_save, file);
}
static os_vm_address_t map_stack(int fd, os_vm_address_t start,
os_vm_address_t end,
long data_page,
char *name)
{
os_vm_size_t len;
start = os_trunc_to_page(start);
len = os_round_up_to_page(end) - start;
if (len != 0) {
#ifdef PRINTNOISE
printf("Mapping %d bytes onto the %s stack at 0x%08x.\n", len, name, start);
#endif
start=os_map(fd, (1+data_page)*CORE_PAGESIZE, start, len);
}
return start;
}
static char *restored_nsp;
void load(int fd, struct machine_state *ms)
{
current_control_stack_pointer = ms->csp;
current_control_frame_pointer = ms->cfp;
#ifdef reg_BSP
current_binding_stack_pointer = ms->bsp;
#endif
map_stack(fd,
(os_vm_address_t)control_stack,
(os_vm_address_t)current_control_stack_pointer,
ms->control_stack_page,
"Control");
map_stack(fd,
(os_vm_address_t)binding_stack,
#ifdef reg_BSP
(os_vm_address_t)current_binding_stack_pointer,
#else
(os_vm_address_t)SymbolValue(BINDING_STACK_POINTER),
#endif
ms->binding_stack_page,
"Binding");
map_stack(fd,
#ifdef NUMBER_STACK_GROWS_UP
NUMBER_STACK_START,
(os_vm_address_t)ms->nsp,
#else
(os_vm_address_t)ms->nsp,
NUMBER_STACK_START+NUMBER_STACK_SIZE,
#endif
ms->number_stack_page,
"Number");
restored_nsp = ms->nsp;
}
void restore(void)
{
restore_state(restored_nsp, 0);
fprintf(stderr, "Hm, tried to restore, but nothing happened.\n");
}