From: James A. Morrison Date: Tue, 15 Feb 2005 20:52:13 +0000 (+0000) Subject: re PR pch/14940 (PCH largefile test fails on various platforms) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=14be52a22cda9918524fa0e4b6bb14ac1c466fdd;p=gcc.git re PR pch/14940 (PCH largefile test fails on various platforms) 2005-02-15 James A. Morrison 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. From-SVN: r95073 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e90c0306a37..42e602b3687 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-02-15 James A. Morrison + + 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. + 2005-02-15 Daniel Berlin * tree-vn.c (get_value_handle): Make sure that given an 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;