]> 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>
Wed, 18 Jul 2018 18:52:32 +0000 (21:52 +0300)
(a cherry-pick of commit 67338bbd from 'release-7_6')

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).

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

index 52b7470ab6362a6cfee1c3277fcead96f6cac713..707ff766c0048b0cd433df77a6b60cb50c76f84b 100644 (file)
@@ -366,6 +366,10 @@ STATIC word GC_register_map_entries(char *maps)
               }
               if (start < 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);
         }
     }
     return 1;
index 103999eb4161980402620a6b38932a5ec83779f7..4195e4ab2118cc4a95955eefc7e22cb6e8a4bcef 100644 (file)
@@ -1577,6 +1577,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 bf8ffc6c35ceb0cae9aa9ea8cdbdfde978a682ff..02c4cafdbcd1cd33180d1e13f7e9ccbfb9d634cc 100644 (file)
@@ -330,6 +330,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(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)) \
     && !defined(NO_DEBUGGING)
   /* Not used at present (except for, may be, debugging purpose).       */