#if defined(HAVE_MMAP)
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include "mmprivate.h"
#define HAVE_MSYNC
#if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
static size_t pagesize;
#if NEED_DECLARATION_GETPAGESIZE
extern int getpagesize PARAMS ((void));
#endif
#define PAGE_ALIGN(addr) (caddr_t) (((long)(addr) + pagesize - 1) & ~(pagesize - 1))
PTR
__mmalloc_mmap_morecore (mdp, size)
struct mdesc *mdp;
int size;
{
PTR result = NULL;
off_t foffset;
size_t mapbytes;
caddr_t moveto;
caddr_t mapto;
char buf = 0;
int flags = 0;
if (pagesize == 0)
{
pagesize = getpagesize ();
}
if (size == 0)
{
return (mdp -> breakval);
}
if (size < 0)
{
if (mdp -> breakval + size >= mdp -> base)
{
result = (PTR) mdp -> breakval;
mdp -> breakval += size;
moveto = PAGE_ALIGN (mdp -> breakval);
#ifdef HAVE_MSYNC
#ifdef MS_SYNC
msync (moveto, (size_t) (mdp -> top - moveto), MS_SYNC | MS_INVALIDATE);
#else
msync (moveto, (size_t) (mdp -> top - moveto));
#endif
#endif
munmap (moveto, (size_t) (mdp -> top - moveto));
mdp -> top = moveto;
return result;
}
else
{
return NULL;
}
}
#ifndef MAP_ANONYMOUS
if (mdp -> fd < 0)
{
char buf[64];
sprintf (buf, "/tmp/mmalloc.XXXXXX");
mdp -> fd = mkstemp (buf);
if (mdp -> fd < 0)
{
fprintf (stderr, "unable to create default mmalloc allocator: %s",
strerror (errno));
return NULL;
}
if (unlink (buf) != 0)
{
fprintf (stderr, "unable to unlink map file for default mmalloc allocator: %s\n",
strerror (errno));
}
}
#endif
if (mdp -> breakval + size <= mdp -> top)
{
result = (PTR) mdp -> breakval;
mdp -> breakval += size;
return result;
}
moveto = PAGE_ALIGN (mdp -> breakval + size);
if ((moveto - mdp -> base) < 128 * 1024 * 1024)
moveto = mdp -> base + (128 * 1024 * 1024);
mapbytes = moveto - mdp -> top;
foffset = mdp -> top - mdp -> base;
#ifdef MAP_ANONYMOUS
if (mdp -> fd < 0)
{
flags = MAP_PRIVATE | MAP_ANONYMOUS;
}
#endif
if (mdp -> fd > 0)
{
lseek (mdp -> fd, foffset + mapbytes - 1, SEEK_SET);
write (mdp -> fd, &buf, 1);
#ifdef MAP_FILE
flags = MAP_SHARED | MAP_FILE;
#else
flags = MAP_SHARED;
#endif
}
if (mdp -> base == 0)
{
mapto = mmap (0, mapbytes, PROT_READ | PROT_WRITE,
flags, mdp -> fd, foffset);
if (mapto != (caddr_t) -1)
{
mdp -> base = mdp -> breakval = mapto;
mdp -> top = mdp -> base + mapbytes;
result = (PTR) mdp -> breakval;
mdp -> breakval += size;
}
}
else
{
mapto = mmap (mdp -> top, mapbytes, PROT_READ | PROT_WRITE,
flags | MAP_FIXED, mdp -> fd, foffset);
if (mapto == mdp -> top)
{
mdp -> top = moveto;
result = (PTR) mdp -> breakval;
mdp -> breakval += size;
}
}
return (result);
}
PTR
__mmalloc_remap_core (mdp)
struct mdesc *mdp;
{
caddr_t base;
base = mmap (mdp -> base, mdp -> top - mdp -> base,
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
mdp -> fd, 0);
return ((PTR) base);
}
PTR
mmalloc_findbase (size)
int size;
{
int fd;
int flags;
caddr_t base = NULL;
if (size < 128 * 1024 * 1024)
size = 128 * 1024 * 1024;
if (pagesize == 0)
{
pagesize = getpagesize ();
}
#ifdef MAP_ANONYMOUS
flags = MAP_PRIVATE | MAP_ANONYMOUS;
fd = -1;
#else
#ifdef MAP_FILE
flags = MAP_PRIVATE | MAP_FILE;
#else
flags = MAP_PRIVATE;
#endif
#endif
#ifndef MAP_ANONYMOUS
{
char buf[64];
sprintf (buf, "/tmp/mmalloc.XXXXXX");
fd = mkstemp (buf);
if (fd < 0)
{
fprintf (stderr, "unable to create default mmalloc allocator: %s",
strerror (errno));
return NULL;
}
if (unlink (buf) != 0)
{
fprintf (stderr, "unable to unlink map file for default mmalloc allocator: %s",
strerror (errno));
}
}
#endif
size = PAGE_ALIGN (size);
base = mmap (0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
if (base != (caddr_t) -1)
{
#ifdef MS_SYNC
msync (base, (size_t) size, MS_SYNC | MS_INVALIDATE);
#else
msync (base, (size_t) size);
#endif
munmap (base, (size_t) size);
}
if (fd != -1)
{
close (fd);
}
if (base == 0)
{
base = (caddr_t) getpagesize ();
}
else if (base == (caddr_t) -1)
{
base = NULL;
}
return ((PTR) base);
}
#else
static char ansi_c_idiots = 69;
#endif