]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Use MADV_DONTNEED for freeing in garbage collector
authorAndi Kleen <ak@linux.intel.com>
Mon, 17 Oct 2011 14:43:37 +0000 (14:43 +0000)
committerAndi Kleen <ak@gcc.gnu.org>
Mon, 17 Oct 2011 14:43:37 +0000 (14:43 +0000)
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

gcc/ChangeLog
gcc/config.in
gcc/configure
gcc/configure.ac
gcc/ggc-page.c

index f367a118c7f5496c353d18562e51217cfdcacc6d..3c8b7b55c72d61558e60d2dbc866b8494ef711ab 100644 (file)
@@ -1,3 +1,13 @@
+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.
+
 2011-10-17  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/50729
index f2847d8789562b36230df6bcd8fb75f52a5a0408..e8148b6d571457eef33ec5927dde22ce348138ad 100644 (file)
 #endif
 
 
+/* Define to 1 if you have the `madvise' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MADVISE
+#endif
+
+
 /* Define to 1 if you have the <malloc.h> header file. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_MALLOC_H
index cb55ddaa2a48373345b85fe534e34e81141f2dae..4a54adfe3e80badce09733694fc77a59540989f5 100755 (executable)
@@ -9001,7 +9001,7 @@ fi
 for ac_func in times clock kill getrlimit setrlimit atoll atoq \
        sysconf strsignal getrusage nl_langinfo \
        gettimeofday mbstowcs wcswidth mmap setlocale \
-       clearerr_unlocked feof_unlocked   ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked   fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked   fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked   putchar_unlocked putc_unlocked
+       clearerr_unlocked feof_unlocked   ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked   fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked   fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked   putchar_unlocked putc_unlocked madvise
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
index a7b94e64451ba77f55d2e16d715ff31463e8de34..357902e8a916db0c196cc7aaa4e740878257bd61 100644 (file)
@@ -1027,7 +1027,7 @@ define(gcc_UNLOCKED_FUNCS, clearerr_unlocked feof_unlocked dnl
 AC_CHECK_FUNCS(times clock kill getrlimit setrlimit atoll atoq \
        sysconf strsignal getrusage nl_langinfo \
        gettimeofday mbstowcs wcswidth mmap setlocale \
-       gcc_UNLOCKED_FUNCS)
+       gcc_UNLOCKED_FUNCS madvise)
 
 if test x$ac_cv_func_mbstowcs = xyes; then
   AC_CACHE_CHECK(whether mbstowcs works, gcc_cv_func_mbstowcs_works,
index beee851dd7f133022452c3750be0295f3792be29..9b352913eb43adf643e724e6d88ec2216e6dc786 100644 (file)
@@ -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;