]> granicus.if.org Git - gc/commitdiff
Fix infinite restarting of mark_some when a static root disappeared (Linux)
authorIvan Maidanski <ivmai@mail.ru>
Mon, 7 May 2018 08:05:15 +0000 (11:05 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Mon, 7 May 2018 08:05:15 +0000 (11:05 +0300)
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.

dyn_load.c
include/private/gc_priv.h
mark_rts.c

index 4072751ed3acf44c6550ef70c72bc92d87688a73..6692321c68e8763024df07feb3ed4e87b6a98dc0 100644 (file)
@@ -389,6 +389,10 @@ STATIC void GC_register_map_entries(char *maps)
               }
               if ((word)start < (word)end)
                   GC_add_roots_inner(start, 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);
         }
     }
 }
index 5ac127a07f2c72c6b4ae8d57d7a0f52f01088d8e..e4f0c228fa32ce58c4784340783e286a9032693a 100644 (file)
@@ -1803,6 +1803,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)
index 1499e457c795ee1879e7095dece150f00e401716..a179effb0ed8a71abc0476d7a04dba2b38b4cdd6 100644 (file)
@@ -372,6 +372,49 @@ STATIC void GC_remove_tmp_roots(void)
   }
 #endif /* !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) */
 
+#ifdef USE_PROC_FOR_LIBRARIES
+  /* If there is a static root containing [b,e) then replace this root  */
+  /* [r_start,r_end) with roots [r_start,b) and [e,r_end).              */
+  /* It is assumed that 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_ASSERT(I_HOLD_LOCK());
+    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)r_start <= (word)b && (word)e <= (word)r_end, FALSE)) {
+#       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
+        GC_remove_root_at_pos(i);
+        GC_rebuild_root_index();
+        if ((word)r_start < (word)b)
+          GC_add_roots_inner(r_start, b, FALSE);
+        if ((word)e < (word)r_end)
+          GC_add_roots_inner(e, r_end, FALSE);
+        break;
+      }
+    }
+  }
+#endif /* USE_PROC_FOR_LIBRARIES */
+
 #if !defined(NO_DEBUGGING)
   /* For the debugging purpose only.                                    */
   /* Workaround for the OS mapping and unmapping behind our back:       */