X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/a2c23c923a6c98500895fc938c2c10157565a438..8030369ccb5c871d3ce11b96c220f318bc741ed8:/src/ralloc.c diff --git a/src/ralloc.c b/src/ralloc.c index f6ae887f4c..9d31320bfc 100644 --- a/src/ralloc.c +++ b/src/ralloc.c @@ -46,7 +46,7 @@ extern void safe_bcopy (); extern int mallopt (); #else /* not DOUG_LEA_MALLOC */ #ifndef SYSTEM_MALLOC -extern int __malloc_extra_blocks; +extern size_t __malloc_extra_blocks; #endif /* SYSTEM_MALLOC */ #endif /* not DOUG_LEA_MALLOC */ @@ -114,6 +114,14 @@ static int extra_bytes; #define MEM_ROUNDUP(addr) (((unsigned long int)(addr) + MEM_ALIGN - 1) \ & ~(MEM_ALIGN - 1)) +/* The hook `malloc' uses for the function which gets more space + from the system. */ + +#ifndef SYSTEM_MALLOC +extern POINTER (*__morecore) (); +#endif + + /*********************************************************************** Implementation using sbrk @@ -926,7 +934,6 @@ r_alloc_sbrk (size) return address; } -#ifndef REL_ALLOC_MMAP /* Allocate a relocatable bloc of storage of size SIZE. A pointer to the data is returned in *PTR. PTR is thus the address of some variable @@ -1217,454 +1224,12 @@ r_alloc_check () #endif /* DEBUG */ -#endif /* not REL_ALLOC_MMAP */ - - -/*********************************************************************** - Implementation based on mmap - ***********************************************************************/ - -#ifdef REL_ALLOC_MMAP - -#include -#include -#ifndef MAP_ANON -#ifdef MAP_ANONYMOUS -#define MAP_ANON MAP_ANONYMOUS -#else -#define MAP_ANON 0 -#endif -#endif -#include -#include -#if !MAP_ANON -#include -#endif - -/* Memory is allocated in regions which are mapped using mmap(2). - The current implementation lets the system select mapped - addresses; we're not using MAP_FIXED in general, except when - trying to enlarge regions. - - Each mapped region starts with a mmap_region structure, the user - area starts after that structure, aligned to MEM_ALIGN. - - +-----------------------+ - | struct mmap_info + | - | padding | - +-----------------------+ - | user data | - | | - | | - +-----------------------+ */ - -struct mmap_region -{ - /* User-specified size. */ - size_t nbytes_specified; - - /* Number of bytes mapped */ - size_t nbytes_mapped; - - /* Pointer to the location holding the address of the memory - allocated with the mmap'd block. The variable actually points - after this structure. */ - POINTER_TYPE **var; - - /* Next and previous in list of all mmap'd regions. */ - struct mmap_region *next, *prev; -}; - -/* Doubly-linked list of mmap'd regions. */ - -static struct mmap_region *mmap_regions; - -/* Temporary storage for mmap_set_vars, see there. */ - -static struct mmap_region *mmap_regions_1; - -/* File descriptor for mmap. If we don't have anonymous mapping, - /dev/zero will be opened on it. */ - -static int mmap_fd = -1; - -/* Value is X rounded up to the next multiple of N. */ - -#define ROUND(X, N) (((X) + (N) - 1) / (N) * (N)) - -/* Size of mmap_region structure plus padding. */ - -#define MMAP_REGION_STRUCT_SIZE \ - ROUND (sizeof (struct mmap_region), MEM_ALIGN) - -/* Given a pointer P to the start of the user-visible part of a mapped - region, return a pointer to the start of the region. */ - -#define MMAP_REGION(P) \ - ((struct mmap_region *) ((char *) (P) - MMAP_REGION_STRUCT_SIZE)) - -/* Given a pointer P to the start of a mapped region, return a pointer - to the start of the user-visible part of the region. */ - -#define MMAP_USER_AREA(P) \ - ((POINTER_TYPE *) ((char *) (P) + MMAP_REGION_STRUCT_SIZE)) - -/* Function prototypes. */ - -static int mmap_free P_ ((struct mmap_region *)); -static int mmap_enlarge P_ ((struct mmap_region *, int)); -static struct mmap_region *mmap_find P_ ((POINTER_TYPE *, POINTER_TYPE *)); -POINTER_TYPE *r_alloc P_ ((POINTER_TYPE **, size_t)); -POINTER_TYPE *r_re_alloc P_ ((POINTER_TYPE **, size_t)); -void r_alloc_free P_ ((POINTER_TYPE **ptr)); - - -void -r_alloc_init_fd () -{ - /* No anonymous mmap -- we need the file descriptor. */ - mmap_fd = open ("/dev/zero", O_RDONLY); - if (mmap_fd < 0) - fatal ("cannot open /dev/zero"); -} - -/* Return a region overlapping address range START...END, or null if - none. END is not including, i.e. the last byte in the range - is at END - 1. */ - -static struct mmap_region * -mmap_find (start, end) - POINTER_TYPE *start, *end; -{ - struct mmap_region *r; - char *s = (char *) start, *e = (char *) end; - - for (r = mmap_regions; r; r = r->next) - { - char *rstart = (char *) r; - char *rend = rstart + r->nbytes_mapped; - - if (/* First byte of range, i.e. START, in this region? */ - (s >= rstart && s < rend) - /* Last byte of range, i.e. END - 1, in this region? */ - || (e > rstart && e <= rend) - /* First byte of this region in the range? */ - || (rstart >= s && rstart < e) - /* Last byte of this region in the range? */ - || (rend > s && rend <= e)) - break; - } - - return r; -} - - -/* Unmap a region. P is a pointer to the start of the user-araa of - the region. Value is non-zero if successful. */ - -static int -mmap_free (r) - struct mmap_region *r; -{ - if (r->next) - r->next->prev = r->prev; - if (r->prev) - r->prev->next = r->next; - else - mmap_regions = r->next; - - if (munmap (r, r->nbytes_mapped) == -1) - { - fprintf (stderr, "munmap: %s\n", emacs_strerror (errno)); - return 0; - } - - return 1; -} - - -/* Enlarge region R by NPAGES pages. NPAGES < 0 means shrink R. - Value is non-zero if successful. */ - -static int -mmap_enlarge (r, npages) - struct mmap_region *r; - int npages; -{ - char *region_end = (char *) r + r->nbytes_mapped; - size_t nbytes; - int success = 1; - - if (npages < 0) - { - /* Unmap pages at the end of the region. */ - nbytes = - npages * page_size; - if (munmap (region_end - nbytes, nbytes) == -1) - { - fprintf (stderr, "munmap: %s\n", emacs_strerror (errno)); - success = 0; - } - else - r->nbytes_mapped -= nbytes; - } - else if (npages > 0) - { - nbytes = npages * page_size; - - /* Try to map additional pages at the end of the region. We - cannot do this if the address range is already occupied by - something else because mmap deletes any previous mapping. - I'm not sure this is worth doing, let's see. */ - if (mmap_find (region_end, region_end + nbytes)) - success = 0; - else - { - POINTER_TYPE *p; - - p = mmap (region_end, nbytes, PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE | MAP_FIXED, mmap_fd, 0); - if (p == MAP_FAILED) - { - fprintf (stderr, "mmap: %s\n", emacs_strerror (errno)); - success = 0; - } - else if (p != (POINTER_TYPE *) region_end) - { - /* Kernels are free to choose a different address. In - that case, unmap what we've mapped above; we have - no use for it. */ - if (munmap (p, nbytes) == -1) - fprintf (stderr, "munmap: %s\n", emacs_strerror (errno)); - success = 0; - } - else - r->nbytes_mapped += nbytes; - } - - success = 0; - } - - return success; -} - - -/* Set or reset variables holding references to mapped regions. If - RESTORE_P is zero, set all variables to null. If RESTORE_P is - non-zero, set all variables to the start of the user-areas - of mapped regions. - - This function is called from Fdump_emacs to ensure that the dumped - Emacs doesn't contain references to memory that won't be mapped - when Emacs starts. */ - -void -mmap_set_vars (restore_p) - int restore_p; -{ - struct mmap_region *r; - static int fd; - - if (restore_p) - { - mmap_regions = mmap_regions_1; - for (r = mmap_regions; r; r = r->next) - *r->var = MMAP_USER_AREA (r); - mmap_fd = fd; - } - else - { - for (r = mmap_regions; r; r = r->next) - *r->var = NULL; - mmap_regions_1 = mmap_regions; - mmap_regions = NULL; - mmap_fd = -1; - } -} - - -/* Return total number of bytes mapped. */ - -size_t -mmap_mapped_bytes () -{ - struct mmap_region *r; - size_t n = 0; - - for (r = mmap_regions; r; r = r->next) - n += r->nbytes_mapped; - - return n; -} - - -/* Allocate a block of storage large enough to hold NBYTES bytes of - data. A pointer to the data is returned in *VAR. VAR is thus the - address of some variable which will use the data area. - - The allocation of 0 bytes is valid. - - If we can't allocate the necessary memory, set *VAR to null, and - return null. */ - -POINTER_TYPE * -r_alloc (var, nbytes) - POINTER_TYPE **var; - size_t nbytes; -{ - void *p; - size_t map; - - if (!r_alloc_initialized) - r_alloc_init (); -#if defined (REL_ALLOC_MMAP) && !MAP_ANON - if (mmap_fd == -1) - r_alloc_init_fd (); -#endif - - map = ROUND (nbytes + MMAP_REGION_STRUCT_SIZE, page_size); - p = mmap (NULL, map, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, - mmap_fd, 0); - - if (p == MAP_FAILED) - { - if (errno != ENOMEM) - fprintf (stderr, "mmap: %s\n", emacs_strerror (errno)); - p = NULL; - } - else - { - struct mmap_region *r = (struct mmap_region *) p; - - r->nbytes_specified = nbytes; - r->nbytes_mapped = map; - r->var = var; - r->prev = NULL; - r->next = mmap_regions; - if (r->next) - r->next->prev = r; - mmap_regions = r; - - p = MMAP_USER_AREA (p); - } - - return *var = p; -} - - -/* Given a pointer at address VAR to data allocated with r_alloc, - resize it to size NBYTES. Change *VAR to reflect the new block, - and return this value. If more memory cannot be allocated, then - leave *VAR unchanged, and return null. */ - -POINTER_TYPE * -r_re_alloc (var, nbytes) - POINTER_TYPE **var; - size_t nbytes; -{ - POINTER_TYPE *result; - - if (!r_alloc_initialized) - r_alloc_init (); -#if defined (REL_ALLOC_MMAP) && !MAP_ANON - if (mmap_fd == -1) - r_alloc_init_fd (); -#endif - - if (*var == NULL) - result = r_alloc (var, nbytes); - else if (nbytes == 0) - { - r_alloc_free (var); - result = r_alloc (var, nbytes); - } - else - { - struct mmap_region *r = MMAP_REGION (*var); - size_t room = r->nbytes_mapped - MMAP_REGION_STRUCT_SIZE; - - if (room < nbytes) - { - /* Must enlarge. */ - POINTER_TYPE *old_ptr = *var; - - /* Try to map additional pages at the end of the region. - If that fails, allocate a new region, copy data - from the old region, then free it. */ - if (mmap_enlarge (r, ROUND (nbytes - room, page_size) / page_size)) - { - r->nbytes_specified = nbytes; - *var = result = old_ptr; - } - else if (r_alloc (var, nbytes)) - { - bcopy (old_ptr, *var, r->nbytes_specified); - mmap_free (MMAP_REGION (old_ptr)); - result = *var; - r = MMAP_REGION (result); - r->nbytes_specified = nbytes; - } - else - { - *var = old_ptr; - result = NULL; - } - } - else if (room - nbytes >= page_size) - { - /* Shrinking by at least a page. Let's give some - memory back to the system. */ - mmap_enlarge (r, - (room - nbytes) / page_size); - result = *var; - r->nbytes_specified = nbytes; - } - else - { - /* Leave it alone. */ - result = *var; - r->nbytes_specified = nbytes; - } - } - - return result; -} - - -/* Free a block of relocatable storage whose data is pointed to by - PTR. Store 0 in *PTR to show there's no block allocated. */ - -void -r_alloc_free (var) - POINTER_TYPE **var; -{ - if (!r_alloc_initialized) - r_alloc_init (); -#if defined (REL_ALLOC_MMAP) && !MAP_ANON - if (mmap_fd == -1) - r_alloc_init_fd (); -#endif - - if (*var) - { - mmap_free (MMAP_REGION (*var)); - *var = NULL; - } -} - -#endif /* REL_ALLOC_MMAP */ - /*********************************************************************** Initialization ***********************************************************************/ -/* The hook `malloc' uses for the function which gets more space - from the system. */ - -#ifndef SYSTEM_MALLOC -extern POINTER (*__morecore) (); -#endif - /* Initialize various things for memory allocation. */ static void @@ -1672,15 +1237,13 @@ r_alloc_init () { if (r_alloc_initialized) return; - r_alloc_initialized = 1; + page_size = PAGE; #ifndef SYSTEM_MALLOC real_morecore = __morecore; __morecore = r_alloc_sbrk; -#endif -#ifndef REL_ALLOC_MMAP first_heap = last_heap = &heap_base; first_heap->next = first_heap->prev = NIL_HEAP; first_heap->start = first_heap->bloc_start @@ -1701,7 +1264,7 @@ r_alloc_init () #endif #endif -#ifndef REL_ALLOC_MMAP +#ifndef SYSTEM_MALLOC first_heap->end = (POINTER) ROUNDUP (first_heap->start); /* The extra call to real_morecore guarantees that the end of the @@ -1720,6 +1283,6 @@ r_alloc_init () (char *) first_heap->end - (char *) first_heap->start); virtual_break_value = break_value = first_heap->bloc_start = first_heap->end; #endif + use_relocatable_buffers = 1; - r_alloc_init_fd (); }