Commit | Line | Data |
---|---|---|
f6cccefe DM |
1 | ghc runtime by default (otherwise depending on a "configure" option) |
2 | does memory allocation on their own by first mmapping a 1 TB range of | |
3 | memory into the process and then parceling out chunks from it. | |
4 | ||
5 | If one of the chunks is not needed, the kernel needs to be informed - | |
6 | otherwise the system would quickly run out of available RAM. | |
7 | ||
8 | ghc does that via madvise(2). | |
9 | ||
10 | There are two options when doing this informing: | |
11 | ||
12 | MADV_FREE - Means "I don't need this range or the data in it any more". | |
13 | Kernel promises to fail later accesses to it. | |
14 | ||
15 | MADV_DONTNEED - Means "I don't need this range right now - and I don't | |
16 | need the data in it anymore". Kernel promises to make later accesses to | |
17 | it succeed (if necessary by providing a new page initialized with zeroes). | |
18 | ||
19 | MADV_FREE was introduced in Linux 4.5. | |
20 | glibc 2.25 and later always define MADV_FREE. | |
21 | ||
22 | Unpatched ghc 8.0.2 will use either MADV_FREE or MADV_DONTNEED, determined | |
23 | at ghc compile time. Which of them will actually succeed is determined | |
24 | by the Linux kernel at run time. | |
25 | ||
26 | This patch makes ghc try MADV_FREE. If it doesn't work, it falls back to | |
27 | MADV_DONTNEED. | |
28 | ||
29 | The end result is that ghc programs free their memory with Linux < 4.5 again. | |
30 | ||
31 | See https://git.haskell.org/ghc.git/commitdiff/6576bf83cdf4eac05eb88a24aa934a736c91e3da for more information. | |
32 | --- a/rts/posix/OSMem.c | |
33 | +++ b/rts/posix/OSMem.c | |
34 | @@ -541,11 +541,24 @@ void osDecommitMemory(void *at, W_ size) | |
35 | ||
36 | #ifdef MADV_FREE | |
37 | // Try MADV_FREE first, FreeBSD has both and MADV_DONTNEED | |
38 | - // just swaps memory out | |
39 | + // just swaps memory out. Linux >= 4.5 has both DONTNEED and FREE; either | |
40 | + // will work as they both allow the system to free anonymous pages. | |
41 | + // It is important that we try both methods as the kernel which we were | |
42 | + // built on may differ from the kernel we are now running on. | |
43 | r = madvise(at, size, MADV_FREE); | |
44 | -#else | |
45 | - r = madvise(at, size, MADV_DONTNEED); | |
46 | + if(r < 0) { | |
47 | + if (errno == EINVAL) { | |
48 | + // Perhaps the system doesn't support MADV_FREE; fall-through and | |
49 | + // try MADV_DONTNEED. | |
50 | + } else { | |
51 | + sysErrorBelch("unable to decommit memory"); | |
52 | + } | |
53 | + } else { | |
54 | + return; | |
55 | + } | |
56 | #endif | |
57 | + | |
58 | + r = madvise(at, size, MADV_DONTNEED); | |
59 | if(r < 0) | |
60 | sysErrorBelch("unable to decommit memory"); | |
61 | } |