| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1 | /* | 
 | 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 Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 19 | #include <errno.h> | 
| Mark Salyzyn | a5e161b | 2016-09-29 08:08:05 -0700 | [diff] [blame] | 20 | #include <fcntl.h> | 
 | 21 | #include <stdint.h> | 
 | 22 | #include <stdlib.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 23 | #include <sys/ioctl.h> | 
| Mark Salyzyn | a5e161b | 2016-09-29 08:08:05 -0700 | [diff] [blame] | 24 | #include <sys/stat.h> | 
 | 25 | #include <sys/types.h> | 
 | 26 | #include <unistd.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 27 |  | 
| Mark Salyzyn | 7823e12 | 2016-09-29 08:08:05 -0700 | [diff] [blame] | 28 | #include <binder/MemoryHeapBase.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 29 | #include <cutils/ashmem.h> | 
 | 30 | #include <cutils/atomic.h> | 
| Mark Salyzyn | 4dad9ce | 2016-09-29 08:08:05 -0700 | [diff] [blame] | 31 | #include <log/log.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 32 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 33 | namespace android { | 
 | 34 |  | 
 | 35 | // --------------------------------------------------------------------------- | 
 | 36 |  | 
| Anu Sundararajan | 5728a92 | 2011-06-22 15:58:59 -0500 | [diff] [blame] | 37 | MemoryHeapBase::MemoryHeapBase() | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 38 |     : mFD(-1), mSize(0), mBase(MAP_FAILED), | 
| Yi Kong | 9163556 | 2018-06-07 14:38:36 -0700 | [diff] [blame] | 39 |       mDevice(nullptr), mNeedUnmap(false), mOffset(0) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 40 | { | 
 | 41 | } | 
 | 42 |  | 
 | 43 | MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name) | 
 | 44 |     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), | 
| Yi Kong | 9163556 | 2018-06-07 14:38:36 -0700 | [diff] [blame] | 45 |       mDevice(nullptr), mNeedUnmap(false), mOffset(0) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 46 | { | 
 | 47 |     const size_t pagesize = getpagesize(); | 
 | 48 |     size = ((size + pagesize-1) & ~(pagesize-1)); | 
| Yi Kong | 9163556 | 2018-06-07 14:38:36 -0700 | [diff] [blame] | 49 |     int fd = ashmem_create_region(name == nullptr ? "MemoryHeapBase" : name, size); | 
| Steve Block | e6f43dd | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 50 |     ALOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno)); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 51 |     if (fd >= 0) { | 
 | 52 |         if (mapfd(fd, size) == NO_ERROR) { | 
 | 53 |             if (flags & READ_ONLY) { | 
 | 54 |                 ashmem_set_prot_region(fd, PROT_READ); | 
 | 55 |             } | 
 | 56 |         } | 
 | 57 |     } | 
 | 58 | } | 
 | 59 |  | 
 | 60 | MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags) | 
 | 61 |     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), | 
| Yi Kong | 9163556 | 2018-06-07 14:38:36 -0700 | [diff] [blame] | 62 |       mDevice(nullptr), mNeedUnmap(false), mOffset(0) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 63 | { | 
| Iliyan Malchev | 0db1a89 | 2009-10-29 22:55:00 -0700 | [diff] [blame] | 64 |     int open_flags = O_RDWR; | 
 | 65 |     if (flags & NO_CACHING) | 
 | 66 |         open_flags |= O_SYNC; | 
 | 67 |  | 
 | 68 |     int fd = open(device, open_flags); | 
| Steve Block | e6f43dd | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 69 |     ALOGE_IF(fd<0, "error opening %s: %s", device, strerror(errno)); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 70 |     if (fd >= 0) { | 
 | 71 |         const size_t pagesize = getpagesize(); | 
 | 72 |         size = ((size + pagesize-1) & ~(pagesize-1)); | 
 | 73 |         if (mapfd(fd, size) == NO_ERROR) { | 
 | 74 |             mDevice = device; | 
 | 75 |         } | 
 | 76 |     } | 
 | 77 | } | 
 | 78 |  | 
| Benny Wong | d4851d7 | 2009-08-17 15:28:30 -0500 | [diff] [blame] | 79 | MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 80 |     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), | 
| Yi Kong | 9163556 | 2018-06-07 14:38:36 -0700 | [diff] [blame] | 81 |       mDevice(nullptr), mNeedUnmap(false), mOffset(0) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 82 | { | 
 | 83 |     const size_t pagesize = getpagesize(); | 
 | 84 |     size = ((size + pagesize-1) & ~(pagesize-1)); | 
| Nick Kralevich | ec9ec7d | 2016-12-17 19:47:27 -0800 | [diff] [blame] | 85 |     mapfd(fcntl(fd, F_DUPFD_CLOEXEC, 0), size, offset); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 86 | } | 
 | 87 |  | 
 | 88 | status_t MemoryHeapBase::init(int fd, void *base, int size, int flags, const char* device) | 
 | 89 | { | 
 | 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 |  | 
| Benny Wong | d4851d7 | 2009-08-17 15:28:30 -0500 | [diff] [blame] | 101 | status_t MemoryHeapBase::mapfd(int fd, size_t size, uint32_t offset) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 102 | { | 
 | 103 |     if (size == 0) { | 
 | 104 |         // try to figure out the size automatically | 
| Elliott Hughes | a5a13a3 | 2013-11-21 12:22:39 -0800 | [diff] [blame] | 105 |         struct stat sb; | 
 | 106 |         if (fstat(fd, &sb) == 0) | 
 | 107 |             size = sb.st_size; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 108 |         // if it didn't work, let mmap() fail. | 
 | 109 |     } | 
 | 110 |  | 
 | 111 |     if ((mFlags & DONT_MAP_LOCALLY) == 0) { | 
| Yi Kong | 9163556 | 2018-06-07 14:38:36 -0700 | [diff] [blame] | 112 |         void* base = (uint8_t*)mmap(nullptr, size, | 
| Benny Wong | d4851d7 | 2009-08-17 15:28:30 -0500 | [diff] [blame] | 113 |                 PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 114 |         if (base == MAP_FAILED) { | 
| Steve Block | e6f43dd | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 115 |             ALOGE("mmap(fd=%d, size=%u) failed (%s)", | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 116 |                     fd, uint32_t(size), strerror(errno)); | 
 | 117 |             close(fd); | 
 | 118 |             return -errno; | 
 | 119 |         } | 
| Steve Block | 9d45368 | 2011-12-20 16:23:08 +0000 | [diff] [blame] | 120 |         //ALOGD("mmap(fd=%d, base=%p, size=%lu)", fd, base, size); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 121 |         mBase = base; | 
 | 122 |         mNeedUnmap = true; | 
 | 123 |     } else  { | 
| Yi Kong | 9163556 | 2018-06-07 14:38:36 -0700 | [diff] [blame] | 124 |         mBase = nullptr; // not MAP_FAILED | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 125 |         mNeedUnmap = false; | 
 | 126 |     } | 
 | 127 |     mFD = fd; | 
 | 128 |     mSize = size; | 
| Anu Sundararajan | 5728a92 | 2011-06-22 15:58:59 -0500 | [diff] [blame] | 129 |     mOffset = offset; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 130 |     return NO_ERROR; | 
 | 131 | } | 
 | 132 |  | 
 | 133 | MemoryHeapBase::~MemoryHeapBase() | 
 | 134 | { | 
 | 135 |     dispose(); | 
 | 136 | } | 
 | 137 |  | 
 | 138 | void MemoryHeapBase::dispose() | 
 | 139 | { | 
 | 140 |     int fd = android_atomic_or(-1, &mFD); | 
 | 141 |     if (fd >= 0) { | 
 | 142 |         if (mNeedUnmap) { | 
| Steve Block | 9d45368 | 2011-12-20 16:23:08 +0000 | [diff] [blame] | 143 |             //ALOGD("munmap(fd=%d, base=%p, size=%lu)", fd, mBase, mSize); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 144 |             munmap(mBase, mSize); | 
 | 145 |         } | 
| Yi Kong | 9163556 | 2018-06-07 14:38:36 -0700 | [diff] [blame] | 146 |         mBase = nullptr; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 147 |         mSize = 0; | 
 | 148 |         close(fd); | 
 | 149 |     } | 
 | 150 | } | 
 | 151 |  | 
 | 152 | int MemoryHeapBase::getHeapID() const { | 
 | 153 |     return mFD; | 
 | 154 | } | 
 | 155 |  | 
 | 156 | void* MemoryHeapBase::getBase() const { | 
 | 157 |     return mBase; | 
 | 158 | } | 
 | 159 |  | 
 | 160 | size_t MemoryHeapBase::getSize() const { | 
 | 161 |     return mSize; | 
 | 162 | } | 
 | 163 |  | 
 | 164 | uint32_t MemoryHeapBase::getFlags() const { | 
 | 165 |     return mFlags; | 
 | 166 | } | 
 | 167 |  | 
 | 168 | const char* MemoryHeapBase::getDevice() const { | 
 | 169 |     return mDevice; | 
 | 170 | } | 
 | 171 |  | 
| Anu Sundararajan | 5728a92 | 2011-06-22 15:58:59 -0500 | [diff] [blame] | 172 | uint32_t MemoryHeapBase::getOffset() const { | 
 | 173 |     return mOffset; | 
 | 174 | } | 
 | 175 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 176 | // --------------------------------------------------------------------------- | 
 | 177 | }; // namespace android |