summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--allchblk.c18
-rw-r--r--include/private/gcconfig.h8
-rw-r--r--os_dep.c32
3 files changed, 53 insertions, 5 deletions
diff --git a/allchblk.c b/allchblk.c
index 90331dc8..8b84aab8 100644
--- a/allchblk.c
+++ b/allchblk.c
@@ -417,6 +417,24 @@ GC_INNER void GC_unmap_old(void)
}
}
+# ifdef MPROTECT_VDB
+ GC_INNER GC_bool GC_has_unmapped_memory(void)
+ {
+ int i;
+
+ for (i = 0; i <= N_HBLK_FLS; ++i) {
+ struct hblk * h;
+ hdr * hhdr;
+
+ for (h = GC_hblkfreelist[i]; h != NULL; h = hhdr -> hb_next) {
+ hhdr = HDR(h);
+ if (!IS_MAPPED(hhdr)) return TRUE;
+ }
+ }
+ return FALSE;
+ }
+# endif /* MPROTECT_VDB */
+
/* Merge all unmapped blocks that are adjacent to other free */
/* blocks. This may involve remapping, since all blocks are either */
/* fully mapped or fully unmapped. */
diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h
index 6a79da0f..a7887d83 100644
--- a/include/private/gcconfig.h
+++ b/include/private/gcconfig.h
@@ -2872,9 +2872,11 @@
# undef GWW_VDB
#endif
-#ifdef USE_MUNMAP
- /* FIXME: Remove this undef if possible. */
-# undef MPROTECT_VDB /* Can't deal with address space holes. */
+#if defined(USE_MUNMAP) && defined(GWW_VDB)
+# undef MPROTECT_VDB /* TODO: Cannot deal with address space holes. */
+ /* Else if MPROTECT_VDB is available but not GWW_VDB then decide */
+ /* whether to disable memory unmapping or mprotect-based virtual */
+ /* dirty bits at runtime when GC_enable_incremental is called. */
#endif
/* PARALLEL_MARK does not cause undef MPROTECT_VDB any longer. */
diff --git a/os_dep.c b/os_dep.c
index fa8ab524..76b5ce73 100644
--- a/os_dep.c
+++ b/os_dep.c
@@ -3324,9 +3324,37 @@ GC_INNER void GC_remove_protection(struct hblk *h, word nblocks,
UNPROTECT(h_trunc, (ptr_t)h_end - (ptr_t)h_trunc);
}
-#if !defined(DARWIN)
+#ifdef USE_MUNMAP
+ GC_INNER GC_bool GC_has_unmapped_memory(void); /* from allchblk.c */
+ GC_INNER GC_bool GC_mprotect_dirty_init(void);
+
+ /* MPROTECT_VDB cannot deal with address space holes (for now), */
+ /* so if the collector is configured with both MPROTECT_VDB and */
+ /* USE_MUNMAP then, as a work around, select only one of them */
+ /* during GC_init or GC_enable_incremental. */
GC_INNER GC_bool GC_dirty_init(void)
{
+ if (GC_unmap_threshold != 0) {
+ if (GETENV("GC_UNMAP_THRESHOLD") != NULL
+ || GETENV("GC_FORCE_UNMAP_ON_GCOLLECT") != NULL
+ || GC_has_unmapped_memory()) {
+ WARN("Can't maintain mprotect-based dirty bits"
+ " in case of unmapping\n", 0);
+ return FALSE;
+ }
+ GC_unmap_threshold = 0; /* in favor of incremental collection */
+ WARN("Memory unmapping is disabled as incompatible"
+ " with MPROTECT_VDB\n", 0);
+ }
+ return GC_mprotect_dirty_init();
+ }
+#else
+# define GC_mprotect_dirty_init GC_dirty_init
+#endif /* !USE_MUNMAP */
+
+#if !defined(DARWIN)
+ GC_INNER GC_bool GC_mprotect_dirty_init(void)
+ {
# if !defined(MSWIN32) && !defined(MSWINCE)
struct sigaction act, oldact;
act.sa_flags = SA_RESTART | SA_SIGINFO;
@@ -4054,7 +4082,7 @@ STATIC void *GC_mprotect_thread(void *arg)
}
#endif /* BROKEN_EXCEPTION_HANDLING */
-GC_INNER GC_bool GC_dirty_init(void)
+GC_INNER GC_bool GC_mprotect_dirty_init(void)
{
kern_return_t r;
mach_port_t me;