]> code.delx.au - gnu-emacs/blobdiff - src/ralloc.c
Merge from emacs-24; up to 2012-05-04T19:17:01Z!monnier@iro.umontreal.ca
[gnu-emacs] / src / ralloc.c
index 896ad9f3155b06fde7914f889f3d2c9fa2e777fb..3877e21d4f681c4e7b1258a1f5dd92764c1ba9db 100644 (file)
@@ -31,9 +31,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <unistd.h>
 
-typedef POINTER_TYPE *POINTER;
-typedef size_t SIZE;
-
 #ifdef DOUG_LEA_MALLOC
 #define M_TOP_PAD           -2
 extern int mallopt (int, int);
@@ -47,9 +44,6 @@ extern size_t __malloc_extra_blocks;
 
 #include <stddef.h>
 
-typedef size_t SIZE;
-typedef void *POINTER;
-
 #include <unistd.h>
 #include <malloc.h>
 
@@ -58,6 +52,8 @@ typedef void *POINTER;
 
 #include "getpagesize.h"
 
+typedef size_t SIZE;
+typedef void *POINTER;
 #define NIL ((POINTER) 0)
 
 /* A flag to indicate whether we have initialized ralloc yet.  For
@@ -95,10 +91,8 @@ static int extra_bytes;
 /* Macros for rounding.  Note that rounding to any value is possible
    by changing the definition of PAGE.  */
 #define PAGE (getpagesize ())
-#define ALIGNED(addr) (((unsigned long int) (addr) & (page_size - 1)) == 0)
 #define ROUNDUP(size) (((unsigned long int) (size) + page_size - 1) \
                       & ~(page_size - 1))
-#define ROUND_TO_PAGE(addr) (addr & (~(page_size - 1)))
 
 #define MEM_ALIGN sizeof (double)
 #define MEM_ROUNDUP(addr) (((unsigned long int)(addr) + MEM_ALIGN - 1) \
@@ -151,7 +145,6 @@ typedef struct heap
 } *heap_ptr;
 
 #define NIL_HEAP ((heap_ptr) 0)
-#define HEAP_PTR_SIZE (sizeof (struct heap))
 
 /* This is the first heap object.
    If we need additional heap objects, each one resides at the beginning of
@@ -366,15 +359,6 @@ relinquish (void)
        }
     }
 }
-
-/* Return the total size in use by relocating allocator,
-   above where malloc gets space.  */
-
-long
-r_alloc_size_in_use (void)
-{
-  return (char *) break_value - (char *) virtual_break_value;
-}
 \f
 /* The meat - allocating, freeing, and relocating blocs.  */
 
@@ -412,7 +396,7 @@ get_bloc (SIZE size)
   register bloc_ptr new_bloc;
   register heap_ptr heap;
 
