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