Fix previous conflict.
[bpt/emacs.git] / src / ralloc.c
index e39ed5a..0a2b156 100644 (file)
@@ -1,13 +1,13 @@
 /* Block-relocating memory allocator.
    Copyright (C) 1993, 1995, 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007  Free Software Foundation, Inc.
+                 2005, 2006, 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+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 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, 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
@@ -15,9 +15,7 @@ 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, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* NOTES:
 
@@ -28,6 +26,7 @@ Boston, MA 02110-1301, USA.  */
 #ifdef emacs
 
 #include <config.h>
+#include <setjmp.h>
 #include "lisp.h"              /* Needed for VALBITS.  */
 #include "blockinput.h"
 
@@ -38,14 +37,9 @@ Boston, MA 02110-1301, USA.  */
 typedef POINTER_TYPE *POINTER;
 typedef size_t SIZE;
 
-/* Declared in dispnew.c, this version doesn't screw up if regions
-   overlap.  */
-
-extern void safe_bcopy ();
-
 #ifdef DOUG_LEA_MALLOC
 #define M_TOP_PAD           -2
-extern int mallopt ();
+extern int mallopt (int, int);
 #else /* not DOUG_LEA_MALLOC */
 #ifndef SYSTEM_MALLOC
 extern size_t __malloc_extra_blocks;
@@ -62,9 +56,6 @@ typedef void *POINTER;
 #include <unistd.h>
 #include <malloc.h>
 
-#define safe_bcopy(x, y, z) memmove (y, x, z)
-#define bzero(x, len) memset (x, 0, len)
-
 #endif /* not emacs */
 
 
@@ -82,7 +73,7 @@ typedef void *POINTER;
 
 static int r_alloc_initialized = 0;
 
-static void r_alloc_init ();
+static void r_alloc_init (void);
 
 \f
 /* Declarations for working with the malloc, ralloc, and system breaks.  */
@@ -179,9 +170,9 @@ static heap_ptr first_heap, last_heap;
    b->data + b->size == b->next->data.
 
    An element with variable==NIL denotes a freed block, which has not yet
