28 #include <memoryapi.h> 49 static constexpr DWORD DWORD_MAX = std::numeric_limits<DWORD>::max();
53 MappedFile::MappedFile(
const MemoryRegion ®ion) : region_(region) {}
56 if (region_.size != 0) {
58 VLOG(2) <<
"munmap'ed " << region_.size <<
" bytes at " << region_.mmap;
60 if (UnmapViewOfFile(region_.mmap) != 0) {
61 LOG(ERROR) <<
"Failed to unmap region: " << GetLastError();
63 CloseHandle(region_.file_mapping);
65 if (munmap(region_.mmap, region_.size) != 0) {
66 LOG(ERROR) <<
"Failed to unmap region: " << strerror(errno);
71 operator delete(
static_cast<char *
>(region_.data) - region_.offset);
81 const auto spos = istrm.tellg();
82 VLOG(2) <<
"memorymap: " << (memorymap ?
"true" :
"false") <<
" source: \"" 84 <<
" size: " << size <<
" offset: " << spos;
85 if (memorymap && spos >= 0 && spos % kArchAlignment == 0) {
86 const size_t pos =
static_cast<size_t>(spos);
88 const int fd = _open(source.c_str(), _O_RDONLY);
90 const int fd = open(source.c_str(), O_RDONLY);
93 std::unique_ptr<MappedFile> mmf(MapFromFileDescriptor(fd, pos, size));
94 if (close(fd) == 0 && mmf !=
nullptr) {
95 istrm.seekg(pos + size, std::ios::beg);
97 VLOG(2) <<
"mmap'ed region of " << size <<
" at offset " << pos
98 <<
" from " << source <<
" to addr " << mmf->region_.mmap;
102 LOG(WARNING) <<
"Mapping of file failed: " << strerror(errno);
109 LOG(WARNING) <<
"File mapping at offset " << spos <<
" of file " << source
110 <<
" could not be honored, reading instead";
113 std::unique_ptr<MappedFile> mf(Allocate(size));
114 auto *buffer =
static_cast<char *
>(mf->mutable_data());
116 const auto next_size = std::min(size, kMaxReadChunk);
117 const auto current_pos = istrm.tellg();
118 if (!istrm.read(buffer, next_size)) {
119 LOG(ERROR) <<
"Failed to read " << next_size <<
" bytes at offset " 120 << current_pos <<
"from \"" << source <<
"\"";
125 VLOG(2) <<
"Read " << next_size <<
" bytes. " << size <<
" remaining";
135 GetSystemInfo(&sysInfo);
136 const DWORD pagesize = sysInfo.dwAllocationGranularity;
138 const int pagesize = sysconf(_SC_PAGESIZE);
141 const size_t offset = pos % pagesize;
142 const size_t offset_pos = pos - offset;
143 const size_t upsize = size + offset;
147 LOG(ERROR) <<
"Invalid file descriptor fd=" << fd;
150 HANDLE file =
reinterpret_cast<HANDLE
>(_get_osfhandle(fd));
151 if (file == INVALID_HANDLE_VALUE) {
152 LOG(ERROR) <<
"Invalid file descriptor fd=" << fd;
155 const DWORD max_size_hi =
156 sizeof(size_t) >
sizeof(DWORD) ? upsize >> (CHAR_BIT *
sizeof(DWORD)) : 0;
157 const DWORD max_size_lo = upsize & DWORD_MAX;
158 HANDLE file_mapping = CreateFileMappingA(file,
nullptr, PAGE_READONLY,
159 max_size_hi, max_size_lo,
nullptr);
160 if (file_mapping == INVALID_HANDLE_VALUE) {
161 LOG(ERROR) <<
"Can't create mapping for fd=" << fd <<
" size=" << upsize
162 <<
": " << GetLastError();
166 const DWORD offset_pos_hi =
167 sizeof(size_t) >
sizeof(DWORD) ? offset_pos >> (CHAR_BIT *
sizeof(DWORD))
169 const DWORD offset_pos_lo = offset_pos & DWORD_MAX;
170 void *map = MapViewOfFile(file_mapping, FILE_MAP_READ,
171 offset_pos_hi, offset_pos_lo, upsize);
173 LOG(ERROR) <<
"mmap failed for fd=" << fd <<
" size=" << upsize
174 <<
" offset=" << offset_pos <<
": " << GetLastError();
175 CloseHandle(file_mapping);
179 void *map = mmap(
nullptr, upsize, PROT_READ, MAP_SHARED, fd, offset_pos);
180 if (map == MAP_FAILED) {
181 LOG(ERROR) <<
"mmap failed for fd=" << fd <<
" size=" << upsize
182 <<
" offset=" << offset_pos;
188 region.
size = upsize;
189 region.
data =
static_cast<void *
>(
static_cast<char *
>(map) + offset);
192 region.file_mapping = file_mapping;
199 region.
data =
nullptr;
204 char *buffer =
static_cast<char *
>(
operator new(size + align));
205 uintptr_t address =
reinterpret_cast<uintptr_t
>(buffer);
206 region.
offset = align - (address % align);
209 region.
mmap =
nullptr;
static MappedFile * Map(std::istream &istrm, bool memorymap, const std::string &source, size_t size)
static MappedFile * Allocate(size_t size, size_t align=kArchAlignment)
static MappedFile * Borrow(void *data)
static MappedFile * MapFromFileDescriptor(int fd, size_t pos, size_t size)