1 /* Heap management routines for GNU Emacs on Windows NT.
2 Copyright (C) 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any later
11 GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 You should have received a copy of the GNU General Public License along
17 with GNU Emacs; see the file COPYING. If not, write to the Free Software
18 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
30 /* This gives us the page size and the size of the allocation unit on NT. */
31 SYSTEM_INFO sysinfo_cache
;
32 unsigned long syspage_mask
= 0;
34 /* These are defined to get Emacs to compile, but are not used. */
38 /* The major and minor versions of NT. */
42 /* Cache information describing the NT system for later use. */
44 cache_system_info (void)
57 /* Cache the version of the operating system. */
58 version
.data
= GetVersion ();
59 nt_major_version
= version
.info
.major
;
60 nt_minor_version
= version
.info
.minor
;
62 /* Cache page size, allocation unit, processor type, etc. */
63 GetSystemInfo (&sysinfo_cache
);
64 syspage_mask
= sysinfo_cache
.dwPageSize
- 1;
67 /* Round ADDRESS up to be aligned with ALIGN. */
69 round_to_next (unsigned char *address
, unsigned long align
)
73 tmp
= (unsigned long) address
;
74 tmp
= (tmp
+ align
- 1) / align
;
76 return (unsigned char *) (tmp
* align
);
79 /* Info for keeping track of our heap. */
80 unsigned char *data_region_base
= NULL
;
81 unsigned char *data_region_end
= NULL
;
82 unsigned char *real_data_region_end
= NULL
;
83 unsigned long data_region_size
= 0;
84 unsigned long reserved_heap_size
= 0;
86 /* The start of the data segment. */
90 return data_region_base
;
93 /* The end of the data segment. */
97 return data_region_end
;
104 unsigned long base
= 0x00030000;
105 unsigned long end
= 0x00D00000;
107 reserved_heap_size
= end
- base
;
109 return VirtualAlloc ((void *) base
,
110 get_reserved_heap_size (),
118 unsigned long start
= 0x400000;
119 unsigned long stop
= 0xD00000;
120 unsigned long increment
= 0x100000;
121 char *ptr
, *begin
= NULL
, *end
= NULL
;
124 for (i
= start
; i
< stop
; i
+= increment
)
126 ptr
= VirtualAlloc ((void *) i
, increment
, MEM_RESERVE
, PAGE_NOACCESS
);
128 begin
= begin
? begin
: ptr
;
140 /* We couldn't allocate any memory for the heap. Exit. */
143 reserved_heap_size
= end
- begin
;
149 /* Emulate Unix sbrk. */
151 sbrk (unsigned long increment
)
154 long size
= (long) increment
;
156 /* Allocate our heap if we haven't done so already. */
157 if (!data_region_base
)
159 data_region_base
= allocate_heap ();
160 if (!data_region_base
)
163 /* Ensure that the addresses don't use the upper 8 bits since
164 the Lisp type goes there (yucko). */
165 if (((unsigned long) data_region_base
& 0xFF000000) != 0)
167 printf ("Error: The heap was allocated in upper memory.\n");
171 data_region_end
= data_region_base
;
172 real_data_region_end
= data_region_end
;
173 data_region_size
= get_reserved_heap_size ();
176 result
= data_region_end
;
178 /* If size is negative, shrink the heap by decommitting pages. */
182 unsigned char *new_data_region_end
;
187 if ((data_region_end
- size
) < data_region_base
)
190 /* We can only decommit full pages, so allow for
191 partial deallocation [cga]. */
192 new_data_region_end
= (data_region_end
- size
);
193 new_data_region_end
= (unsigned char *)
194 ((long) (new_data_region_end
+ syspage_mask
) & ~syspage_mask
);
195 new_size
= real_data_region_end
- new_data_region_end
;
196 real_data_region_end
= new_data_region_end
;
199 /* Decommit size bytes from the end of the heap. */
200 if (!VirtualFree (real_data_region_end
, new_size
, MEM_DECOMMIT
))
204 data_region_end
-= size
;
206 /* If size is positive, grow the heap by committing reserved pages. */
210 if ((data_region_end
+ size
) >
211 (data_region_base
+ get_reserved_heap_size ()))
214 /* Commit more of our heap. */
215 if (VirtualAlloc (data_region_end
, size
, MEM_COMMIT
,
216 PAGE_READWRITE
) == NULL
)
218 data_region_end
+= size
;
220 /* We really only commit full pages, so record where
221 the real end of committed memory is [cga]. */
222 real_data_region_end
= (unsigned char *)
223 ((long) (data_region_end
+ syspage_mask
) & ~syspage_mask
);
229 /* Recreate the heap from the data that was dumped to the executable.
230 EXECUTABLE_PATH tells us where to find the executable. */
232 recreate_heap (char *executable_path
)
236 /* First reserve the upper part of our heap. (We reserve first
237 because there have been problems in the past where doing the
238 mapping first has loaded DLLs into the VA space of our heap.) */
239 tmp
= VirtualAlloc ((void *) get_heap_end (),
240 get_reserved_heap_size () - get_committed_heap_size (),
246 /* We read in the data for the .bss section from the executable
247 first and map in the heap from the executable second to prevent
248 any funny interactions between file I/O and file mapping. */
249 read_in_bss (executable_path
);
250 map_in_heap (executable_path
);
253 /* Round the heap up to the given alignment. */
255 round_heap (unsigned long align
)
257 unsigned long needs_to_be
;
258 unsigned long need_to_alloc
;
260 needs_to_be
= (unsigned long) round_to_next (get_heap_end (), align
);
261 need_to_alloc
= needs_to_be
- (unsigned long) get_heap_end ();
264 sbrk (need_to_alloc
);