X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fruntime%2Fgencgc.c;h=b6917abccd6575cfbfd553cc965a91850f70c07a;hb=2675adcb29d689ee6d270f52658af17f2deeaf77;hp=5ca100a465333c13aa9f2b267debe26dc4e3b265;hpb=9ab3c4123f5802bc5d4771eda564680d1a2c1a2f;p=sbcl.git diff --git a/src/runtime/gencgc.c b/src/runtime/gencgc.c index 5ca100a..b6917ab 100644 --- a/src/runtime/gencgc.c +++ b/src/runtime/gencgc.c @@ -687,7 +687,7 @@ add_new_area(int first_page, int offset, int size) max_new_areas = new_areas_index; } -/* Update the tables for the alloc_region. The region maybe added to +/* Update the tables for the alloc_region. The region may be added to * the new_areas. * * When done the alloc_region is set up so that the next quick alloc @@ -3671,29 +3671,47 @@ garbage_collect_generation(int generation, int raise) unprotect_oldspace(); /* Scavenge the stacks' conservative roots. */ + + /* there are potentially two stacks for each thread: the main + * stack, which may contain Lisp pointers, and the alternate stack. + * We don't ever run Lisp code on the altstack, but it may + * host a sigcontext with lisp objects in it */ + + /* what we need to do: (1) find the stack pointer for the main + * stack; scavenge it (2) find the interrupt context on the + * alternate stack that might contain lisp values, and scavenge + * that */ + + /* we assume that none of the preceding applies to the thread that + * initiates GC. If you ever call GC from inside an altstack + * handler, you will lose. */ for_each_thread(th) { void **ptr; - void **esp= (void **) &raise; - int i=0,free; + void **esp=(void **)-1; + int i,free; #ifdef LISP_FEATURE_SB_THREAD - if(th!=arch_os_get_current_thread()) { - os_context_t *last_context=get_interrupt_context_for_thread(th); - esp = (void **)*os_context_register_addr(last_context,reg_ESP); + if(th==arch_os_get_current_thread()) { + esp = (void **) &raise; + } else { + void **esp1; + free=fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,th)); + for(i=free-1;i>=0;i--) { + os_context_t *c=th->interrupt_contexts[i]; + esp1 = (void **) *os_context_register_addr(c,reg_ESP); + if(esp1>=th->control_stack_start&& esp1control_stack_end){ + if(esp1=(void **)c; ptr--) { + preserve_pointer(*ptr); + } + } + } } +#else + esp = (void **) &raise; #endif 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;iinterrupt_contexts[i]; - if(c>=th->control_stack_end && c=(void **)c; ptr--) { - preserve_pointer(*ptr); - } - } } #if QSHOW @@ -4231,9 +4249,13 @@ alloc(int nbytes) */ if (auto_gc_trigger && bytes_allocated > auto_gc_trigger) { /* set things up so that GC happens when we finish the PA - * section. */ + * section. We only do this if there wasn't a pending handler + * already, in case it was a gc. If it wasn't a GC, the next + * allocation will get us back to this point anyway, so no harm done + */ struct interrupt_data *data=th->interrupt_data; - maybe_defer_handler(interrupt_maybe_gc_int,data,0,0,0); + if(!data->pending_handler) + maybe_defer_handler(interrupt_maybe_gc_int,data,0,0,0); } new_obj = gc_alloc_with_region(nbytes,0,region,0); return (new_obj);