From: Nikodemus Siivola Date: Sun, 28 Mar 2010 10:51:51 +0000 (+0000) Subject: 1.0.37.4: robuster page table pickup X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=ae7270bf456d2b46d46d104baba1cd3ad7a3962b;p=sbcl.git 1.0.37.4: robuster page table pickup The Problem: It is rare, but apparently possible, for there to be free pages in the middle of allocated pages even after the double-collection we do in gc_and_save(). Previously this was not an issue, since the static space pickup mechanism just ended up marking those pages as boxed and full -- so we could get a page or few of (0 . 0) in the static generation. No biggie. Now, however, we save page table information into the core (for normal, not cold cores). This means that a would get a page marked as free, but since it was below alloc_ptr gencgc_pickup_dynamic() would mark it having bytes_used=PAGE_BYTES, etc. ...and later, find_freeish_pages() would look at the page and cry out in existential anguish becaue it should be free but didn't have bytes_used==0. Oh Noes! The Fix: gencgc_pickup_dynamic() needs to be careful about pages marked free if partial pickup has already been done from the core. --- diff --git a/NEWS b/NEWS index c59c33b..f4daf3c 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ changes relative to sbcl-1.0.36: * enhancement: *STANDARD-OUTPUT*, *STANDARD-INPUT*, and *ERROR-OUTPUT* are now bivalent. * bug fix: correct restart text for the continuable error in MAKE-PACKAGE. + * bug fix: a rare case of startup-time page table corruption. changes in sbcl-1.0.37 relative to sbcl-1.0.36: * enhancement: Backtrace from THROW to uncaught tag on x86oids now shows diff --git a/src/runtime/gencgc.c b/src/runtime/gencgc.c index 62fdcc8..0df9e92 100644 --- a/src/runtime/gencgc.c +++ b/src/runtime/gencgc.c @@ -4634,13 +4634,18 @@ gencgc_pickup_dynamic(void) generation_index_t gen = PSEUDO_STATIC_GENERATION; do { lispobj *first,*ptr= (lispobj *)page_address(page); - page_table[page].gen = gen; - page_table[page].bytes_used = PAGE_BYTES; - page_table[page].large_object = 0; - page_table[page].write_protected = 0; - page_table[page].write_protected_cleared = 0; - page_table[page].dont_move = 0; - page_table[page].need_to_zero = 1; + + if (!gencgc_partial_pickup || page_allocated_p(page)) { + /* It is possible, though rare, for the saved page table + * to contain free pages below alloc_ptr. */ + page_table[page].gen = gen; + page_table[page].bytes_used = PAGE_BYTES; + page_table[page].large_object = 0; + page_table[page].write_protected = 0; + page_table[page].write_protected_cleared = 0; + page_table[page].dont_move = 0; + page_table[page].need_to_zero = 1; + } if (!gencgc_partial_pickup) { page_table[page].allocated = BOXED_PAGE_FLAG; diff --git a/version.lisp-expr b/version.lisp-expr index 6424f02..a83e306 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"1.0.37.3" +"1.0.37.4"