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.
* enhancement: *STANDARD-OUTPUT*, *STANDARD-INPUT*, and *ERROR-OUTPUT* are
now bivalent.
* bug fix: correct restart text for the continuable error in MAKE-PACKAGE.
* 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
changes in sbcl-1.0.37 relative to sbcl-1.0.36:
* enhancement: Backtrace from THROW to uncaught tag on x86oids now shows
generation_index_t gen = PSEUDO_STATIC_GENERATION;
do {
lispobj *first,*ptr= (lispobj *)page_address(page);
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;
if (!gencgc_partial_pickup) {
page_table[page].allocated = BOXED_PAGE_FLAG;
;;; 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".)
;;; 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".)