summaryrefslogtreecommitdiff
path: root/mark_rts.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2011-07-26 15:28:12 +0200
committerIvan Maidanski <ivmai@mail.ru>2011-07-26 15:28:12 +0200
commit111a44f98adde07d205c92656ad9b935ca2a39a8 (patch)
tree8a0cb4e60f636fd09dd0d2e1a3a7f3a4ac0a1bb0 /mark_rts.c
parentf3632431e72d48bc7772b0752e29bb1e2a0901c6 (diff)
gc6.2 tarball importgc6_2
Diffstat (limited to 'mark_rts.c')
-rw-r--r--mark_rts.c114
1 files changed, 90 insertions, 24 deletions
diff --git a/mark_rts.c b/mark_rts.c
index 628cba2..55eb5d5 100644
--- a/mark_rts.c
+++ b/mark_rts.c
@@ -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? */
@@ -506,6 +545,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(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,19 +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;
/*
* 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 */
@@ -541,6 +592,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) {
@@ -549,8 +612,11 @@ 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
/*