-   been collected.  They may only appear while r_alloc_freeze > 0, and will be
-   freed when the arena is thawed.  Currently, these blocs are not reusable,
-   while the arena is frozen.  Very inefficient.  */
+   been collected.  They may only appear while r_alloc_freeze_level > 0,
+   and will be freed when the arena is thawed.  Currently, these blocs are
+   not reusable, while the arena is frozen.  Very inefficient.  */
 
 typedef struct bp
 {
@@ -211,8 +202,7 @@ static int r_alloc_freeze_level;
 /* Find the heap that ADDRESS falls within.  */
 
 static heap_ptr
-find_heap (address)
-    POINTER address;
+find_heap (POINTER address)
 {
   heap_ptr heap;
 
@@ -244,9 +234,7 @@ find_heap (address)
    allocate the memory.  */
 
 static POINTER
-obtain (address, size)
-    POINTER address;
-    SIZE size;
+obtain (POINTER address, SIZE size)
 {
   heap_ptr heap;
   SIZE already_available;
@@ -327,7 +315,7 @@ obtain (address, size)
    it can also eliminate the last heap entirely.  */
 
 static void
-relinquish ()
+relinquish (void)
 {
   register heap_ptr h;
   long excess = 0;
@@ -386,7 +374,7 @@ relinquish ()
    above where malloc gets space.  */
 
 long
-r_alloc_size_in_use ()
+r_alloc_size_in_use (void)
 {
   return (char *) break_value - (char *) virtual_break_value;
 }
@@ -397,13 +385,17 @@ r_alloc_size_in_use ()
    to that block.  */
 
 static bloc_ptr
-find_bloc (ptr)
-     POINTER *ptr;
+find_bloc (POINTER *ptr)
 {
   register bloc_ptr p = first_bloc;
 
   while (p != NIL_BLOC)
     {
+      /* Consistency check. Don't return inconsistent blocs.
+        Don't abort here, as callers might be expecting this,  but
+        callers that always expect a bloc to be returned should abort
+        if one isn't to avoid a memory corruption bug that is
+        difficult to track down.  */
       if (p->variable == ptr && p->data == *ptr)
        return p;
 
@@ -418,8 +410,7 @@ find_bloc (ptr)
    memory for the new block.  */
 
 static bloc_ptr
-get_bloc (size)
-     SIZE size;
+get_bloc (SIZE size)
 {
   register bloc_ptr new_bloc;
   register heap_ptr heap;
@@ -427,8 +418,7 @@ get_bloc (size)
   if (! (new_bloc = (bloc_ptr) malloc (BLOC_PTR_SIZE))
       || ! (new_bloc->data = obtain (break_value, size)))
     {
-      if (new_bloc)
-       free (new_bloc);
+      free (new_bloc);
 
       return 0;
     }
@@ -475,10 +465,7 @@ get_bloc (size)
    Do not touch the contents of blocs or break_value.  */
 
 static int
-relocate_blocs (bloc, heap, address)
-    bloc_ptr bloc;
-    heap_ptr heap;
-    POINTER address;
+relocate_blocs (bloc_ptr bloc, heap_ptr heap, POINTER address)
 {
   register bloc_ptr b = bloc;
 
@@ -538,8 +525,7 @@ relocate_blocs (bloc, heap, address)
    before that of BEFORE.  */
 
 static void
-reorder_bloc (bloc, before)
-     bloc_ptr bloc, before;
+reorder_bloc (bloc_ptr bloc, bloc_ptr before)
 {
   bloc_ptr prev, next;
 
@@ -567,9 +553,7 @@ reorder_bloc (bloc, before)
    with heap HEAP and bloc BLOC.  */
 
 static void
-update_heap_bloc_correspondence (bloc, heap)
-     bloc_ptr bloc;
-     heap_ptr heap;
+update_heap_bloc_correspondence (bloc_ptr bloc, heap_ptr heap)
 {
   register bloc_ptr b;
 
@@ -631,9 +615,7 @@ update_heap_bloc_correspondence (bloc, heap)
    that come after BLOC in memory.  */
 
 static int
-resize_bloc (bloc, size)
-    bloc_ptr bloc;
-    SIZE size;
+resize_bloc (bloc_ptr bloc, SIZE size)
 {
   register bloc_ptr b;
   heap_ptr heap;
@@ -686,7 +668,7 @@ resize_bloc (bloc, size)
             }
          else
            {
-             safe_bcopy (b->data, b->new_data, b->size);
+             memmove (b->new_data, b->data, b->size);
              *b->variable = b->data = b->new_data;
             }
        }
@@ -697,8 +679,8 @@ resize_bloc (bloc, size)
        }
       else
        {
-         safe_bcopy (bloc->data, bloc->new_data, old_size);
-         bzero ((char *) bloc->new_data + old_size, size - old_size);
+         memmove (bloc->new_data, bloc->data, old_size);
+         memset (bloc->new_data + old_size, 0, size - old_size);
          *bloc->variable = bloc->data = bloc->new_data;
        }
     }
@@ -713,7 +695,7 @@ resize_bloc (bloc, size)
             }
          else
            {
-             safe_bcopy (b->data, b->new_data, b->size);
+             memmove (b->new_data, b->data, b->size);
              *b->variable = b->data = b->new_data;
            }
        }
@@ -730,8 +712,7 @@ resize_bloc (bloc, size)
    This may return space to the system.  */
 
 static void
-free_bloc (bloc)
-     bloc_ptr bloc;
+free_bloc (bloc_ptr bloc)
 {
   heap_ptr heap = bloc->heap;
 
@@ -797,8 +778,7 @@ free_bloc (bloc)
    GNU malloc package.  */
 
 POINTER
-r_alloc_sbrk (size)
-     long size;
+r_alloc_sbrk (long int size)
 {
   register bloc_ptr b;
   POINTER address;
@@ -868,7 +848,7 @@ r_alloc_sbrk (size)
             header.  */
          for (b = last_bloc; b != NIL_BLOC; b = b->prev)
            {
-             safe_bcopy (b->data, b->new_data, b->size);
+             memmove (b->new_data, b->data, b->size);
              *b->variable = b->data = b->new_data;
            }
 
@@ -895,7 +875,7 @@ r_alloc_sbrk (size)
            last_heap = first_heap;
        }
 
-      bzero (address, size);
+      memset (address, 0, size);
     }
   else /* size < 0 */
     {
@@ -914,7 +894,7 @@ r_alloc_sbrk (size)
 
          for (b = first_bloc; b != NIL_BLOC; b = b->next)
            {
-             safe_bcopy (b->data, b->new_data, b->size);
+             memmove (b->new_data, b->data, b->size);
              *b->variable = b->data = b->new_data;
            }
        }
@@ -942,16 +922,14 @@ r_alloc_sbrk (size)
    which will use the data area.
 
    The allocation of 0 bytes is valid.
-   In case r_alloc_freeze is set, a best fit of unused blocs could be done
-   before allocating a new area.  Not yet done.
+   In case r_alloc_freeze_level is set, a best fit of unused blocs could be
+   done before allocating a new area.  Not yet done.
 
    If we can't allocate the necessary memory, set *PTR to zero, and
    return zero.  */
 
 POINTER
-r_alloc (ptr, size)
-     POINTER *ptr;
-     SIZE size;
+r_alloc (POINTER *ptr, SIZE size)
 {
   register bloc_ptr new_bloc;
 
@@ -974,8 +952,7 @@ r_alloc (ptr, size)
    Store 0 in *PTR to show there's no block allocated.  */
 
 void
-r_alloc_free (ptr)
-     register POINTER *ptr;
+r_alloc_free (register POINTER *ptr)
 {
   register bloc_ptr dead_bloc;
 
@@ -984,7 +961,7 @@ r_alloc_free (ptr)
 
   dead_bloc = find_bloc (ptr);
   if (dead_bloc == NIL_BLOC)
-    abort ();
+    abort (); /* Double free? PTR not originally used to allocate?  */
 
   free_bloc (dead_bloc);
   *ptr = 0;
@@ -999,7 +976,7 @@ r_alloc_free (ptr)
    SIZE is less than or equal to the current bloc size, in which case
    do nothing.
 
-   In case r_alloc_freeze is set, a new bloc is allocated, and the
+   In case r_alloc_freeze_level is set, a new bloc is allocated, and the
    memory copied to it.  Not very efficient.  We could traverse the
    bloc_list for a best fit of free blocs first.
 
@@ -1009,9 +986,7 @@ r_alloc_free (ptr)
    return zero.  */
 
 POINTER
-r_re_alloc (ptr, size)
-     POINTER *ptr;
-     SIZE size;
+r_re_alloc (POINTER *ptr, SIZE size)
 {
   register bloc_ptr bloc;
 
@@ -1028,7 +1003,7 @@ r_re_alloc (ptr, size)
 
   bloc = find_bloc (ptr);
   if (bloc == NIL_BLOC)
-    abort ();
+    abort (); /* Already freed? PTR not originally used to allocate?  */
 
   if (size < bloc->size)
     {
@@ -1072,8 +1047,7 @@ r_re_alloc (ptr, size)
    malloc must return a null pointer.  */
 
 void
-r_alloc_freeze (size)
-     long size;
+r_alloc_freeze (long int size)
 {
   if (! r_alloc_initialized)
     r_alloc_init ();
@@ -1090,7 +1064,7 @@ r_alloc_freeze (size)
 }
 
 void
-r_alloc_thaw ()
+r_alloc_thaw (void)
 {
 
   if (! r_alloc_initialized)
@@ -1100,7 +1074,7 @@ r_alloc_thaw ()
     abort ();
 
   /* This frees all unused blocs.  It is not too inefficient, as the resize
-     and bcopy is done only once.  Afterwards, all unreferenced blocs are
+     and memcpy is done only once.  Afterwards, all unreferenced blocs are
      already shrunk to zero size.  */
   if (!r_alloc_freeze_level)
     {
@@ -1119,7 +1093,7 @@ r_alloc_thaw ()
 /* Reinitialize the morecore hook variables after restarting a dumped
    Emacs.  This is needed when using Doug Lea's malloc from GNU libc.  */
 void
-r_alloc_reinit ()
+r_alloc_reinit (void)
 {
   /* Only do this if the hook has been reset, so that we don't get an
      infinite loop, in case Emacs was linked statically.  */
@@ -1226,6 +1200,33 @@ r_alloc_check ()
 
 #endif /* DEBUG */
 
+/* Update the internal record of which variable points to some data to NEW.
+   Used by buffer-swap-text in Emacs to restore consistency after it
+   swaps the buffer text between two buffer objects.  The OLD pointer
+   is checked to ensure that memory corruption does not occur due to
+   misuse.  */
+void
+r_alloc_reset_variable (POINTER *old, POINTER *new)
+{
+  bloc_ptr bloc = first_bloc;
+
+  /* Find the bloc that corresponds to the data pointed to by pointer.
+     find_bloc cannot be used, as it has internal consistency checks
+     which fail when the variable needs reseting.  */
+  while (bloc != NIL_BLOC)
+    {
+      if (bloc->data == *new)
+       break;
+
+      bloc = bloc->next;
+    }
+
+  if (bloc == NIL_BLOC || bloc->variable != old)
+    abort (); /* Already freed? OLD not originally used to allocate?  */
+
+  /* Update variable to point to the new location.  */
+  bloc->variable = new;
+}
 
 \f
 /***********************************************************************
@@ -1235,7 +1236,7 @@ r_alloc_check ()
 /* Initialize various things for memory allocation.  */
 
 static void
-r_alloc_init ()
+r_alloc_init (void)
 {
   if (r_alloc_initialized)
     return;
@@ -1283,8 +1284,8 @@ r_alloc_init ()
      even though it is after the sbrk value.  */
   /* Doubly true, with the additional call that explicitly adds the
      rest of that page to the address space.  */
-  bzero (first_heap->start,
-        (char *) first_heap->end - (char *) first_heap->start);
+  memset (first_heap->start, 0,
+         (char *) first_heap->end - (char *) first_heap->start);
   virtual_break_value = break_value = first_heap->bloc_start = first_heap->end;
 #endif