]> code.delx.au - gnu-emacs/blobdiff - src/w32heap.c
upstream
[gnu-emacs] / src / w32heap.c
index bbdabd2350261f4ac255dab4dda8351f4262f555..8b9b19ea35de383499863d2c0cc0a7eb3368454b 100644 (file)
@@ -1,5 +1,5 @@
-/* Heap management routines for GNU Emacs on the Microsoft W32 API.
-   Copyright (C) 1994, 2001-2011  Free Software Foundation, Inc.
+/* Heap management routines for GNU Emacs on the Microsoft Windows API.
+   Copyright (C) 1994, 2001-2012  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -22,12 +22,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
-#include <setjmp.h>
 
 #include "w32heap.h"
 #include "lisp.h"  /* for VALMASK */
 
-#define RVA_TO_PTR(rva) ((unsigned char *)((DWORD)(rva) + (DWORD)GetModuleHandle (NULL)))
+#define RVA_TO_PTR(rva) ((unsigned char *)((DWORD_PTR)(rva) + (DWORD_PTR)GetModuleHandle (NULL)))
 
 /* This gives us the page size and the size of the allocation unit on NT.  */
 SYSTEM_INFO sysinfo_cache;
@@ -35,7 +34,7 @@ SYSTEM_INFO sysinfo_cache;
 /* This gives us version, build, and platform identification.  */
 OSVERSIONINFO osinfo_cache;
 
-unsigned long syspage_mask = 0;
+size_t syspage_mask = 0;
 
 /* The major and minor versions of NT.  */
 int w32_major_version;
@@ -66,7 +65,7 @@ cache_system_info (void)
   w32_minor_version = version.info.minor;
 
   if (version.info.platform & 0x8000)
-    os_subtype = OS_WIN95;
+    os_subtype = OS_9X;
   else
     os_subtype = OS_NT;
 
@@ -79,7 +78,7 @@ cache_system_info (void)
   GetVersionEx (&osinfo_cache);
 
   w32_build_number = osinfo_cache.dwBuildNumber;
-  if (os_subtype == OS_WIN95)
+  if (os_subtype == OS_9X)
     w32_build_number &= 0xffff;
 }
 
@@ -98,7 +97,7 @@ PIMAGE_SECTION_HEADER preload_heap_section;
 unsigned char *data_region_base = NULL;
 unsigned char *data_region_end = NULL;
 unsigned char *real_data_region_end = NULL;
-unsigned long  reserved_heap_size = 0;
+size_t  reserved_heap_size = 0;
 
 /* The start of the data segment.  */
 unsigned char *
@@ -114,6 +113,7 @@ get_data_end (void)
   return data_region_end;
 }
 
