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
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&& esp1<th->control_stack_end){
+ if(esp1<esp) esp=esp1;
+ for(ptr = (void **)(c+1); ptr>=(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;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
*/
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);