aboutsummaryrefslogtreecommitdiff
path: root/gcc/ggc-page.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2011-10-17 14:43:37 +0000
committerAndi Kleen <ak@gcc.gnu.org>2011-10-17 14:43:37 +0000
commit711a3d82e524cae4fa2acce8f2e363f0f23a6032 (patch)
treeb0f5ec12dbc9d0cd2f36e94c063c914fbfe5bb72 /gcc/ggc-page.c
parent411f92de7a3e15a42d3d640e5f7a0bc4cfc3e049 (diff)
downloadgcc-711a3d82e524cae4fa2acce8f2e363f0f23a6032.zip
gcc-711a3d82e524cae4fa2acce8f2e363f0f23a6032.tar.gz
gcc-711a3d82e524cae4fa2acce8f2e363f0f23a6032.tar.bz2
Use MADV_DONTNEED for freeing in garbage collector
Use the Linux MADV_DONTNEED call to unmap free pages in the garbage collector.Then keep the unmapped pages in the free list. This avoid excessive memory fragmentation on large LTO bulds, which can lead to gcc bumping into the Linux vm_max_map limit per process. gcc/: 2011-10-08 Andi Kleen <ak@linux.intel.com> PR other/50636 * config.in, configure: Regenerate. * configure.ac (madvise): Add to AC_CHECK_FUNCS. * ggc-page.c (USING_MADVISE): Add. (page_entry): Add discarded field. (alloc_page): Check for discarded pages. (release_pages): Add USING_MADVISE branch. From-SVN: r180093
Diffstat (limited to 'gcc/ggc-page.c')
-rw-r--r--gcc/ggc-page.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index beee851..9b35291 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -50,6 +50,10 @@ along with GCC; see the file COPYING3. If not see
#define USING_MALLOC_PAGE_GROUPS
#endif
+#if defined(HAVE_MADVISE) && defined(MADV_DONTNEED)
+# define USING_MADVISE
+#endif
+
/* Strategy:
This garbage-collecting allocator allocates objects on one of a set
@@ -277,6 +281,9 @@ typedef struct page_entry
/* The lg of size of objects allocated from this page. */
unsigned char order;
+ /* Discarded page? */
+ bool discarded;
+
/* A bit vector indicating whether or not objects are in use. The
Nth bit is one if the Nth object on this page is allocated. This
array is dynamically sized. */
@@ -740,6 +747,10 @@ alloc_page (unsigned order)
if (p != NULL)
{
+ if (p->discarded)
+ G.bytes_mapped += p->bytes;
+ p->discarded = false;
+
/* Recycle the allocated memory from this page ... */
*pp = p->next;
page = p->page;
@@ -956,7 +967,42 @@ free_page (page_entry *entry)
static void
release_pages (void)
{
-#ifdef USING_MMAP
+#ifdef USING_MADVISE
+ page_entry *p, *start_p;
+ char *start;
+ size_t len;
+
+ for (p = G.free_pages; p; )
+ {
+ if (p->discarded)
+ {
+ p = p->next;
+ continue;
+ }
+ start = p->page;
+ len = p->bytes;
+ start_p = p;
+ p = p->next;
+ while (p && p->page == start + len)
+ {
+ len += p->bytes;
+ p = p->next;
+ }
+ /* Give the page back to the kernel, but don't free the mapping.
+ This avoids fragmentation in the virtual memory map of the
+ process. Next time we can reuse it by just touching it. */
+ madvise (start, len, MADV_DONTNEED);
+ /* Don't count those pages as mapped to not touch the garbage collector
+ unnecessarily. */
+ G.bytes_mapped -= len;
+ while (start_p != p)
+ {
+ start_p->discarded = true;
+ start_p = start_p->next;
+ }
+ }
+#endif
+#if defined(USING_MMAP) && !defined(USING_MADVISE)
page_entry *p, *next;
char *start;
size_t len;