summaryrefslogtreecommitdiff
path: root/gcc/config/host-linux.c
diff options
context:
space:
mode:
authorphython <phython@138bc75d-0d04-0410-961f-82ee72b054a4>2005-02-15 20:52:13 +0000
committerphython <phython@138bc75d-0d04-0410-961f-82ee72b054a4>2005-02-15 20:52:13 +0000
commitda7821f5ace0eab6f00aa80bcdd1906773514a4c (patch)
treeaf007bbc8798751e7bf2b9c728971dfb3058f047 /gcc/config/host-linux.c
parent7209680744855b9ca24c2d4ab0c958c5684cbe35 (diff)
downloadgcc-da7821f5ace0eab6f00aa80bcdd1906773514a4c.tar.gz
2005-02-15 James A. Morrison <phython@gcc.gnu.org>
PR pch/14940 PR target/19300 * config/host-linux.c (linux_gt_pch_use_address): Copy from config/pa/pa-host.c:pa_gt_pch_use_address. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@95073 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/host-linux.c')
-rw-r--r--gcc/config/host-linux.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/gcc/config/host-linux.c b/gcc/config/host-linux.c
index 717f96cdc66..7683c720c05 100644
--- a/gcc/config/host-linux.c
+++ b/gcc/config/host-linux.c
@@ -61,6 +61,9 @@
#undef HOST_HOOKS_GT_PCH_GET_ADDRESS
#define HOST_HOOKS_GT_PCH_GET_ADDRESS linux_gt_pch_get_address
+#undef HOST_HOOKS_GT_PCH_USE_ADDRESS
+#define HOST_HOOKS_GT_PCH_USE_ADDRESS linux_gt_pch_use_address
+
/* For various ports, try to guess a fixed spot in the vm space
that's probably free. */
#if defined(__alpha)
@@ -143,5 +146,68 @@ linux_gt_pch_get_address (size_t size, int fd)
return addr;
}
+/* Map SIZE bytes of FD+OFFSET at BASE. Return 1 if we succeeded at
+ mapping the data at BASE, -1 if we couldn't.
+
+ It's not possibly to reliably mmap a file using MAP_PRIVATE to
+ a specific START address on either hpux or linux. First we see
+ if mmap with MAP_PRIVATE works. If it does, we are off to the
+ races. If it doesn't, we try an anonymous private mmap since the
+ kernel is more likely to honor the BASE address in anonymous maps.
+ We then copy the data to the anonymous private map. This assumes
+ of course that we don't need to change the data in the PCH file
+ after it is created.
+
+ This approach obviously causes a performance penalty but there is
+ little else we can do given the current PCH implementation. */
+
+static int
+linux_gt_pch_use_address (void *base, size_t size, int fd, size_t offset)
+{
+ void *addr;
+
+ /* We're called with size == 0 if we're not planning to load a PCH
+ file at all. This allows the hook to free any static space that
+ we might have allocated at link time. */
+ if (size == 0)
+ return -1;
+
+ /* Try to map the file with MAP_PRIVATE. */
+ addr = mmap (base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset);
+
+ if (addr == base)
+ return 1;
+
+ if (addr != (void *) MAP_FAILED)
+ munmap (addr, size);
+
+ /* Try to make an anonymous private mmap at the desired location. */
+ addr = mmap (base, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ if (addr != base)
+ {
+ if (addr != (void *) MAP_FAILED)
+ munmap (addr, size);
+ return -1;
+ }
+
+ if (lseek (fd, offset, SEEK_SET) == (off_t)-1)
+ return -1;
+
+ while (size)
+ {
+ ssize_t nbytes;
+
+ nbytes = read (fd, base, MIN (size, SSIZE_MAX));
+ if (nbytes <= 0)
+ return -1;
+ base = (char *) base + nbytes;
+ size -= nbytes;
+ }
+
+ return 1;
+}
+
const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;