aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2019-01-18 17:04:00 +0200
committerEli Zaretskii2019-01-18 17:04:00 +0200
commit5e3b0f5239027a413775d375f04376a3c97d0bf9 (patch)
tree7d6e6dbe03a405a2bd7e527e39a12fbf0dd1aa64 /src
parentf943409183559b0af0e89f52bf0a93f8431c2dcf (diff)
downloademacs-5e3b0f5239027a413775d375f04376a3c97d0bf9.tar.gz
emacs-5e3b0f5239027a413775d375f04376a3c97d0bf9.zip
Clean up memory allocation and unexec support on MS-Windows
* src/w32heap.c (report_temacs_memory_usage): Condition on !CANNOT_DUMP, in addition to ENABLE_CHECKING. (init_heap): Accept an argument, which tells us what heap allocation method to use. (DUMPED_HEAP_SIZE) [CANNOT_DUMP]: Define to a small value, as we don't use dumped_data[] in this case. * src/w32heap.h (init_heap): Adjust prototype. <using_dynamic_heap>: Remove declaration. * src/emacs.c (main) [WINDOWSNT]: Determine heap allocation method based on whether we are in temacs and whether unexec will be used to dump Emacs. Pass the heap allocation method to init_heap, which is now called after parsing the --temacs=METHOD option. * src/unexw32.c (unexec): Don't fiddle with using_dynamic_heap. <using_dynamic_heap>: Remove definition. * src/w32proc.c (malloc_before_init, realloc_before_init) (free_before_init): New functions, to catch memory allocation before heap allocation method is set up.
Diffstat (limited to 'src')
-rw-r--r--src/emacs.c19
-rw-r--r--src/unexw32.c10
-rw-r--r--src/w32heap.c49
-rw-r--r--src/w32heap.h3
-rw-r--r--src/w32proc.c37
5 files changed, 78 insertions, 40 deletions
diff --git a/src/emacs.c b/src/emacs.c
index 834f55b6f32..b9f50397241 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -871,8 +871,25 @@ main (int argc, char **argv)
871#endif 871#endif
872 872
873#if defined WINDOWSNT || defined HAVE_NTGUI 873#if defined WINDOWSNT || defined HAVE_NTGUI
874 /* Grab our malloc arena space now, before anything important
875 happens. This relies on the static heap being needed only in
876 temacs and only if we are going to dump with unexec. */
877 bool use_dynamic_heap = false;
878 if (strstr (argv[0], "temacs") != NULL)
879 {
880 eassert (temacs);
881 /* Note that gflags are set at this point only if we have been
882 called with the --temacs=METHOD option. We assume here that
883 temacs is always called that way, otherwise the functions
884 that rely on gflags, like will_dump_with_pdumper_p below,
885 will not do their job. */
886 use_dynamic_heap = will_dump_with_pdumper_p ();
887 }
888 else
889 use_dynamic_heap = true;
890 init_heap (use_dynamic_heap);
874 /* Set global variables used to detect Windows version. Do this as 891 /* Set global variables used to detect Windows version. Do this as
875 early as possible. (unexw32.c calls this function as well, but 892 early as possible. (w32proc.c calls this function as well, but
876 the additional call here is harmless.) */ 893 the additional call here is harmless.) */
877 cache_system_info (); 894 cache_system_info ();
878#ifdef WINDOWSNT 895#ifdef WINDOWSNT
diff --git a/src/unexw32.c b/src/unexw32.c
index 6fa0fa055a6..59feaa74b9f 100644
--- a/src/unexw32.c
+++ b/src/unexw32.c
@@ -45,9 +45,6 @@ extern char *my_begbss_static;
45 45
46#include "w32heap.h" 46#include "w32heap.h"
47 47
48/* Basically, our "initialized" flag. */
49BOOL using_dynamic_heap = FALSE;
50
51void get_section_info (file_data *p_file); 48void get_section_info (file_data *p_file);
52void copy_executable_and_dump_data (file_data *, file_data *); 49void copy_executable_and_dump_data (file_data *, file_data *);
53void dump_bss_and_heap (file_data *p_infile, file_data *p_outfile); 50void dump_bss_and_heap (file_data *p_infile, file_data *p_outfile);
@@ -649,15 +646,8 @@ unexec (const char *new_name, const char *old_name)
649 exit (1); 646 exit (1);
650 } 647 }
651 648
652 /* Set the flag (before dumping). */
653 using_dynamic_heap = TRUE;
654
655 copy_executable_and_dump_data (&in_file, &out_file); 649 copy_executable_and_dump_data (&in_file, &out_file);
656 650
657 /* Unset it because it is plain wrong to keep it after dumping.
658 Malloc can still occur! */
659 using_dynamic_heap = FALSE;
660
661 /* Patch up header fields; profiler is picky about this. */ 651 /* Patch up header fields; profiler is picky about this. */
662 { 652 {
663 PIMAGE_DOS_HEADER dos_header; 653 PIMAGE_DOS_HEADER dos_header;
diff --git a/src/w32heap.c b/src/w32heap.c
index 3de8f245ccc..8a2c1b5877b 100644
--- a/src/w32heap.c
+++ b/src/w32heap.c
@@ -28,7 +28,7 @@
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: 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' 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 33 * unfortunately, this heap cannot be made growable, so the size of
34 blocks it can allocate is limited to (0x80000 - pagesize) 34 blocks it can allocate is limited to (0x80000 - pagesize)
@@ -37,7 +37,7 @@
37 We use a very simple first-fit scheme to reuse those blocks. 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 38 * we check that the private heap does not cross the area used
39 by the bigger chunks. 39 by the bigger chunks.
40 - During the emacs phase: 40 - During the emacs phase, or always if pdumper is used:
41 * we create a private heap for new memory blocks 41 * we create a private heap for new memory blocks
42 * we make sure that we never free a block that has been dumped. 42 * we make sure that we never free a block that has been dumped.
43 Freeing a dumped block could work in principle, but may prove 43 Freeing a dumped block could work in principle, but may prove
@@ -115,10 +115,16 @@ typedef struct _RTL_HEAP_PARAMETERS {
115 than half of the size stated below. It would be nice to find a way 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, 116 to build only the first bootstrap-emacs.exe with the large size,
117 and reset that to a lower value afterwards. */ 117 and reset that to a lower value afterwards. */
118#if defined _WIN64 || defined WIDE_EMACS_INT 118#ifdef CANNOT_DUMP
119# define DUMPED_HEAP_SIZE (23*1024*1024) 119/* We don't use dumped_data[] when CANNOT_DUMP, so define to a small
120 size that won't matter. */
121# define DUMPED_HEAP_SIZE 10
120#else 122#else
121# define DUMPED_HEAP_SIZE (13*1024*1024) 123# if defined _WIN64 || defined WIDE_EMACS_INT
124# define DUMPED_HEAP_SIZE (23*1024*1024)
125# else
126# define DUMPED_HEAP_SIZE (13*1024*1024)
127# endif
122#endif 128#endif
123 129
124static unsigned char dumped_data[DUMPED_HEAP_SIZE]; 130static unsigned char dumped_data[DUMPED_HEAP_SIZE];
@@ -173,8 +179,8 @@ static DWORD blocks_number = 0;
173static unsigned char *bc_limit; 179static unsigned char *bc_limit;
174 180
175/* Handle for the private heap: 181/* Handle for the private heap:
176 - inside the dumped_data[] array before dump, 182 - inside the dumped_data[] array before dump with unexec,
177 - outside of it after dump. 183 - outside of it after dump, or always if pdumper is used.
178*/ 184*/
179HANDLE heap = NULL; 185HANDLE heap = NULL;
180 186
@@ -188,8 +194,8 @@ free_fn the_free_fn;
188 http://stackoverflow.com/questions/307060/what-is-the-purpose-of-allocating-pages-in-the-pagefile-with-createfilemapping */ 194 http://stackoverflow.com/questions/307060/what-is-the-purpose-of-allocating-pages-in-the-pagefile-with-createfilemapping */
189 195
190/* This is the function to commit memory when the heap allocator 196/* This is the function to commit memory when the heap allocator
191 claims for new memory. Before dumping, we allocate space 197 claims for new memory. Before dumping with unexec, we allocate
192 from the fixed size dumped_data[] array. 198 space from the fixed size dumped_data[] array.
193*/ 199*/
194static NTSTATUS NTAPI 200static NTSTATUS NTAPI
195dumped_data_commit (PVOID Base, PVOID *CommitAddress, PSIZE_T CommitSize) 201dumped_data_commit (PVOID Base, PVOID *CommitAddress, PSIZE_T CommitSize)
@@ -223,22 +229,14 @@ typedef enum _HEAP_INFORMATION_CLASS {
223typedef WINBASEAPI BOOL (WINAPI * HeapSetInformation_Proc)(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T); 229typedef WINBASEAPI BOOL (WINAPI * HeapSetInformation_Proc)(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T);
224#endif 230#endif
225 231
226#ifdef HAVE_PDUMPER
227BOOL using_dynamic_heap = FALSE;
228#endif
229
230void 232void
231init_heap (void) 233init_heap (bool use_dynamic_heap)
232{ 234{
233#ifdef HAVE_PDUMPER 235 /* FIXME: Remove the condition, the 'else' branch below, and all the
234 using_dynamic_heap = TRUE; 236 related definitions and code, including dumped_data[], when unexec
235#endif 237 support is removed from Emacs. */
236 if (using_dynamic_heap) 238 if (use_dynamic_heap)
237 { 239 {
238#ifndef MINGW_W64
239 unsigned long enable_lfh = 2;
240#endif
241
242 /* After dumping, use a new private heap. We explicitly enable 240 /* After dumping, use a new private heap. We explicitly enable
243 the low fragmentation heap (LFH) here, for the sake of pre 241 the low fragmentation heap (LFH) here, for the sake of pre
244 Vista versions. Note: this will harmlessly fail on Vista and 242 Vista versions. Note: this will harmlessly fail on Vista and
@@ -255,6 +253,7 @@ init_heap (void)
255 heap = HeapCreate (0, 0, 0); 253 heap = HeapCreate (0, 0, 0);
256 254
257#ifndef MINGW_W64 255#ifndef MINGW_W64
256 unsigned long enable_lfh = 2;
258 /* Set the low-fragmentation heap for OS before Vista. */ 257 /* Set the low-fragmentation heap for OS before Vista. */
259 HMODULE hm_kernel32dll = LoadLibrary ("kernel32.dll"); 258 HMODULE hm_kernel32dll = LoadLibrary ("kernel32.dll");
260 HeapSetInformation_Proc s_pfn_Heap_Set_Information = 259 HeapSetInformation_Proc s_pfn_Heap_Set_Information =
@@ -283,7 +282,7 @@ init_heap (void)
283 the_free_fn = free_after_dump; 282 the_free_fn = free_after_dump;
284 } 283 }
285 } 284 }
286 else 285 else /* Before dumping with unexec: use static heap. */
287 { 286 {
288 /* Find the RtlCreateHeap function. Headers for this function 287 /* Find the RtlCreateHeap function. Headers for this function
289 are provided with the w32 DDK, but the function is available 288 are provided with the w32 DDK, but the function is available
@@ -362,6 +361,8 @@ malloc_after_dump (size_t size)
362 return p; 361 return p;
363} 362}
364 363
364/* FIXME: The *_before_dump functions should be removed when pdumper
365 becomes the only dumping method. */
365void * 366void *
366malloc_before_dump (size_t size) 367malloc_before_dump (size_t size)
367{ 368{
@@ -596,7 +597,7 @@ free_after_dump_9x (void *ptr)
596 } 597 }
597} 598}
598 599
599#ifdef ENABLE_CHECKING 600#if !defined (CANNOT_DUMP) && defined (ENABLE_CHECKING)
600void 601void
601report_temacs_memory_usage (void) 602report_temacs_memory_usage (void)
602{ 603{
diff --git a/src/w32heap.h b/src/w32heap.h
index 6b9dca38a3b..13f7a6325b2 100644
--- a/src/w32heap.h
+++ b/src/w32heap.h
@@ -31,7 +31,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
31extern unsigned char *get_data_start (void); 31extern unsigned char *get_data_start (void);
32extern unsigned char *get_data_end (void); 32extern unsigned char *get_data_end (void);
33extern size_t reserved_heap_size; 33extern size_t reserved_heap_size;
34extern BOOL using_dynamic_heap;
35 34
36extern void *mmap_realloc (void **, size_t); 35extern void *mmap_realloc (void **, size_t);
37extern void mmap_free (void **); 36extern void mmap_free (void **);
@@ -43,7 +42,7 @@ extern void report_temacs_memory_usage (void);
43extern void *sbrk (ptrdiff_t size); 42extern void *sbrk (ptrdiff_t size);
44 43
45/* Initialize heap structures for sbrk on startup. */ 44/* Initialize heap structures for sbrk on startup. */
46extern void init_heap (void); 45extern void init_heap (bool);
47 46
48/* ----------------------------------------------------------------- */ 47/* ----------------------------------------------------------------- */
49/* Useful routines for manipulating memory-mapped files. */ 48/* Useful routines for manipulating memory-mapped files. */
diff --git a/src/w32proc.c b/src/w32proc.c
index a5d08f60117..05e6c46b336 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -81,6 +81,36 @@ static sigset_t sig_mask;
81 81
82static CRITICAL_SECTION crit_sig; 82static CRITICAL_SECTION crit_sig;
83 83
84/* Catch memory allocation before the heap allocation scheme is set
85 up. These functions should never be called, unless code is added
86 early on in 'main' that runs before init_heap is called. */
87_Noreturn void * malloc_before_init (size_t);
88_Noreturn void * realloc_before_init (void *, size_t);
89_Noreturn void free_before_init (void *);
90
91_Noreturn void *
92malloc_before_init (size_t size)
93{
94 fprintf (stderr,
95 "error: 'malloc' called before setting up heap allocation; exiting.\n");
96 exit (-1);
97}
98
99_Noreturn void *
100realloc_before_init (void *ptr, size_t size)
101{
102 fprintf (stderr,
103 "error: 'realloc' called before setting up heap allocation; exiting.\n");
104 exit (-1);
105}
106
107_Noreturn void
108free_before_init (void *ptr)
109{
110 fprintf (stderr,
111 "error: 'free' called before setting up heap allocation; exiting.\n");
112 exit (-1);
113}
84 114
85extern BOOL ctrl_c_handler (unsigned long type); 115extern BOOL ctrl_c_handler (unsigned long type);
86 116
@@ -110,12 +140,13 @@ _start (void)
110 DebugBreak (); 140 DebugBreak ();
111#endif 141#endif
112 142
143 the_malloc_fn = malloc_before_init;
144 the_realloc_fn = realloc_before_init;
145 the_free_fn = free_before_init;
146
113 /* Cache system info, e.g., the NT page size. */ 147 /* Cache system info, e.g., the NT page size. */
114 cache_system_info (); 148 cache_system_info ();
115 149
116 /* Grab our malloc arena space now, before CRT starts up. */
117 init_heap ();
118
119 /* This prevents ctrl-c's in shells running while we're suspended from 150 /* This prevents ctrl-c's in shells running while we're suspended from
120 having us exit. */ 151 having us exit. */
121 SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrl_c_handler, TRUE); 152 SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrl_c_handler, TRUE);