blob: f44939cac7f0db2eb0d02b74b3247e34f721c66e [file] [log] [blame]
Brian Carlstromdb4d5402011-08-09 12:18:28 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_SRC_MEM_MAP_H_
18#define ART_SRC_MEM_MAP_H_
19
20#include <sys/mman.h>
21
22#include "utils.h"
23
24namespace art {
25
26// Used to keep track of mmap segments.
27class MemMap {
28 public:
29
30 // Request an anonymous region of a specified length.
31 //
32 // On success, returns returns a MemMap instance. On failure, returns a NULL;
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070033 static MemMap* Map(size_t length, int prot) {
34 return Map(NULL, length, prot);
35 }
36
37 // Request an anonymous region of a specified length and a requested base address.
38 //
39 // On success, returns returns a MemMap instance. On failure, returns a NULL;
40 static MemMap* Map(byte* addr, size_t length, int prot) {
41 CHECK_NE(0U, length);
42 CHECK_NE(0, prot);
Brian Carlstromdb4d5402011-08-09 12:18:28 -070043 size_t page_aligned_size = RoundUp(length, kPageSize);
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070044 byte* actual = reinterpret_cast<byte*>(mmap(addr,
45 page_aligned_size,
46 prot,
47 MAP_PRIVATE | MAP_ANONYMOUS,
48 -1,
49 0));
50 if (actual == MAP_FAILED) {
51 PLOG(ERROR) << "mmap failed";
Brian Carlstromdb4d5402011-08-09 12:18:28 -070052 return NULL;
53 }
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070054 return new MemMap(actual, length, actual, page_aligned_size);
Brian Carlstromdb4d5402011-08-09 12:18:28 -070055 }
56
57 // Map part of a file, taking care of non-page aligned offsets. The
58 // "start" offset is absolute, not relative.
59 //
60 // On success, returns returns a MemMap instance. On failure, returns a NULL;
61 static MemMap* Map(size_t length, int prot, int flags, int fd, off_t start) {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070062 return Map(NULL, length, prot, flags, fd, start);
63 }
64
65 // Map part of a file, taking care of non-page aligned offsets. The
66 // "start" offset is absolute, not relative. This version allows
67 // requesting a specific address for the base of the mapping.
68 //
69 // On success, returns returns a MemMap instance. On failure, returns a NULL;
70 static MemMap* Map(byte* addr, size_t length, int prot, int flags, int fd, off_t start) {
71 CHECK_NE(0U, length);
72 CHECK_NE(0, prot);
73 CHECK(flags & MAP_SHARED || flags & MAP_PRIVATE);
Brian Carlstromdb4d5402011-08-09 12:18:28 -070074 // adjust to be page-aligned
75 int page_offset = start % kPageSize;
76 off_t page_aligned_offset = start - page_offset;
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070077 size_t page_aligned_size = RoundUp(length + page_offset, kPageSize);
78 byte* actual = reinterpret_cast<byte*>(mmap(addr,
79 page_aligned_size,
80 prot,
81 flags,
82 fd,
83 page_aligned_offset));
84 if (actual == MAP_FAILED) {
85 PLOG(ERROR) << "mmap failed";
Brian Carlstromdb4d5402011-08-09 12:18:28 -070086 return NULL;
87 }
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070088 return new MemMap(actual + page_offset, length, actual, page_aligned_size);
Brian Carlstromdb4d5402011-08-09 12:18:28 -070089 }
90
91 ~MemMap() {
92 Unmap();
Brian Carlstrom4e777d42011-08-15 13:53:52 -070093 }
Brian Carlstromdb4d5402011-08-09 12:18:28 -070094
95 // Release a memory mapping, returning true on success or it was previously unmapped.
96 bool Unmap() {
97 if (base_addr_ == NULL && base_length_ == 0) {
98 return true;
99 }
100 int result = munmap(base_addr_, base_length_);
101 base_addr_ = NULL;
102 base_length_ = 0;
103 if (result == -1) {
104 return false;
105 }
106 return true;
107 }
108
109 byte* GetAddress() const {
110 return addr_;
111 }
112
113 size_t GetLength() const {
114 return length_;
115 }
116
Brian Carlstromb765be02011-08-17 23:54:10 -0700117 byte* GetLimit() const {
118 return addr_ + length_;
119 }
120
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700121 private:
122 MemMap(byte* addr, size_t length, void* base_addr, size_t base_length)
123 : addr_(addr), length_(length), base_addr_(base_addr), base_length_(base_length) {
124 CHECK(addr_ != NULL);
125 CHECK(length_ != 0);
126 CHECK(base_addr_ != NULL);
127 CHECK(base_length_ != 0);
128 };
129
130 byte* addr_; // start of data
131 size_t length_; // length of data
132
133 void* base_addr_; // page-aligned base address
134 size_t base_length_; // length of mapping
135};
136
137} // namespace art
138
139#endif // ART_SRC_MEM_MAP_H_