aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2011-10-29 01:02:14 +0000
committerAndi Kleen <ak@gcc.gnu.org>2011-10-29 01:02:14 +0000
commit25f0ea8135b221a7d560e9062d30d14be33c5582 (patch)
treeeb03fae09ae19353a8f309e094443984ebd18f82
parentd33ef9a52bb4a561ec8fb14ad4f45c68dc57bc72 (diff)
downloadgcc-25f0ea8135b221a7d560e9062d30d14be33c5582.zip
gcc-25f0ea8135b221a7d560e9062d30d14be33c5582.tar.gz
gcc-25f0ea8135b221a7d560e9062d30d14be33c5582.tar.bz2
Add a fragmentation fallback in ggc-page v2
There were some concerns that the earlier munmap patch could lead to address space being freed that cannot be allocated again by ggc due to fragmentation. This patch adds a fragmentation fallback to solve this: when a GGC_QUIRE_SIZE sized allocation fails, try again with a page sized allocation. Passes bootstrap and testing on x86_64-linux with the fallback forced artificially. v2: fix missed initialization bug added in last minute edit. gcc/: 2011-10-20 Andi Kleen <ak@linux.intel.com> * ggc-page (alloc_anon): Add check argument. (alloc_page): Add fallback to 1 page allocation. Adjust alloc_anon calls to new argument. From-SVN: r180649
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/ggc-page.c23
2 files changed, 21 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3b24734..0c442cd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2011-10-20 Andi Kleen <ak@linux.intel.com>
+
+ * ggc-page (alloc_anon): Add check argument.
+ (alloc_page): Add fallback to 1 page allocation.
+ Adjust alloc_anon calls to new argument.
+
2011-10-18 Andi Kleen <ak@linux.intel.com>
* ggc-page (release_pages): First free large continuous
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 7bef4c0..c796160 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -483,7 +483,7 @@ static int ggc_allocated_p (const void *);
static page_entry *lookup_page_table_entry (const void *);
static void set_page_table_entry (void *, page_entry *);
#ifdef USING_MMAP
-static char *alloc_anon (char *, size_t);
+static char *alloc_anon (char *, size_t, bool check);
#endif
#ifdef USING_MALLOC_PAGE_GROUPS
static size_t page_group_index (char *, char *);
@@ -662,7 +662,7 @@ debug_print_page_list (int order)
compile error unless exactly one of the HAVE_* is defined. */
static inline char *
-alloc_anon (char *pref ATTRIBUTE_UNUSED, size_t size)
+alloc_anon (char *pref ATTRIBUTE_UNUSED, size_t size, bool check)
{
#ifdef HAVE_MMAP_ANON
char *page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
@@ -675,6 +675,8 @@ alloc_anon (char *pref ATTRIBUTE_UNUSED, size_t size)
if (page == (char *) MAP_FAILED)
{
+ if (!check)
+ return NULL;
perror ("virtual memory exhausted");
exit (FATAL_EXIT_CODE);
}
@@ -777,13 +779,18 @@ alloc_page (unsigned order)
extras on the freelist. (Can only do this optimization with
mmap for backing store.) */
struct page_entry *e, *f = G.free_pages;
- int i;
+ int i, entries = GGC_QUIRE_SIZE;
- page = alloc_anon (NULL, G.pagesize * GGC_QUIRE_SIZE);
+ page = alloc_anon (NULL, G.pagesize * GGC_QUIRE_SIZE, false);
+ if (page == NULL)
+ {
+ page = alloc_anon(NULL, G.pagesize, true);
+ entries = 1;
+ }
/* This loop counts down so that the chain will be in ascending
memory order. */
- for (i = GGC_QUIRE_SIZE - 1; i >= 1; i--)
+ for (i = entries - 1; i >= 1; i--)
{
e = XCNEWVAR (struct page_entry, page_entry_size);
e->order = order;
@@ -796,7 +803,7 @@ alloc_page (unsigned order)
G.free_pages = f;
}
else
- page = alloc_anon (NULL, entry_size);
+ page = alloc_anon (NULL, entry_size, true);
#endif
#ifdef USING_MALLOC_PAGE_GROUPS
else
@@ -1649,14 +1656,14 @@ init_ggc (void)
believe, is an unaligned page allocation, which would cause us to
hork badly if we tried to use it. */
{
- char *p = alloc_anon (NULL, G.pagesize);
+ char *p = alloc_anon (NULL, G.pagesize, true);
struct page_entry *e;
if ((size_t)p & (G.pagesize - 1))
{
/* How losing. Discard this one and try another. If we still
can't get something useful, give up. */
- p = alloc_anon (NULL, G.pagesize);
+ p = alloc_anon (NULL, G.pagesize, true);
gcc_assert (!((size_t)p & (G.pagesize - 1)));
}