X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/9899d01a0ccec166e04caa60657a44e614be50cd..6ce950f336909aa19d6c5ea6f3e1910b247f3d38:/src/ralloc.c
diff --git a/src/ralloc.c b/src/ralloc.c
index e39ed5a441..5f2b52fcc4 100644
--- a/src/ralloc.c
+++ b/src/ralloc.c
@@ -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 . */
/* NOTES:
@@ -28,6 +26,7 @@ Boston, MA 02110-1301, USA. */
#ifdef emacs
#include
+#include
#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
#include
-#define safe_bcopy(x, y, z) memmove (y, x, z)
-#define bzero(x, len) memset (x, 0, len)
-
#endif /* not emacs */
@@ -82,13 +73,13 @@ typedef void *POINTER;
static int r_alloc_initialized = 0;
-static void r_alloc_init ();
+static void r_alloc_init (void);
/* Declarations for working with the malloc, ralloc, and system breaks. */
/* Function to set the real break value. */
-POINTER (*real_morecore) ();
+POINTER (*real_morecore) (long int);
/* The break value, as seen by malloc. */
static POINTER virtual_break_value;
@@ -120,7 +111,7 @@ static int extra_bytes;
from the system. */
#ifndef SYSTEM_MALLOC
-extern POINTER (*__morecore) ();
+extern POINTER (*__morecore) (long int);
#endif
@@ -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;
@@ -532,44 +519,12 @@ relocate_blocs (bloc, heap, address)
return 1;
}
-
-/* Reorder the bloc BLOC to go before bloc BEFORE in the doubly linked list.
- This is necessary if we put the memory of space of BLOC
- before that of BEFORE. */
-
-static void
-reorder_bloc (bloc, before)
- bloc_ptr bloc, before;
-{
- bloc_ptr prev, next;
-
- /* Splice BLOC out from where it is. */
- prev = bloc->prev;
- next = bloc->next;
-
- if (prev)
- prev->next = next;
- if (next)
- next->prev = prev;
-
- /* Splice it in before BEFORE. */
- prev = before->prev;
-
- if (prev)
- prev->next = bloc;
- bloc->prev = prev;
-
- before->prev = bloc;
- bloc->next = before;
-}
/* Update the records of which heaps contain which blocs, starting
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 +586,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 +639,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 +650,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 +666,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 +683,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 +749,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 +819,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 +846,7 @@ r_alloc_sbrk (size)
last_heap = first_heap;
}
- bzero (address, size);
+ memset (address, 0, size);
}
else /* size < 0 */
{
@@ -914,7 +865,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 +893,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 +923,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 +932,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 +947,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 +957,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 +974,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 +1018,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 +1035,7 @@ r_alloc_freeze (size)
}
void
-r_alloc_thaw ()
+r_alloc_thaw (void)
{
if (! r_alloc_initialized)
@@ -1100,7 +1045,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 +1064,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 +1171,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;
+}
/***********************************************************************
@@ -1235,7 +1207,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 +1255,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