diff options
author | phython <phython@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-02-15 20:52:13 +0000 |
---|---|---|
committer | phython <phython@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-02-15 20:52:13 +0000 |
commit | da7821f5ace0eab6f00aa80bcdd1906773514a4c (patch) | |
tree | af007bbc8798751e7bf2b9c728971dfb3058f047 /gcc/config/host-linux.c | |
parent | 7209680744855b9ca24c2d4ab0c958c5684cbe35 (diff) | |
download | gcc-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.c | 66 |
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; |