Remove everything having to do with the use of mmap.

This commit is contained in:
Gerd Moellmann 2000-09-14 15:14:28 +00:00
parent 39c75ccb52
commit 02bb17d31c

View file

@ -926,7 +926,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,420 +1216,6 @@ r_alloc_check ()
#endif /* DEBUG */
#endif /* not REL_ALLOC_MMAP */
/***********************************************************************
Implementation based on mmap
***********************************************************************/
#ifdef REL_ALLOC_MMAP
#include <sys/types.h>
#include <sys/mman.h>
#ifndef MAP_ANON
#ifdef MAP_ANONYMOUS
#define MAP_ANON MAP_ANONYMOUS
#else
#define MAP_ANON 0
#endif
#endif
#include <stdio.h>
#include <errno.h>
#if MAP_ANON == 0
#include <fcntl.h>
#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;
/* File descriptor for mmap. If we don't have anonymous mapping,
/dev/zero will be opened on it. */
static int mmap_fd;
/* Temporary storage for mmap_set_vars, see there. */
static struct mmap_region *mmap_regions_1;
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));
/* 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 = 0;
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));
else
{
r->nbytes_mapped -= nbytes;
success = 1;
}
}
else if (npages > 0)
{
struct mmap_region *r2;
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. */
r2 = mmap_find (region_end, region_end + nbytes);
if (r2 == NULL)
{
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));
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));
}
else
{
r->nbytes_mapped += nbytes;
success = 1;
}
}
}
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;
if (restore_p)
{
mmap_regions = mmap_regions_1;
mmap_fd = mmap_fd_1;
for (r = mmap_regions; r; r = r->next)
*r->var = MMAP_USER_AREA (r);
}
else
{
for (r = mmap_regions; r; r = r->next)
*r->var = NULL;
mmap_regions_1 = mmap_regions;
mmap_regions = NULL;
mmap_fd_1 = mmap_fd;
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;
r_alloc_init ();
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;
r_alloc_init ();
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;
{
r_alloc_init ();
if (*var)
{
mmap_free (MMAP_REGION (*var));
*var = NULL;
}
}
#endif /* REL_ALLOC_MMAP */
/***********************************************************************
@ -1650,24 +1235,9 @@ extern POINTER (*__morecore) ();
static void
r_alloc_init ()
{
#if defined REL_ALLOC_MMAP && MAP_ANON == 0
/* The value of mmap_fd is initially 0 in temacs, and -1
in a dumped Emacs. */
if (mmap_fd <= 0)
{
/* No anonymous mmap -- we need the file descriptor. */
mmap_fd = open ("/dev/zero", O_RDONLY);
if (mmap_fd == -1)
fatal ("Cannot open /dev/zero: %s", emacs_strerror (errno));
}
#endif /* REL_ALLOC_MMAP && MAP_ANON == 0 */
if (r_alloc_initialized)
return;
r_alloc_initialized = 1;
#if defined REL_ALLOC_MMAP && MAP_ANON != 0
mmap_fd = -1;
#endif
page_size = PAGE;
#ifndef SYSTEM_MALLOC