LLVM API Documentation

Memory.inc

Go to the documentation of this file.
00001 //===- Unix/Memory.cpp - Generic UNIX System Configuration ------*- C++ -*-===//
00002 // 
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by Reid Spencer and is distributed under the 
00006 // University of Illinois Open Source License. See LICENSE.TXT for details.
00007 // 
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines some functions for various memory management utilities.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "Unix.h"
00015 #include "llvm/System/Process.h"
00016 
00017 #ifdef HAVE_SYS_MMAN_H
00018 #include <sys/mman.h>
00019 #endif
00020 
00021 namespace llvm {
00022 
00023 /// AllocateRWXMemory - Allocate a slab of memory with read/write/execute
00024 /// permissions.  This is typically used for JIT applications where we want
00025 /// to emit code to the memory then jump to it.  Getting this type of memory
00026 /// is very OS specific.
00027 ///
00028 MemoryBlock Memory::AllocateRWX(unsigned NumBytes, const MemoryBlock* NearBlock) {
00029   if (NumBytes == 0) return MemoryBlock();
00030 
00031   long pageSize = Process::GetPageSize();
00032   unsigned NumPages = (NumBytes+pageSize-1)/pageSize;
00033 
00034   int fd = -1;
00035 #ifdef NEED_DEV_ZERO_FOR_MMAP
00036   static int zero_fd = open("/dev/zero", O_RDWR);
00037   if (zero_fd == -1) {
00038     ThrowErrno("Can't open /dev/zero device");
00039   }
00040   fd = zero_fd;
00041 #endif
00042 
00043   int flags = MAP_PRIVATE |
00044 #ifdef HAVE_MMAP_ANONYMOUS
00045   MAP_ANONYMOUS
00046 #else
00047   MAP_ANON
00048 #endif
00049   ;
00050 
00051   void* start = NearBlock ? (unsigned char*) NearBlock->base() + NearBlock->size() : 0;
00052 
00053   void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
00054                     flags, fd, 0);
00055   if (pa == MAP_FAILED) {
00056     if (NearBlock) //Try again without a near hint
00057       return AllocateRWX(NumBytes, 0);
00058     else
00059       ThrowErrno("Can't allocate RWX Memory");
00060   }
00061   MemoryBlock result;
00062   result.Address = pa;
00063   result.Size = NumPages*pageSize;
00064   return result;
00065 }
00066 
00067 void Memory::ReleaseRWX(MemoryBlock& M) {
00068   if (M.Address == 0 || M.Size == 0) return;
00069   if (0 != ::munmap(M.Address, M.Size)) {
00070     ThrowErrno("Can't release RWX Memory");
00071   }
00072 }
00073 
00074 }
00075