blob: 3a4d76cf10d7ad1371ed7be691e532aa3b5ce86f [file] [log] [blame]
//===- PageManager.cpp - Implementation of the page allocator -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the PageManager.h interface.
//
//===----------------------------------------------------------------------===//
#include "PageManager.h"
#ifndef _POSIX_MAPPED_FILES
#define _POSIX_MAPPED_FILES
#endif
#include <unistd.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "poolalloc/MMAPSupport.h"
#include "poolalloc/Support/MallocAllocator.h"
#include <vector>
#include <iostream>
// this is for Mac OS X
#include <mach/mach_vm.h>
#include <mach/mach.h>
// Define this if we want to use memalign instead of mmap to get pages.
// Empirically, this slows down the pool allocator a LOT.
#define USE_MEMALIGN 0
//#define STATISTIC
unsigned PageSize = 0;
unsigned AddressSpaceUsage1 = 0;
unsigned AddressSpaceUsage2 = 0;
unsigned AddressSpaceUsage3 = 0;
unsigned mmapstart = 0x20000000;
unsigned mmapstart2 = 0x40000000;
unsigned numPages = 8;
int fd;
FILE *f;
void InitializePageManager() {
if (!PageSize) {
PageSize = sysconf(_SC_PAGESIZE);
#ifdef FILESTATISTIC
f = fopen("/tmp/ftpdl", "a");
#endif
}
}
// Explicitly use the malloc allocator here, to avoid depending on the C++
// runtime library.
typedef std::vector<void*, llvm::MallocAllocator<void*> > RemappablePagesListType;
static RemappablePagesListType &getRemappablePageList() {
static RemappablePagesListType *RemappablePages = 0;
if (!RemappablePages) {
// Avoid using operator new!
RemappablePages = (RemappablePagesListType*)malloc(sizeof(RemappablePagesListType));
// Use placement new now.
new (RemappablePages) std::vector<void*, llvm::MallocAllocator<void*> >();
}
return *RemappablePages;
}
void logusage() {
pid_t pid = getpid();
char sbuf[150];
bzero(sbuf,150);
sprintf(sbuf,"/tmp/ftpdlog.%d", pid);
// int fd = open(sbuf, O_CREAT|O_APPEND|O_SYNC, 00777);
// sprintf(sbuf,
// write(fd, sbuf, strlen(sbuf));
// close(fd);
if (fprintf(f, "pid %d, Address space usage2 %d, Address space usage1 %d AddressSpaceUsage3 %d\n",pid, AddressSpaceUsage2, AddressSpaceUsage1, AddressSpaceUsage3) < 0) abort();
fflush(f);
// fclose(f);
}
/*
void *RemapPage(void *va) {
//This is for creating an alias
// return va;
void *nva = mremap(va, 0, PageSize, MREMAP_MAYMOVE);
return va;
if (nva == (void *)-1) {
perror(" mremap error \n");
printf(" no of pages used %d %d %d\n", AddressSpaceUsage1, AddressSpaceUsage2, AddressSpaceUsage2+AddressSpaceUsage1);
abort();
}
#ifdef FILESTATISTIC
logusage();
#endif
#ifdef STATISTIC
AddressSpaceUsage2++;
#endif
return nva;
}
*/
void *RemapPage(void * va){
kern_return_t kr;
mach_vm_address_t target_addr=0;
mach_vm_address_t source_addr;
vm_prot_t prot_cur = VM_PROT_READ | VM_PROT_WRITE;
vm_prot_t prot_max = VM_PROT_READ | VM_PROT_WRITE;
source_addr = (mach_vm_address_t) va;
kr = mach_vm_remap (mach_task_self(),
&target_addr,
PageSize,
0,
TRUE,
mach_task_self(),
source_addr,
FALSE,
&prot_cur,
&prot_max,
VM_INHERIT_SHARE);
if (kr != KERN_SUCCESS) {
printf(" mremap error: %d \n", kr);
printf(" no of pages used %d %d %d\n", AddressSpaceUsage1, AddressSpaceUsage2, AddressSpaceUsage2+AddressSpaceUsage1);
abort();
}
va = (void *) target_addr;
return va;
#ifdef FILESTATISTIC
logusage();
#endif
#ifdef STATISTIC
AddressSpaceUsage2++;
#endif
}
// AllocatePage - This function returns a chunk of memory with size and
// alignment specified by PageSize.
void *AllocatePage() {
RemappablePagesListType &FPL = getRemappablePageList();
if (!FPL.empty()) {
void *Result = FPL.back();
FPL.pop_back();
void *Ptr = mmap(Result, PageSize, PROT_READ|PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
AddressSpaceUsage3++;
return Ptr;
}
// Allocate a page using mmap shared
// int sd = shmget(IPC_PRIVATE, PageSize, 0x1c0|0600);
// void *Ptr = shmat(sd, 0,0);
// shmctl(sd, IPC_RMID, 0);
void *Ptr = mmap(0, PageSize, PROT_READ|PROT_WRITE, MAP_SHARED |MAP_ANONYMOUS, -1, 0);
// void *Ptr = mmap((void *)mmapstart, PageSize, PROT_READ|PROT_WRITE, MAP_SHARED |MAP_ANONYMOUS|MAP_FIXED, -1, 0);
if (Ptr == (void *)-1 ) {
perror("couldn't mmap\n");
printf(" no of pages used %d %d %d\n", AddressSpaceUsage1, AddressSpaceUsage2, AddressSpaceUsage2+AddressSpaceUsage1);
abort();
}
#ifdef STATISTIC
mmapstart += PageSize;
AddressSpaceUsage1++;
#endif
return Ptr;
}
void *AllocateNPages(unsigned Num) {
if (Num <= 1) return AllocatePage();
void *Ptr = mmap(0, PageSize * Num, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
#ifdef STATISTIC
AddressSpaceUsage1++;
#endif
return Ptr;
}
// MprotectPage - This function changes the protection status of the page to become
// none-accessible
void MprotectPage(void *pa, unsigned numPages) {
kern_return_t kr;
kr = mprotect(pa, numPages * PageSize, PROT_NONE);
if (kr != KERN_SUCCESS)
perror(" mprotect error \n");
return;
}
// FreePage - This function returns the specified page to the pagemanager for
// future allocation.
void FreePage(void *Page) {
munmap(Page, PageSize);
RemappablePagesListType &FPL = getRemappablePageList();
FPL.push_back(Page);
}