1/* 2 * Copyright (C) 2006 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// 18// Shared file mapping class. 19// 20 21#define LOG_TAG "filemap" 22 23#include <utils/FileMap.h> 24#include <utils/Log.h> 25 26#if defined(__MINGW32__) && !defined(__USE_MINGW_ANSI_STDIO) 27# define PRId32 "I32d" 28# define PRIx32 "I32x" 29# define PRId64 "I64d" 30#else 31#include <inttypes.h> 32#endif 33#include <stdio.h> 34#include <stdlib.h> 35 36#if !defined(__MINGW32__) 37#include <sys/mman.h> 38#endif 39 40#include <string.h> 41#include <memory.h> 42#include <errno.h> 43#include <assert.h> 44 45using namespace android; 46 47/*static*/ long FileMap::mPageSize = -1; 48 49// Constructor. Create an empty object. 50FileMap::FileMap(void) 51 : mFileName(NULL), mBasePtr(NULL), mBaseLength(0), 52 mDataPtr(NULL), mDataLength(0) 53{ 54} 55 56// Destructor. 57FileMap::~FileMap(void) 58{ 59 if (mFileName != NULL) { 60 free(mFileName); 61 } 62#if defined(__MINGW32__) 63 if (mBasePtr && UnmapViewOfFile(mBasePtr) == 0) { 64 ALOGD("UnmapViewOfFile(%p) failed, error = %" PRId32 "\n", mBasePtr, 65 GetLastError() ); 66 } 67 if (mFileMapping != INVALID_HANDLE_VALUE) { 68 CloseHandle(mFileMapping); 69 } 70#else 71 if (mBasePtr && munmap(mBasePtr, mBaseLength) != 0) { 72 ALOGD("munmap(%p, %zu) failed\n", mBasePtr, mBaseLength); 73 } 74#endif 75} 76 77 78// Create a new mapping on an open file. 79// 80// Closing the file descriptor does not unmap the pages, so we don't 81// claim ownership of the fd. 82// 83// Returns "false" on failure. 84bool FileMap::create(const char* origFileName, int fd, off64_t offset, size_t length, 85 bool readOnly) 86{ 87#if defined(__MINGW32__) 88 int adjust; 89 off64_t adjOffset; 90 size_t adjLength; 91 92 if (mPageSize == -1) { 93 SYSTEM_INFO si; 94 95 GetSystemInfo( &si ); 96 mPageSize = si.dwAllocationGranularity; 97 } 98 99 DWORD protect = readOnly ? PAGE_READONLY : PAGE_READWRITE; 100 101 mFileHandle = (HANDLE) _get_osfhandle(fd); 102 mFileMapping = CreateFileMapping( mFileHandle, NULL, protect, 0, 0, NULL); 103 if (mFileMapping == NULL) { 104 ALOGE("CreateFileMapping(%p, %" PRIx32 ") failed with error %" PRId32 "\n", 105 mFileHandle, protect, GetLastError() ); 106 return false; 107 } 108 109 adjust = offset % mPageSize; 110 adjOffset = offset - adjust; 111 adjLength = length + adjust; 112 113 mBasePtr = MapViewOfFile( mFileMapping, 114 readOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS, 115 0, 116 (DWORD)(adjOffset), 117 adjLength ); 118 if (mBasePtr == NULL) { 119 ALOGE("MapViewOfFile(%" PRId64 ", %zu) failed with error %" PRId32 "\n", 120 adjOffset, adjLength, GetLastError() ); 121 CloseHandle(mFileMapping); 122 mFileMapping = INVALID_HANDLE_VALUE; 123 return false; 124 } 125#else // !defined(__MINGW32__) 126 int prot, flags, adjust; 127 off64_t adjOffset; 128 size_t adjLength; 129 130 void* ptr; 131 132 assert(fd >= 0); 133 assert(offset >= 0); 134 assert(length > 0); 135 136 // init on first use 137 if (mPageSize == -1) { 138 mPageSize = sysconf(_SC_PAGESIZE); 139 if (mPageSize == -1) { 140 ALOGE("could not get _SC_PAGESIZE\n"); 141 return false; 142 } 143 } 144 145 adjust = offset % mPageSize; 146 adjOffset = offset - adjust; 147 adjLength = length + adjust; 148 149 flags = MAP_SHARED; 150 prot = PROT_READ; 151 if (!readOnly) 152 prot |= PROT_WRITE; 153 154 ptr = mmap(NULL, adjLength, prot, flags, fd, adjOffset); 155 if (ptr == MAP_FAILED) { 156 ALOGE("mmap(%lld,%zu) failed: %s\n", 157 (long long)adjOffset, adjLength, strerror(errno)); 158 return false; 159 } 160 mBasePtr = ptr; 161#endif // !defined(__MINGW32__) 162 163 mFileName = origFileName != NULL ? strdup(origFileName) : NULL; 164 mBaseLength = adjLength; 165 mDataOffset = offset; 166 mDataPtr = (char*) mBasePtr + adjust; 167 mDataLength = length; 168 169 assert(mBasePtr != NULL); 170 171 ALOGV("MAP: base %p/%zu data %p/%zu\n", 172 mBasePtr, mBaseLength, mDataPtr, mDataLength); 173 174 return true; 175} 176 177// Provide guidance to the system. 178#if !defined(_WIN32) 179int FileMap::advise(MapAdvice advice) 180{ 181 int cc, sysAdvice; 182 183 switch (advice) { 184 case NORMAL: sysAdvice = MADV_NORMAL; break; 185 case RANDOM: sysAdvice = MADV_RANDOM; break; 186 case SEQUENTIAL: sysAdvice = MADV_SEQUENTIAL; break; 187 case WILLNEED: sysAdvice = MADV_WILLNEED; break; 188 case DONTNEED: sysAdvice = MADV_DONTNEED; break; 189 default: 190 assert(false); 191 return -1; 192 } 193 194 cc = madvise(mBasePtr, mBaseLength, sysAdvice); 195 if (cc != 0) 196 ALOGW("madvise(%d) failed: %s\n", sysAdvice, strerror(errno)); 197 return cc; 198} 199 200#else 201int FileMap::advise(MapAdvice /* advice */) 202{ 203 return -1; 204} 205#endif 206