blob: afa8f03117fb5d195a77bff9083afc72b1a7ce24 [file] [log] [blame]
Reid Spencer41b21bf2004-09-11 04:57:25 +00001//===- Unix/Memory.cpp - Generic UNIX System Configuration ------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer41b21bf2004-09-11 04:57:25 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file defines some functions for various memory management utilities.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Unix.h"
Reid Spencer07c00d32004-12-27 06:17:03 +000015#include "llvm/System/Process.h"
16
17#ifdef HAVE_SYS_MMAN_H
18#include <sys/mman.h>
19#endif
Reid Spencer41b21bf2004-09-11 04:57:25 +000020
Reid Spencer07c00d32004-12-27 06:17:03 +000021/// AllocateRWXMemory - Allocate a slab of memory with read/write/execute
22/// permissions. This is typically used for JIT applications where we want
23/// to emit code to the memory then jump to it. Getting this type of memory
24/// is very OS specific.
25///
Chris Lattnerbed22d82006-07-07 17:32:37 +000026llvm::sys::MemoryBlock
27llvm::sys::Memory::AllocateRWX(unsigned NumBytes, const MemoryBlock* NearBlock,
28 std::string *ErrMsg) {
Reid Spencer07c00d32004-12-27 06:17:03 +000029 if (NumBytes == 0) return MemoryBlock();
30
31 long pageSize = Process::GetPageSize();
32 unsigned NumPages = (NumBytes+pageSize-1)/pageSize;
33
34 int fd = -1;
35#ifdef NEED_DEV_ZERO_FOR_MMAP
36 static int zero_fd = open("/dev/zero", O_RDWR);
37 if (zero_fd == -1) {
Reid Spencer51c5a282006-08-23 20:34:57 +000038 MakeErrMsg(ErrMsg, "Can't open /dev/zero device");
Chris Lattnerbed22d82006-07-07 17:32:37 +000039 return MemoryBlock();
Reid Spencer07c00d32004-12-27 06:17:03 +000040 }
41 fd = zero_fd;
42#endif
43
44 int flags = MAP_PRIVATE |
45#ifdef HAVE_MMAP_ANONYMOUS
46 MAP_ANONYMOUS
47#else
48 MAP_ANON
49#endif
50 ;
Andrew Lenhartha00269b2005-07-29 23:40:16 +000051
Chris Lattnerbed22d82006-07-07 17:32:37 +000052 void* start = NearBlock ? (unsigned char*)NearBlock->base() +
53 NearBlock->size() : 0;
Andrew Lenhartha00269b2005-07-29 23:40:16 +000054
55 void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
Reid Spencer07c00d32004-12-27 06:17:03 +000056 flags, fd, 0);
57 if (pa == MAP_FAILED) {
Andrew Lenhartha00269b2005-07-29 23:40:16 +000058 if (NearBlock) //Try again without a near hint
59 return AllocateRWX(NumBytes, 0);
Chris Lattnerbed22d82006-07-07 17:32:37 +000060
Reid Spencer51c5a282006-08-23 20:34:57 +000061 MakeErrMsg(ErrMsg, "Can't allocate RWX Memory");
Chris Lattnerbed22d82006-07-07 17:32:37 +000062 return MemoryBlock();
Reid Spencer07c00d32004-12-27 06:17:03 +000063 }
64 MemoryBlock result;
65 result.Address = pa;
66 result.Size = NumPages*pageSize;
67 return result;
68}
69
Chris Lattnerbed22d82006-07-07 17:32:37 +000070bool llvm::sys::Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) {
71 if (M.Address == 0 || M.Size == 0) return false;
72 if (0 != ::munmap(M.Address, M.Size))
Reid Spencer51c5a282006-08-23 20:34:57 +000073 return MakeErrMsg(ErrMsg, "Can't release RWX Memory");
Chris Lattnerbed22d82006-07-07 17:32:37 +000074 return false;
Reid Spencer41b21bf2004-09-11 04:57:25 +000075}
76