+#if !USE_LSB_TAG
 static char *
 allocate_heap (void)
 {
@@ -121,16 +121,20 @@ allocate_heap (void)
      the preload heap section up to the usable address limit.  Since GNU
      malloc can handle gaps in the memory it gets from sbrk, we can
      simply set the sbrk pointer to the base of the new heap region.  */
-  unsigned long base =
+  DWORD_PTR base =
     ROUND_UP ((RVA_TO_PTR (preload_heap_section->VirtualAddress)
               + preload_heap_section->Misc.VirtualSize),
              get_allocation_unit ());
-  unsigned long end  = 1 << VALBITS; /* 256MB */
+  DWORD_PTR end  = ((unsigned __int64)1) << VALBITS; /* 256MB */
   void *ptr = NULL;
 
   while (!ptr && (base < end))
     {
+#ifdef _WIN64
+      reserved_heap_size = min(end - base, 0x4000000000i64); /* Limit to 256Gb */
+#else
       reserved_heap_size = end - base;
+#endif
       ptr = VirtualAlloc ((void *) base,
                          get_reserved_heap_size (),
                          MEM_RESERVE,
@@ -140,21 +144,47 @@ allocate_heap (void)
 
   return ptr;
 }
+#else  /* USE_LSB_TAG */
+static char *
+allocate_heap (void)
+{
+#ifdef _WIN64
+  size_t size = 0x4000000000i64; /* start by asking for 32GB */
+#else
+  size_t size = 0x80000000; /* start by asking for 2GB */
+#endif
+  void *ptr = NULL;
+
+  while (!ptr && size > 0x00100000)
+    {
+      reserved_heap_size = size;
+      ptr = VirtualAlloc (NULL,
+                         get_reserved_heap_size (),
+                         MEM_RESERVE,
+                         PAGE_NOACCESS);
+      size -= 0x00800000; /* if failed, decrease request by 8MB */
+    }
+
+  return ptr;
+}
+#endif /* USE_LSB_TAG */
 
 
-/* Emulate Unix sbrk.  */
+/* Emulate Unix sbrk.  Note that ralloc.c expects the return value to
+   be the address of the _start_ (not end) of the new block in case of
+   success, and zero (not -1) in case of failure.  */
 void *
-sbrk (unsigned long increment)
+sbrk (ptrdiff_t increment)
 {
   void *result;
-  long size = (long) increment;
+  ptrdiff_t size = increment;
 
   result = data_region_end;
 
   /* If size is negative, shrink the heap by decommitting pages.  */
   if (size < 0)
     {
-      int new_size;
+      ptrdiff_t new_size;
       unsigned char *new_data_region_end;
 
       size = -size;
@@ -167,7 +197,7 @@ sbrk (unsigned long increment)
         partial deallocation [cga].  */
       new_data_region_end = (data_region_end - size);
       new_data_region_end = (unsigned char *)
-       ((long) (new_data_region_end + syspage_mask) & ~syspage_mask);
+       ((DWORD_PTR) (new_data_region_end + syspage_mask) & ~syspage_mask);
       new_size = real_data_region_end - new_data_region_end;
       real_data_region_end = new_data_region_end;
       if (new_size > 0)
@@ -198,7 +228,7 @@ sbrk (unsigned long increment)
       /* We really only commit full pages, so record where
         the real end of committed memory is [cga].  */
       real_data_region_end = (unsigned char *)
-         ((long) (data_region_end + syspage_mask) & ~syspage_mask);
+         ((DWORD_PTR) (data_region_end + syspage_mask) & ~syspage_mask);
     }
 
   return result;
@@ -223,7 +253,7 @@ init_heap (void)
   PIMAGE_NT_HEADERS nt_header;
 
   dos_header = (PIMAGE_DOS_HEADER) RVA_TO_PTR (0);
-  nt_header = (PIMAGE_NT_HEADERS) (((unsigned long) dos_header) +
+  nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) dos_header) +
                                   dos_header->e_lfanew);
   preload_heap_section = find_section ("EMHEAP", nt_header);
 
@@ -236,10 +266,10 @@ init_heap (void)
          exit (1);
        }
 
-#if !defined (USE_LISP_UNION_TYPE) && !defined (USE_LSB_TAG)
+#if !USE_LSB_TAG
       /* Ensure that the addresses don't use the upper tag bits since
         the Lisp type goes there.  */
-      if (((unsigned long) data_region_base & ~VALMASK) != 0)
+      if (((DWORD_PTR) data_region_base & ~VALMASK) != 0)
        {
          printf ("Error: The heap was allocated in upper memory.\n");
          exit (1);
@@ -262,38 +292,14 @@ init_heap (void)
 
 /* Round the heap up to the given alignment.  */
 void
-round_heap (unsigned long align)
+round_heap (size_t align)
 {
-  unsigned long needs_to_be;
-  unsigned long need_to_alloc;
+  DWORD_PTR needs_to_be;
+  DWORD_PTR need_to_alloc;
 
-  needs_to_be = (unsigned long) ROUND_UP (get_heap_end (), align);
-  need_to_alloc = needs_to_be - (unsigned long) get_heap_end ();
+  needs_to_be = (DWORD_PTR) ROUND_UP (get_heap_end (), align);
+  need_to_alloc = needs_to_be - (DWORD_PTR) get_heap_end ();
 
   if (need_to_alloc)
     sbrk (need_to_alloc);
 }
-
-#if (_MSC_VER >= 1000 && _MSC_VER < 1300 && !defined (USE_CRT_DLL))
-
-/* MSVC 4.2 invokes these functions from mainCRTStartup to initialize
-   a heap via HeapCreate.  They are normally defined by the runtime,
-   but we override them here so that the unnecessary HeapCreate call
-   is not performed.  */
-
-int __cdecl
-_heap_init (void)
-{
-  /* Stepping through the assembly indicates that mainCRTStartup is
-     expecting a nonzero success return value.  */
-  return 1;
-}
-
-void __cdecl
-_heap_term (void)
-{
-  return;
-}
-
-#endif
-