blob: 621184e426058981c0ae7977b38fb003cc293201 [file] [log] [blame]
Dan Gohmanf17a25c2007-07-18 16:29:46 +00001//===- Unix/Memory.cpp - Generic UNIX System Configuration ------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner081ce942007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Dan Gohmanf17a25c2007-07-18 16:29:46 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file defines some functions for various memory management utilities.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Unix.h"
15#include "llvm/System/Process.h"
16
17#ifdef HAVE_SYS_MMAN_H
18#include <sys/mman.h>
19#endif
20
Evan Chengd23312a2008-09-16 17:28:18 +000021/// AllocateRWX - Allocate a slab of memory with read/write/execute
Dan Gohmanf17a25c2007-07-18 16:29:46 +000022/// 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///
26llvm::sys::MemoryBlock
27llvm::sys::Memory::AllocateRWX(unsigned NumBytes, const MemoryBlock* NearBlock,
28 std::string *ErrMsg) {
29 if (NumBytes == 0) return MemoryBlock();
30
Evan Cheng591bfc82008-05-05 18:30:58 +000031 unsigned pageSize = Process::GetPageSize();
Dan Gohmanf17a25c2007-07-18 16:29:46 +000032 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) {
38 MakeErrMsg(ErrMsg, "Can't open /dev/zero device");
39 return MemoryBlock();
40 }
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 ;
51
52 void* start = NearBlock ? (unsigned char*)NearBlock->base() +
53 NearBlock->size() : 0;
54
55 void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
56 flags, fd, 0);
57 if (pa == MAP_FAILED) {
58 if (NearBlock) //Try again without a near hint
59 return AllocateRWX(NumBytes, 0);
60
61 MakeErrMsg(ErrMsg, "Can't allocate RWX Memory");
62 return MemoryBlock();
63 }
64 MemoryBlock result;
65 result.Address = pa;
66 result.Size = NumPages*pageSize;
67 return result;
68}
69
Dan Gohmanf17a25c2007-07-18 16:29:46 +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))
73 return MakeErrMsg(ErrMsg, "Can't release RWX Memory");
74 return false;
75}
76