From: Ivan Maidanski Date: Mon, 7 May 2018 08:05:15 +0000 (+0300) Subject: Fix infinite restarting of mark_some when a static root disappeared (Linux) X-Git-Tag: v7.6.8~84 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=67338bbd70f48cd8f5b3db463f5bda4574326c84;p=gc Fix infinite restarting of mark_some when a static root disappeared (Linux) (a cherry-pick of commits 38d194a3, e849b45c from 'master') Issue #218 (bdwgc). * dyn_load.c [USE_PROC_FOR_LIBRARIES] (GC_register_map_entries): Call GC_remove_roots_subregion for each region which has prot starting with "---"; add comment. * include/private/gc_priv.h [USE_PROC_FOR_LIBRARIES] (GC_remove_roots_subregion): Declare function. * mark_rts.c [USE_PROC_FOR_LIBRARIES] (GC_remove_roots_subregion): Implement (including partial overlapping). --- diff --git a/dyn_load.c b/dyn_load.c index 8e2026bd..ba09ab31 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -390,6 +390,10 @@ STATIC void GC_register_map_entries(char *maps) } if ((word)start < (word)end) GC_add_roots_inner((char *)start, (char *)end, TRUE); + } else if (prot[0] == '-' && prot[1] == '-' && prot[2] == '-') { + /* Even roots added statically might disappear partially */ + /* (e.g. the roots added by INCLUDE_LINUX_THREAD_DESCR). */ + GC_remove_roots_subregion(start, end); } } } diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 7c286062..3d6ac07a 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1739,6 +1739,9 @@ GC_INNER void GC_set_fl_marks(ptr_t p); /* set. Abort if not. */ #endif void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp); +#ifdef USE_PROC_FOR_LIBRARIES + GC_INNER void GC_remove_roots_subregion(ptr_t b, ptr_t e); +#endif GC_INNER void GC_exclude_static_roots_inner(void *start, void *finish); #if defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \ || defined(CYGWIN32) || defined(PCR) diff --git a/mark_rts.c b/mark_rts.c index 37777487..6c87546f 100644 --- a/mark_rts.c +++ b/mark_rts.c @@ -364,6 +364,85 @@ STATIC void GC_remove_tmp_roots(void) } #endif /* !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) */ +#ifdef USE_PROC_FOR_LIBRARIES + /* Remove given range from every static root which intersects with */ + /* the range. It is assumed GC_remove_tmp_roots is called before */ + /* this function is called repeatedly by GC_register_map_entries. */ + GC_INNER void GC_remove_roots_subregion(ptr_t b, ptr_t e) + { + int i; + GC_bool rebuild = FALSE; + + GC_ASSERT(I_HOLD_LOCK()); + GC_ASSERT((word)b % sizeof(word) == 0 && (word)e % sizeof(word) == 0); + for (i = 0; i < n_root_sets; i++) { + ptr_t r_start, r_end; + + if (GC_static_roots[i].r_tmp) { + /* The remaining roots are skipped as they are all temporary. */ +# ifdef GC_ASSERTIONS + int j; + for (j = i + 1; j < n_root_sets; j++) { + GC_ASSERT(GC_static_roots[j].r_tmp); + } +# endif + break; + } + r_start = GC_static_roots[i].r_start; + r_end = GC_static_roots[i].r_end; + if (!EXPECT((word)e <= (word)r_start || (word)r_end <= (word)b, TRUE)) { +# ifdef DEBUG_ADD_DEL_ROOTS + GC_log_printf("Removing %p .. %p from root section %d (%p .. %p)\n", + (void *)b, (void *)e, + i, (void *)r_start, (void *)r_end); +# endif + if ((word)r_start < (word)b) { + GC_root_size -= r_end - b; + GC_static_roots[i].r_end = b; + /* No need to rebuild as hash does not use r_end value. */ + if ((word)e < (word)r_end) { + int j; + + if (rebuild) { + GC_rebuild_root_index(); + rebuild = FALSE; + } + GC_add_roots_inner(e, r_end, FALSE); /* updates n_root_sets */ + for (j = i + 1; j < n_root_sets; j++) + if (GC_static_roots[j].r_tmp) + break; + if (j < n_root_sets-1 && !GC_static_roots[n_root_sets-1].r_tmp) { + /* Exchange the roots to have all temporary ones at the end. */ + ptr_t tmp_r_start = GC_static_roots[j].r_start; + ptr_t tmp_r_end = GC_static_roots[j].r_end; + + GC_static_roots[j].r_start = + GC_static_roots[n_root_sets-1].r_start; + GC_static_roots[j].r_end = GC_static_roots[n_root_sets-1].r_end; + GC_static_roots[j].r_tmp = FALSE; + GC_static_roots[n_root_sets-1].r_start = tmp_r_start; + GC_static_roots[n_root_sets-1].r_end = tmp_r_end; + GC_static_roots[n_root_sets-1].r_tmp = TRUE; + rebuild = TRUE; + } + } + } else { + if ((word)e < (word)r_end) { + GC_root_size -= e - r_start; + GC_static_roots[i].r_start = e; + } else { + GC_remove_root_at_pos(i); + i--; + } + rebuild = TRUE; + } + } + } + if (rebuild) + GC_rebuild_root_index(); + } +#endif /* USE_PROC_FOR_LIBRARIES */ + #if !defined(NO_DEBUGGING) /* For the debugging purpose only. */ /* Workaround for the OS mapping and unmapping behind our back: */