aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Innes1999-01-17 19:22:55 +0000
committerAndrew Innes1999-01-17 19:22:55 +0000
commit30d2b1c27b6a85742c49521edf6b76d5e1fbaf95 (patch)
tree24dd566c908b687fa2c0864ce0f37978ecd4ac40 /src
parent5b79dba5b941740286727d2d24091bdec94e2f6f (diff)
downloademacs-30d2b1c27b6a85742c49521edf6b76d5e1fbaf95.tar.gz
emacs-30d2b1c27b6a85742c49521edf6b76d5e1fbaf95.zip
(RVA_TO_PTR): Redefine to convert RVA to address in
current process. (round_to_next): Obsolete function removed. (preload_heap_section): New variable. (data_region_size): Obsolete variable removed. (allocate_heap): Modified to determine end of static heap section used during preload, and use that as initial base address for dynamic heap instead of hard-coded value. (sbrk): Remove call to allocate_heap; handled by init_heap. Skip calls to commit or decommit pages when allocating from static heap section during preload. (recreate_heap): Obsolete function removed. (init_heap): New function to initialize internal sbrk heap variables. Uses static heap section during preload, otherwise calls allocate_heap to reserve a heap region dynamically. (round_heap): Use ROUND_UP macro instead of round_to_next.
Diffstat (limited to 'src')
-rw-r--r--src/w32heap.c173
1 files changed, 69 insertions, 104 deletions
diff --git a/src/w32heap.c b/src/w32heap.c
index 8051ce10cb5..38f7ffe0534 100644
--- a/src/w32heap.c
+++ b/src/w32heap.c
@@ -29,6 +29,9 @@ Boston, MA 02111-1307, USA.
29#include "w32heap.h" 29#include "w32heap.h"
30#include "lisp.h" /* for VALMASK */ 30#include "lisp.h" /* for VALMASK */
31 31
32#undef RVA_TO_PTR
33#define RVA_TO_PTR(rva) ((DWORD)(rva) + (DWORD)GetModuleHandle (NULL))
34
32/* This gives us the page size and the size of the allocation unit on NT. */ 35/* This gives us the page size and the size of the allocation unit on NT. */
33SYSTEM_INFO sysinfo_cache; 36SYSTEM_INFO sysinfo_cache;
34unsigned long syspage_mask = 0; 37unsigned long syspage_mask = 0;
@@ -81,23 +84,14 @@ getpagesize (void)
81 return sysinfo_cache.dwPageSize; 84 return sysinfo_cache.dwPageSize;
82} 85}
83 86
84/* Round ADDRESS up to be aligned with ALIGN. */ 87/* Info for managing our preload heap, which is essentially a fixed size
85unsigned char * 88 data area in the executable. */
86round_to_next (unsigned char *address, unsigned long align) 89PIMAGE_SECTION_HEADER preload_heap_section;
87{
88 unsigned long tmp;
89
90 tmp = (unsigned long) address;
91 tmp = (tmp + align - 1) / align;
92
93 return (unsigned char *) (tmp * align);
94}
95 90
96/* Info for keeping track of our heap. */ 91/* Info for keeping track of our heap. */
97unsigned char *data_region_base = NULL; 92unsigned char *data_region_base = NULL;
98unsigned char *data_region_end = NULL; 93unsigned char *data_region_end = NULL;
99unsigned char *real_data_region_end = NULL; 94unsigned char *real_data_region_end = NULL;
100unsigned long data_region_size = 0;
101unsigned long reserved_heap_size = 0; 95unsigned long reserved_heap_size = 0;
102 96
103/* The start of the data segment. */ 97/* The start of the data segment. */
@@ -117,49 +111,17 @@ get_data_end (void)
117static char * 111static char *
118allocate_heap (void) 112allocate_heap (void)
119{ 113{
120 /* The base address for our GNU malloc heap is chosen in conjuction 114 /* Try to get as much as possible of the address range from the end of
121 with the link settings for temacs.exe which control the stack size, 115 the preload heap section up to the usable address limit. Since GNU
122 the initial default process heap size and the executable image base 116 malloc can handle gaps in the memory it gets from sbrk, we can
123 address. The link settings and the malloc heap base below must all 117 simply set the sbrk pointer to the base of the new heap region. */
124 correspond; the relationship between these values depends on how NT 118 unsigned long base =
125 and Windows 95 arrange the virtual address space for a process (and on 119 ROUND_UP ((RVA_TO_PTR (preload_heap_section->VirtualAddress)
126 the size of the code and data segments in temacs.exe). 120 + preload_heap_section->Misc.VirtualSize),
127 121 get_allocation_unit ());
128 The most important thing is to make base address for the executable
129 image high enough to leave enough room between it and the 4MB floor
130 of the process address space on Windows 95 for the primary thread stack,
131 the process default heap, and other assorted odds and ends
132 (eg. environment strings, private system dll memory etc) that are
133 allocated before temacs has a chance to grab its malloc arena. The
134 malloc heap base can then be set several MB higher than the
135 executable image base, leaving enough room for the code and data
136 segments.
137
138 Because some parts of Emacs can use rather a lot of stack space
139 (for instance, the regular expression routines can potentially
140 allocate several MB of stack space) we allow 8MB for the stack.
141
142 Allowing 1MB for the default process heap, and 1MB for odds and
143 ends, we can base the executable at 16MB and still have a generous
144 safety margin. At the moment, the executable has about 810KB of
145 code (for x86) and about 550KB of data - on RISC platforms the code
146 size could be roughly double, so if we allow 4MB for the executable
147 we will have plenty of room for expansion.
148
149 Thus we would like to set the malloc heap base to 20MB. However,
150 Windows 95 refuses to allocate the heap starting at this address, so we
151 set the base to 27MB to make it happy. Since Emacs now leaves
152 28 bits available for pointers, this lets us use the remainder of
153 the region below the 256MB line for our malloc arena - 229MB is
154 still a pretty decent arena to play in! */
155
156 unsigned long base = 0x01B00000; /* 27MB */
157 unsigned long end = 1 << VALBITS; /* 256MB */ 122 unsigned long end = 1 << VALBITS; /* 256MB */
158 void *ptr = NULL; 123 void *ptr = NULL;
159 124
160#define NTHEAP_PROBE_BASE 1
161#if NTHEAP_PROBE_BASE
162 /* Try various addresses looking for one the kernel will let us have. */
163 while (!ptr && (base < end)) 125 while (!ptr && (base < end))
164 { 126 {
165 reserved_heap_size = end - base; 127 reserved_heap_size = end - base;
@@ -169,13 +131,6 @@ allocate_heap (void)
169 PAGE_NOACCESS); 131 PAGE_NOACCESS);
170 base += 0x00100000; /* 1MB increment */ 132 base += 0x00100000; /* 1MB increment */
171 } 133 }
172#else
173 reserved_heap_size = end - base;
174 ptr = VirtualAlloc ((void *) base,
175 get_reserved_heap_size (),
176 MEM_RESERVE,
177 PAGE_NOACCESS);
178#endif
179 134
180 return ptr; 135 return ptr;
181} 136}
@@ -188,26 +143,6 @@ sbrk (unsigned long increment)
188 void *result; 143 void *result;
189 long size = (long) increment; 144 long size = (long) increment;
190 145
191 /* Allocate our heap if we haven't done so already. */
192 if (!data_region_base)
193 {
194 data_region_base = allocate_heap ();
195 if (!data_region_base)
196 return NULL;
197
198 /* Ensure that the addresses don't use the upper tag bits since
199 the Lisp type goes there. */
200 if (((unsigned long) data_region_base & ~VALMASK) != 0)
201 {
202 printf ("Error: The heap was allocated in upper memory.\n");
203 exit (1);
204 }
205
206 data_region_end = data_region_base;
207 real_data_region_end = data_region_end;
208 data_region_size = get_reserved_heap_size ();
209 }
210
211 result = data_region_end; 146 result = data_region_end;
212 147
213 /* If size is negative, shrink the heap by decommitting pages. */ 148 /* If size is negative, shrink the heap by decommitting pages. */
@@ -229,10 +164,11 @@ sbrk (unsigned long increment)
229 ((long) (new_data_region_end + syspage_mask) & ~syspage_mask); 164 ((long) (new_data_region_end + syspage_mask) & ~syspage_mask);
230 new_size = real_data_region_end - new_data_region_end; 165 new_size = real_data_region_end - new_data_region_end;
231 real_data_region_end = new_data_region_end; 166 real_data_region_end = new_data_region_end;
232 if (new_size > 0) 167 if (new_size > 0)
233 { 168 {
234 /* Decommit size bytes from the end of the heap. */ 169 /* Decommit size bytes from the end of the heap. */
235 if (!VirtualFree (real_data_region_end, new_size, MEM_DECOMMIT)) 170 if (using_dynamic_heap
171 && !VirtualFree (real_data_region_end, new_size, MEM_DECOMMIT))
236 return NULL; 172 return NULL;
237 } 173 }
238 174
@@ -247,8 +183,9 @@ sbrk (unsigned long increment)
247 return NULL; 183 return NULL;
248 184
249 /* Commit more of our heap. */ 185 /* Commit more of our heap. */
250 if (VirtualAlloc (data_region_end, size, MEM_COMMIT, 186 if (using_dynamic_heap
251 PAGE_READWRITE) == NULL) 187 && VirtualAlloc (data_region_end, size, MEM_COMMIT,
188 PAGE_READWRITE) == NULL)
252 return NULL; 189 return NULL;
253 data_region_end += size; 190 data_region_end += size;
254 191
@@ -261,28 +198,56 @@ sbrk (unsigned long increment)
261 return result; 198 return result;
262} 199}
263 200
264/* Recreate the heap from the data that was dumped to the executable. 201/* Initialize the internal heap variables used by sbrk. When running in
265 EXECUTABLE_PATH tells us where to find the executable. */ 202 preload phase (ie. in the undumped executable), we rely entirely on a
203 fixed size heap section included in the .exe itself; this is
204 preserved during dumping, and truncated to the size actually used.
205
206 When running in the dumped executable, we reserve as much as possible
207 of the address range that is addressable by Lisp object pointers, to
208 supplement what is left of the preload heap. Although we cannot rely
209 on the dynamically allocated arena being contiguous with the static
210 heap area, it is not a problem because sbrk can pretend that the gap
211 was allocated by something else; GNU malloc detects when there is a
212 jump in the sbrk values, and starts a new heap block. */
266void 213void
267recreate_heap (char *executable_path) 214init_heap ()
268{ 215{
269 unsigned char *tmp; 216 PIMAGE_DOS_HEADER dos_header;
270 217 PIMAGE_NT_HEADERS nt_header;
271 /* First reserve the upper part of our heap. (We reserve first 218
272 because there have been problems in the past where doing the 219 dos_header = (PIMAGE_DOS_HEADER) RVA_TO_PTR (0);
273 mapping first has loaded DLLs into the VA space of our heap.) */ 220 nt_header = (PIMAGE_NT_HEADERS) (((unsigned long) dos_header) +
274 tmp = VirtualAlloc ((void *) get_heap_end (), 221 dos_header->e_lfanew);
275 get_reserved_heap_size () - get_committed_heap_size (), 222 preload_heap_section = find_section ("EMHEAP", nt_header);
276 MEM_RESERVE, 223
277 PAGE_NOACCESS); 224 if (using_dynamic_heap)
278 if (!tmp) 225 {
279 w32_fatal_reload_error ("Reserving upper heap address space."); 226 data_region_base = allocate_heap ();
280 227 if (!data_region_base)
281 /* We read in the data for the .bss section from the executable 228 {
282 first and map in the heap from the executable second to prevent 229 printf ("Error: Could not reserve dynamic heap area.\n");
283 any funny interactions between file I/O and file mapping. */ 230 exit (1);
284 read_in_bss (executable_path); 231 }
285 map_in_heap (executable_path); 232
233 /* Ensure that the addresses don't use the upper tag bits since
234 the Lisp type goes there. */
235 if (((unsigned long) data_region_base & ~VALMASK) != 0)
236 {
237 printf ("Error: The heap was allocated in upper memory.\n");
238 exit (1);
239 }
240
241 data_region_end = data_region_base;
242 real_data_region_end = data_region_end;
243 }
244 else
245 {
246 data_region_base = RVA_TO_PTR (preload_heap_section->VirtualAddress);
247 data_region_end = data_region_base;
248 real_data_region_end = data_region_end;
249 reserved_heap_size = preload_heap_section->Misc.VirtualSize;
250 }
286 251
287 /* Update system version information to match current system. */ 252 /* Update system version information to match current system. */
288 cache_system_info (); 253 cache_system_info ();
@@ -295,7 +260,7 @@ round_heap (unsigned long align)
295 unsigned long needs_to_be; 260 unsigned long needs_to_be;
296 unsigned long need_to_alloc; 261 unsigned long need_to_alloc;
297 262
298 needs_to_be = (unsigned long) round_to_next (get_heap_end (), align); 263 needs_to_be = (unsigned long) ROUND_UP (get_heap_end (), align);
299 need_to_alloc = needs_to_be - (unsigned long) get_heap_end (); 264 need_to_alloc = needs_to_be - (unsigned long) get_heap_end ();
300 265
301 if (need_to_alloc) 266 if (need_to_alloc)