| 320 | } |
| 321 | |
| 322 | static bool shouldUseMmap(sys::fs::file_t FD, |
| 323 | size_t FileSize, |
| 324 | size_t MapSize, |
| 325 | off_t Offset, |
| 326 | bool RequiresNullTerminator, |
| 327 | int PageSize, |
| 328 | bool IsVolatile) { |
| 329 | // mmap may leave the buffer without null terminator if the file size changed |
| 330 | // by the time the last page is mapped in, so avoid it if the file size is |
| 331 | // likely to change. |
| 332 | if (IsVolatile && RequiresNullTerminator) |
| 333 | return false; |
| 334 | |
| 335 | // We don't use mmap for small files because this can severely fragment our |
| 336 | // address space. |
| 337 | if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize) |
| 338 | return false; |
| 339 | |
| 340 | if (!RequiresNullTerminator) |
| 341 | return true; |
| 342 | |
| 343 | // If we don't know the file size, use fstat to find out. fstat on an open |
| 344 | // file descriptor is cheaper than stat on a random path. |
| 345 | // FIXME: this chunk of code is duplicated, but it avoids a fstat when |
| 346 | // RequiresNullTerminator = false and MapSize != -1. |
| 347 | if (FileSize == size_t(-1)) { |
| 348 | sys::fs::file_status Status; |
| 349 | if (sys::fs::status(FD, Status)) |
| 350 | return false; |
| 351 | FileSize = Status.getSize(); |
| 352 | } |
| 353 | |
| 354 | // If we need a null terminator and the end of the map is inside the file, |
| 355 | // we cannot use mmap. |
| 356 | size_t End = Offset + MapSize; |
| 357 | assert(End <= FileSize); |
| 358 | if (End != FileSize) |
| 359 | return false; |
| 360 | |
| 361 | // Don't try to map files that are exactly a multiple of the system page size |
| 362 | // if we need a null terminator. |
| 363 | if ((FileSize & (PageSize -1)) == 0) |
| 364 | return false; |
| 365 | |
| 366 | #if defined(__CYGWIN__) |
| 367 | // Don't try to map files that are exactly a multiple of the physical page size |
| 368 | // if we need a null terminator. |
| 369 | // FIXME: We should reorganize again getPageSize() on Win32. |
| 370 | if ((FileSize & (4096 - 1)) == 0) |
| 371 | return false; |
| 372 | #endif |
| 373 | |
| 374 | return true; |
| 375 | } |
| 376 | |
| 377 | static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>> |
| 378 | getReadWriteFile(const Twine &Filename, uint64_t FileSize, uint64_t MapSize, |
no test coverage detected