X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fgencgc.c;h=6c6828f5e8955b8545b9ca7e1882ab915ad0b949;hb=b7eed59f1877263e1af5ad80299e641e8276f77d;hp=1afe504dc67479ce11d0b6411e41c48e9a73df31;hpb=fc999187f3f80dfcf170348df676386b8403e261;p=sbcl.git diff --git a/src/runtime/gencgc.c b/src/runtime/gencgc.c index 1afe504..6c6828f 100644 --- a/src/runtime/gencgc.c +++ b/src/runtime/gencgc.c @@ -51,6 +51,13 @@ /* assembly language stub that executes trap_PendingInterrupt */ void do_pending_interrupt(void); +/* forward declarations */ +int gc_find_freeish_pages(int *restart_page_ptr, int nbytes, int unboxed, struct alloc_region *alloc_region); +void gc_set_region_empty(struct alloc_region *region); +void gc_alloc_update_all_page_tables(void); +static void gencgc_pickup_dynamic(void); +boolean interrupt_maybe_gc_int(int, siginfo_t *, void *); + /* * GC parameters @@ -337,6 +344,8 @@ gen_av_mem_age(int gen) / ((double)generations[gen].bytes_allocated); } +void fpu_save(int *); /* defined in x86-assem.S */ +void fpu_restore(int *); /* defined in x86-assem.S */ /* The verbose argument controls how much to print: 0 for normal * level of detail; 1 for debugging. */ static void @@ -506,7 +515,7 @@ gc_alloc_new_region(int nbytes, int unboxed, struct alloc_region *alloc_region) gc_assert((alloc_region->first_page == 0) && (alloc_region->last_page == -1) && (alloc_region->free_pointer == alloc_region->end_addr)); - get_spinlock(&free_pages_lock,alloc_region); + get_spinlock(&free_pages_lock,(int) alloc_region); if (unboxed) { first_page = generations[gc_alloc_generation].alloc_unboxed_start_page; @@ -568,7 +577,7 @@ gc_alloc_new_region(int nbytes, int unboxed, struct alloc_region *alloc_region) (lispobj)(((char *)heap_base) + last_free_page*4096), 0); } - free_pages_lock=0; + release_spinlock(&free_pages_lock); /* we can do this after releasing free_pages_lock */ if (gencgc_zero_check) { @@ -710,7 +719,7 @@ gc_alloc_update_page_tables(int unboxed, struct alloc_region *alloc_region) next_page = first_page+1; - get_spinlock(&free_pages_lock,alloc_region); + get_spinlock(&free_pages_lock,(int) alloc_region); if (alloc_region->free_pointer != alloc_region->start_addr) { /* some bytes were allocated in the region */ orig_first_page_bytes_used = page_table[first_page].bytes_used; @@ -814,7 +823,7 @@ gc_alloc_update_page_tables(int unboxed, struct alloc_region *alloc_region) page_table[next_page].allocated = FREE_PAGE; next_page++; } - free_pages_lock=0; + release_spinlock(&free_pages_lock); /* alloc_region is per-thread, we're ok to do this unlocked */ gc_set_region_empty(alloc_region); } @@ -857,7 +866,7 @@ gc_alloc_large(int nbytes, int unboxed, struct alloc_region *alloc_region) index ahead of the current region and bumped up here to save a lot of re-scanning. */ - get_spinlock(&free_pages_lock,alloc_region); + get_spinlock(&free_pages_lock,(int) alloc_region); if (unboxed) { first_page = @@ -957,7 +966,7 @@ gc_alloc_large(int nbytes, int unboxed, struct alloc_region *alloc_region) SetSymbolValue(ALLOCATION_POINTER, (lispobj)(((char *)heap_base) + last_free_page*4096),0); } - free_pages_lock=0; + release_spinlock(&free_pages_lock); return((void *)(page_address(first_page)+orig_first_page_bytes_used)); } @@ -2689,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); @@ -3586,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; @@ -3649,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 @@ -3661,28 +3673,14 @@ garbage_collect_generation(int generation, int raise) /* Scavenge the stacks' conservative roots. */ for_each_thread(th) { void **ptr; + void **esp= (void **) &raise; #ifdef LISP_FEATURE_SB_THREAD - struct user_regs_struct regs; - if(ptrace(PTRACE_GETREGS,th->pid,0,®s)){ - /* probably doesn't exist any more. */ - fprintf(stderr,"child pid %d, %s\n",th->pid,strerror(errno)); - perror("PTRACE_GETREGS"); + 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); } - preserve_pointer(regs.ebx); - preserve_pointer(regs.ecx); - preserve_pointer(regs.edx); - preserve_pointer(regs.esi); - preserve_pointer(regs.edi); - preserve_pointer(regs.ebp); - preserve_pointer(regs.eax); -#endif - for (ptr = th->control_stack_end; -#ifdef LISP_FEATURE_SB_THREAD - ptr > regs.esp; -#else - ptr > (void **)&raise; #endif - ptr--) { + for (ptr = (void **)th->control_stack_end; ptr > esp; ptr--) { preserve_pointer(*ptr); } } @@ -3985,7 +3983,7 @@ collect_garbage(unsigned last_gen) update_x86_dynamic_space_free_pointer(); auto_gc_trigger = bytes_allocated + bytes_consed_between_gcs; if(gencgc_verbose) - fprintf(stderr,"Next gc when %d bytes have been consed\n", + fprintf(stderr,"Next gc when %ld bytes have been consed\n", auto_gc_trigger); SHOW("returning from collect_garbage"); } @@ -4167,7 +4165,6 @@ gc_initialize_pointers(void) -extern boolean maybe_gc_pending ; /* alloc(..) is the external interface for memory allocation. It * allocates to generation 0. It is not called from within the garbage * collector as it is only external uses that need the check for heap @@ -4204,7 +4201,7 @@ alloc(int nbytes) __asm__("movl %fs,%0" : "=r" (fs) : ); fprintf(stderr, "fs is %x, th->tls_cookie=%x (should be identical)\n", debug_get_fs(),th->tls_cookie); - lose("If you see this message before 2003.05.01, mail details to sbcl-devel\n"); + lose("If you see this message before 2003.12.01, mail details to sbcl-devel\n"); } #else gc_assert(SymbolValue(PSEUDO_ATOMIC_ATOMIC,th)); @@ -4224,8 +4221,8 @@ 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. */ - maybe_gc_pending=1; - SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(1),th); + struct interrupt_data *data=th->interrupt_data; + maybe_defer_handler(interrupt_maybe_gc_int,data,0,0,0); } new_obj = gc_alloc_with_region(nbytes,0,region,0); return (new_obj); @@ -4306,10 +4303,9 @@ gencgc_handle_wp_violation(void* fault_addr) */ if(page_table[page_index].write_protected_cleared != 1) lose("fault in heap page not marked as write-protected"); - - /* Don't worry, we can handle it. */ - return 1; } + /* Don't worry, we can handle it. */ + return 1; } } /* This is to be called when we catch a SIGSEGV/SIGBUS, determine that @@ -4320,7 +4316,7 @@ void unhandled_sigmemoryfault() {} -gc_alloc_update_all_page_tables(void) +void gc_alloc_update_all_page_tables(void) { /* Flush the alloc regions updating the tables. */ struct thread *th;