aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathaniel Shead <nathanieloshead@gmail.com>2024-12-21 23:42:28 +1100
committerNathaniel Shead <nathanieloshead@gmail.com>2024-12-29 11:15:44 +1100
commit84aa7065deec49bab9fb0b085cd0a0dcc42cc479 (patch)
tree204b49257be7cb45e5146ff682c6437f7e9d2145
parentce81cd2eac686dc0f1c91ada0000c779add550b0 (diff)
downloadgcc-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.cc19
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;
}