FileMap.cpp 6.5 KB

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