diff options
-rw-r--r-- | allchblk.c | 18 | ||||
-rw-r--r-- | include/private/gcconfig.h | 8 | ||||
-rw-r--r-- | os_dep.c | 32 |
3 files changed, 53 insertions, 5 deletions
@@ -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. */ @@ -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; |