1.0.37.4: robuster page table pickup
authorNikodemus Siivola <nikodemus@random-state.net>
Sun, 28 Mar 2010 10:51:51 +0000 (10:51 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Sun, 28 Mar 2010 10:51:51 +0000 (10:51 +0000)
 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.

NEWS
src/runtime/gencgc.c
version.lisp-expr

diff --git a/NEWS b/NEWS
index c59c33b..f4daf3c 100644 (file)
--- 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
index 62fdcc8..0df9e92 100644 (file)
@@ -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;
index 6424f02..a83e306 100644 (file)
@@ -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"