diff options
| author | Pip Cet | 2024-08-20 18:48:42 +0000 |
|---|---|---|
| committer | Stefan Kangas | 2024-12-12 22:48:11 +0100 |
| commit | aab5a2fe4c4164019b8b5bf09cce835b2aa8549c (patch) | |
| tree | d308566405e1a2cb66e580321c2e1a8e731554de | |
| parent | b2bc337a5f8d84978029873ce8e51b8d3d53121a (diff) | |
| download | emacs-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.c | 25 | ||||
| -rw-r--r-- | src/w32heap.c | 197 |
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 | |||
| 130 | static 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. */ |
| 133 | unsigned char *data_region_base = NULL; | 90 | unsigned char *data_region_base = NULL; |
| 134 | unsigned char *data_region_end = NULL; | 91 | unsigned char *data_region_end = NULL; |
| @@ -178,12 +135,6 @@ static struct | |||
| 178 | static DWORD blocks_number = 0; | 135 | static DWORD blocks_number = 0; |
| 179 | static unsigned char *bc_limit; | 136 | static 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 | */ | ||
| 185 | HANDLE heap = NULL; | ||
| 186 | |||
| 187 | /* We redirect the standard allocation functions. */ | 138 | /* We redirect the standard allocation functions. */ |
| 188 | malloc_fn the_malloc_fn; | 139 | malloc_fn the_malloc_fn; |
| 189 | realloc_fn the_realloc_fn; | 140 | realloc_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 | */ | ||
| 220 | static NTSTATUS NTAPI | ||
| 221 | dumped_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 | ||
| 252 | void | 179 | void |
| 253 | init_heap (bool use_dynamic_heap) | 180 | init_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 (¶ms, 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, ¶ms); | ||
| 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. */ |