]> code.delx.au - gnu-emacs/blobdiff - src/w32heap.c
Update copyright year to 2016
[gnu-emacs] / src / w32heap.c
index 94ba34287946c6b392fc34eccabaf75be35e1942..54646bfbe3e8b8b7de12c9fe0e744cce108bda21 100644 (file)
@@ -1,5 +1,5 @@
-/* Heap management routines for GNU Emacs on the Microsoft Windows
-   API.  Copyright (C) 1994, 2001-2014 Free Software Foundation, Inc.
+/* Heap management routines for GNU Emacs on the Microsoft Windows API.
+   Copyright (C) 1994, 2001-2016 Free Software Foundation, Inc.
 
    This file is part of GNU Emacs.
 
@@ -52,7 +52,7 @@
 #include <sys/mman.h>
 #include "w32common.h"
 #include "w32heap.h"
-#include "lisp.h"  /* for VALMASK */
+#include "lisp.h"
 
 /* We chose to leave those declarations here.  They are used only in
    this file.  The RtlCreateHeap is available since XP.  It is located
@@ -114,10 +114,10 @@ typedef struct _RTL_HEAP_PARAMETERS {
    than half of the size stated below.  It would be nice to find a way
    to build only the first bootstrap-emacs.exe with the large size,
    and reset that to a lower value afterwards.  */
-#ifdef _WIN64
-# define DUMPED_HEAP_SIZE (18*1024*1024)
+#if defined _WIN64 || defined WIDE_EMACS_INT
+# define DUMPED_HEAP_SIZE (20*1024*1024)
 #else
-# define DUMPED_HEAP_SIZE (11*1024*1024)
+# define DUMPED_HEAP_SIZE (12*1024*1024)
 #endif
 
 static unsigned char dumped_data[DUMPED_HEAP_SIZE];
@@ -200,12 +200,11 @@ dumped_data_commit (PVOID Base, PVOID *CommitAddress, PSIZE_T CommitSize)
      as requests arrive.  */
   *CommitAddress = data_region_base + committed;
   committed += *CommitSize;
+  /* Check that the private heap area does not overlap the big chunks area.  */
   if (((unsigned char *)(*CommitAddress)) + *CommitSize >= bc_limit)
     {
-      /* Check that the private heap area does not overlap the big
-        chunks area.  */
-      fprintf(stderr,
-             "dumped_data_commit: memory exhausted.\nEnlarge dumped_data[]!\n");
+      fprintf (stderr,
+              "dumped_data_commit: memory exhausted.\nEnlarge dumped_data[]!\n");
       exit (-1);
     }
   return 0;
@@ -215,7 +214,7 @@ dumped_data_commit (PVOID Base, PVOID *CommitAddress, PSIZE_T CommitSize)
 
 /* We want to turn on Low Fragmentation Heap for XP and older systems.
    MinGW32 lacks those definitions.  */
-#ifndef _W64
+#ifndef MINGW_W64
 typedef enum _HEAP_INFORMATION_CLASS {
   HeapCompatibilityInformation
 } HEAP_INFORMATION_CLASS;
@@ -243,18 +242,20 @@ init_heap (void)
       data_region_end = data_region_base;
 
       /* Create the private heap.  */
-      heap = HeapCreate(0, 0, 0);
+      heap = HeapCreate (0, 0, 0);
 
-#ifndef _W64
+#ifndef MINGW_W64
       /* Set the low-fragmentation heap for OS before Vista.  */
-      HMODULE hm_kernel32dll = LoadLibrary("kernel32.dll");
-      HeapSetInformation_Proc s_pfn_Heap_Set_Information = (HeapSetInformation_Proc) GetProcAddress(hm_kernel32dll, "HeapSetInformation");
+      HMODULE hm_kernel32dll = LoadLibrary ("kernel32.dll");
+      HeapSetInformation_Proc s_pfn_Heap_Set_Information = (HeapSetInformation_Proc) GetProcAddress (hm_kernel32dll, "HeapSetInformation");
       if (s_pfn_Heap_Set_Information != NULL)
-        if (s_pfn_Heap_Set_Information ((PVOID) heap,
-                                        HeapCompatibilityInformation,
-                                        &enable_lfh, sizeof(enable_lfh)) == 0)
-          DebPrint (("Enabling Low Fragmentation Heap failed: error %ld\n",
-                    GetLastError ()));
+       {
+         if (s_pfn_Heap_Set_Information ((PVOID) heap,
+                                         HeapCompatibilityInformation,
+                                         &enable_lfh, sizeof(enable_lfh)) == 0)
+           DebPrint (("Enabling Low Fragmentation Heap failed: error %ld\n",
+                      GetLastError ()));
+       }
 #endif
 
       the_malloc_fn = malloc_after_dump;
