blob: e1cbc1996d7f3606c23556e4d7437f33064a292b [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
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#define LOG_TAG "MemoryHeapBase"
18
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080019#include <errno.h>
Mark Salyzyna5e161b2016-09-29 08:08:05 -070020#include <fcntl.h>
21#include <stdint.h>
22#include <stdlib.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080023#include <sys/ioctl.h>
Mark Salyzyna5e161b2016-09-29 08:08:05 -070024#include <sys/stat.h>
25#include <sys/types.h>
26#include <unistd.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080027
Mark Salyzyn7823e122016-09-29 08:08:05 -070028#include <binder/MemoryHeapBase.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080029#include <cutils/ashmem.h>
30#include <cutils/atomic.h>
Mark Salyzyn4dad9ce2016-09-29 08:08:05 -070031#include <log/log.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080032
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080033namespace android {
34
35// ---------------------------------------------------------------------------
36
Anu Sundararajan5728a922011-06-22 15:58:59 -050037MemoryHeapBase::MemoryHeapBase()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080038 : mFD(-1), mSize(0), mBase(MAP_FAILED),
Yi Kong91635562018-06-07 14:38:36 -070039 mDevice(nullptr), mNeedUnmap(false), mOffset(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080040{
41}
42
43MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name)
44 : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
Yi Kong91635562018-06-07 14:38:36 -070045 mDevice(nullptr), mNeedUnmap(false), mOffset(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080046{
47 const size_t pagesize = getpagesize();
48 size = ((size + pagesize-1) & ~(pagesize-1));
Yi Kong91635562018-06-07 14:38:36 -070049 int fd = ashmem_create_region(name == nullptr ? "MemoryHeapBase" : name, size);
Steve Blocke6f43dd2012-01-06 19:20:56 +000050 ALOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080051 if (fd >= 0) {
Ytai Ben-Tsvidacdbd12020-10-22 15:40:45 -070052 if (mapfd(fd, true, size) == NO_ERROR) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080053 if (flags & READ_ONLY) {
54 ashmem_set_prot_region(fd, PROT_READ);
55 }
56 }
57 }
58}
59
60MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags)
61 : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
Yi Kong91635562018-06-07 14:38:36 -070062 mDevice(nullptr), mNeedUnmap(false), mOffset(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080063{
Iliyan Malchev0db1a892009-10-29 22:55:00 -070064 int open_flags = O_RDWR;
65 if (flags & NO_CACHING)
66 open_flags |= O_SYNC;
67
68 int fd = open(device, open_flags);
Steve Blocke6f43dd2012-01-06 19:20:56 +000069 ALOGE_IF(fd<0, "error opening %s: %s", device, strerror(errno));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080070 if (fd >= 0) {
71 const size_t pagesize = getpagesize();
72 size = ((size + pagesize-1) & ~(pagesize-1));
Ytai Ben-Tsvidacdbd12020-10-22 15:40:45 -070073 if (mapfd(fd, false, size) == NO_ERROR) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080074 mDevice = device;
75 }
76 }
77}
78
Andy Hung5b028522018-10-22 15:29:49 -070079MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, off_t offset)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080080 : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
Yi Kong91635562018-06-07 14:38:36 -070081 mDevice(nullptr), mNeedUnmap(false), mOffset(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080082{
83 const size_t pagesize = getpagesize();
84 size = ((size + pagesize-1) & ~(pagesize-1));
Ytai Ben-Tsvidacdbd12020-10-22 15:40:45 -070085 mapfd(fcntl(fd, F_DUPFD_CLOEXEC, 0), false, size, offset);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080086}
87
Andy Hung5b028522018-10-22 15:29:49 -070088status_t MemoryHeapBase::init(int fd, void *base, size_t size, int flags, const char* device)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080089{
90 if (mFD != -1) {
91 return INVALID_OPERATION;
92 }
93 mFD = fd;
94 mBase = base;
95 mSize = size;
96 mFlags = flags;
97 mDevice = device;
98 return NO_ERROR;
99}
100
Ytai Ben-Tsvidacdbd12020-10-22 15:40:45 -0700101status_t MemoryHeapBase::mapfd(int fd, bool writeableByCaller, size_t size, off_t offset)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800102{
103 if (size == 0) {
104 // try to figure out the size automatically
Elliott Hughesa5a13a32013-11-21 12:22:39 -0800105 struct stat sb;
Andy Hung5b028522018-10-22 15:29:49 -0700106 if (fstat(fd, &sb) == 0) {
107 size = (size_t)sb.st_size;
108 // sb.st_size is off_t which on ILP32 may be 64 bits while size_t is 32 bits.
109 if ((off_t)size != sb.st_size) {
110 ALOGE("%s: size of file %lld cannot fit in memory",
111 __func__, (long long)sb.st_size);
112 return INVALID_OPERATION;
113 }
114 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800115 // if it didn't work, let mmap() fail.
116 }
117
118 if ((mFlags & DONT_MAP_LOCALLY) == 0) {
Ytai Ben-Tsvidacdbd12020-10-22 15:40:45 -0700119 int prot = PROT_READ;
120 if (writeableByCaller || (mFlags & READ_ONLY) == 0) {
121 prot |= PROT_WRITE;
122 }
Yi Kong91635562018-06-07 14:38:36 -0700123 void* base = (uint8_t*)mmap(nullptr, size,
Ytai Ben-Tsvidacdbd12020-10-22 15:40:45 -0700124 prot, MAP_SHARED, fd, offset);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800125 if (base == MAP_FAILED) {
Andy Hung5b028522018-10-22 15:29:49 -0700126 ALOGE("mmap(fd=%d, size=%zu) failed (%s)",
127 fd, size, strerror(errno));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800128 close(fd);
129 return -errno;
130 }
Andy Hung5b028522018-10-22 15:29:49 -0700131 //ALOGD("mmap(fd=%d, base=%p, size=%zu)", fd, base, size);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800132 mBase = base;
133 mNeedUnmap = true;
134 } else {
Yi Kong91635562018-06-07 14:38:36 -0700135 mBase = nullptr; // not MAP_FAILED
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800136 mNeedUnmap = false;
137 }
138 mFD = fd;
139 mSize = size;
Anu Sundararajan5728a922011-06-22 15:58:59 -0500140 mOffset = offset;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800141 return NO_ERROR;
142}
143
144MemoryHeapBase::~MemoryHeapBase()
145{
146 dispose();
147}
148
149void MemoryHeapBase::dispose()
150{
151 int fd = android_atomic_or(-1, &mFD);
152 if (fd >= 0) {
153 if (mNeedUnmap) {
Andy Hung5b028522018-10-22 15:29:49 -0700154 //ALOGD("munmap(fd=%d, base=%p, size=%zu)", fd, mBase, mSize);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800155 munmap(mBase, mSize);
156 }
Yi Kong91635562018-06-07 14:38:36 -0700157 mBase = nullptr;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800158 mSize = 0;
159 close(fd);
160 }
161}
162
163int MemoryHeapBase::getHeapID() const {
164 return mFD;
165}
166
167void* MemoryHeapBase::getBase() const {
168 return mBase;
169}
170
171size_t MemoryHeapBase::getSize() const {
172 return mSize;
173}
174
175uint32_t MemoryHeapBase::getFlags() const {
176 return mFlags;
177}
178
179const char* MemoryHeapBase::getDevice() const {
180 return mDevice;
181}
182
Andy Hung5b028522018-10-22 15:29:49 -0700183off_t MemoryHeapBase::getOffset() const {
Anu Sundararajan5728a922011-06-22 15:58:59 -0500184 return mOffset;
185}
186
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800187// ---------------------------------------------------------------------------
Steven Moreland61ff8492019-09-26 16:05:45 -0700188} // namespace android