LLVM API Documentation
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