Mercurial > emacs
annotate src/unexaix.c @ 531:202463e1df14
*** empty log message ***
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Tue, 04 Feb 1992 02:27:43 +0000 |
parents | 8c615e453683 |
children | 68111c4a3885 |
rev | line source |
---|---|
117
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
1 /* |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
2 This file is not used because it occasionally fails to work. This |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
3 happens because the bss address when Emacs is run is not always the |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
4 same. If it happens to be different from what it was |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
5 when Emacs was dumped, the dumped data won't work. |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
6 No one has been able to prevent the address from varying. |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
7 |
485 | 8 The following comments should be in share-lib/MACHINES if this |
9 dumping is ever made to work: | |
117
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
10 |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
11 Note that Emacs can store the pure Lisp data in a shared segment on |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
12 this machine, but only if you put this command in one of the boot |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
13 scripts |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
14 |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
15 emacs -batch -q |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
16 |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
17 so that it is run as root when the machine is booted. This command |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
18 creates a read-only shared segment owned by root. Otherwise the |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
19 pure data is not shared. The pure data size is around 100K, which |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
20 may not be enough to matter for most users of this machine. |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
21 */ |
08356dc1077c
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
110
diff
changeset
|
22 |
110 | 23 /* Dumping and loading data areas, for Emacs under AIX. |
24 (It may also work on other kinds of system V.) | |
25 Copyright (C) 1990 Free Software Foundation, Inc. | |
26 | |
27 This file is part of GNU Emacs. | |
28 | |
29 GNU Emacs is free software; you can redistribute it and/or modify | |
30 it under the terms of the GNU General Public License as published by | |
31 the Free Software Foundation; either version 1, or (at your option) | |
32 any later version. | |
33 | |
34 GNU Emacs is distributed in the hope that it will be useful, | |
35 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
36 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
37 GNU General Public License for more details. | |
38 | |
39 You should have received a copy of the GNU General Public License | |
40 along with GNU Emacs; see the file COPYING. If not, write to | |
41 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
42 | |
43 /* This is based on a public domain program written by IBM. */ | |
44 | |
45 /*************** SYSTEM DEFINES *********************************/ | |
46 | |
47 #include "config.h" | |
48 #include "paths.h" | |
49 #include <sys/types.h> | |
50 #include <sys/files.h> | |
51 #include <fcntl.h> | |
52 #include <sys/mode.h> | |
53 #include <sys/ipc.h> | |
54 #include <sys/shm.h> | |
55 #include <malloc.h> | |
56 #include <stdio.h> /* MWW */ | |
57 #include "lisp.h" | |
58 | |
59 /*************** LOCAL DEFINES **********************************/ | |
60 | |
61 struct data_header /* saved data header */ | |
62 { | |
63 char *start; /* dump _data addr */ | |
64 char *end; /* dump _end addr */ | |
65 char *sbrk1; /* dump original sbrk addr */ | |
66 char *sbrk2; /* dump final sbrk addr */ | |
67 int puresize; /* size of pure data dumped */ | |
68 }; | |
69 | |
70 #define EMACSSHMKEY "EMACSSHMKEY" | |
71 #define EMACS_DATA_FILE "EMACS-DATA" | |
72 #define NEW_SHMGET_FLAGS (IPC_CREAT | S_IWUSR | S_IRUSR \ | |
73 | S_IWGRP | S_IRGRP | S_IWOTH | S_IROTH) | |
74 #define OLD_SHMAT_FLAGS SHM_RDONLY | |
75 #define OLD_SHMGET_FLAGS (S_IRUSR | S_IRGRP | S_IROTH) | |
76 #define OLD_OPEN_FLAGS O_RDONLY | |
77 #define NEW_OPEN_FLAGS (O_RDWR | O_CREAT | O_TRUNC) | |
78 | |
79 /*************** EXTERNAL / GLOBAL DATA AREA ********************/ | |
80 | |
81 extern char _data; /* start of data addr */ | |
82 extern char _end; /* end of all data + 1 addr */ | |
83 static char *original_sbrk; /* sbrk when dump first run */ | |
84 | |
85 void | |
86 map_in_data (use_dumped_data) | |
87 int use_dumped_data; | |
88 { | |
89 int bufsize; /* malloc buffer size */ | |
90 struct data_header dh; /* saved data header */ | |
91 int fd; /* saved data file descriptor */ | |
92 char *finaladdr; /* last addr in bucket */ | |
93 char *ipckey = getenv (EMACSSHMKEY); /* env ipc key string */ | |
94 int length; /* dumped data lengths */ | |
95 char *newaddr; /* new malloc buffer addr */ | |
96 int numblks; /* number of remaining mallocs */ | |
97 int shmid; /* shared memory id */ | |
98 key_t shmkey; /* shared memory key */ | |
99 /* Note that using malloc here may not be safe. */ | |
100 char name[sizeof (PATH_EXEC) + sizeof (EMACS_DATA_FILE) + 2]; | |
101 | |
102 /* Consume remaining malloc space without increasing */ | |
103 /* the end of data space */ | |
104 original_sbrk = sbrk (0); | |
105 for (bufsize = 16; bufsize < getpagesize (); bufsize *= 2) | |
106 { | |
107 while ((newaddr = (char *)malloc (bufsize - 8)) < original_sbrk) | |
108 ; | |
109 for (numblks = (getpagesize () / bufsize) - 1; numblks > 0; numblks--) | |
110 malloc (bufsize - 8); | |
111 finaladdr = sbrk (0); | |
112 } | |
113 original_sbrk = sbrk (0); | |
114 | |
115 /* If we don't want the dumped data, get an unshared segment. */ | |
116 if (!use_dumped_data) | |
117 { | |
118 shmid = shmget (IPC_PRIVATE, PURESIZE, NEW_SHMGET_FLAGS); | |
119 if (shmid == -1 | |
120 || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1) | |
121 { | |
122 fprintf (stderr, "emacs: failure obtaining new unshared memory segment.\n"); | |
123 exit (1); | |
124 } | |
125 return; | |
126 } | |
127 | |
128 /* Compute the file name with the dumped data. */ | |
129 strcpy (name, PATH_EXEC); | |
130 strcat (name, "/"); | |
131 strcat (name, EMACS_DATA_FILE); | |
132 | |
133 /* Open the file and make sure the addresses have not changed. */ | |
134 fd = open (name, OLD_OPEN_FLAGS, 0); | |
135 if (fd < 0) | |
136 { | |
137 fprintf (stderr, "emacs: failure opening `%s'\n", name); | |
138 exit (1); | |
139 } | |
140 if (read (fd, (char *)&dh, sizeof (dh)) != sizeof (dh) | |
141 || dh.start != &_data | |
142 || dh.end != &_end | |
143 || dh.sbrk1 != original_sbrk | |
144 || dh.puresize != PURESIZE) | |
145 { | |
146 fprintf (stderr, "emacs: header mismatch in `%s'\n", name); | |
147 exit (1); | |
148 } | |
149 | |
150 /* Load in the unshared contents. */ | |
151 if (!(length = dh.end - dh.start) | |
152 || read (fd, (char *)&_data, length) != length | |
153 || !(length = dh.sbrk2 - dh.sbrk1) | |
154 || brk (dh.sbrk2) == -1 | |
155 || read (fd, dh.sbrk1, length) != length) | |
156 { | |
157 fprintf (stderr, "emacs: failure loading unshared data.\n"); | |
158 exit (1); | |
159 } | |
160 | |
161 /* Determine ipc key from environment or default */ | |
162 if (ipckey && *ipckey) | |
163 shmkey = atoi (ipckey); | |
164 else | |
165 shmkey = SHMKEY; | |
166 | |
167 /* Attach to "pure data" shared memory segment */ | |
168 if ((shmid = shmget (shmkey, 0, 0)) == -1 | |
169 || (newaddr = shmat (shmid, (char *)PURE_SEG_BITS, OLD_SHMAT_FLAGS)) == -1) | |
170 { | |
171 /* We were unable to open an existing segment. Make a new one. */ | |
172 struct shmid_ds buf; | |
173 | |
174 /* First get rid of the one we tried to get. */ | |
175 shmdt ((char *)PURE_SEG_BITS); | |
176 shmctl (shmid, IPC_RMID, 0); | |
177 | |
178 /* If we could not write the data file, | |
179 don't make a shared segment that we could write. | |
180 Make an unshared segment instead. */ | |
181 if (access (name, W_OK) == 0) | |
182 { | |
183 shmid = shmget (IPC_PRIVATE, PURESIZE, NEW_SHMGET_FLAGS); | |
184 if (shmid == -1 | |
185 || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1) | |
186 { | |
187 fprintf (stderr, "emacs: failure obtaining new unshared memory segment.\n"); | |
188 exit (1); | |
189 } | |
190 | |
191 /* Load the proper data into it. */ | |
192 if (read (fd, PURE_SEG_BITS, PURESIZE) != PURESIZE) | |
193 { | |
194 fprintf (stderr, "emacs: failure loading shared memory data.\n"); | |
195 shmdt ((char *)PURE_SEG_BITS); | |
196 shmctl (shmid, IPC_RMID, 0); | |
197 exit (1); | |
198 } | |
199 | |
200 close (fd); | |
201 return; | |
202 } | |
203 | |
204 /* Allocate the new shared segment and arrange to write it. */ | |
205 if ((shmid = shmget (shmkey, PURESIZE, NEW_SHMGET_FLAGS)) == -1 | |
206 || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1) | |
207 { | |
208 fprintf (stderr, "emacs: failure obtaining new shared memory segment.\n"); | |
209 shmdt ((char *)PURE_SEG_BITS); | |
210 shmctl (shmid, IPC_RMID, 0); | |
211 exit (1); | |
212 } | |
213 | |
214 /* Load the proper data into it. */ | |
215 if (read (fd, PURE_SEG_BITS, PURESIZE) != PURESIZE) | |
216 { | |
217 fprintf (stderr, "emacs: failure loading shared memory data.\n"); | |
218 shmdt ((char *)PURE_SEG_BITS); | |
219 shmctl (shmid, IPC_RMID, 0); | |
220 exit (1); | |
221 } | |
222 | |
223 /* Detach from the segment and bring it back readonly. */ | |
224 shmdt ((char *)PURE_SEG_BITS); | |
225 | |
226 shmctl (shmid, IPC_STAT, &buf); | |
227 buf.shm_perm.mode = OLD_SHMGET_FLAGS; | |
228 shmctl (shmid, IPC_SET, &buf); | |
229 | |
230 newaddr = shmat (shmid, (char *)PURE_SEG_BITS, OLD_SHMAT_FLAGS); | |
231 if (newaddr == -1) | |
232 { | |
233 fprintf (stderr, "emacs: failure reattaching shared memory segment.\n"); | |
234 shmctl (shmid, IPC_RMID, 0); | |
235 exit (1); | |
236 } | |
237 } | |
238 | |
239 close (fd); | |
240 } | |
241 | |
242 /* Dump the appropriate parts of memory into a file named NEW | |
243 from which the shared segment can be initialized. */ | |
244 | |
245 void | |
246 map_out_data (new) | |
247 char *new; | |
248 { | |
249 struct data_header dh; /* saved data header */ | |
250 int fd; /* saved data file descriptor */ | |
251 int length; /* dumped data length; */ | |
252 | |
253 | |
254 /* Create "saved data" file header */ | |
255 dh.start = &_data; | |
256 dh.end = &_end; | |
257 dh.sbrk1 = original_sbrk; | |
258 dh.sbrk2 = sbrk (0); | |
259 dh.puresize = PURESIZE; | |
260 | |
261 /* Create new "saved data" dump file */ | |
262 unlink (new); | |
263 fd = open (new, NEW_OPEN_FLAGS, 0666); | |
264 if (fd < 0) | |
265 report_file_error ("Opening dump file", Fcons (build_string (new), Qnil)); | |
266 | |
267 /* Write saved header and data */ | |
268 length = sizeof (dh); | |
269 if (write (fd, (char *)&dh, length) != length) | |
270 report_file_error ("Writing dump file header", | |
271 Fcons (build_string (new), Qnil)); | |
272 length = dh.end - dh.start; | |
273 if (write (fd, dh.start, length) != length) | |
274 report_file_error ("Writing low core in dump file", | |
275 Fcons (build_string (new), Qnil)); | |
276 length = dh.sbrk2 - dh.sbrk1; | |
277 if (write (fd, dh.sbrk1, length) != length) | |
278 report_file_error ("Writing heap in dump file", | |
279 Fcons (build_string (new), Qnil)); | |
280 length = PURESIZE; | |
281 if (write (fd, PURE_SEG_BITS, length) != length) | |
282 report_file_error ("Writing pure data in dump file", | |
283 Fcons (build_string (new), Qnil)); | |
284 close (fd); | |
285 } |