home *** CD-ROM | disk | FTP | other *** search
- #include "efence.h"
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/mman.h>
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
-
- /*
- * For some reason, I can't find mprotect() in any of the headers on
- * IRIX or SunOS 4.1.2
- */
- extern C_LINKAGE int mprotect(caddr_t addr, size_t len, int prot);
-
- static caddr_t startAddr = (caddr_t) 0;
-
- #if ( !defined(sgi) && !defined(_AIX) )
- extern int sys_nerr;
- extern char * sys_errlist[];
- #endif
-
- static const char *
- stringErrorReport(void)
- {
- #if ( defined(sgi) )
- return strerror(oserror());
- #elif ( defined(_AIX) )
- return strerror(errno);
- #else
- if ( errno > 0 && errno < sys_nerr )
- return sys_errlist[errno];
- else
- return "Unknown error.\n";
- #endif
- }
-
- /*
- * Create memory.
- */
- #if defined(MAP_ANONYMOUS)
- void *
- Page_Create(size_t size)
- {
- caddr_t allocation;
-
- /*
- * In this version, "startAddr" is a _hint_, not a demand.
- * When the memory I map here is contiguous with other
- * mappings, the allocator can coalesce the memory from two
- * or more mappings into one large contiguous chunk, and thus
- * might be able to find a fit that would not otherwise have
- * been possible. I could _force_ it to be contiguous by using
- * the MMAP_FIXED flag, but I don't want to stomp on memory mappings
- * generated by other software, etc.
- */
- allocation = mmap(
- startAddr
- ,(int)size
- ,PROT_READ|PROT_WRITE
- ,MAP_PRIVATE|MAP_ANONYMOUS
- ,-1
- ,0);
-
- startAddr = allocation + size;
-
- if ( allocation == (caddr_t)-1 )
- EF_Exit("mmap() failed: %s", stringErrorReport());
-
- return (void *)allocation;
- }
- #else
- void *
- Page_Create(size_t size)
- {
- static int devZeroFd = -1;
- caddr_t allocation;
-
- if ( devZeroFd == -1 ) {
- devZeroFd = open("/dev/zero", O_RDWR);
- if ( devZeroFd < 0 )
- EF_Exit(
- "open() on /dev/zero failed: %s"
- ,stringErrorReport());
- }
-
- /*
- * In this version, "startAddr" is a _hint_, not a demand.
- * When the memory I map here is contiguous with other
- * mappings, the allocator can coalesce the memory from two
- * or more mappings into one large contiguous chunk, and thus
- * might be able to find a fit that would not otherwise have
- * been possible. I could _force_ it to be contiguous by using
- * the MMAP_FIXED flag, but I don't want to stomp on memory mappings
- * generated by other software, etc.
- */
- allocation = mmap(
- startAddr
- ,(int)size
- ,PROT_READ|PROT_WRITE
- ,MAP_PRIVATE
- ,devZeroFd
- ,0);
-
- startAddr = allocation + size;
-
- if ( allocation == (caddr_t)-1 )
- EF_Exit("mmap() failed: %s", stringErrorReport());
-
- return (void *)allocation;
- }
- #endif
-
- static void
- mprotectFailed(void)
- {
- EF_Exit("mprotect() failed: %s", stringErrorReport());
- }
-
- void
- Page_AllowAccess(void * address, size_t size)
- {
- if ( mprotect((caddr_t)address, size, PROT_READ|PROT_WRITE) < 0 )
- mprotectFailed();
- }
-
- void
- Page_DenyAccess(void * address, size_t size)
- {
- if ( mprotect((caddr_t)address, size, PROT_NONE) < 0 )
- mprotectFailed();
- }
-
- void
- Page_Delete(void * address, size_t size)
- {
- /*
- * My SGI ONYX running IRIX 5.0 crashes reliably when "tstheap 3072" is
- * run with the munmap call below compiled in. I'd like to hear how well
- * other operating systems handle it, so that I can enable it on those
- * systems.
- */
- #if ( defined(_AIX) )
- if ( munmap((caddr_t)address, size) < 0 )
- EF_Exit("munmap() failed: %s", stringErrorReport());
- #else
- Page_DenyAccess(address, size);
- #endif
- }
-
- #if defined(_SC_PAGESIZE)
- size_t
- Page_Size(void)
- {
- return (size_t)sysconf(_SC_PAGESIZE);
- }
- #elif defined(_SC_PAGE_SIZE)
- size_t
- Page_Size(void)
- {
- return (size_t)sysconf(_SC_PAGE_SIZE);
- }
- #else
- extern int getpagesize();
- size_t
- Page_Size(void)
- {
- return getpagesize();
- }
- #endif
-