/* mem-mmap.c
*
* COPYRIGHT (c) 1993 by AT&T Bell Laboratories.
*
* Memory sub-system for systems that provide mmap.
*/
#include "ml-unixdep.h"
#include "ml-osdep.h"
#include <sys/mman.h>
#include INCLUDE_FCNTL_H
#include "ml-base.h"
#include "memory.h"
#if !(defined(HAS_MMAP) || defined(HAS_ANON_MMAP))
# error expected HAS_MMAP or HAS_ANON_MMAP
#endif
/* protection mode for mmap memory */
#define PROT_ALL (PROT_READ|PROT_WRITE|PROT_EXEC)
/* flags for mmap */
#ifdef HAS_ANON_MMAP
# define MMAP_FLGS (MAP_ANONYMOUS|MAP_PRIVATE)
#else
# define MMAP_FLGS MAP_PRIVATE
#endif
#if (defined(HOST_ALPHA32) && (defined(OPSYS_OSF1) || defined(OPSYS_DUNIX)))
/* To insure that mmap returns a 32-bit address, we need to specify a non-zero
* address to mmap(). The address 0x2000000 is the location of the text segment,
* which is a good minimum value since the C stack lives just below this address
* and mmap will find regions above it.
*/
# define MMAP_ADDR (caddr_t)0x2000000
#else
# define MMAP_ADDR 0
#endif
struct mem_obj {
Word_t *base; /* the base address of the object. */
Addr_t sizeB; /* the object's size (in bytes) */
#ifdef HAS_PARTIAL_MUNMAP
# define mapBase base
# define mapSizeB sizeB
#else
Word_t *mapBase; /* base address of the mapped region containing */
/* the object */
Addr_t mapSizeB; /* the size of the mapped region containing */
/* the object */
#endif
};
extern int errno;
#define ALLOC_MEMOBJ() NEW_OBJ(mem_obj_t)
#define FREE_MEMOBJ(p) FREE(p)
#include "mem-common.ins"
/* MEM_InitMemory:
*/
void MEM_InitMemory ()
{
InitMemory();
} /* MEM_InitMemory */
/* MapMemory:
*
* Map a BIBOP_PAGE_SZB aligned chunk of szb bytes of virtual memory. Return
* the address of the mapped memory (or NIL on failure).
*/
PVT status_t MapMemory (mem_obj_t *obj, Addr_t szb)
{
int fd;
Addr_t addr, offset;
#ifdef HAS_ANON_MMAP
fd = -1;
#else
/* Note: we use O_RDONLY, because some OS are configured such that /dev/zero
* is not writable. This works because we are using MAP_PRIVATE as the
* mapping mode.
*/
if ((fd = open("/dev/zero", O_RDONLY)) == -1) {
Error ("unable to open /dev/zero, errno = %d\n", errno);
return FAILURE;
}
#endif
/* we grab an extra BIBOP_PAGE_SZB bytes to give us some room for alignment */
addr = (Addr_t) mmap (MMAP_ADDR, szb+BIBOP_PAGE_SZB, PROT_ALL, MMAP_FLGS, fd, 0);
if (addr == -1) {
Error ("unable to map %d bytes, errno = %d\n", szb, errno);
#ifndef HAS_ANON_MMAP
close (fd); /* NOTE: this call clobbers errno */
#endif
return FAILURE;
}
#ifndef HAS_ANON_MMAP
close (fd);
#endif
/* insure BIBOP_PAGE_SZB alignment */
offset = BIBOP_PAGE_SZB - (addr & (BIBOP_PAGE_SZB-1));
#ifdef HAS_PARTIAL_MUNMAP
if (offset != BIBOP_PAGE_SZB) {
/* align addr and discard unused portions of memory */
munmap ((void *)addr, offset);
addr += offset;
munmap ((void *)(addr+szb), BIBOP_PAGE_SZB-offset);
}
else {
munmap ((void *)(addr+szb), BIBOP_PAGE_SZB);
}
#else
obj->mapBase = (Word_t *)addr;
obj->mapSizeB = szb+BIBOP_PAGE_SZB;
addr += offset;
#endif
obj->base = (Word_t *)addr;
obj->sizeB = szb;
return SUCCESS;
} /* end of MapMemory */
/* UnmapMemory:
*
* Unmap a szb byte chunk of virtual memory at addr.
*/
PVT void UnmapMemory (mem_obj_t *obj)
{
if (munmap((caddr_t)(obj->mapBase), obj->mapSizeB) == -1) {
Die ("error unmapping [%#x, %#x), errno = %d\n",
obj->mapBase, (Addr_t)(obj->mapBase) + obj->mapSizeB, errno);
}
} /* end of UnmapMemory */
syntax highlighted by Code2HTML, v. 0.9.1