diff options
author | Simon Marlow <marlowsd@gmail.com> | 2008-12-10 11:57:51 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2008-12-10 11:57:51 +0000 |
commit | d4a17c3a253d02c2ebf2315e71a29cb740278977 (patch) | |
tree | 74854b32d76bf9b1abd47907ad4d37b8071c66bf /rts/Linker.c | |
parent | 4d13f3e61e4dc3aaa169bad0b8d67e8256624aee (diff) | |
download | haskell-d4a17c3a253d02c2ebf2315e71a29cb740278977.tar.gz |
On FreeBSD, try MAP_FIXED if ordinary mmap() fails to give us suitable memory
This appears to be necessary on FreeBSD. It might be necessary on
other OSs too, but I'm being cautious because using MAP_FIXED can lead
to crashes by overwriting existing mappings, and we have no (easy) way
to prevent that.
Diffstat (limited to 'rts/Linker.c')
-rw-r--r-- | rts/Linker.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/rts/Linker.c b/rts/Linker.c index 21192620c8..ac06cda1a9 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -1302,6 +1302,7 @@ mmapForLinker (size_t bytes, nat flags, int fd) void *map_addr = NULL; void *result; int pagesize, size; + static nat fixed = 0; pagesize = getpagesize(); size = ROUND_UP(bytes, pagesize); @@ -1315,10 +1316,11 @@ mmap_again: #endif result = mmap(map_addr, size, PROT_EXEC|PROT_READ|PROT_WRITE, - MAP_PRIVATE|TRY_MAP_32BIT|flags, fd, 0); + MAP_PRIVATE|TRY_MAP_32BIT|fixed|flags, fd, 0); if (result == MAP_FAILED) { - sysErrorBelch("mmap"); + sysErrorBelch("mmap %lu bytes at %p",(lnat)size,map_addr); + errorBelch("Try specifying an address with +RTS -xm<addr> -RTS"); stg_exit(EXIT_FAILURE); } @@ -1329,8 +1331,16 @@ mmap_again: } else { if ((W_)result > 0x80000000) { // oops, we were given memory over 2Gb - // ... try allocating memory somewhere else?; - barf("loadObj: failed to mmap() memory below 2Gb; asked for %lu bytes at %p, got %p. Try specifying an address with +RTS -xm<addr> -RTS", size, map_addr, result); +#if defined(freebsd_HOST_OS) + // Some platforms require MAP_FIXED. This is normally + // a bad idea, because MAP_FIXED will overwrite + // existing mappings. + munmap(result,size); + fixed = MAP_FIXED; + goto mmap_again; +#else + barf("loadObj: failed to mmap() memory below 2Gb; asked for %lu bytes at %p. Try specifying an address with +RTS -xm<addr> -RTS", size, map_addr, result); +#endif } else { // hmm, we were given memory somewhere else, but it's // still under 2Gb so we can use it. Next time, ask |