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