aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPip Cet2024-08-20 18:48:42 +0000
committerStefan Kangas2024-12-12 22:48:11 +0100
commitaab5a2fe4c4164019b8b5bf09cce835b2aa8549c (patch)
treed308566405e1a2cb66e580321c2e1a8e731554de
parentb2bc337a5f8d84978029873ce8e51b8d3d53121a (diff)
downloademacs-aab5a2fe4c4164019b8b5bf09cce835b2aa8549c.tar.gz
emacs-aab5a2fe4c4164019b8b5bf09cce835b2aa8549c.zip
Unexec removal: Adjust and simplify W32-specific code
* src/emacs.c (main): Unconditionally call 'init_heap' without an argument. Adjust comment. * src/w32heap.c (dumped_data, DUMPED_HEAP_SIZE): Remove definitions. (heap): Remove variable. (dumped_data_commit): Remove function. (init_heap): Drop unexec-specific code.
-rw-r--r--src/emacs.c25
-rw-r--r--src/w32heap.c197
2 files changed, 41 insertions, 181 deletions
diff --git a/src/emacs.c b/src/emacs.c
index 8e606604d6b..eba103bd807 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1334,26 +1334,8 @@ main (int argc, char **argv)
1334 1334
1335#ifdef WINDOWSNT 1335#ifdef WINDOWSNT
1336 /* Grab our malloc arena space now, before anything important 1336 /* Grab our malloc arena space now, before anything important
1337 happens. This relies on the static heap being needed only in 1337 happens. */
1338 temacs and only if we are going to dump with unexec. */ 1338 init_heap ();
1339 bool use_dynamic_heap = true;
1340 if (temacs)
1341 {
1342 char *temacs_str = NULL, *p;
1343 for (p = argv[0]; (p = strstr (p, "temacs")) != NULL; p++)
1344 temacs_str = p;
1345 if (temacs_str != NULL
1346 && (temacs_str == argv[0] || IS_DIRECTORY_SEP (temacs_str[-1])))
1347 {
1348 /* Note that gflags are set at this point only if we have been
1349 called with the --temacs=METHOD option. We assume here that
1350 temacs is always called that way, otherwise the functions
1351 that rely on gflags, like will_dump_with_pdumper_p below,
1352 will not do their job. */
1353 use_dynamic_heap = will_dump_with_pdumper_p ();
1354 }
1355 }
1356 init_heap (use_dynamic_heap);
1357 initial_cmdline = GetCommandLine (); 1339 initial_cmdline = GetCommandLine ();
1358#endif 1340#endif
1359#if defined WINDOWSNT || defined HAVE_NTGUI 1341#if defined WINDOWSNT || defined HAVE_NTGUI
@@ -1881,8 +1863,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1881 && !defined DOUG_LEA_MALLOC 1863 && !defined DOUG_LEA_MALLOC
1882 /* Do not make gmalloc thread-safe when creating bootstrap-emacs, as 1864 /* Do not make gmalloc thread-safe when creating bootstrap-emacs, as
1883 that causes an infinite recursive loop with FreeBSD. See 1865 that causes an infinite recursive loop with FreeBSD. See
1884 Bug#14569. The part of this bug involving Cygwin is no longer 1866 Bug#14569. */
1885 relevant, now that Cygwin defines HYBRID_MALLOC. */
1886 if (!noninteractive || !will_dump_p ()) 1867 if (!noninteractive || !will_dump_p ())
1887 malloc_enable_thread (); 1868 malloc_enable_thread ();
1888#endif 1869#endif
diff --git a/src/w32heap.c b/src/w32heap.c
index c5777622c56..f850fe1cf19 100644
--- a/src/w32heap.c
+++ b/src/w32heap.c
@@ -28,15 +28,6 @@
28 Memory allocation scheme for w32/w64: 28 Memory allocation scheme for w32/w64:
29 29
30 - Buffers are mmap'ed using a very simple emulation of mmap/munmap 30 - Buffers are mmap'ed using a very simple emulation of mmap/munmap
31 - During the temacs phase, if unexec is to be used:
32 * we use a private heap declared to be stored into the `dumped_data'
33 * unfortunately, this heap cannot be made growable, so the size of
34 blocks it can allocate is limited to (0x80000 - pagesize)
35 * the blocks that are larger than this are allocated from the end
36 of the `dumped_data' array; there are not so many of them.
37 We use a very simple first-fit scheme to reuse those blocks.
38 * we check that the private heap does not cross the area used
39 by the bigger chunks.
40 - During the emacs phase, or always if pdumper is used: 31 - During the emacs phase, or always if pdumper is used:
41 * we create a private heap for new memory blocks 32 * we create a private heap for new memory blocks
42 * we make sure that we never free a block that has been dumped. 33 * we make sure that we never free a block that has been dumped.
@@ -95,40 +86,6 @@ typedef struct _RTL_HEAP_PARAMETERS {
95 SIZE_T Reserved[ 2 ]; 86 SIZE_T Reserved[ 2 ];
96} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS; 87} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS;
97 88
98/* We reserve space for dumping emacs lisp byte-code inside a static
99 array. By storing it in an array, the generic mechanism in
100 unexecw32.c will be able to dump it without the need to add a
101 special segment to the executable. In order to be able to do this
102 without losing too much space, we need to create a Windows heap at
103 the specific address of the static array. The RtlCreateHeap
104 available inside the NT kernel since XP will do this. It allows the
105 creation of a non-growable heap at a specific address. So before
106 dumping, we create a non-growable heap at the address of the
107 dumped_data[] array. After dumping, we reuse memory allocated
108 there without being able to free it (but most of it is not meant to
109 be freed anyway), and we use a new private heap for all new
110 allocations. */
111
112/* FIXME: Most of the space reserved for dumped_data[] is only used by
113 the 1st bootstrap-emacs.exe built while bootstrapping. Once the
114 preloaded Lisp files are byte-compiled, the next loadup uses less
115 than half of the size stated below. It would be nice to find a way
116 to build only the first bootstrap-emacs.exe with the large size,
117 and reset that to a lower value afterwards. */
118#ifndef HAVE_UNEXEC
119/* We don't use dumped_data[], so define to a small size that won't
120 matter. */
121# define DUMPED_HEAP_SIZE 10
122#else
123# if defined _WIN64 || defined WIDE_EMACS_INT
124# define DUMPED_HEAP_SIZE (28*1024*1024)
125# else
126# define DUMPED_HEAP_SIZE (24*1024*1024)
127# endif
128#endif
129
130static unsigned char dumped_data[DUMPED_HEAP_SIZE];
131
132/* Info for keeping track of our dynamic heap used after dumping. */ 89/* Info for keeping track of our dynamic heap used after dumping. */
133unsigned char *data_region_base = NULL; 90unsigned char *data_region_base = NULL;
134unsigned char *data_region_end = NULL; 91unsigned char *data_region_end = NULL;
@@ -178,12 +135,6 @@ static struct
178static DWORD blocks_number = 0; 135static DWORD blocks_number = 0;
179static unsigned char *bc_limit; 136static unsigned char *bc_limit;
180 137
181/* Handle for the private heap:
182 - inside the dumped_data[] array before dump with unexec,
183 - outside of it after dump, or always if pdumper is used.
184*/
185HANDLE heap = NULL;
186
187/* We redirect the standard allocation functions. */ 138/* We redirect the standard allocation functions. */
188malloc_fn the_malloc_fn; 139malloc_fn the_malloc_fn;
189realloc_fn the_realloc_fn; 140realloc_fn the_realloc_fn;
@@ -213,30 +164,6 @@ heap_realloc (void *ptr, size_t size)
213 It would be if the memory was shared. 164 It would be if the memory was shared.
214 https://stackoverflow.com/questions/307060/what-is-the-purpose-of-allocating-pages-in-the-pagefile-with-createfilemapping */ 165 https://stackoverflow.com/questions/307060/what-is-the-purpose-of-allocating-pages-in-the-pagefile-with-createfilemapping */
215 166
216/* This is the function to commit memory when the heap allocator
217 claims for new memory. Before dumping with unexec, we allocate
218 space from the fixed size dumped_data[] array.
219*/
220static NTSTATUS NTAPI
221dumped_data_commit (PVOID Base, PVOID *CommitAddress, PSIZE_T CommitSize)
222{
223 /* This is used before dumping.
224
225 The private heap is stored at dumped_data[] address.
226 We commit contiguous areas of the dumped_data array
227 as requests arrive. */
228 *CommitAddress = data_region_base + committed;
229 committed += *CommitSize;
230 /* Check that the private heap area does not overlap the big chunks area. */
231 if (((unsigned char *)(*CommitAddress)) + *CommitSize >= bc_limit)
232 {
233 fprintf (stderr,
234 "dumped_data_commit: memory exhausted.\nEnlarge dumped_data[]!\n");
235 exit (-1);
236 }
237 return 0;
238}
239
240/* Heap creation. */ 167/* Heap creation. */
241 168
242/* We want to turn on Low Fragmentation Heap for XP and older systems. 169/* We want to turn on Low Fragmentation Heap for XP and older systems.
@@ -250,99 +177,51 @@ typedef WINBASEAPI BOOL (WINAPI * HeapSetInformation_Proc)(HANDLE,HEAP_INFORMATI
250#endif 177#endif
251 178
252void 179void
253init_heap (bool use_dynamic_heap) 180init_heap (void)
254{ 181{
255 /* FIXME: Remove the condition, the 'else' branch below, and all the 182 /* After dumping, use a new private heap. We explicitly enable
256 related definitions and code, including dumped_data[], when unexec 183 the low fragmentation heap (LFH) here, for the sake of pre
257 support is removed from Emacs. */ 184 Vista versions. Note: this will harmlessly fail on Vista and
258 if (use_dynamic_heap) 185 later, where the low-fragmentation heap is enabled by
259 { 186 default. It will also fail on pre-Vista versions when Emacs
260 /* After dumping, use a new private heap. We explicitly enable 187 is run under a debugger; set _NO_DEBUG_HEAP=1 in the
261 the low fragmentation heap (LFH) here, for the sake of pre 188 environment before starting GDB to get low fragmentation heap
262 Vista versions. Note: this will harmlessly fail on Vista and 189 on XP and older systems, for the price of losing "certain
263 later, where the low-fragmentation heap is enabled by 190 heap debug options"; for the details see
264 default. It will also fail on pre-Vista versions when Emacs 191 https://msdn.microsoft.com/en-us/library/windows/desktop/aa366705%28v=vs.85%29.aspx. */
265 is run under a debugger; set _NO_DEBUG_HEAP=1 in the 192 data_region_end = data_region_base;
266 environment before starting GDB to get low fragmentation heap 193
267 on XP and older systems, for the price of losing "certain 194 /* Create the private heap. */
268 heap debug options"; for the details see 195 heap = HeapCreate (0, 0, 0);
269 https://msdn.microsoft.com/en-us/library/windows/desktop/aa366705%28v=vs.85%29.aspx. */
270 data_region_end = data_region_base;
271
272 /* Create the private heap. */
273 heap = HeapCreate (0, 0, 0);
274 196
275#ifndef MINGW_W64 197#ifndef MINGW_W64
276 unsigned long enable_lfh = 2; 198 unsigned long enable_lfh = 2;
277 /* Set the low-fragmentation heap for OS before Vista. */ 199 /* Set the low-fragmentation heap for OS before Vista. */
278 HMODULE hm_kernel32dll = LoadLibrary ("kernel32.dll"); 200 HMODULE hm_kernel32dll = LoadLibrary ("kernel32.dll");
279 HeapSetInformation_Proc s_pfn_Heap_Set_Information = 201 HeapSetInformation_Proc s_pfn_Heap_Set_Information =
280 (HeapSetInformation_Proc) get_proc_addr (hm_kernel32dll, 202 (HeapSetInformation_Proc) get_proc_addr (hm_kernel32dll,
281 "HeapSetInformation"); 203 "HeapSetInformation");
282 if (s_pfn_Heap_Set_Information != NULL) 204 if (s_pfn_Heap_Set_Information != NULL)
283 { 205 {
284 if (s_pfn_Heap_Set_Information ((PVOID) heap, 206 if (s_pfn_Heap_Set_Information ((PVOID) heap,
285 HeapCompatibilityInformation, 207 HeapCompatibilityInformation,
286 &enable_lfh, sizeof(enable_lfh)) == 0) 208 &enable_lfh, sizeof(enable_lfh)) == 0)
287 DebPrint (("Enabling Low Fragmentation Heap failed: error %ld\n", 209 DebPrint (("Enabling Low Fragmentation Heap failed: error %ld\n",
288 GetLastError ())); 210 GetLastError ()));
289 } 211 }
290#endif 212#endif
291 213
292 if (os_subtype == OS_SUBTYPE_9X) 214 if (os_subtype == OS_SUBTYPE_9X)
293 { 215 {
294 the_malloc_fn = malloc_after_dump_9x; 216 the_malloc_fn = malloc_after_dump_9x;
295 the_realloc_fn = realloc_after_dump_9x; 217 the_realloc_fn = realloc_after_dump_9x;
296 the_free_fn = free_after_dump_9x; 218 the_free_fn = free_after_dump_9x;
297 }
298 else
299 {
300 the_malloc_fn = malloc_after_dump;
301 the_realloc_fn = realloc_after_dump;
302 the_free_fn = free_after_dump;
303 }
304 } 219 }
305 else /* Before dumping with unexec: use static heap. */ 220 else
306 { 221 {
307 /* Find the RtlCreateHeap function. Headers for this function 222 the_malloc_fn = malloc_after_dump;
308 are provided with the w32 DDK, but the function is available 223 the_realloc_fn = realloc_after_dump;
309 in ntdll.dll since XP. */ 224 the_free_fn = free_after_dump;
310 HMODULE hm_ntdll = LoadLibrary ("ntdll.dll");
311 RtlCreateHeap_Proc s_pfn_Rtl_Create_Heap
312 = (RtlCreateHeap_Proc) get_proc_addr (hm_ntdll, "RtlCreateHeap");
313 /* Specific parameters for the private heap. */
314 RTL_HEAP_PARAMETERS params;
315 ZeroMemory (&params, sizeof(params));
316 params.Length = sizeof(RTL_HEAP_PARAMETERS);
317
318 data_region_base = (unsigned char *)ROUND_UP (dumped_data, 0x1000);
319 data_region_end = bc_limit = dumped_data + DUMPED_HEAP_SIZE;
320
321 params.InitialCommit = committed = 0x1000;
322 params.InitialReserve = sizeof(dumped_data);
323 /* Use our own routine to commit memory from the dumped_data
324 array. */
325 params.CommitRoutine = &dumped_data_commit;
326
327 /* Create the private heap. */
328 if (s_pfn_Rtl_Create_Heap == NULL)
329 {
330 fprintf (stderr, "Cannot build Emacs without RtlCreateHeap being available; exiting.\n");
331 exit (-1);
332 }
333 heap = s_pfn_Rtl_Create_Heap (0, data_region_base, 0, 0, NULL, &params);
334
335 if (os_subtype == OS_SUBTYPE_9X)
336 {
337 fprintf (stderr, "Cannot dump Emacs on Windows 9X; exiting.\n");
338 exit (-1);
339 }
340 else
341 {
342 the_malloc_fn = malloc_before_dump;
343 the_realloc_fn = realloc_before_dump;
344 the_free_fn = free_before_dump;
345 }
346 } 225 }
347 226
348 /* Update system version information to match current system. */ 227 /* Update system version information to match current system. */