-  if (! (new_bloc = (bloc_ptr) malloc (BLOC_PTR_SIZE))
+  if (! (new_bloc = malloc (BLOC_PTR_SIZE))
       || ! (new_bloc->data = obtain (break_value, size)))
     {
       free (new_bloc);
@@ -686,6 +670,7 @@ static void
 free_bloc (bloc_ptr bloc)
 {
   heap_ptr heap = bloc->heap;
+  heap_ptr h;
 
   if (r_alloc_freeze_level)
     {
@@ -715,20 +700,38 @@ free_bloc (bloc_ptr bloc)
       bloc->prev->next = bloc->next;
     }
 
-  /* Update the records of which blocs are in HEAP.  */
-  if (heap->first_bloc == bloc)
-    {
-      if (bloc->next != 0 && bloc->next->heap == heap)
-       heap->first_bloc = bloc->next;
-      else
-       heap->first_bloc = heap->last_bloc = NIL_BLOC;
-    }
-  if (heap->last_bloc == bloc)
+  /* Sometimes, 'heap' obtained from bloc->heap above is not really a
+     'heap' structure.  It can even be beyond the current break point,
+     which will cause crashes when we dereference it below (see
+     bug#12242).  Evidently, the reason is bloc allocations done while
+     use_relocatable_buffers was non-positive, because additional
+     memory we get then is not recorded in the heaps we manage.  If
+     bloc->heap records such a "heap", we cannot (and don't need to)
+     update its records.  So we validate the 'heap' value by making
+     sure it is one of the heaps we manage via the heaps linked list,
+     and don't touch a 'heap' that isn't found there.  This avoids
+     accessing memory we know nothing about.  */
+  for (h = first_heap; h != NIL_HEAP; h = h->next)
+    if (heap == h)
+      break;
+
+  if (h)
     {
-      if (bloc->prev != 0 && bloc->prev->heap == heap)
-       heap->last_bloc = bloc->prev;
-      else
-       heap->first_bloc = heap->last_bloc = NIL_BLOC;
+      /* Update the records of which blocs are in HEAP.  */
+      if (heap->first_bloc == bloc)
+       {
+         if (bloc->next != 0 && bloc->next->heap == heap)
+           heap->first_bloc = bloc->next;
+         else
+           heap->first_bloc = heap->last_bloc = NIL_BLOC;
+       }
+      if (heap->last_bloc == bloc)
+       {
+         if (bloc->prev != 0 && bloc->prev->heap == heap)
+           heap->last_bloc = bloc->prev;
+         else
+           heap->first_bloc = heap->last_bloc = NIL_BLOC;
+       }
     }
 
   relinquish ();
@@ -748,7 +751,7 @@ free_bloc (bloc_ptr bloc)
    __morecore hook values - in particular, __default_morecore in the
    GNU malloc package.  */
 
-POINTER
+static POINTER
 r_alloc_sbrk (long int size)
 {
   register bloc_ptr b;
@@ -757,7 +760,7 @@ r_alloc_sbrk (long int size)
   if (! r_alloc_initialized)
     r_alloc_init ();
 
-  if (! use_relocatable_buffers)
+  if (use_relocatable_buffers <= 0)
     return (*real_morecore) (size);
 
   if (size == 0)
@@ -1014,52 +1017,6 @@ r_re_alloc (POINTER *ptr, SIZE size)
   return *ptr;
 }
 
-/* Disable relocations, after making room for at least SIZE bytes
-   of non-relocatable heap if possible.  The relocatable blocs are
-   guaranteed to hold still until thawed, even if this means that
-   malloc must return a null pointer.  */
-
-void
-r_alloc_freeze (long int size)
-{
-  if (! r_alloc_initialized)
-    r_alloc_init ();
-
-  /* If already frozen, we can't make any more room, so don't try.  */
-  if (r_alloc_freeze_level > 0)
-    size = 0;
-  /* If we can't get the amount requested, half is better than nothing.  */
-  while (size > 0 && r_alloc_sbrk (size) == 0)
-    size /= 2;
-  ++r_alloc_freeze_level;
-  if (size > 0)
-    r_alloc_sbrk (-size);
-}
-
-void
-r_alloc_thaw (void)
-{
-
-  if (! r_alloc_initialized)
-    r_alloc_init ();
-
-  if (--r_alloc_freeze_level < 0)
-    abort ();
-
-  /* This frees all unused blocs.  It is not too inefficient, as the resize
-     and memcpy is done only once.  Afterwards, all unreferenced blocs are
-     already shrunk to zero size.  */
-  if (!r_alloc_freeze_level)
-    {
-      bloc_ptr *b = &first_bloc;
-      while (*b)
-       if (!(*b)->variable)
-         free_bloc (*b);
-       else
-         b = &(*b)->next;
-    }
-}
-
 
 #if defined (emacs) && defined (DOUG_LEA_MALLOC)
 
@@ -1201,6 +1158,17 @@ r_alloc_reset_variable (POINTER *old, POINTER *new)
   bloc->variable = new;
 }
 
+void
+r_alloc_inhibit_buffer_relocation (int inhibit)
+{
+  if (use_relocatable_buffers > 1)
+    use_relocatable_buffers = 1;
+  if (inhibit)
+    use_relocatable_buffers--;
+  else if (use_relocatable_buffers < 1)
+    use_relocatable_buffers++;
+}
+
 \f
 /***********************************************************************
                            Initialization