summaryrefslogtreecommitdiff
path: root/src/w32heap.c
diff options
context:
space:
mode:
authorRichard M. Stallman <rms@gnu.org>1994-11-01 10:27:02 +0000
committerRichard M. Stallman <rms@gnu.org>1994-11-01 10:27:02 +0000
commitb806b54d0af3bf1b2bb68eb4806ed3545ac19c3f (patch)
treebeb54470412d29369c4af72d104fff21e9fb9b07 /src/w32heap.c
parentb2bb196bf2a68779e6a49092ea4a1cf9e9e3adc3 (diff)
downloademacs-b806b54d0af3bf1b2bb68eb4806ed3545ac19c3f.tar.gz
Initial revision
Diffstat (limited to 'src/w32heap.c')
-rw-r--r--src/w32heap.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/src/w32heap.c b/src/w32heap.c
new file mode 100644
index 00000000000..aac860e769b
--- /dev/null
+++ b/src/w32heap.c
@@ -0,0 +1,198 @@
+/* Heap management routines for GNU Emacs on Windows NT.
+ Copyright (C) 1994 Free Software Foundation, Inc.
+
+ This file is part of GNU Emacs.
+
+ GNU Emacs is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with GNU Emacs; see the file COPYING. If not, write to the Free Software
+ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Geoff Voelker (voelker@cs.washington.edu) 7-29-94
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "ntheap.h"
+
+/* This gives us the page size and the size of the allocation unit on NT. */
+SYSTEM_INFO sysinfo_cache;
+
+/* These are defined to get Emacs to compile, but are not used. */
+int edata;
+int etext;
+
+/* The major and minor versions of NT. */
+int nt_major_version;
+int nt_minor_version;
+
+/* Cache information describing the NT system for later use. */
+void
+cache_system_info (void)
+{
+ union
+ {
+ struct info
+ {
+ char major;
+ char minor;
+ short platform;
+ } info;
+ DWORD data;
+ } version;
+
+ /* Cache the version of the operating system. */
+ version.data = GetVersion ();
+ nt_major_version = version.info.major;
+ nt_minor_version = version.info.minor;
+
+ /* Cache page size, allocation unit, processor type, etc. */
+ GetSystemInfo (&sysinfo_cache);
+}
+
+/* Round ADDRESS up to be aligned with ALIGN. */
+unsigned char *
+round_to_next (unsigned char *address, unsigned long align)
+{
+ unsigned long tmp;
+
+ tmp = (unsigned long) address;
+ tmp = (tmp + align - 1) / align;
+
+ return (unsigned char *) (tmp * align);
+}
+
+/* Info for keeping track of our heap. */
+unsigned char *data_region_base = NULL;
+unsigned char *data_region_end = NULL;
+unsigned long data_region_size = 0;
+
+/* The start of the data segment. */
+unsigned char *
+get_data_start (void)
+{
+ return data_region_base;
+}
+
+/* The end of the data segment. */
+unsigned char *
+get_data_end (void)
+{
+ return data_region_end;
+}
+
+/* Emulate Unix sbrk. */
+void *
+sbrk (unsigned long increment)
+{
+ void *result;
+ long size = (long) increment;
+
+ /* Allocate our heap if we haven't done so already. */
+ if (!data_region_base)
+ {
+ data_region_base = VirtualAlloc ((void *) get_data_region_base (),
+ get_reserved_heap_size (),
+ MEM_RESERVE,
+ PAGE_NOACCESS);
+ if (!data_region_base)
+ return NULL;
+
+ /* Ensure that the addresses don't use the upper 8 bits since
+ the Lisp type goes there (yucko). */
+ if (((unsigned long) data_region_base & 0xFF000000) != 0)
+ {
+ printf ("Error: The heap was allocated in upper memory.\n");
+ exit (1);
+ }
+
+ data_region_end = data_region_base;
+ data_region_size = get_reserved_heap_size ();
+ }
+
+ result = data_region_end;
+
+ /* If size is negative, shrink the heap by decommitting pages. */
+ if (size < 0)
+ {
+ size = -size;
+
+ /* Sanity checks. */
+ if (size % get_page_size () != 0)
+ return NULL;
+ if ((data_region_end - size) < data_region_base)
+ return NULL;
+
+ /* Decommit size bytes from the end of the heap. */
+ if (!VirtualFree (data_region_end - size, size, MEM_DECOMMIT))
+ return NULL;
+
+ data_region_end -= size;
+ }
+ /* If size is positive, grow the heap by committing reserved pages. */
+ else if (size > 0)
+ {
+ /* Sanity checks. */
+ if (size % get_page_size () != 0)
+ return NULL;
+ if ((data_region_end + size) >
+ (data_region_base + get_reserved_heap_size ()))
+ return NULL;
+
+ /* Commit more of our heap. */
+ if (VirtualAlloc (data_region_end, size, MEM_COMMIT,
+ PAGE_READWRITE) == NULL)
+ return NULL;
+ data_region_end += size;
+ }
+
+ return result;
+}
+
+/* Recreate the heap from the data that was dumped to the executable.
+ EXECUTABLE_PATH tells us where to find the executable. */
+void
+recreate_heap (char *executable_path)
+{
+ unsigned char *tmp;
+
+ /* First reserve the upper part of our heap. (We reserve first
+ because there have been problems in the past where doing the
+ mapping first has loaded DLLs into the VA space of our heap.) */
+ tmp = VirtualAlloc ((void *) get_heap_end (),
+ get_reserved_heap_size () - get_committed_heap_size (),
+ MEM_RESERVE,
+ PAGE_NOACCESS);
+ if (!tmp)
+ exit (1);
+
+ /* We read in the data for the .bss section from the executable
+ first and map in the heap from the executable second to prevent
+ any funny interactions between file I/O and file mapping. */
+ read_in_bss (executable_path);
+ map_in_heap (executable_path);
+}
+
+/* Round the heap up to the given alignment. */
+void
+round_heap (unsigned long align)
+{
+ unsigned long needs_to_be;
+ unsigned long need_to_alloc;
+
+ needs_to_be = (unsigned long) round_to_next (get_heap_end (), align);
+ need_to_alloc = needs_to_be - (unsigned long) get_heap_end ();
+
+ if (need_to_alloc)
+ sbrk (need_to_alloc);
+}