#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);
#include <stddef.h>
-typedef size_t SIZE;
-typedef void *POINTER;
-
#include <unistd.h>
#include <malloc.h>
#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
/* 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) \
} *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
}
}
}
-
-/* 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. */
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);
free_bloc (bloc_ptr bloc)
{
heap_ptr heap = bloc->heap;
+ heap_ptr h;
if (r_alloc_freeze_level)
{
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 ();
__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;
if (! r_alloc_initialized)
r_alloc_init ();
- if (! use_relocatable_buffers)
+ if (use_relocatable_buffers <= 0)
return (*real_morecore) (size);
if (size == 0)
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)
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