From 33e97745e9d3404dcb04b718edc526838674aa19 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 5 Sep 2014 17:47:51 -0600 Subject: [PATCH] treat OS page manager (especially Linux) more gently Batch up mprotect() calls when cleaning up a place. Hopefully, this will avoid ENOMEM errors from mprotect() on DrDr's build. --- racket/src/racket/gc2/newgc.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/racket/src/racket/gc2/newgc.c b/racket/src/racket/gc2/newgc.c index 275ab249f5..78532f1de1 100644 --- a/racket/src/racket/gc2/newgc.c +++ b/racket/src/racket/gc2/newgc.c @@ -5116,14 +5116,25 @@ static void free_child_gc(void) gen0_free_big_pages(gc); gen0_free_entire_nursery(gc); + /* First, unprotect all pages. It's important to "queue" up all this work + as a batch to minimize commuincation with the OS and avoid fragmenting + the OS's table (in the case of Linux) that tracks page permissions. */ + for(i = 0; i < PAGE_TYPES; i++) { + if(i != PAGE_ATOMIC) { + for (work = gc->gen1_pages[i]; work; work = next) { + next = work->next; + if (work->mprotected) { + work->mprotected = 0; + mmu_queue_write_unprotect_range(gc->mmu, work->addr, real_page_size(work), page_mmu_type(work), &work->mmu_src_block); + } + } + } + } + mmu_flush_write_unprotect_ranges(gc->mmu); + for(i = 0; i < PAGE_TYPES; i++) { for (work = gc->gen1_pages[i]; work; work = next) { next = work->next; - - if (work->mprotected) - { - mmu_write_unprotect_page(gc->mmu, work->addr, real_page_size(work)); - } GCVERBOSEPAGE(gc, "Cleaning up GC DYING", work); gen1_free_mpage(pagemap, work); }