This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH v2] Allow shrinking of arena heaps using mmap based onovercommit settings when available
Hi,
Here's an updated patch with changes according to Roland's review
comments. This works fine on my x86_64 Fedora 16 laptop and does not
cause regressions in the testsuite.
Regards,
Siddhesh
ChangeLog:
* malloc/arena.c: Include malloc-sysdep.h.
(shrink_heap): Use check_may_shrink_heap to decide if madvise
is sufficient to shrink the heap or an unmap is needed.
* sysdeps/generic/malloc-sysdep.h: New file. Define
new function check_may_shrink_heap.
* sysdeps/unix/sysv/linux/malloc-sysdep.h: New file. Define
new function check_may_shrink_heap.
diff --git a/malloc/arena.c b/malloc/arena.c
index 9e5e332..480491b 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -20,6 +20,9 @@
#include <stdbool.h>
+/* Get the implementation for check_may_shrink_heap. */
+#include <malloc-sysdep.h>
+
/* Compile-time constants. */
#define HEAP_MIN_SIZE (32*1024)
@@ -622,9 +625,9 @@ shrink_heap(heap_info *h, long diff)
new_size = (long)h->size - diff;
if(new_size < (long)sizeof(*h))
return -1;
- /* Try to re-map the extra heap space freshly to save memory, and
- make it inaccessible. */
- if (__builtin_expect (__libc_enable_secure, 0))
+ /* Try to re-map the extra heap space freshly to save memory, and make it
+ inaccessible. See malloc-sysdep.h to know when this is true. */
+ if (__builtin_expect (check_may_shrink_heap (), 0))
{
if((char *)MMAP((char *)h + new_size, diff, PROT_NONE,
MAP_FIXED) == (char *) MAP_FAILED)
diff --git a/sysdeps/generic/malloc-sysdep.h b/sysdeps/generic/malloc-sysdep.h
new file mode 100644
index 0000000..4ea85aa
--- /dev/null
+++ b/sysdeps/generic/malloc-sysdep.h
@@ -0,0 +1,28 @@
+/* System-specific implementations for some malloc support functions.
+
+ Copyright (C) 2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+
+/* Force an unmap on heap shrink for setuid programs. This is so that the
+ kernel immediately drops the PTE for the mapping. */
+static inline bool
+check_may_shrink_heap (void)
+{
+ return __libc_enable_secure;
+}
diff --git a/sysdeps/unix/sysv/linux/malloc-sysdep.h b/sysdeps/unix/sysv/linux/malloc-sysdep.h
new file mode 100644
index 0000000..be5c6d3
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/malloc-sysdep.h
@@ -0,0 +1,61 @@
+/* System-specific implementations for some malloc support functions.
+
+ Copyright (C) 2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <not-cancel.h>
+
+/* The Linux kernel overcommits address space by default and if there is not
+ enough memory available, it uses various parameters to decide the process to
+ kill. It is however possible to disable or curb this overcommit behaviour
+ by setting the proc sysctl vm.overcommit_memory to the value '2' and with
+ that, a process is only allowed to use the maximum of a pre-determined
+ fraction of the total address space. In such a case, we want to make sure
+ that we are judicious with our heap usage as well, and explicitly give away
+ the freed top of the heap to reduce our commit charge. See the proc(5) man
+ page to know more about overcommit behaviour.
+
+ Other than that, we also force an unmap for setuid programs. */
+static inline bool
+check_may_shrink_heap (void)
+{
+ static int may_shrink_heap = -1;
+
+ if (__builtin_expect (may_shrink_heap >= 0, 1))
+ return may_shrink_heap;
+
+ may_shrink_heap = __libc_enable_secure;
+
+ if (__builtin_expect (may_shrink_heap, 0))
+ return may_shrink_heap;
+
+ int fd = open_not_cancel_2 ("/proc/sys/vm/overcommit_memory",
+ O_RDONLY | O_CLOEXEC);
+
+ if (fd != -1)
+ {
+ char val = 0;
+ int n = read_not_cancel (fd, &val, 1);
+
+ may_shrink_heap = (n > 0 && val == 2);
+ close_not_cancel_no_status (fd);
+ }
+
+ return may_shrink_heap;
+}