From 35c88088bf4bebec9d6dbbf152fc8cb2895ee807 Mon Sep 17 00:00:00 2001 From: hboehm Date: Sat, 8 Aug 2009 00:49:29 +0000 Subject: [PATCH] 2009-08-07 Hans Boehm (Really Ivan Maidanski) diff111 (supersedes diff101_cvs which, in turn, resembles diff52, diff75, diff83 partly) * Makefile.direct (MARK_BIT_PER_OBJ, PRINT_BLACK_LIST, USE_PROC_FOR_LIBRARIES): Fix typo in the comments. * Makefile.direct (USE_MMAP, USE_MUNMAP, THREAD_LOCAL_ALLOC, PARALLEL_MARK, STATIC): Update the comments. * include/private/gcconfig.h (GC_PREFER_MPROTECT_VDB): New macro recognized (only if MPROTECT_VDB). * Makefile.direct (DONT_USE_USER32_DLL, GC_PREFER_MPROTECT_VDB): Add the comments for. * os_dep.c (detect_GetWriteWatch): Recognize "GC_USE_GETWRITEWATCH" environment variable (only if MPROTECT_VDB, if the variable is unset when GC_PREFER_MPROTECT_VDB macro controls the strategy). * doc/README.environment (GC_USE_GETWRITEWATCH): New variable. * include/private/gcconfig.h (MPROTECT_VDB): Add FIXME for USE_MUNMAP and PARALLEL_MARK cases (to relax the conditions in the future). * misc.c (GC_get_heap_size, GC_get_free_bytes): Ignore the memory space returned to OS (GC_unmapped_bytes). * include/gc.h (GC_get_heap_size, GC_get_free_bytes): Update the comments. * misc.c (GC_get_unmapped_bytes): New API function. * include/gc.h (GC_get_unmapped_bytes): New API prototype. * include/private/gc_priv.h (GC_unmapped_bytes): Define as 0 for not USE_MUNMAP case. * os_dep.c (GC_dirty_init): Move "ifdef GWW_VDB" block out of "ifdef MSWIN32" one (for Cygwin). --- ChangeLog | 29 +++++++++++++++++++++++++++++ Makefile.direct | 35 +++++++++++++++++++---------------- doc/README.environment | 8 ++++++++ include/gc.h | 13 ++++++++++--- include/private/gcconfig.h | 10 +++++++++- misc.c | 21 +++++++++++++++++++-- os_dep.c | 29 +++++++++++++++++++++++++---- 7 files changed, 119 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7ef84a5..1c9e895 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2009-08-07 Hans Boehm (Really Ivan Maidanski) + diff111 (supersedes diff101_cvs which, in turn, resembles diff52, diff75, diff83 partly) + + * Makefile.direct (MARK_BIT_PER_OBJ, PRINT_BLACK_LIST, + USE_PROC_FOR_LIBRARIES): Fix typo in the comments. + * Makefile.direct (USE_MMAP, USE_MUNMAP, THREAD_LOCAL_ALLOC, + PARALLEL_MARK, STATIC): Update the comments. + * include/private/gcconfig.h (GC_PREFER_MPROTECT_VDB): New macro + recognized (only if MPROTECT_VDB). + * Makefile.direct (DONT_USE_USER32_DLL, GC_PREFER_MPROTECT_VDB): + Add the comments for. + * os_dep.c (detect_GetWriteWatch): Recognize "GC_USE_GETWRITEWATCH" + environment variable (only if MPROTECT_VDB, if the variable is + unset when GC_PREFER_MPROTECT_VDB macro controls the strategy). + * doc/README.environment (GC_USE_GETWRITEWATCH): New variable. + * include/private/gcconfig.h (MPROTECT_VDB): Add FIXME for + USE_MUNMAP and PARALLEL_MARK cases (to relax the conditions in + the future). + * misc.c (GC_get_heap_size, GC_get_free_bytes): Ignore the memory + space returned to OS (GC_unmapped_bytes). + * include/gc.h (GC_get_heap_size, GC_get_free_bytes): Update the + comments. + * misc.c (GC_get_unmapped_bytes): New API function. + * include/gc.h (GC_get_unmapped_bytes): New API prototype. + * include/private/gc_priv.h (GC_unmapped_bytes): Define as 0 for + not USE_MUNMAP case. + * os_dep.c (GC_dirty_init): Move "ifdef GWW_VDB" block out of + "ifdef MSWIN32" one (for Cygwin). + 2009-08-01 Hans Boehm (Really Ivan Maidanski) diff100_cvs (diff51 and diff55, partly) diff --git a/Makefile.direct b/Makefile.direct index c2a2dd5..8100344 100644 --- a/Makefile.direct +++ b/Makefile.direct @@ -169,7 +169,7 @@ HOSTCFLAGS=$(CFLAGS) # cache footprint. Normally it is best to let this decision be # made automatically depending on platform. # -DMARK_BIT_PER_OBJ requests that a mark bit be allocated for each -# object instead of allocation granule. The opposiet of +# object instead of allocation granule. The opposite of # MARK_BIT_PER_GRANULE. # -DHBLKSIZE=ddd, where ddd is a power of 2 between 512 and 16384, explicitly # sets the heap block size. Each heap block is devoted to a single size and @@ -177,18 +177,18 @@ HOSTCFLAGS=$(CFLAGS) # the most likely page size. Otherwise large values result in more # fragmentation, but generally better performance for large heaps. # -DUSE_MMAP use MMAP instead of sbrk to get new memory. -# Works for Solaris and Irix. +# Works for Linux, FreeBSD, Cygwin, Solaris and Irix. # -DUSE_MUNMAP causes memory to be returned to the OS under the right -# circumstances. This currently disables VM-based incremental collection. -# This is currently experimental, and works only under some Unix, -# Linux and Windows versions. Requires -DUSE_MMAP, even under Windows, -# where USE_MMAP doesn't do anything. +# circumstances. This currently disables VM-based incremental collection +# (except for Win32 with GetWriteWatch available). +# Works under some Unix, Linux and Windows versions. +# Requires -DUSE_MMAP except for Windows. # -DMMAP_STACKS (for Solaris threads) Use mmap from /dev/zero rather than # GC_scratch_alloc() to get stack memory. # -DPRINT_BLACK_LIST Whenever a black list entry is added, i.e. whenever # the garbage collector detects a value that looks almost, but not quite, # like a pointer, print both the address containing the value, and the -# value of the near-bogus-pointer. Can be used to identifiy regions of +# value of the near-bogus-pointer. Can be used to identify regions of # memory that are likely to contribute misidentified pointers. # -DKEEP_BACK_PTRS Add code to save back pointers in debugging headers # for objects allocated with the debugging allocator. If all objects @@ -254,8 +254,7 @@ HOSTCFLAGS=$(CFLAGS) # -DTHREAD_LOCAL_ALLOC defines GC_malloc(), GC_malloc_atomic() # and GC_gcj_malloc() to use a per-thread set of free-lists. # These then allocate in a way that usually does not involve -# acquisition of a global lock. Currently supported only on platforms -# such as Linux that use pthread_support.c. Recommended for multiprocessors. +# acquisition of a global lock. Recommended for multiprocessors. # Requires explicit GC_INIT() call, unless REDIRECT_MALLOC is # defined and GC_malloc is used first. # -DUSE_COMPILER_TLS causes thread local allocation to use compiler-supported @@ -263,9 +262,7 @@ HOSTCFLAGS=$(CFLAGS) # may help performance on recent Linux installations. (It failed for # me on RedHat 8, but appears to work on RedHat 9.) # -DPARALLEL_MARK allows the marker to run in multiple threads. Recommended -# for multiprocessors. Currently works only on some pthreads platforms, -# though support for other platforms should be fairly easy to add, -# if the thread implementation is otherwise supported. +# for multiprocessors. # -DNO_GETENV prevents the collector from looking at environment variables. # These may otherwise alter its configuration, or turn off GC altogether. # I don't know of a reason to disable this, except possibly if the @@ -312,7 +309,7 @@ HOSTCFLAGS=$(CFLAGS) # for applications that don't support proper stack unwinding. # -DUSE_PROC_FOR_LIBRARIES Causes the Linux collector to treat writable # memory mappings (as reported by /proc) as roots, if it doesn't have -# otherinformation about them. It no longer traverses dynamic loader +# other information about them. It no longer traverses dynamic loader # data structures to find dynamic library static data. This may be # required for applications that store pointers in mmapped segments without # informaing the collector. But it typically performs poorly, especially @@ -324,9 +321,15 @@ HOSTCFLAGS=$(CFLAGS) # happens implicitly on Darwin, Hurd, or ARM or MIPS hardware. # It is explicitly needed for some old versions of FreeBSD. # -DSTATIC=static Causes various GC_ symbols that could logically be -# declared static to be declared. Reduces the number of visible symbols, -# which is probably cleaner, but may make some kinds of debugging and -# profiling harder. +# declared static to be declared (this is the default if -DNO_DEBUGGING is +# specified). Reduces the number of visible symbols (letting the optimizer +# do its work better), which is probably cleaner, but may make some kinds of +# debugging and profiling harder. +# -DDONT_USE_USER32_DLL (Win32 only) Don't use "user32" DLL import library +# (containing MessageBox() entry); useful for a static GC library. +# -DGC_PREFER_MPROTECT_VDB Choose MPROTECT_VDB manually in case of multiple +# virtual dirty bit strategies are implemented (at present useful on Win32 +# to force MPROTECT_VDB strategy instead of the default GWW_VDB one). # CXXFLAGS= $(CFLAGS) diff --git a/doc/README.environment b/doc/README.environment index 8b852a6..a5e110e 100644 --- a/doc/README.environment +++ b/doc/README.environment @@ -94,6 +94,14 @@ GC_RETRY_SIGNALS, GC_NO_RETRY_SIGNALS - Try to compensate for lost was turned into a runtime flag to enable last-minute work-arounds. +GC_USE_GETWRITEWATCH= - Only if MPROTECT_VDB and GWW_VDB are both defined + (Win32 only). Explicitly specify which strategy of + keeping track of dirtied pages should be used. + If n=0 then GetWriteWatch() is not used (falling back to + protecting pages and catching memory faults strategy) + else the collector tries to use GetWriteWatch-based + strategy (GWW_VDB) first if available. + GC_DISABLE_INCREMENTAL - Ignore runtime requests to enable incremental GC. Useful for debugging. diff --git a/include/gc.h b/include/gc.h index 89de621..c62b148 100644 --- a/include/gc.h +++ b/include/gc.h @@ -422,13 +422,20 @@ typedef int (GC_CALLBACK * GC_stop_func)(void); GC_API int GC_CALL GC_try_to_collect(GC_stop_func stop_func); /* Return the number of bytes in the heap. Excludes collector private */ -/* data structures. Includes empty blocks and fragmentation loss. */ -/* Includes some pages that were allocated but never written. */ +/* data structures. Excludes the unmapped memory (retuned to the OS). */ +/* Includes empty blocks and fragmentation loss. Includes some pages */ +/* that were allocated but never written. */ GC_API size_t GC_CALL GC_get_heap_size(void); -/* Return a lower bound on the number of free bytes in the heap. */ +/* Return a lower bound on the number of free bytes in the heap */ +/* (excluding the unmapped memory space). */ GC_API size_t GC_CALL GC_get_free_bytes(void); +/* Return the size (in bytes) of the unmapped memory (which is returned */ +/* to the OS but could be remapped back by the collector later unless */ +/* the OS runs out of system/virtual memory). */ +GC_API size_t GC_CALL GC_get_unmapped_bytes(void); + /* Return the number of bytes allocated since the last collection. */ GC_API size_t GC_CALL GC_get_bytes_since_gc(void); diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 75190dd..e8c261d 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -2117,14 +2117,22 @@ # endif # ifdef USE_MUNMAP + /* FIXME: Remove this undef if possible. */ # undef MPROTECT_VDB /* Can't deal with address space holes. */ # endif # if defined(PARALLEL_MARK) - /* FIXME: Should we undef it even in case of GWW_VDB? */ + /* FIXME: Remove this undef if possible. */ # undef MPROTECT_VDB /* For now. */ # endif +# if defined(MPROTECT_VDB) && defined(GC_PREFER_MPROTECT_VDB) + /* Choose MPROTECT_VDB manually (if multiple strategies available). */ +# undef PCR_VDB +# undef PROC_VDB + /* #undef GWW_VDB - handled in os_dep.c */ +# endif + # if !defined(PCR_VDB) && !defined(PROC_VDB) && !defined(MPROTECT_VDB) \ && !defined(GWW_VDB) # define DEFAULT_VDB diff --git a/misc.c b/misc.c index ed9574b..d8fc82b 100644 --- a/misc.c +++ b/misc.c @@ -381,7 +381,9 @@ GC_API size_t GC_CALL GC_get_heap_size(void) size_t value; DCL_LOCK_STATE; LOCK(); - value = GC_heapsize; + /* ignore the memory space returned to OS (i.e. count only the */ + /* space owned by the garbage collector) */ + value = (size_t)(GC_heapsize - GC_unmapped_bytes); UNLOCK(); return value; } @@ -391,11 +393,26 @@ GC_API size_t GC_CALL GC_get_free_bytes(void) size_t value; DCL_LOCK_STATE; LOCK(); - value = GC_large_free_bytes; + /* ignore the memory space returned to OS */ + value = (size_t)(GC_large_free_bytes - GC_unmapped_bytes); UNLOCK(); return value; } +GC_API size_t GC_CALL GC_get_unmapped_bytes(void) +{ +# ifdef USE_MUNMAP + size_t value; + DCL_LOCK_STATE; + LOCK(); + value = (size_t)GC_unmapped_bytes; + UNLOCK(); + return value; +# else + return 0; +# endif +} + GC_API size_t GC_CALL GC_get_bytes_since_gc(void) { size_t value; diff --git a/os_dep.c b/os_dep.c index bc41216..7fb1f59 100644 --- a/os_dep.c +++ b/os_dep.c @@ -1286,6 +1286,26 @@ void GC_register_data_segments(void) if (done) return; +# if defined(MPROTECT_VDB) + { + char * str = GETENV("GC_USE_GETWRITEWATCH"); +# if defined(GC_PREFER_MPROTECT_VDB) + if (str == NULL || (*str == '0' && *(str + 1) == '\0')) { + /* GC_USE_GETWRITEWATCH is unset or set to "0". */ + done = TRUE; /* falling back to MPROTECT_VDB strategy. */ + /* This should work as if GWW_VDB is undefined. */ + return; + } +# else + if (str != NULL && *str == '0' && *(str + 1) == '\0') { + /* GC_USE_GETWRITEWATCH is set "0". */ + done = TRUE; /* falling back to MPROTECT_VDB strategy. */ + return; + } +# endif + } +# endif + GetWriteWatch_func = (GetWriteWatch_type) GetProcAddress(GetModuleHandle("kernel32.dll"), "GetWriteWatch"); if (GetWriteWatch_func != NULL) { @@ -2045,6 +2065,7 @@ void GC_remap(ptr_t start, size_t bytes) ptr_t end_addr = GC_unmap_end(start, bytes); word len = end_addr - start_addr; + /* FIXME: Should we handle out-of-memory here? */ # if defined(MSWIN32) || defined(MSWINCE) ptr_t result; @@ -2898,11 +2919,11 @@ void GC_dirty_init(void) } # endif /* HPUX || LINUX || HURD || (FREEBSD && SUNOS5SIGS) */ # endif /* ! MS windows */ +# if defined(GWW_VDB) + if (GC_gww_dirty_init()) + return; +# endif # if defined(MSWIN32) -# if defined(GWW_VDB) - if (GC_gww_dirty_init()) - return; -# endif GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler); if (GC_old_segv_handler != NULL) { if (GC_print_stats) -- 2.7.4