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
This commit is contained in:
Andi Kleen 2011-10-17 14:43:37 +00:00 committed by Andi Kleen
parent 411f92de7a
commit 711a3d82e5
5 changed files with 65 additions and 3 deletions

View 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

View File

@ -1276,6 +1276,12 @@
#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

2
gcc/configure vendored
View File

@ -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"

View 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,

View 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;