diff options
author | Nathaniel Shead <nathanieloshead@gmail.com> | 2024-12-21 23:42:28 +1100 |
---|---|---|
committer | Nathaniel Shead <nathanieloshead@gmail.com> | 2024-12-29 11:15:44 +1100 |
commit | 84aa7065deec49bab9fb0b085cd0a0dcc42cc479 (patch) | |
tree | 204b49257be7cb45e5146ff682c6437f7e9d2145 | |
parent | ce81cd2eac686dc0f1c91ada0000c779add550b0 (diff) | |
download | gcc-84aa7065deec49bab9fb0b085cd0a0dcc42cc479.zip gcc-84aa7065deec49bab9fb0b085cd0a0dcc42cc479.tar.gz gcc-84aa7065deec49bab9fb0b085cd0a0dcc42cc479.tar.bz2 |
c++/modules: Fallback to ftruncate if posix_fallocate fails [PR115008]
Depending on the libc and filesystem, in cases where posix_fallocate
cannot do an efficient preallocation it may return EINVAL. In such a
case we should fall back to ftruncate instead.
Apparently, depending on the system the use of posix_fallocate can have
a noticeable speedup over ftruncate in general (depending on the system)
so it probably isn't worth it to use ftruncate in all cases.
PR c++/100358
PR c++/115008
gcc/cp/ChangeLog:
* module.cc (elf_out::create_mapping): Fallback to ftruncate if
posix_fallocate fails.
Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
-rw-r--r-- | gcc/cp/module.cc | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index b9cf164..9ad587e 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -1905,13 +1905,23 @@ elf_in::begin (location_t loc) void elf_out::create_mapping (unsigned ext, bool extending) { -#ifndef HAVE_POSIX_FALLOCATE -#define posix_fallocate(fd,off,len) ftruncate (fd, off + len) + /* A wrapper around posix_fallocate, falling back to ftruncate + if the underlying filesystem does not support the operation. */ + auto allocate = [](int fd, off_t offset, off_t length) + { +#ifdef HAVE_POSIX_FALLOCATE + int result = posix_fallocate (fd, offset, length); + if (result != EINVAL) + return result == 0; + /* Not supported by the underlying filesystem, fallback to ftruncate. */ #endif + return ftruncate (fd, offset + length) == 0; + }; + void *mapping = MAP_FAILED; if (extending && ext < 1024 * 1024) { - if (!posix_fallocate (fd, offset, ext * 2)) + if (allocate (fd, offset, ext * 2)) mapping = mmap (NULL, ext * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset); if (mapping != MAP_FAILED) @@ -1919,7 +1929,7 @@ elf_out::create_mapping (unsigned ext, bool extending) } if (mapping == MAP_FAILED) { - if (!extending || !posix_fallocate (fd, offset, ext)) + if (!extending || allocate (fd, offset, ext)) mapping = mmap (NULL, ext, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset); if (mapping == MAP_FAILED) @@ -1929,7 +1939,6 @@ elf_out::create_mapping (unsigned ext, bool extending) ext = 0; } } -#undef posix_fallocate hdr.buffer = (char *)mapping; extent = ext; } |