X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=boehm-gc%2Fmark_rts.c;h=94eb0ddb37f3e81f70260e9361e67f517cce81f7;hb=5a756a52fe0ddeba5154a9fd525e19a1822b8985;hp=a082e2b2e06904b815418e22c7aaaa89fc1c65b6;hpb=fa4ee1f113cb5cb7452551cdd2a608656c06a45c;p=pf3gnuchains%2Fgcc-fork.git diff --git a/boehm-gc/mark_rts.c b/boehm-gc/mark_rts.c index a082e2b2e06..94eb0ddb37f 100644 --- a/boehm-gc/mark_rts.c +++ b/boehm-gc/mark_rts.c @@ -22,7 +22,7 @@ struct roots { ptr_t r_start; ptr_t r_end; - # if !defined(MSWIN32) && !defined(MSWINCE) + # if !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) struct roots * r_next; # endif GC_bool r_tmp; @@ -87,7 +87,7 @@ ptr_t p; return(FALSE); } -#if !defined(MSWIN32) && !defined(MSWINCE) +#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) /* # define LOG_RT_SIZE 6 # define RT_SIZE (1 << LOG_RT_SIZE) -- Power of 2, may be != MAX_ROOT_SETS @@ -139,7 +139,7 @@ struct roots *p; GC_root_index[h] = p; } -# else /* MSWIN32 || MSWINCE */ +# else /* MSWIN32 || MSWINCE || CYGWIN32 */ # define add_roots_to_index(p) @@ -175,7 +175,7 @@ GC_bool tmp; { struct roots * old; -# if defined(MSWIN32) || defined(MSWINCE) +# if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) /* Spend the time to ensure that there are no overlapping */ /* or adjacent intervals. */ /* This could be done faster with e.g. a */ @@ -244,7 +244,7 @@ GC_bool tmp; GC_static_roots[n_root_sets].r_start = (ptr_t)b; GC_static_roots[n_root_sets].r_end = (ptr_t)e; GC_static_roots[n_root_sets].r_tmp = tmp; -# if !defined(MSWIN32) && !defined(MSWINCE) +# if !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) GC_static_roots[n_root_sets].r_next = 0; # endif add_roots_to_index(GC_static_roots + n_root_sets); @@ -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)) { @@ -263,7 +263,7 @@ void GC_clear_roots GC_PROTO((void)) roots_were_cleared = TRUE; n_root_sets = 0; GC_root_size = 0; -# if !defined(MSWIN32) && !defined(MSWINCE) +# if !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) { register int i; @@ -275,35 +275,74 @@ 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) && !defined(CYGWIN32) +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) && !defined(CYGWIN32) + GC_rebuild_root_index(); + #endif +} + +#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) +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) && !defined(CYGWIN32) */ -#if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION) +#if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION) || defined(CYGWIN32) /* Workaround for the OS mapping and unmapping behind our back: */ /* Is the address p in one of the temporary static root sections? */ GC_bool GC_is_tmp_root(p) @@ -325,16 +364,25 @@ ptr_t p; } return(FALSE); } -#endif /* MSWIN32 || _WIN32_WCE_EMULATION */ +#endif /* MSWIN32 || _WIN32_WCE_EMULATION || defined(CYGWIN32) */ ptr_t GC_approx_sp() { - word dummy; + VOLATILE word dummy; + dummy = 42; /* Force stack to grow if necessary. Otherwise the */ + /* later accesses might cause the kernel to think we're */ + /* doing something wrong. */ # ifdef _MSC_VER # pragma warning(disable:4172) # endif - return((ptr_t)(&dummy)); +#ifdef __GNUC__ + /* Eliminate a warning from GCC about taking the address of a + local variable. */ + return __builtin_frame_address (0); +#else + return ((ptr_t)(&dummy)); +#endif /* __GNUC__ */ # ifdef _MSC_VER # pragma warning(default:4172) # endif @@ -506,6 +554,17 @@ void GC_push_gc_structures GC_PROTO((void)) void GC_mark_thread_local_free_lists(); #endif +void GC_cond_register_dynamic_libraries() +{ +# if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \ + || defined(CYGWIN32) || 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. @@ -519,29 +578,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 */ @@ -551,6 +601,18 @@ 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) { @@ -559,24 +621,38 @@ ptr_t cold_gc_frame; /* 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 - GC_mark_thread_local_free_lists(); + 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 */ /* 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. */ }