@@ -271,7 +272,7 @@ init_heap (void)
        = (RtlCreateHeap_Proc) GetProcAddress (hm_ntdll, "RtlCreateHeap");
       /* Specific parameters for the private heap.  */
       RTL_HEAP_PARAMETERS params;
-      ZeroMemory(&params, sizeof(params));
+      ZeroMemory (&params, sizeof(params));
       params.Length = sizeof(RTL_HEAP_PARAMETERS);
 
       data_region_base = (unsigned char *)ROUND_UP (dumped_data, 0x1000);
@@ -284,6 +285,11 @@ init_heap (void)
       params.CommitRoutine = &dumped_data_commit;
 
       /* Create the private heap.  */
+      if (s_pfn_Rtl_Create_Heap == NULL)
+       {
+         fprintf (stderr, "Cannot build Emacs without RtlCreateHeap being available; exiting.\n");
+         exit (-1);
+       }
       heap = s_pfn_Rtl_Create_Heap (0, data_region_base, 0, 0, NULL, &params);
       the_malloc_fn = malloc_before_dump;
       the_realloc_fn = realloc_before_dump;
@@ -299,9 +305,10 @@ init_heap (void)
 #undef free
 
 /* FREEABLE_P checks if the block can be safely freed.  */
-#define FREEABLE_P(addr)                                        \
-    ((unsigned char *)(addr) < dumped_data                      \
-     || (unsigned char *)(addr) >= dumped_data + DUMPED_HEAP_SIZE)
+#define FREEABLE_P(addr)                                               \
+    ((unsigned char *)(addr) > 0                                       \
+     && ((unsigned char *)(addr) < dumped_data                         \
+        || (unsigned char *)(addr) >= dumped_data + DUMPED_HEAP_SIZE))
 
 void *
 malloc_after_dump (size_t size)
@@ -358,8 +365,8 @@ malloc_before_dump (size_t size)
             array.  */
          if (blocks_number >= MAX_BLOCKS)
            {
-             fprintf(stderr,
-                     "malloc_before_dump: no more big chunks available.\nEnlarge MAX_BLOCKS!\n");
+             fprintf (stderr,
+                      "malloc_before_dump: no more big chunks available.\nEnlarge MAX_BLOCKS!\n");
              exit (-1);
            }
          bc_limit -= size;
@@ -369,11 +376,11 @@ malloc_before_dump (size_t size)
          blocks[blocks_number].size = size;
          blocks[blocks_number].occupied = TRUE;
          blocks_number++;
+         /* Check that areas do not overlap.  */
          if (bc_limit < dumped_data + committed)
            {
-             /* Check that areas do not overlap.  */
-             fprintf(stderr,
-                     "malloc_before_dump: memory exhausted.\nEnlarge dumped_data[]!\n");
+             fprintf (stderr,
+                      "malloc_before_dump: memory exhausted.\nEnlarge dumped_data[]!\n");
              exit (-1);
            }
        }
@@ -401,10 +408,10 @@ realloc_after_dump (void *ptr, size_t size)
       /* If the block lies in the dumped data, do not free it.  Only
          allocate a new one.  */
       p = HeapAlloc (heap, 0, size);
-      if (p)
-       CopyMemory (p, ptr, size);
-      else
+      if (!p)
        errno = ENOMEM;
+      else if (ptr)
+       CopyMemory (p, ptr, size);
     }
   /* After dump, keep track of the "brk value" for sbrk(0).  */
   if (p)
@@ -443,7 +450,7 @@ realloc_before_dump (void *ptr, size_t size)
         of failing the call as below.  But this doesn't seem to be
         worth the added complexity, as loadup allocates only a very
         small number of large blocks, and never reallocates them.  */
-      if (p)
+      if (p && ptr)
        {
          CopyMemory (p, ptr, size);
          free_before_dump (ptr);
@@ -467,6 +474,9 @@ free_after_dump (void *ptr)
 void
 free_before_dump (void *ptr)
 {
+  if (!ptr)
+    return;
+
   /* Before dumping.  */
   if (dumped_data < (unsigned char *)ptr
       && (unsigned char *)ptr < bc_limit)