diff options
authorRelease Manager <>2017-04-06 21:55:21 +0200
committerVolker Braun <>2017-04-08 00:23:55 +0200
commitfc8ed1426f8486a71758f0e5ba1d68d220ba2999 (patch)
parentTrac #16820: Implement ABCs and categories for Lie algebras and finite dimens... (diff)
parentmmap() PARI stack with MAP_NORESERVE (for Cygwin) (diff)
Trac #22633: Pari default stack size results in huge physical memory commit after fork on Cygwin
It turns out #21582 causes big problems for fork on Cygwin. This is due to an implementation detail of how Cygwin handles copy-on-write private mappings when forking. A fact that might, unfortunately, be difficult to avoid. The problem with this on Cygwin is that, while Windows does not commit pages to physical memory until they are accessed, they ''do'' become committed upon any access (even reads, when they haven't already been written to). So when a process with a private mmap is forked, it loops over all pages in the mmap'd region and copies them into the child's copy of the mmap'd region. This results in committing physical memory on both the parent and the child, even for pages that haven't been written to yet. TL;DR, if there's a huge private|anonymous mmap in a process, and that process is forked, it will commit the full size of the mmap to memory in both the parent and child processes. This is a big problem in Sage since we set a very large default stack size for Pari. This was not a problem prior to #21582, since Pari used the MAP_NORESERVE flag which circumvents this issue (only dirty pages need to be copied). The changes in #21582 make sense for Linux, but for Cygwin the opposite is true. Different but unfortunate implementation details on both platforms. The best way forward is to use `MAP_NORESERVE` anyway, which helps Cygwin and won't hurt other platforms. '''Upstream bug''': bin/bugreport.cgi?bug=1912 URL: Reported by: embray Ticket author(s): Erik Bray, Jeroen Demeyer Reviewer(s): Erik Bray, Jeroen Demeyer
2 files changed, 54 insertions, 1 deletions
diff --git a/build/pkgs/pari/package-version.txt b/build/pkgs/pari/package-version.txt
index c457e4f..fb3a232 100644
--- a/build/pkgs/pari/package-version.txt
+++ b/build/pkgs/pari/package-version.txt
@@ -1 +1 @@
diff --git a/build/pkgs/pari/patches/prot_none_4.patch b/build/pkgs/pari/patches/prot_none_4.patch
new file mode 100644
index 00000000..36e9528
--- /dev/null
+++ b/build/pkgs/pari/patches/prot_none_4.patch
@@ -0,0 +1,53 @@
+commit c3dc1546580eda3bff6243cf563801c8a26ec67f
+Author: Jeroen Demeyer <>
+Date: Mon Apr 3 16:11:54 2017 +0200
+ mmap the PARI stack with MAP_NORESERVE
+diff --git a/src/language/init.c b/src/language/init.c
+index 34cce31..acebe2f 100644
+--- a/src/language/init.c
++++ b/src/language/init.c
+@@ -597,12 +597,26 @@ pari_add_defaults_module(entree *ep)
+ #endif
++#define MAP_NORESERVE 0
+ static void *
+ pari_mainstack_malloc(size_t size)
+ {
++ /* Check that the system allows reserving "size" bytes. This is just
++ * a check, we immediately free the memory. */
+ void *b = mmap(NULL, size, PROT_READ|PROT_WRITE,
+- return (b == MAP_FAILED) ? NULL: b;
++ if (b == MAP_FAILED) return NULL;
++ munmap(b, size);
++ /* Map again, this time with MAP_NORESERVE. On some operating systems
++ * like Cygwin, this is needed because remapping with PROT_NONE and
++ * MAP_NORESERVE does not work as expected. */
++ b = mmap(NULL, size, PROT_READ|PROT_WRITE,
++ if (b == MAP_FAILED) return NULL;
++ return b;
+ }
+ static void
+@@ -628,7 +642,13 @@ static void
+ pari_mainstack_mreset(pari_sp from, pari_sp to)
+ {
+ size_t s = to - from;
+- mmap((void*)from, s, PROT_NONE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
++ void *addr, *res;
++ if (!s) return;
++ addr = (void*)from;
++ res = mmap(addr, s, PROT_NONE,
++ if (res != addr) pari_err(e_MEM);
+ }
+ /* Commit (make available) the virtual memory mapped between the