]> code.delx.au - gnu-emacs/blobdiff - src/w32heap.c
Update copyright year to 2014 by running admin/update-copyright.
[gnu-emacs] / src / w32heap.c
index 35ac4cbf31ff6c71ce16e5d8f2a3ea5acecd6e08..8ab2f58c6e70c6a80849f9ec15163393e9e4638d 100644 (file)
@@ -1,5 +1,5 @@
-/* Heap management routines for GNU Emacs on the Microsoft W32 API.
-   Copyright (C) 1994, 2001-201 Free Software Foundation, Inc.
+/* Heap management routines for GNU Emacs on the Microsoft Windows API.
+   Copyright (C) 1994, 2001-2014 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -22,66 +22,12 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
-#include <setjmp.h>
 
+#include "w32common.h"
 #include "w32heap.h"
 #include "lisp.h"  /* for VALMASK */
 
-#define RVA_TO_PTR(rva) ((unsigned char *)((DWORD)(rva) + (DWORD)GetModuleHandle (NULL)))
-
-/* This gives us the page size and the size of the allocation unit on NT.  */
-SYSTEM_INFO sysinfo_cache;
-
-/* This gives us version, build, and platform identification.  */
-OSVERSIONINFO osinfo_cache;
-
-unsigned long syspage_mask = 0;
-
-/* The major and minor versions of NT.  */
-int w32_major_version;
-int w32_minor_version;
-int w32_build_number;
-
-/* Distinguish between Windows NT and Windows 95.  */
-int os_subtype;
-
-/* 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 ();
-  w32_major_version = version.info.major;
-  w32_minor_version = version.info.minor;
-
-  if (version.info.platform & 0x8000)
-    os_subtype = OS_WIN95;
-  else
-    os_subtype = OS_NT;
-
-  /* Cache page size, allocation unit, processor type, etc.  */
-  GetSystemInfo (&sysinfo_cache);
-  syspage_mask = sysinfo_cache.dwPageSize - 1;
-
-  /* Cache os info.  */
-  osinfo_cache.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
-  GetVersionEx (&osinfo_cache);
-
-  w32_build_number = osinfo_cache.dwBuildNumber;
-  if (os_subtype == OS_WIN95)
-    w32_build_number &= 0xffff;
-}
+#define RVA_TO_PTR(rva) ((unsigned char *)((DWORD_PTR)(rva) + (DWORD_PTR)GetModuleHandle (NULL)))
 
 /* Emulate getpagesize.  */
 int
@@ -98,7 +44,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,7 +60,7 @@ get_data_end (void)
   return data_region_end;
 }
 
-#if !defined (USE_LISP_UNION_TYPE) && !defined (USE_LSB_TAG)
+#if !USE_LSB_TAG
 static char *
 allocate_heap (void)
 {
@@ -122,16 +68,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, 0x4000000000ull); /* Limit to 256Gb */
+#else
       reserved_heap_size = end - base;
+#endif
       ptr = VirtualAlloc ((void *) base,
                          get_reserved_heap_size (),
                          MEM_RESERVE,
@@ -141,11 +91,19 @@ allocate_heap (void)
 
   return ptr;
 }
-#else  /* USE_LISP_UNION_TYPE || USE_LSB_TAG */
+#else  /* USE_LSB_TAG */
 static char *
 allocate_heap (void)
 {
-  unsigned long size = 0x80000000; /* start by asking for 2GB */
+#ifdef _WIN64
+  size_t size = 0x4000000000ull; /* start by asking for 32GB */
+#else
+  /* We used to start with 2GB here, but on Windows 7 that would leave
+     too little room in the address space for threads started by
+     Windows on our behalf, e.g. when we pop up the file selection
+     dialog.  */
+  size_t size = 0x68000000; /* start by asking for 1.7GB */
+#endif
   void *ptr = NULL;
 
   while (!ptr && size > 0x00100000)
@@ -160,24 +118,24 @@ allocate_heap (void)
 
   return ptr;
 }
-#endif /* USE_LISP_UNION_TYPE || USE_LSB_TAG */
+#endif /* USE_LSB_TAG */
 
 
 /* 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;
@@ -190,7 +148,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)
@@ -221,7 +179,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;
@@ -246,7 +204,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);
 
@@ -259,10 +217,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);
@@ -285,38 +243,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
-