LLVM API Documentation

Unix/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 /// AllocateRWXMemory - Allocate a slab of memory with read/write/execute
00022 /// permissions.  This is typically used for JIT applications where we want
00023 /// to emit code to the memory then jump to it.  Getting this type of memory
00024 /// is very OS specific.
00025 ///
00026 llvm::sys::MemoryBlock 
00027 llvm::sys::Memory::AllocateRWX(unsigned NumBytes, const MemoryBlock* NearBlock,
00028                                std::string *ErrMsg) {
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     GetErrno("Can't open /dev/zero device", ErrMsg);
00039     return MemoryBlock();
00040   }
00041   fd = zero_fd;
00042 #endif
00043 
00044   int flags = MAP_PRIVATE |
00045 #ifdef HAVE_MMAP_ANONYMOUS
00046   MAP_ANONYMOUS
00047 #else
00048   MAP_ANON
00049 #endif
00050   ;
00051 
00052   void* start = NearBlock ? (unsigned char*)NearBlock->base() + 
00053                             NearBlock->size() : 0;
00054 
00055   void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
00056                     flags, fd, 0);
00057   if (pa == MAP_FAILED) {
00058     if (NearBlock) //Try again without a near hint
00059       return AllocateRWX(NumBytes, 0);
00060 
00061     GetErrno("Can't allocate RWX Memory", ErrMsg);
00062     return MemoryBlock();
00063   }
00064   MemoryBlock result;
00065   result.Address = pa;
00066   result.Size = NumPages*pageSize;
00067   return result;
00068 }
00069 
00070 bool llvm::sys::Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) {
00071   if (M.Address == 0 || M.Size == 0) return false;
00072   if (0 != ::munmap(M.Address, M.Size))
00073     return GetErrno("Can't release RWX Memory", ErrMsg);
00074   return false;
00075 }
00076