|
5 | 5 | #include <fcntl.h> // for open, O_RDONLY
|
6 | 6 | #include <sys/mman.h> // for mmap, mmap64, munmap
|
7 | 7 | #include <sys/stat.h>
|
8 |
| -#include <unistd.h> // for close |
| 8 | +#include <unistd.h> // for close, getpagesize |
| 9 | +#elif defined(_MSC_VER) |
| 10 | +#include <windows.h> |
9 | 11 | #endif // defined(__unix__)
|
| 12 | + |
10 | 13 | #include <algorithm>
|
11 | 14 | #include <cerrno> // for errno
|
12 | 15 | #include <cstdio>
|
@@ -157,34 +160,78 @@ std::string FileExtension(std::string fname, bool lower) {
|
157 | 160 | }
|
158 | 161 | }
|
159 | 162 |
|
160 |
| -void* PrivateMmapStream::Open(StringView path, bool read_only, std::size_t offset, |
| 163 | +std::size_t GetPageSize() { |
| 164 | +#if defined(_MSC_VER) |
| 165 | + SYSTEM_INFO sys_info; |
| 166 | + GetSystemInfo(&sys_info); |
| 167 | + return sys_info.dwPageSize; |
| 168 | +#else |
| 169 | + return getpagesize(); |
| 170 | +#endif |
| 171 | +} |
| 172 | + |
| 173 | +struct PrivateMmapStream::MMAPFile { |
| 174 | +#if defined(_MSC_VER) |
| 175 | + HANDLE fd; |
| 176 | +#else |
| 177 | + std::int32_t fd; |
| 178 | +#endif |
| 179 | + std::string path; |
| 180 | +}; |
| 181 | + |
| 182 | +PrivateMmapStream::PrivateMmapStream(std::string path, bool read_only, std::size_t offset, |
| 183 | + std::size_t length) |
| 184 | + : MemoryFixSizeBuffer{Open(std::move(path), read_only, offset, length), length} {} |
| 185 | + |
| 186 | +void* PrivateMmapStream::Open(std::string path, bool read_only, std::size_t offset, |
161 | 187 | std::size_t length) {
|
162 |
| - fd_ = open(path.c_str(), O_RDONLY); |
163 |
| - CHECK_GE(fd_, 0) << "Failed to open:" << path << ". " << strerror(errno); |
| 188 | +#if defined(_MSC_VER) |
| 189 | + HANDLE fd = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, |
| 190 | + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, nullptr); |
| 191 | + CHECK_NE(fd, INVALID_HANDLE_VALUE) << "Failed to open:" << path; |
| 192 | +#else |
| 193 | + auto fd = open(path.c_str(), O_RDONLY); |
| 194 | +#endif |
| 195 | + CHECK_GE(fd, 0) << "Failed to open:" << path << ". " << strerror(errno); |
| 196 | + handle_ = std::make_unique<MMAPFile>(fd, std::move(path)); |
164 | 197 |
|
165 |
| - char* ptr{nullptr}; |
| 198 | + void* ptr{nullptr}; |
| 199 | +#if defined(__linux__) || defined(__GLIBC__) |
166 | 200 | int prot{PROT_READ};
|
167 | 201 | if (!read_only) {
|
168 | 202 | prot |= PROT_WRITE;
|
169 | 203 | }
|
170 |
| -#if defined(__linux__) || defined(__GLIBC__) |
171 | 204 | ptr = reinterpret_cast<char*>(mmap64(nullptr, length, prot, MAP_PRIVATE, fd_, offset));
|
| 205 | + CHECK_NE(ptr, MAP_FAILED) << "Failed to map: " << path << ". " << strerror(errno); |
172 | 206 | #elif defined(_MSC_VER)
|
173 |
| - // fixme: not yet implemented |
174 |
| - ptr = reinterpret_cast<char*>(mmap(nullptr, length, prot, MAP_PRIVATE, fd_, offset)); |
| 207 | + auto file_size = GetFileSize(handle_->fd, nullptr); |
| 208 | + DWORD access = read_only ? PAGE_READONLY : PAGE_READWRITE; |
| 209 | + auto map_file = CreateFileMapping(handle_->fd, nullptr, access, 0, file_size, nullptr); |
| 210 | + access = read_only ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS; |
| 211 | + ptr = MapViewOfFile(map_file, access, 0, offset, length); |
| 212 | + CHECK_NE(ptr, nullptr) << "Failed to map: " << path << ". " << GetLastError(); |
175 | 213 | #else
|
176 | 214 | CHECK_LE(offset, std::numeric_limits<off_t>::max())
|
177 | 215 | << "File size has exceeded the limit on the current system.";
|
| 216 | + int prot{PROT_READ}; |
| 217 | + if (!read_only) { |
| 218 | + prot |= PROT_WRITE; |
| 219 | + } |
178 | 220 | ptr = reinterpret_cast<char*>(mmap(nullptr, length, prot, MAP_PRIVATE, fd_, offset));
|
179 |
| -#endif // defined(__linux__) |
180 | 221 | CHECK_NE(ptr, MAP_FAILED) << "Failed to map: " << path << ". " << strerror(errno);
|
| 222 | +#endif // defined(__linux__) |
181 | 223 | return ptr;
|
182 | 224 | }
|
183 | 225 |
|
184 | 226 | PrivateMmapStream::~PrivateMmapStream() {
|
| 227 | +#if defined(_MSC_VER) |
| 228 | + CHECK(UnmapViewOfFile(p_buffer_)) "Faled to munmap." << path_ << ". " << GetLastError(); |
| 229 | + CloseHandle(); |
| 230 | +#else |
185 | 231 | CHECK_NE(munmap(p_buffer_, buffer_size_), -1)
|
186 | 232 | << "Faled to munmap." << path_ << ". " << strerror(errno);
|
187 | 233 | CHECK_NE(close(fd_), -1) << "Faled to close: " << path_ << ". " << strerror(errno);
|
| 234 | +#endif |
188 | 235 | }
|
189 | 236 | } // namespace common
|
190 | 237 | } // namespace xgboost
|
0 commit comments