=================================================================== RCS file: /home/cvs/OpenXM_contrib2/asir2000/gc/mark_rts.c,v retrieving revision 1.4 retrieving revision 1.7 diff -u -p -r1.4 -r1.7 --- OpenXM_contrib2/asir2000/gc/mark_rts.c 2001/04/20 07:39:19 1.4 +++ OpenXM_contrib2/asir2000/gc/mark_rts.c 2003/06/24 05:11:33 1.7 @@ -252,7 +252,7 @@ GC_bool tmp; n_root_sets++; } -static roots_were_cleared = FALSE; +static GC_bool roots_were_cleared = FALSE; void GC_clear_roots GC_PROTO((void)) { @@ -275,34 +275,73 @@ void GC_clear_roots GC_PROTO((void)) } /* Internal use only; lock held. */ +static void GC_remove_root_at_pos(i) +int i; +{ + GC_root_size -= (GC_static_roots[i].r_end - GC_static_roots[i].r_start); + GC_static_roots[i].r_start = GC_static_roots[n_root_sets-1].r_start; + GC_static_roots[i].r_end = GC_static_roots[n_root_sets-1].r_end; + GC_static_roots[i].r_tmp = GC_static_roots[n_root_sets-1].r_tmp; + n_root_sets--; +} + +#if !defined(MSWIN32) && !defined(MSWINCE) +static void GC_rebuild_root_index() +{ + register int i; + + for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0; + for (i = 0; i < n_root_sets; i++) + add_roots_to_index(GC_static_roots + i); +} +#endif + +/* Internal use only; lock held. */ void GC_remove_tmp_roots() { register int i; for (i = 0; i < n_root_sets; ) { if (GC_static_roots[i].r_tmp) { - GC_root_size -= - (GC_static_roots[i].r_end - GC_static_roots[i].r_start); - GC_static_roots[i].r_start = GC_static_roots[n_root_sets-1].r_start; - GC_static_roots[i].r_end = GC_static_roots[n_root_sets-1].r_end; - GC_static_roots[i].r_tmp = GC_static_roots[n_root_sets-1].r_tmp; - n_root_sets--; + GC_remove_root_at_pos(i); } else { i++; - } } -# if !defined(MSWIN32) && !defined(MSWINCE) - { - register int i; - - for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0; - for (i = 0; i < n_root_sets; i++) - add_roots_to_index(GC_static_roots + i); } -# endif + #if !defined(MSWIN32) && !defined(MSWINCE) + GC_rebuild_root_index(); + #endif +} + +#if !defined(MSWIN32) && !defined(MSWINCE) +void GC_remove_roots(b, e) +char * b; char * e; +{ + DCL_LOCK_STATE; + DISABLE_SIGNALS(); + LOCK(); + GC_remove_roots_inner(b, e); + UNLOCK(); + ENABLE_SIGNALS(); } +/* Should only be called when the lock is held */ +void GC_remove_roots_inner(b,e) +char * b; char * e; +{ + int i; + for (i = 0; i < n_root_sets; ) { + if (GC_static_roots[i].r_start >= (ptr_t)b && GC_static_roots[i].r_end <= (ptr_t)e) { + GC_remove_root_at_pos(i); + } else { + i++; + } + } + GC_rebuild_root_index(); +} +#endif /* !defined(MSWIN32) && !defined(MSWINCE) */ + #if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION) /* Workaround for the OS mapping and unmapping behind our back: */ /* Is the address p in one of the temporary static root sections? */ @@ -471,8 +510,9 @@ ptr_t cold_gc_frame; cold_gc_bs_pointer = bsp - 2048; if (cold_gc_bs_pointer < BACKING_STORE_BASE) { cold_gc_bs_pointer = BACKING_STORE_BASE; + } else { + GC_push_all_stack(BACKING_STORE_BASE, cold_gc_bs_pointer); } - GC_push_all_stack(BACKING_STORE_BASE, cold_gc_bs_pointer); } else { cold_gc_bs_pointer = BACKING_STORE_BASE; } @@ -501,6 +541,21 @@ void GC_push_gc_structures GC_PROTO((void)) # endif } +#ifdef THREAD_LOCAL_ALLOC + void GC_mark_thread_local_free_lists(); +#endif + +void GC_cond_register_dynamic_libraries() +{ +# if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \ + || defined(PCR)) && !defined(SRC_M3) + GC_remove_tmp_roots(); + if (!GC_no_dls) GC_register_dynamic_libraries(); +# else + GC_no_dls = TRUE; +# endif +} + /* * Call the mark routines (GC_tl_push for a single pointer, GC_push_conditional * on groups of pointers) on every top level accessible pointer. @@ -514,29 +569,20 @@ void GC_push_roots(all, cold_gc_frame) GC_bool all; ptr_t cold_gc_frame; { - register int i; + int i; + int kind; /* - * push registers - i.e., call GC_push_one(r) for each - * register contents r. - */ -# ifdef USE_GENERIC_PUSH_REGS - GC_generic_push_regs(cold_gc_frame); -# else - GC_push_regs(); /* usually defined in machine_dep.c */ -# endif - - /* * Next push static data. This must happen early on, since it's * not robust against mark stack overflow. */ - /* Reregister dynamic libraries, in case one got added. */ -# if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \ - || defined(PCR)) && !defined(SRC_M3) - GC_remove_tmp_roots(); - if (!GC_no_dls) GC_register_dynamic_libraries(); -# else - GC_no_dls = TRUE; + /* Reregister dynamic libraries, in case one got added. */ + /* There is some argument for doing this as late as possible, */ + /* especially on win32, where it can change asynchronously. */ + /* In those cases, we do it here. But on other platforms, it's */ + /* not safe with the world stopped, so we do it earlier. */ +# if !defined(REGISTER_LIBRARIES_EARLY) + GC_cond_register_dynamic_libraries(); # endif /* Mark everything in static data areas */ @@ -546,26 +592,58 @@ ptr_t cold_gc_frame; GC_static_roots[i].r_end, all); } + /* Mark all free list header blocks, if those were allocated from */ + /* the garbage collected heap. This makes sure they don't */ + /* disappear if we are not marking from static data. It also */ + /* saves us the trouble of scanning them, and possibly that of */ + /* marking the freelists. */ + for (kind = 0; kind < GC_n_kinds; kind++) { + GC_PTR base = GC_base(GC_obj_kinds[kind].ok_freelist); + if (0 != base) { + GC_set_mark_bit(base); + } + } + /* Mark from GC internal roots if those might otherwise have */ /* been excluded. */ if (GC_no_dls || roots_were_cleared) { GC_push_gc_structures(); } + /* Mark thread local free lists, even if their mark */ + /* descriptor excludes the link field. */ + /* If the world is not stopped, this is unsafe. It is */ + /* also unnecessary, since we will do this again with the */ + /* world stopped. */ +# ifdef THREAD_LOCAL_ALLOC + if (GC_world_stopped) GC_mark_thread_local_free_lists(); +# endif + /* - * Now traverse stacks. + * Now traverse stacks, and mark from register contents. + * These must be done last, since they can legitimately overflow + * the mark stack. */ -# if !defined(USE_GENERIC_PUSH_REGS) +# ifdef USE_GENERIC_PUSH_REGS + GC_generic_push_regs(cold_gc_frame); + /* Also pushes stack, so that we catch callee-save registers */ + /* saved inside the GC_push_regs frame. */ +# else + /* + * push registers - i.e., call GC_push_one(r) for each + * register contents r. + */ + GC_push_regs(); /* usually defined in machine_dep.c */ GC_push_current_stack(cold_gc_frame); - /* IN the threads case, this only pushes collector frames. */ - /* In the USE_GENERIC_PUSH_REGS case, this is done inside */ - /* GC_push_regs, so that we catch callee-save registers saved */ - /* inside the GC_push_regs frame. */ - /* In the case of linux threads on Ia64, the hot section of */ + /* In the threads case, this only pushes collector frames. */ + /* In the case of linux threads on IA64, the hot section of */ /* the main stack is marked here, but the register stack */ /* backing store is handled in the threads-specific code. */ # endif if (GC_push_other_roots != 0) (*GC_push_other_roots)(); /* In the threads case, this also pushes thread stacks. */ + /* Note that without interior pointer recognition lots */ + /* of stuff may have been pushed already, and this */ + /* should be careful about mark stack overflows. */ }