0.8.3.76
[sbcl.git] / src / runtime / gencgc.c
index 08e3bc4..5ca100a 100644 (file)
@@ -2698,8 +2698,9 @@ update_page_write_prot(int page)
     gc_assert(page_table[page].allocated != FREE_PAGE);
     gc_assert(page_table[page].bytes_used != 0);
 
-    /* Skip if it's already write-protected or an unboxed page. */
+    /* Skip if it's already write-protected, pinned, or unboxed */
     if (page_table[page].write_protected
+       || page_table[page].dont_move
        || (page_table[page].allocated & UNBOXED_PAGE))
        return (0);
 
@@ -3595,6 +3596,7 @@ write_protect_generation_pages(int generation)
     for (i = 0; i < last_free_page; i++)
        if ((page_table[i].allocated == BOXED_PAGE)
            && (page_table[i].bytes_used != 0)
+           && !page_table[i].dont_move
            && (page_table[i].gen == generation))  {
            void *page_start;
 
@@ -3658,7 +3660,8 @@ garbage_collect_generation(int generation, int raise)
     /* Before any pointers are preserved, the dont_move flags on the
      * pages need to be cleared. */
     for (i = 0; i < last_free_page; i++)
-       page_table[i].dont_move = 0;
+       if(page_table[i].gen==from_space)
+           page_table[i].dont_move = 0;
 
     /* Un-write-protect the old-space pages. This is essential for the
      * promoted pages as they may contain pointers into the old-space
@@ -3671,6 +3674,7 @@ garbage_collect_generation(int generation, int raise)
     for_each_thread(th) {
        void **ptr;
        void **esp= (void **) &raise;
+       int i=0,free;
 #ifdef LISP_FEATURE_SB_THREAD
        if(th!=arch_os_get_current_thread()) {
            os_context_t *last_context=get_interrupt_context_for_thread(th);
@@ -3680,6 +3684,16 @@ garbage_collect_generation(int generation, int raise)
        for (ptr = (void **)th->control_stack_end; ptr > esp;  ptr--) {
            preserve_pointer(*ptr);
        }
+       /* also need to check registers in any interrupt contexts on
+        * an alternate signal stack */
+       free=fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,th));
+       for(i=0;i<free;i++){
+           os_context_t *c=th->interrupt_contexts[i];
+           if(c>=th->control_stack_end && c<esp) continue;
+           for(ptr = (void **)(c+1); ptr>=(void **)c; ptr--) {
+               preserve_pointer(*ptr);
+           }
+       }
     }
 
 #if QSHOW