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 19#include <stdlib.h> 20#include <stdint.h> 21#include <unistd.h> 22#include <fcntl.h> 23#include <errno.h> 24#include <sys/types.h> 25#include <sys/stat.h> 26#include <sys/ioctl.h> 27 28#include <cutils/log.h> 29#include <cutils/ashmem.h> 30#include <cutils/atomic.h> 31 32#include <binder/MemoryHeapBase.h> 33 34namespace android { 35 36// --------------------------------------------------------------------------- 37 38MemoryHeapBase::MemoryHeapBase() 39 : mFD(-1), mSize(0), mBase(MAP_FAILED), 40 mDevice(NULL), mNeedUnmap(false), mOffset(0) 41{ 42} 43 44MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name) 45 : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), 46 mDevice(0), mNeedUnmap(false), mOffset(0) 47{ 48 const size_t pagesize = getpagesize(); 49 size = ((size + pagesize-1) & ~(pagesize-1)); 50 int fd = ashmem_create_region(name == NULL ? "MemoryHeapBase" : name, size); 51 ALOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno)); 52 if (fd >= 0) { 53 if (mapfd(fd, size) == NO_ERROR) { 54 if (flags & READ_ONLY) { 55 ashmem_set_prot_region(fd, PROT_READ); 56 } 57 } 58 } 59} 60 61MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags) 62 : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), 63 mDevice(0), mNeedUnmap(false), mOffset(0) 64{ 65 int open_flags = O_RDWR; 66 if (flags & NO_CACHING) 67 open_flags |= O_SYNC; 68 69 int fd = open(device, open_flags); 70 ALOGE_IF(fd<0, "error opening %s: %s", device, strerror(errno)); 71 if (fd >= 0) { 72 const size_t pagesize = getpagesize(); 73 size = ((size + pagesize-1) & ~(pagesize-1)); 74 if (mapfd(fd, size) == NO_ERROR) { 75 mDevice = device; 76 } 77 } 78} 79 80MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset) 81 : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), 82 mDevice(0), mNeedUnmap(false), mOffset(0) 83{ 84 const size_t pagesize = getpagesize(); 85 size = ((size + pagesize-1) & ~(pagesize-1)); 86 mapfd(dup(fd), size, offset); 87} 88 89status_t MemoryHeapBase::init(int fd, void *base, int size, int flags, const char* device) 90{ 91 if (mFD != -1) { 92 return INVALID_OPERATION; 93 } 94 mFD = fd; 95 mBase = base; 96 mSize = size; 97 mFlags = flags; 98 mDevice = device; 99 return NO_ERROR; 100} 101 102status_t MemoryHeapBase::mapfd(int fd, size_t size, uint32_t offset) 103{ 104 if (size == 0) { 105 // try to figure out the size automatically 106 struct stat sb; 107 if (fstat(fd, &sb) == 0) 108 size = sb.st_size; 109 // if it didn't work, let mmap() fail. 110 } 111 112 if ((mFlags & DONT_MAP_LOCALLY) == 0) { 113 void* base = (uint8_t*)mmap(0, size, 114 PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset); 115 if (base == MAP_FAILED) { 116 ALOGE("mmap(fd=%d, size=%u) failed (%s)", 117 fd, uint32_t(size), strerror(errno)); 118 close(fd); 119 return -errno; 120 } 121 //ALOGD("mmap(fd=%d, base=%p, size=%lu)", fd, base, size); 122 mBase = base; 123 mNeedUnmap = true; 124 } else { 125 mBase = 0; // not MAP_FAILED 126 mNeedUnmap = false; 127 } 128 mFD = fd; 129 mSize = size; 130 mOffset = offset; 131 return NO_ERROR; 132} 133 134MemoryHeapBase::~MemoryHeapBase() 135{ 136 dispose(); 137} 138 139void MemoryHeapBase::dispose() 140{ 141 int fd = android_atomic_or(-1, &mFD); 142 if (fd >= 0) { 143 if (mNeedUnmap) { 144 //ALOGD("munmap(fd=%d, base=%p, size=%lu)", fd, mBase, mSize); 145 munmap(mBase, mSize); 146 } 147 mBase = 0; 148 mSize = 0; 149 close(fd); 150 } 151} 152 153int MemoryHeapBase::getHeapID() const { 154 return mFD; 155} 156 157void* MemoryHeapBase::getBase() const { 158 return mBase; 159} 160 161size_t MemoryHeapBase::getSize() const { 162 return mSize; 163} 164 165uint32_t MemoryHeapBase::getFlags() const { 166 return mFlags; 167} 168 169const char* MemoryHeapBase::getDevice() const { 170 return mDevice; 171} 172 173uint32_t MemoryHeapBase::getOffset() const { 174 return mOffset; 175} 176 177// --------------------------------------------------------------------------- 178}; // namespace android 179