diff -Nru libgc-8.0.4/AUTHORS libgc-8.0.6/AUTHORS --- libgc-8.0.4/AUTHORS 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/AUTHORS 2021-11-25 21:36:27.000000000 +0000 @@ -28,6 +28,7 @@ Alain Novak Alan Dosser Alan J. Demers +Alaskan Emily Aleksey Demakov Alessandro Bruni Alex Ronne Petersen @@ -102,8 +103,10 @@ Christian Joensson Christian Limpach Christian Thalinger +Christian Weisgerber Christoffe Raffali Clay Spence +Clement Chigot Colin LeMahieu Craig McDaniel Dai Sato @@ -135,6 +138,7 @@ Demyan Kimitsa Dick Porter Dietmar Planitzer +Dima Pasechnik Dimitris Vyzovitis Dimitry Andric Djamel Magri @@ -182,6 +186,7 @@ Igor Khavkine Ivan Demakov Ivan Maidanski +Ivan R Jaap Boender Jack Andrews Jacob Navia @@ -192,6 +197,7 @@ Jan Wielemaker Jani Kajala Jared McNeill +Jasper Lievisse Adriaanse Jay Krell Jean-Baptiste Nivois Jean-Claude Beaudoin @@ -214,10 +220,12 @@ Johannes Totz John Bowman John Clements +John David Anglin John Ellis John Merryweather Cooper Jon Moore Jonas Echterhoff +Jonas Hahnfeld Jonathan Bachrach Jonathan Chambers Jonathan Clark @@ -254,6 +262,7 @@ Lucas Meijer Ludovic Courtes Maarten Thibaut +Mahder Gebremedhin Manuel A. Fernandez Montecelo Manuel Serrano Marc Recht @@ -270,6 +279,7 @@ Martin Hirzel Martin Koeppe Martin Tauchmann +Massimiliano Gubinelli Matt Austern Matthew Flatt Matthias Andree @@ -297,6 +307,7 @@ Neil Sharman Nicolas Cannasse Niibe Yutaka +Nikita Ermakov Niklas Therning Noah Lavine Nobuyuki Hikichi @@ -313,6 +324,7 @@ Paul Nash Per Bothner Peter Bigot +Peter Budai Peter Chubb Peter Colson Peter Housel @@ -343,6 +355,7 @@ Richard Earnshaw Richard Henderson Richard Sandiford +Richard Zidlicky Rob Haack Robert Brazile Rodrigo Kumpera @@ -365,6 +378,7 @@ Simon Gornall Simon Posnjak Slava Sysoltsev +Sorawee Porncharoenwase Stefan Ring Stefano Rivera Sugioka Toshinobu @@ -381,9 +395,11 @@ Thomas Linder Puls Thomas Maier Thomas Schwinge +Thomas Thiriez Thorsten Glaser Tilman Vogel Tim Bingham +Tim Gates Timothy N. Newsham Tom Tromey Tommaso Tagliapietra @@ -398,6 +414,7 @@ Uros Bizjak Vernon Lee Victor Ivrii +Victor Romero Vitaly Magerya Vladimir Tsichevski Walter Bright diff -Nru libgc-8.0.4/CMakeLists.txt libgc-8.0.6/CMakeLists.txt --- libgc-8.0.4/CMakeLists.txt 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/CMakeLists.txt 2021-11-25 21:36:27.000000000 +0000 @@ -32,12 +32,6 @@ ADD_DEFINITIONS("-D_CRT_SECURE_NO_DEPRECATE -DALL_INTERIOR_POINTERS -DNO_EXECUTE_PERMISSION") -IF(APPLE) - IF("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "") - SET(CMAKE_OSX_ARCHITECTURES "ppc;i386;x86_64" CACHE STRING "Build architectures for Mac OS X" FORCE) - ENDIF() -ENDIF(APPLE) - #LIBATOMIC #TODO #ADD_LIBRARY(atomic_ops STATIC ) #SET_TARGET_PROPERTIES(atomic_ops PROPERTIES COMPILE_FLAGS -DNO_DEBUGGING) @@ -83,16 +77,17 @@ # Thread Detection. Relying on cmake for lib and includes. #TODO check cmake detection IF(CMAKE_USE_PTHREADS_INIT) - SET(SRC ${SRC} pthread_start.c pthread_support.c pthread_stop_world.c) + SET(SRC ${SRC} gc_dlopen.c pthread_start.c pthread_stop_world.c + pthread_support.c) # Common defines for most POSIX platforms. - IF( HOST MATCHES .*-.*-aix.*|.*-.*-android.*|.*-.*-cygwin.*|.*-.*-darwin.*|.*-.*-.*freebsd.*|.*-.*-haiku.*|.*-.*-gnu.*|.*-.*-hpux11.*|.*-.*-irix.*|.*-.*-.*linux.*|.*-.*-nacl.*|.*-.*-netbsd.*|.*-.*-openbsd.*|.*-.*-osf.*|.*-.*-solaris.*) + IF( HOST MATCHES .*-.*-aix.*|.*-.*-android.*|.*-.*-cygwin.*|.*-.*-darwin.*|.*-.*-.*freebsd.*|.*-.*-haiku.*|.*-.*-gnu.*|.*-.*-hpux11.*|.*-.*-irix.*|.*-.*-.*linux.*|.*-.*-msys.*|.*-.*-nacl.*|.*-.*-netbsd.*|.*-.*-openbsd.*|.*-.*-osf.*|.*-.*-solaris.*) ADD_DEFINITIONS("-DGC_THREADS -D_REENTRANT") IF(enable_parallel_mark) ADD_DEFINITIONS("-DPARALLEL_MARK") ENDIF(enable_parallel_mark) IF(enable_thread_local_alloc) ADD_DEFINITIONS("-DTHREAD_LOCAL_ALLOC") - SET(SRC ${SRC} thread_local_alloc.c) + SET(SRC ${SRC} specific.c thread_local_alloc.c) ENDIF(enable_thread_local_alloc) MESSAGE("Explicit GC_INIT() calls may be required.") ENDIF() @@ -114,7 +109,7 @@ ADD_DEFINITIONS("-DHANDLE_FORK") ENDIF(enable_handle_fork) ENDIF() - IF ( HOST MATCHES .*-.*-cygwin.*) + IF ( HOST MATCHES .*-.*-cygwin.*|.*-.*-msys.*) SET(SRC ${SRC} win32_threads.c) ENDIF() IF ( HOST MATCHES .*-.*-darwin.*) @@ -242,10 +237,6 @@ COMPILE_DEFINITIONS GC_NOT_DLL) #TODO TARGET_LINK_LIBRARIES(... ... ${LIBS}) -ADD_LIBRARY( gcmt-lib STATIC ${SRC}) -SET_TARGET_PROPERTIES(gcmt-lib PROPERTIES - COMPILE_DEFINITIONS GC_NOT_DLL) - ADD_LIBRARY( gcmt-dll SHARED ${SRC}) IF(WIN32) diff -Nru libgc-8.0.4/ChangeLog libgc-8.0.6/ChangeLog --- libgc-8.0.4/ChangeLog 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/ChangeLog 2021-11-25 21:36:27.000000000 +0000 @@ -1,4 +1,101 @@ +== [8.0.6] 2021-09-28 == + +* Add loop to handle abort error like in suspend logic on Darwin +* Add support of OpenBSD/aarch64 +* Add threading libraries to bdw-gc.pc +* Allocate start_info struct on the stack in GC_pthread_create +* Allow GC_PAUSE_TIME_TARGET environment variable values smaller than 5 ms +* Avoid compiler warning about unused d in GC_CALLOC/MALLOC_EXPLICITLY_TYPED +* Avoid gcc stringop-overflow warning for intended overflow in smashtest +* Check _MSVC_LANG macro in addition to __cplusplus (MS VC) +* Compile C++ code with exception handling enabled in NT_MAKEFILE +* Define OS_TYPE and DATAEND for UWP targets +* Disable mprotect-based incremental GC if /proc roots are used (Linux) +* Do not report 'Incremental GC incompatible' warning more than once +* Do not use Manual VDB mode if C malloc is redirected +* Do not use iOS private symbols +* Eliminate 'GC_non_gc_bytes is deprecated' warning in new_gc_alloc.h +* Eliminate 'GC_old_bus_handler defined but not used' compiler warning +* Eliminate 'cast between incompatible func types' warnings for FARPROC vars +* Eliminate 'comparing signed and unsigned values' BCC warning in cordtest +* Eliminate 'gc_pthread_redirects.h should contain header guard' code defect +* Eliminate 'implicit declaration of sbrk' gcc warning if -std=c11 on Cygwin +* Eliminate 'possible loss of data' BCC and MS VC warnings +* Eliminate 'static GC_sysinfo definition has incomplete type' Clang warning +* Eliminate 'unused function' compiler warnings (GC_add_map_entry, GC_lock) +* Eliminate 'while clause does not guard' GCC warning in GC_parse_map_entry +* Enable sbrk-to-mmap fallback on major supported Unix-like platforms +* Ensure process is running on one CPU core if AO ops are emulated with locks +* Explicitly zero-initialize trace_buf (fix trace_buf initialization) +* Fix 'ACCESS_VIOLATION in marker' GC warning on Win32 async thread start +* Fix 'GC_generic_malloc must be available' GCC error in new_gc_alloc.h +* Fix 'ISO C++17 does not allow dynamic exception spec' clang-8 error +* Fix 'Wrong __data_start/_end pair' if -Bsymbolic-functions used (Linux) +* Fix 'condition pred!=NULL is always true' compiler warning +* Fix 'external linkage required for var because of dllimport' error on MinGW +* Fix 'ulong undefined' compilation error on AIX +* Fix 'undefined reference to __data_start' linker error on RISC-V +* Fix 'use of undeclared BUS_PAGE_FAULT' compilation error on FreeBSD 12 +* Fix 'write to GC log failed' error (Cygwin) +* Fix 'wrong finalization data' gctest failure on Windows +* Fix CMake build on macOS Catalina +* Fix GC_OPENBSD_THREADS definition (OpenBSD/hppa) +* Fix GC_proc_fd value in child process at fork (Solaris) +* Fix GC_with_callee_saves_pushed for Android NDK r23 (clang-12) +* Fix MPROTECT_VDB definition for single-threaded GC builds +* Fix OS_TYPE and USE_MMAP_ANON definitions for Cygwin/x64 +* Fix STACKBOTTOM on 32-bit HP/UX 11.11 +* Fix abort in GC_printf when gctest is built as WinMain executable (Cygwin) +* Fix assertion violation in register_dynlib_callback on Android +* Fix build for OS X (CMake) +* Fix building of shared library with C++ support on MinGW +* Fix compiling by Makefile.direct on OpenBSD/UltraSparc +* Fix configure message about 'AIX gcc optimization fix' +* Fix cordtest build in SMakefile.amiga +* Fix data race regarding *rlh value in generic_malloc_many +* Fix first_thread stack_base initialization if custom GC_stackbottom (Win32) +* Fix gc_allocator.h compilation by Clang +* Fix gc_cflags variable name in configure (HP/UX) +* Fix handling of areas smaller than page size in GC_scratch_recycle +* Fix incorrect markup formatting in documentation +* Fix misaligned tlfs passed to AO_load on m68k +* Fix missing GC_quiet declaration in pcr_interface.c +* Fix missing gc_dlopen.c and specific.c in CMake script +* Fix missing scratch_last_end_ptr update (Irix) +* Fix mmap() failures on AIX, HP/UX and Haiku +* Fix overflow of scratch_free_ptr value +* Fix page_was_[ever_]dirty() for static roots (Solaris) +* Fix printf format specifier in simple_example.md +* Fix save_callers for multi-threaded case if built-in backtrace unavailable +* Fix subexpression widening in memhash() of disclaim_weakmap_test +* Fix test_cpp failure caused by arbitrary link order (Win32) +* Fix test_cpp failure when gc_cpp resides in a dll (Borland, Watcom) +* Fix various typos mostly in documentation files +* Fix word size, data start and alignment for OpenBSD/mips64(el) +* Include when using alloca on AIX +* Limit number of unmapped regions (Linux and DragonFly) +* New macro to avoid system-wide new/delete inlining in gc_cpp.h (Win32) +* Prevent GetThreadContext failure (Windows) +* Prevent WARN of incompatible incremental GC if default or manual VDB +* Reduce a time period between GetExitCodeThread and SuspendThread (Win32) +* Refactoring of WoW64 workaround (Win32) +* Refine GC_INIT documentation about its multiple invocation +* Refine GC_parallel documentation in gc.h +* Refine do_blocking() documentation in gc.h +* Remove a misleading comment about Solaris in gc.h +* Remove cord .h files from list of non-installed headers (Automake) +* Remove dead part of condition to define NEED_FIND_LIMIT in gc_priv.h +* Remove gcmt-lib generation by CMake +* Support MSYS builds by CMake and configure +* Update documentation about the incremental collector support +* Use HEURISTIC2 on OpenBSD when single-threaded +* Use pstat_getprocvm to determine main stack bottom on HP-UX +* Workaround 'expression is only useful for its side effects' WCC warning +* Workaround clang-3.8/s390x bug when processing __builtin_frame_address +* Workaround fread fail after enable_incremental if malloc redirected (Linux) + + == [8.0.4] 2019-03-02 == * Avoid a full GC when growing finalizer tables if in incremental mode @@ -318,6 +415,61 @@ * Workaround Thread Sanitizer (TSan) false positive warnings +== [7.6.14] 2021-09-28 == + +* Add loop to handle abort error like in suspend logic on Darwin +* Add support of OpenBSD/aarch64 +* Add threading libraries to bdw-gc.pc +* Disable mprotect-based incremental GC if /proc roots are used (Linux) +* Do not use iOS private symbols +* Eliminate 'GC_old_bus_handler defined but not used' compiler warning +* Eliminate 'comparing signed and unsigned values' BCC warning in cordtest +* Eliminate 'possible loss of data' BCC and MS VC warnings +* Eliminate 'static GC_sysinfo definition has incomplete type' Clang warning +* Eliminate 'unused function GC_add_map_entry' compiler warning +* Eliminate 'while clause does not guard' GCC warning in GC_parse_map_entry +* Explicitly zero-initialize trace_buf (fix trace_buf initialization) +* Fix 'ACCESS_VIOLATION in marker' GC warning on Win32 async thread start +* Fix 'GC_generic_malloc must be available' GCC error in new_gc_alloc.h +* Fix 'ulong undefined' compilation error on AIX +* Fix 'undefined reference to __data_start' linker error on RISC-V +* Fix 'write to GC log failed' error +* Fix GC_proc_fd value in child process at fork (Solaris) +* Fix MPROTECT_VDB definition for single-threaded GC builds +* Fix OS_TYPE and USE_MMAP_ANON definitions for Cygwin/x64 +* Fix STACKBOTTOM on 32-bit HP/UX 11.11 +* Fix abort in GC_printf when gctest is built as WinMain executable (Cygwin) +* Fix assertion violation in register_dynlib_callback on Android +* Fix compiling by Makefile.direct on OpenBSD/UltraSparc +* Fix configure message about 'AIX gcc optimization fix' +* Fix cordtest build in SMakefile.amiga +* Fix data race regarding *rlh value in generic_malloc_many +* Fix first_thread stack_base initialization if custom GC_stackbottom (Win32) +* Fix gc_allocator.h compilation by Clang +* Fix gc_cflags variable name in configure (HP/UX) +* Fix handling of areas smaller than page size in GC_scratch_recycle +* Fix incorrect define GC_OPENBSD_THREADS on sparc64 +* Fix misaligned tlfs passed to AO_load on m68k +* Fix missing GC_quiet declaration in pcr_interface.c +* Fix missing gc_dlopen.c in CMake script +* Fix missing scratch_last_end_ptr update (Irix) +* Fix overflow of scratch_free_ptr value +* Fix page_was_[ever_]dirty() for static roots (Solaris) +* Fix printf format specifier in simple_example.html +* Fix save_callers for multi-threaded case if built-in backtrace unavailable +* Fix test_cpp failure caused by arbitrary link order (Win32) +* Fix test_cpp failure when gc_cpp resides in a dll (Borland, Watcom) +* Fix various typos mostly in documentation files +* Fix word size, data start and alignment for OpenBSD/mips64(el) +* Prevent GetThreadContext failure (Windows) +* Prevent WARN of incompatible incremental GC if default or manual VDB +* Reduce a time period between GetExitCodeThread and SuspendThread (Win32) +* Refactoring of WoW64 workaround (Win32) +* Remove a misleading comment about Solaris in gc.h +* Workaround 'expression is only useful for its side effects' WCC warning +* Workaround fread fail after enable_incremental if malloc redirected (Linux) + + == [7.6.12] 2019-03-01 == * Eliminate 'assigned value never used' compiler warning in test_cpp WinMain @@ -804,6 +956,22 @@ Also, includes 7.4.4 changes +== [7.4.20] 2021-09-28 == + +* Do not hold GC_fault_handler_lock when in Sleep (Windows) +* Eliminate 'static GC_sysinfo definition has incomplete type' Clang warning +* Eliminate 'unused function GC_add_map_entry' compiler warning +* Eliminate 'while clause does not guard' GCC warning in GC_parse_map_entry +* Fix OS_TYPE and USE_MMAP_ANON definitions for Cygwin/x64 +* Fix abort in GC_printf when gctest is built as WinMain executable (Cygwin) +* Fix configure message about 'AIX gcc optimization fix' +* Fix cordtest build in SMakefile.amiga +* Prevent GetThreadContext failure (Windows) +* Refactoring of WoW64 workaround (Win32) + +Also, includes 7.2o changes + + == [7.4.18] 2019-03-01 == * Fix 'wrong __data_start/_end pair' error on Android @@ -1314,6 +1482,39 @@ Also, includes 7.2 changes +== [7.2o] 2021-09-28 == + +* Add loop to handle abort error like in suspend logic on Darwin +* Disable mprotect-based incremental GC if /proc roots are used (Linux) +* Explicitly zero-initialize trace_buf (fix trace_buf initialization) +* Fix 'ACCESS_VIOLATION in marker' GC warning on Win32 async thread start +* Fix 'GC_generic_malloc must be available' GCC error in new_gc_alloc.h +* Fix 'expected function body after declarator' clang error in gc_cpp.cc +* Fix 'write to GC log failed' error +* Fix GC_proc_fd value in child process at fork (Solaris) +* Fix assertion violation in register_dynlib_callback on Android +* Fix configure message about 'AIX gcc optimization fix' +* Fix data race regarding *rlh value in generic_malloc_many +* Fix first_thread stack_base initialization if custom GC_stackbottom (Win32) +* Fix fread failure after enable_incremental if malloc is redirected (Linux) +* Fix gc_cflags variable name in configure (HP/UX) +* Fix handling of areas smaller than page size on recycle scratch area +* Fix incorrect define GC_OPENBSD_THREADS on sparc64 +* Fix misaligned tlfs passed to AO_load on m68k +* Fix missing GC_quiet declaration in pcr_interface.c +* Fix missing gc_dlopen.c in CMake script +* Fix missing scratch_last_end_ptr update (Irix) +* Fix overflow of scratch_free_ptr value +* Fix page_was_[ever_]dirty() for static roots (Solaris) +* Fix printf format specifier in simple_example.html +* Fix save_callers for multi-threaded case if built-in backtrace unavailable +* Fix various typos in comments and documentation files +* Fix word size, data start and alignment for OpenBSD/mips64(el) +* Prevent WARN of incompatible incremental GC if default or manual VDB +* Reduce a time period between GetExitCodeThread and SuspendThread (Win32) +* Remove a misleading comment about Solaris in gc.h + + == [7.2n] 2019-03-01 == * Fix 'mprotect remapping failed' abort on NetBSD with PaX enabled @@ -8014,7 +8215,7 @@ * Separate gc_conf_macros.h from gc.h. * Added generic GC_THREADS client-defined macro to set the appropriate GC_XXX_THREADS internal macro. (gc_config_macros.h.) -* Add debugging versions of _ignore_off_page allocation primitves. +* Add debugging versions of _ignore_off_page allocation primitives. * Moved declarations of GC_make_closure and GC_debug_invoke_finalizer from gc.h to gc_priv.h. * Reset GC_fail_count even if only a small allocation succeeds. diff -Nru libgc-8.0.4/Makefile.am libgc-8.0.6/Makefile.am --- libgc-8.0.4/Makefile.am 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/Makefile.am 2021-11-25 21:36:27.000000000 +0000 @@ -14,8 +14,8 @@ # Info (current:revision:age) for the Libtool versioning system. # These numbers should be updated at most once just before the release, # and, optionally, at most once during the development (after the release). -LIBGC_VER_INFO = 5:3:4 -LIBGCCPP_VER_INFO = 5:0:4 +LIBGC_VER_INFO = 5:4:4 +LIBGCCPP_VER_INFO = 5:1:4 ## FIXME: `make distcheck' in this directory will not currently work. ## This is most likely to the explicit flags passed to submakes. diff -Nru libgc-8.0.4/Makefile.direct libgc-8.0.6/Makefile.direct --- libgc-8.0.4/Makefile.direct 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/Makefile.direct 2021-11-25 21:36:27.000000000 +0000 @@ -226,7 +226,7 @@ $(srcdir)/include/gc.h gc_cpp.o base_lib $(UTILS) rm -f test_cpp$(EXEEXT) ./if_mach HP_PA HPUX $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/tests/test_cpp.cc gc_cpp.o gc.a -ldld `./threadlibs` - ./if_not_there test_cpp$(EXEEXT) || $(CXX) $(CXXFLAGS) -o test_cpp$(EXEEXT) $(srcdir)/tests/test_cpp.cc gc_cpp.o gc.a `./threadlibs` + ./if_not_there test_cpp$(EXEEXT) || $(CXX) $(CXXFLAGS) -DGC_NOT_DLL -o test_cpp$(EXEEXT) $(srcdir)/tests/test_cpp.cc gc_cpp.o gc.a `./threadlibs` check-cpp: test_cpp$(EXEEXT) ./test_cpp @@ -289,12 +289,11 @@ # touch liblinuxgc.so mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/sparc_mach_dep.S \ - $(srcdir)/sparc_sunos4_mach_dep.s \ $(srcdir)/ia64_save_regs_in_stack.s \ $(srcdir)/sparc_netbsd_mach_dep.s $(UTILS) rm -f mach_dep.o ./if_mach SPARC SOLARIS $(CC) -c -o mach_dep2.o $(srcdir)/sparc_mach_dep.S - ./if_mach SPARC OPENBSD $(AS) -o mach_dep2.o $(srcdir)/sparc_sunos4_mach_dep.s + ./if_mach SPARC OPENBSD $(CC) -c -o mach_dep2.o $(srcdir)/sparc_mach_dep.S ./if_mach SPARC NETBSD $(AS) -o mach_dep2.o $(srcdir)/sparc_netbsd_mach_dep.s ./if_mach SPARC "" $(CC) -c -o mach_dep1.o $(SPECIALCFLAGS) $(srcdir)/mach_dep.c ./if_mach SPARC "" $(LD) -r -o mach_dep.o mach_dep1.o mach_dep2.o diff -Nru libgc-8.0.4/Makefile.in libgc-8.0.6/Makefile.in --- libgc-8.0.4/Makefile.in 2019-03-02 08:55:47.000000000 +0000 +++ libgc-8.0.6/Makefile.in 2021-11-25 21:36:27.000000000 +0000 @@ -949,6 +949,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -967,8 +968,8 @@ # Info (current:revision:age) for the Libtool versioning system. # These numbers should be updated at most once just before the release, # and, optionally, at most once during the development (after the release). -LIBGC_VER_INFO = 5:3:4 -LIBGCCPP_VER_INFO = 5:0:4 +LIBGC_VER_INFO = 5:4:4 +LIBGCCPP_VER_INFO = 5:1:4 # We currently use the source files directly from libatomic_ops, if we # use the internal version. This is done since libatomic_ops doesn't @@ -1030,8 +1031,7 @@ # headers which are not installed # -dist_noinst_HEADERS = include/cord.h include/cord_pos.h include/ec.h \ - include/gc_alloc_ptrs.h include/new_gc_alloc.h \ +dist_noinst_HEADERS = include/gc_alloc_ptrs.h include/new_gc_alloc.h \ include/private/darwin_semaphore.h \ include/private/darwin_stop_world.h include/private/dbg_mlc.h \ include/private/gc_atomic_ops.h include/private/gc_hdrs.h \ diff -Nru libgc-8.0.4/NT_MAKEFILE libgc-8.0.6/NT_MAKEFILE --- libgc-8.0.4/NT_MAKEFILE 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/NT_MAKEFILE 2021-11-25 21:36:27.000000000 +0000 @@ -78,6 +78,8 @@ CFLAGS_DEFAULT=-DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION -DUSE_MUNMAP +CXXFLAGS_SPECIFIC=/EHsc + # Make sure that .cc is not viewed as a suffix. It is for VC++2005, but # not earlier versions. We can deal with either, but not inconsistency. .SUFFIXES: @@ -99,7 +101,7 @@ # of safe uses of strncpy. It would be nice to leave the rest enabled. .cpp.obj: - $(cc) $(cdebug) $(cflags) $(CFLAGS_SPECIFIC) -Iinclude $(CFLAGS_DEFAULT) -D_CRT_SECURE_NO_DEPRECATE $*.cpp /Fo$*.obj + $(cc) $(cdebug) $(cflags) $(CFLAGS_SPECIFIC) -Iinclude $(CFLAGS_DEFAULT) $(CXXFLAGS_SPECIFIC) -D_CRT_SECURE_NO_DEPRECATE $*.cpp /Fo$*.obj $(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\gc_disclaim.h include\private\msvc_dbg.h diff -Nru libgc-8.0.4/OS2_MAKEFILE libgc-8.0.6/OS2_MAKEFILE --- libgc-8.0.4/OS2_MAKEFILE 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/OS2_MAKEFILE 2021-11-25 21:36:27.000000000 +0000 @@ -20,7 +20,7 @@ $(OBJS) test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h ## ERASE THE LIB FIRST - if it is already there then this command will fail -## (make sure its there or erase will fail!) +## (make sure it is there or erase will fail!) gc.lib: $(OBJS) echo . > gc.lib erase gc.lib diff -Nru libgc-8.0.4/README.QUICK libgc-8.0.6/README.QUICK --- libgc-8.0.4/README.QUICK 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/README.QUICK 2021-11-25 21:36:27.000000000 +0000 @@ -2,7 +2,7 @@ Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. Copyright (c) 1999-2001 by Hewlett-Packard. All rights reserved. -Copyright (c) 2009-2018 Ivan Maidanski +Copyright (c) 2009-2019 Ivan Maidanski THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. diff -Nru libgc-8.0.4/README.md libgc-8.0.6/README.md --- libgc-8.0.4/README.md 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/README.md 2021-11-25 21:36:27.000000000 +0000 @@ -1,6 +1,6 @@ # Boehm-Demers-Weiser Garbage Collector -This is version 8.0.4 of a conservative garbage +This is version 8.0.6 of a conservative garbage collector for C and C++. @@ -103,7 +103,7 @@ There are a number of routines which modify the pointer recognition algorithm. `GC_register_displacement` allows certain interior pointers -to be recognized even if `ALL_INTERIOR_POINTERS` is nor defined. +to be recognized even if `ALL_INTERIOR_POINTERS` is not defined. `GC_malloc_ignore_off_page` allows some pointers into the middle of large objects to be disregarded, greatly reducing the probability of accidental retention of large objects. For most purposes it seems @@ -264,7 +264,7 @@ `GC_add_roots` calls may be required if the collector has to trace from nonstandard places (e.g. from dynamic library data areas on a machine on which the collector doesn't already understand them.) On -some machines, it may be desirable to set `GC_stacktop` to a good +some machines, it may be desirable to set `GC_stackbottom` to a good approximation of the stack base. (This enhances code portability on HP PA machines, since there is no good way for the collector to compute this value.) Client code may include "gc.h", which defines @@ -359,7 +359,7 @@ #define malloc(n) GC_malloc(n) #define calloc(m,n) GC_malloc((m)*(n)) -For small pieces of VERY allocation intensive code, gc_inl.h includes +For small pieces of VERY allocation intensive code, gc_inline.h includes some allocation macros that may be used in place of `GC_malloc` and friends. @@ -458,7 +458,7 @@ defined, then all these macros will instead be defined to their nondebugging equivalents. (`GC_REGISTER_FINALIZER` is necessary, since pointers to objects with debugging information are really pointers to a displacement -of 16 bytes form the object beginning, and some translation is necessary +of 16 bytes from the object beginning, and some translation is necessary when finalization routines are invoked. For details, about what's stored in the header, see the definition of the type oh in dbg_mlc.c file.) @@ -515,7 +515,7 @@ is enabled. (On 2007 vintage machines, GC times may be on the order of 5 msecs -per MB of accessible memory that needs to be scanned and processor. +per MB of accessible memory that needs to be scanned and processed. Your mileage may vary.) The incremental/generational collection facility may help in some cases. @@ -551,7 +551,7 @@ * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. * Copyright (c) 1999-2011 by Hewlett-Packard Development Company. - * Copyright (c) 2008-2018 Ivan Maidanski + * Copyright (c) 2008-2019 Ivan Maidanski The files pthread_stop_world.c, pthread_support.c and some others are also diff -Nru libgc-8.0.4/SMakefile.amiga libgc-8.0.6/SMakefile.amiga --- libgc-8.0.4/SMakefile.amiga 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/SMakefile.amiga 2021-11-25 21:36:27.000000000 +0000 @@ -52,7 +52,7 @@ all: gctest setjmp_t cord/cordtest clean: - delete *.lib gctest setjmp_t *.o *.lnk cord/*.o cord/*.lib cord/*.lnk cord/cordtest + delete *.lib gctest setjmp_t *.o *.lnk cord/*.o cord/*.lib cord/*.lnk cord/tests/*.o cord/cordtest smake test: setjmp_t gctest cord/cordtest @@ -66,8 +66,8 @@ setjmp_t: setjmp_t.o gc.h $(LINKER) LIB:c.o setjmp_t.o to setjmp_t lib LIB:sc.lib -cord/cordtest: cord/cordtest.o cord/cord$(CPU).lib gc$(CPU).lib - slink LIB:c.o cord/cordtest.o LIB $(MATHLIB) gc$(CPU).lib cord/cord$(CPU).lib LIB:sc.lib TO cord/cordtest +cord/cordtest: cord/tests/cordtest.o cord/cord$(CPU).lib gc$(CPU).lib + slink LIB:c.o cord/tests/cordtest.o LIB $(MATHLIB) gc$(CPU).lib cord/cord$(CPU).lib LIB:sc.lib TO cord/cordtest #------------------LIBBING---------------------------- @@ -168,5 +168,5 @@ cord/cordxtra.o: cord/cordxtra.c sc cord/cordxtra.c $(CSCOPT) -cord/cordtest.o: cord/tests/cordtest.c +cord/tests/cordtest.o: cord/tests/cordtest.c sc cord/tests/cordtest.c $(CSCOPT) diff -Nru libgc-8.0.4/allchblk.c libgc-8.0.6/allchblk.c --- libgc-8.0.4/allchblk.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/allchblk.c 2021-11-25 21:36:27.000000000 +0000 @@ -326,8 +326,8 @@ GC_remove_from_fl_at(hhdr, GC_hblk_fl_from_blocks(divHBLKSZ(hhdr->hb_sz))); } -/* Return a pointer to the free block ending just before h, if any. */ -STATIC struct hblk * GC_free_block_ending_at(struct hblk *h) +/* Return a pointer to the block ending just before h, if any. */ +static struct hblk * get_block_ending_at(struct hblk *h) { struct hblk * p = h - 1; hdr * phdr; @@ -338,16 +338,27 @@ phdr = HDR(p); } if (0 != phdr) { - if(HBLK_IS_FREE(phdr)) { + return p; + } + p = GC_prev_block(h - 1); + if (p) { + phdr = HDR(p); + if ((ptr_t)p + phdr -> hb_sz == (ptr_t)h) { return p; - } else { - return 0; } } - p = GC_prev_block(h - 1); - if (0 != p) { - phdr = HDR(p); - if (HBLK_IS_FREE(phdr) && (ptr_t)p + phdr -> hb_sz == (ptr_t)h) { + return NULL; +} + +/* Return a pointer to the free block ending just before h, if any. */ +STATIC struct hblk * GC_free_block_ending_at(struct hblk *h) +{ + struct hblk * p = get_block_ending_at(h); + + if (p /* != NULL */) { /* CPPCHECK */ + hdr * phdr = HDR(p); + + if (HBLK_IS_FREE(phdr)) { return p; } } @@ -395,6 +406,60 @@ GC_INNER int GC_unmap_threshold = MUNMAP_THRESHOLD; +#ifdef COUNT_UNMAPPED_REGIONS + /* GC_unmap_old will avoid creating more than this many unmapped regions, */ + /* but an unmapped region may be split again so exceeding the limit. */ + + /* Return the change in number of unmapped regions if the block h swaps */ + /* from its current state of mapped/unmapped to the opposite state. */ + static int calc_num_unmapped_regions_delta(struct hblk *h, hdr *hhdr) + { + struct hblk * prev = get_block_ending_at(h); + struct hblk * next; + GC_bool prev_unmapped = FALSE; + GC_bool next_unmapped = FALSE; + + next = GC_next_block((struct hblk *)((ptr_t)h + hhdr->hb_sz), TRUE); + /* Ensure next is contiguous with h. */ + if ((ptr_t)next != GC_unmap_end((ptr_t)h, (size_t)hhdr->hb_sz)) { + next = NULL; + } + if (prev != NULL) { + hdr * prevhdr = HDR(prev); + prev_unmapped = !IS_MAPPED(prevhdr); + } + if (next != NULL) { + hdr * nexthdr = HDR(next); + next_unmapped = !IS_MAPPED(nexthdr); + } + + if (prev_unmapped && next_unmapped) { + /* If h unmapped, merge two unmapped regions into one. */ + /* If h remapped, split one unmapped region into two. */ + return IS_MAPPED(hhdr) ? -1 : 1; + } + if (!prev_unmapped && !next_unmapped) { + /* If h unmapped, create an isolated unmapped region. */ + /* If h remapped, remove it. */ + return IS_MAPPED(hhdr) ? 1 : -1; + } + /* If h unmapped, merge it with previous or next unmapped region. */ + /* If h remapped, reduce either previous or next unmapped region. */ + /* In either way, no change to the number of unmapped regions. */ + return 0; + } +#endif /* COUNT_UNMAPPED_REGIONS */ + +/* Update GC_num_unmapped_regions assuming the block h changes */ +/* from its current state of mapped/unmapped to the opposite state. */ +GC_INLINE void GC_adjust_num_unmapped(struct hblk *h GC_ATTR_UNUSED, + hdr *hhdr GC_ATTR_UNUSED) +{ +# ifdef COUNT_UNMAPPED_REGIONS + GC_num_unmapped_regions += calc_num_unmapped_regions_delta(h, hhdr); +# endif +} + /* Unmap blocks that haven't been recently touched. This is the only way */ /* way blocks are ever unmapped. */ GC_INNER void GC_unmap_old(void) @@ -403,6 +468,12 @@ if (GC_unmap_threshold == 0) return; /* unmapping disabled */ +# ifdef COUNT_UNMAPPED_REGIONS + /* Skip unmapping if we have already exceeded the soft limit. */ + /* This forgoes any opportunities to merge unmapped regions though. */ + if (GC_num_unmapped_regions >= GC_UNMAPPED_REGIONS_SOFT_LIMIT) + return; +# endif for (i = 0; i <= N_HBLK_FLS; ++i) { struct hblk * h; @@ -416,6 +487,19 @@ /* truncated counter value wrapping is handled correctly). */ if ((unsigned short)(GC_gc_no - hhdr->hb_last_reclaimed) > (unsigned short)GC_unmap_threshold) { +# ifdef COUNT_UNMAPPED_REGIONS + /* Continue with unmapping the block only if it will not */ + /* create too many unmapped regions, or if unmapping */ + /* reduces the number of regions. */ + int delta = calc_num_unmapped_regions_delta(h, hhdr); + signed_word regions = GC_num_unmapped_regions + delta; + + if (delta >= 0 && regions >= GC_UNMAPPED_REGIONS_SOFT_LIMIT) { + GC_COND_LOG_PRINTF("Unmapped regions limit reached!\n"); + return; + } + GC_num_unmapped_regions = regions; +# endif GC_unmap((ptr_t)h, (size_t)hhdr->hb_sz); hhdr -> hb_flags |= WAS_UNMAPPED; } @@ -472,17 +556,21 @@ if (IS_MAPPED(hhdr) && !IS_MAPPED(nexthdr)) { /* make both consistent, so that we can merge */ if (size > nextsize) { + GC_adjust_num_unmapped(next, nexthdr); GC_remap((ptr_t)next, nextsize); } else { + GC_adjust_num_unmapped(h, hhdr); GC_unmap((ptr_t)h, size); GC_unmap_gap((ptr_t)h, size, (ptr_t)next, nextsize); hhdr -> hb_flags |= WAS_UNMAPPED; } } else if (IS_MAPPED(nexthdr) && !IS_MAPPED(hhdr)) { if (size > nextsize) { + GC_adjust_num_unmapped(next, nexthdr); GC_unmap((ptr_t)next, nextsize); GC_unmap_gap((ptr_t)h, size, (ptr_t)next, nextsize); } else { + GC_adjust_num_unmapped(h, hhdr); GC_remap((ptr_t)h, size); hhdr -> hb_flags &= ~WAS_UNMAPPED; hhdr -> hb_last_reclaimed = nexthdr -> hb_last_reclaimed; @@ -731,6 +819,7 @@ /* Make sure it's mapped before we mangle it. */ # ifdef USE_MUNMAP if (!IS_MAPPED(hhdr)) { + GC_adjust_num_unmapped(hbp, hhdr); GC_remap((ptr_t)hbp, (size_t)hhdr->hb_sz); hhdr -> hb_flags &= ~WAS_UNMAPPED; } @@ -805,6 +894,7 @@ if( size_avail >= size_needed ) { # ifdef USE_MUNMAP if (!IS_MAPPED(hhdr)) { + GC_adjust_num_unmapped(hbp, hhdr); GC_remap((ptr_t)hbp, (size_t)hhdr->hb_sz); hhdr -> hb_flags &= ~WAS_UNMAPPED; /* Note: This may leave adjacent, mapped free blocks. */ diff -Nru libgc-8.0.4/alloc.c libgc-8.0.6/alloc.c --- libgc-8.0.4/alloc.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/alloc.c 2021-11-25 21:36:27.000000000 +0000 @@ -3,7 +3,7 @@ * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved. * Copyright (c) 1998 by Silicon Graphics. All rights reserved. * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P. - * Copyright (c) 2008-2018 Ivan Maidanski + * Copyright (c) 2008-2019 Ivan Maidanski * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -124,7 +124,7 @@ "Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. ", "Copyright (c) 1996-1998 by Silicon Graphics. All rights reserved. ", "Copyright (c) 1999-2009 by Hewlett-Packard Company. All rights reserved. ", -"Copyright (c) 2008-2018 Ivan Maidanski ", +"Copyright (c) 2008-2019 Ivan Maidanski ", "THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY", " EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.", "See source code for details." }; @@ -1261,7 +1261,7 @@ GC_heapsize += bytes; /* Normally the caller calculates a new GC_collect_at_heapsize, - * but this is also called directly from alloc_mark_stack, so + * but this is also called directly from GC_scratch_recycle_inner, so * adjust here. It will be recalculated when called from * GC_expand_hp_inner. */ diff -Nru libgc-8.0.4/backgraph.c libgc-8.0.6/backgraph.c --- libgc-8.0.4/backgraph.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/backgraph.c 2021-11-25 21:36:27.000000000 +0000 @@ -240,7 +240,7 @@ if (((word)pred & FLAG_MANY) != 0) { n_edges = e -> n_edges; - } else if (pred != NULL && ((word)pred & 1) == 0) { + } else if (((word)pred & 1) == 0) { /* A misinterpreted freelist link. */ n_edges = 1; local = -1; diff -Nru libgc-8.0.4/bdw-gc.pc.in libgc-8.0.6/bdw-gc.pc.in --- libgc-8.0.4/bdw-gc.pc.in 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/bdw-gc.pc.in 2021-11-25 21:36:27.000000000 +0000 @@ -6,5 +6,5 @@ Name: Boehm-Demers-Weiser Conservative Garbage Collector Description: A garbage collector for C and C++ Version: @PACKAGE_VERSION@ -Libs: -L${libdir} @ATOMIC_OPS_LIBS@ -lgc +Libs: -L${libdir} @ATOMIC_OPS_LIBS@ -lgc @THREADDLLIBS@ Cflags: -I${includedir} diff -Nru libgc-8.0.4/configure libgc-8.0.6/configure --- libgc-8.0.4/configure 2019-03-02 08:55:46.000000000 +0000 +++ libgc-8.0.6/configure 2021-11-25 21:36:27.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for gc 8.0.4. +# Generated by GNU Autoconf 2.69 for gc 8.0.6. # # Report bugs to . # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='gc' PACKAGE_TARNAME='gc' -PACKAGE_VERSION='8.0.4' -PACKAGE_STRING='gc 8.0.4' +PACKAGE_VERSION='8.0.6' +PACKAGE_STRING='gc 8.0.6' PACKAGE_BUGREPORT='https://github.com/ivmai/bdwgc/issues' PACKAGE_URL='' @@ -805,6 +805,7 @@ docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -921,6 +922,7 @@ sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1173,6 +1175,15 @@ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1310,7 +1321,7 @@ for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1423,7 +1434,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures gc 8.0.4 to adapt to many kinds of systems. +\`configure' configures gc 8.0.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1463,6 +1474,7 @@ --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1494,7 +1506,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of gc 8.0.4:";; + short | recursive ) echo "Configuration of gc 8.0.6:";; esac cat <<\_ACEOF @@ -1663,7 +1675,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -gc configure 8.0.4 +gc configure 8.0.6 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2153,7 +2165,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by gc $as_me 8.0.4, which was +It was created by gc $as_me 8.0.6, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3166,7 +3178,7 @@ # Define the identity of the package. PACKAGE='gc' - VERSION='8.0.4' + VERSION='8.0.6' cat >>confdefs.h <<_ACEOF @@ -16175,9 +16187,9 @@ gc_cflags="${gc_cflags} -fexceptions" else case "$host" in - hppa*-*-hpux* ) + hppa*-*-hpux* ) if test :$GCC: != :"yes": ; then - gc_cflags="${gc_flags} +ESdbgasm" + gc_cflags="${gc_cflags} +ESdbgasm" fi # :TODO: actually we should check using Autoconf if # the compiler supports this option. @@ -16362,7 +16374,7 @@ case "$host" in *-*-aix* | *-*-android* | *-*-cygwin* | *-*-darwin* | *-*-dragonfly* | \ *-*-freebsd* | *-*-haiku* | *-*-hpux11* | *-*-irix* | \ - *-*-kfreebsd*-gnu | *-*-gnu* | *-*-*linux* | *-*-nacl* | \ + *-*-kfreebsd*-gnu | *-*-gnu* | *-*-*linux* | *-*-msys* | *-*-nacl* | \ *-*-netbsd* | *-*-openbsd* | *-*-osf* | *-*-solaris*) $as_echo "#define GC_THREADS 1" >>confdefs.h @@ -16449,7 +16461,7 @@ *-*-solaris*) THREADDLLIBS="-lpthread -lrt" ;; - *-*-cygwin*) + *-*-cygwin* | *-*-msys*) # Cygwin doesn't have a real libpthread, so Libtool can't link # against it. THREADDLLIBS="" @@ -16791,8 +16803,8 @@ mips-sgi-irix6*) ;; # We never want libdl on darwin. It is a fake libdl that just ends up making # dyld calls anyway. The same applies to Cygwin. - *-*-darwin*) ;; - *-*-cygwin*) ;; + *-*-cygwin* | *-*-darwin* | *-*-msys*) + ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } @@ -16915,7 +16927,7 @@ if test "$GCC" = yes; then if test "${enable_cplusplus}" = yes; then case "$host" in - *-*-cygwin* | *-*-mingw*) + *-*-cygwin* | *-*-mingw* | *-*-msys*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libsupc++ required" >&5 $as_echo_n "checking whether libsupc++ required... " >&6; } SUPC="`$CXX -print-file-name=libsupc++.a 2>/dev/null`" @@ -16982,8 +16994,7 @@ $as_echo "$enable_shared" >&6; } # Compile with GC_DLL defined unless building static libraries. -if test "${enable_shared}" = yes; then - if test "${enable_static}" = no; then +if test "${enable_shared}" = yes -a "${enable_static}" = no; then $as_echo "#define GC_DLL 1" >>confdefs.h if test "$GCC" = yes; then @@ -17018,7 +17029,16 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fvisibility_hidden" >&5 $as_echo "$ac_cv_fvisibility_hidden" >&6; } fi - fi +else + + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-msys*) + # Use inline version of GC new and delete operators in test_cpp + # otherwise the system ones might be used instead because of arbitrary + # ordering of object files when linking. + CXXFLAGS="$CXXFLAGS -DGC_NOT_DLL" + ;; + esac fi # Configuration of machine-dependent code @@ -17090,8 +17110,8 @@ fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Solaris gcc optimization fix is necessary" >&5 -$as_echo_n "checking whether Solaris gcc optimization fix is necessary... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether AIX gcc optimization fix is necessary" >&5 +$as_echo_n "checking whether AIX gcc optimization fix is necessary... " >&6; } case "$host" in *aix*) if test "$GCC" = yes; then @@ -18523,7 +18543,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by gc $as_me 8.0.4, which was +This file was extended by gc $as_me 8.0.6, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -18589,7 +18609,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -gc config.status 8.0.4 +gc config.status 8.0.6 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru libgc-8.0.4/configure.ac libgc-8.0.6/configure.ac --- libgc-8.0.4/configure.ac 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/configure.ac 2021-11-25 21:36:27.000000000 +0000 @@ -1,6 +1,6 @@ # Copyright (c) 1999-2001 by Red Hat, Inc. All rights reserved. # Copyright (c) 2005-2009 Hewlett-Packard Development Company, L.P. -# Copyright (c) 2009-2018 Ivan Maidanski +# Copyright (c) 2009-2019 Ivan Maidanski # # THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED # OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -14,7 +14,7 @@ dnl Process this file with autoconf to produce configure. dnl Initialization. -AC_INIT(gc,8.0.4,https://github.com/ivmai/bdwgc/issues) +AC_INIT(gc,8.0.6,https://github.com/ivmai/bdwgc/issues) dnl Version must conform to: [0-9]+[.][0-9]+[.][0-9]+ AC_CONFIG_SRCDIR(gcj_mlc.c) @@ -52,9 +52,9 @@ gc_cflags="${gc_cflags} -fexceptions" else case "$host" in - hppa*-*-hpux* ) + hppa*-*-hpux* ) if test :$GCC: != :"yes": ; then - gc_cflags="${gc_flags} +ESdbgasm" + gc_cflags="${gc_cflags} +ESdbgasm" fi # :TODO: actually we should check using Autoconf if # the compiler supports this option. @@ -200,7 +200,7 @@ case "$host" in *-*-aix* | *-*-android* | *-*-cygwin* | *-*-darwin* | *-*-dragonfly* | \ *-*-freebsd* | *-*-haiku* | *-*-hpux11* | *-*-irix* | \ - *-*-kfreebsd*-gnu | *-*-gnu* | *-*-*linux* | *-*-nacl* | \ + *-*-kfreebsd*-gnu | *-*-gnu* | *-*-*linux* | *-*-msys* | *-*-nacl* | \ *-*-netbsd* | *-*-openbsd* | *-*-osf* | *-*-solaris*) AC_DEFINE(GC_THREADS) AC_DEFINE([_REENTRANT], [1], @@ -241,7 +241,7 @@ *-*-solaris*) THREADDLLIBS="-lpthread -lrt" ;; - *-*-cygwin*) + *-*-cygwin* | *-*-msys*) # Cygwin doesn't have a real libpthread, so Libtool can't link # against it. THREADDLLIBS="" @@ -435,8 +435,8 @@ mips-sgi-irix6*) ;; # We never want libdl on darwin. It is a fake libdl that just ends up making # dyld calls anyway. The same applies to Cygwin. - *-*-darwin*) ;; - *-*-cygwin*) ;; + *-*-cygwin* | *-*-darwin* | *-*-msys*) + ;; *) AC_CHECK_LIB(dl, dlopen, THREADDLLIBS="$THREADDLLIBS -ldl") ;; @@ -497,7 +497,7 @@ if test "$GCC" = yes; then if test "${enable_cplusplus}" = yes; then case "$host" in - *-*-cygwin* | *-*-mingw*) + *-*-cygwin* | *-*-mingw* | *-*-msys*) AC_MSG_CHECKING([whether libsupc++ required]) SUPC="`$CXX -print-file-name=libsupc++.a 2>/dev/null`" if test -n "$SUPC" -a "$SUPC" != "libsupc++.a"; then @@ -532,8 +532,7 @@ AC_MSG_RESULT($enable_shared) # Compile with GC_DLL defined unless building static libraries. -if test "${enable_shared}" = yes; then - if test "${enable_static}" = no; then +if test "${enable_shared}" = yes -a "${enable_static}" = no; then AC_DEFINE(GC_DLL) if test "$GCC" = yes; then # Pass -fvisibility=hidden option if supported @@ -548,7 +547,16 @@ [CFLAGS="-DGC_NO_VISIBILITY $CFLAGS"]) AC_MSG_RESULT($ac_cv_fvisibility_hidden) fi - fi +else + + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-msys*) + # Use inline version of GC new and delete operators in test_cpp + # otherwise the system ones might be used instead because of arbitrary + # ordering of object files when linking. + CXXFLAGS="$CXXFLAGS -DGC_NOT_DLL" + ;; + esac fi # Configuration of machine-dependent code @@ -618,10 +626,9 @@ AC_EXEEXT fi -dnl As of 4.13a2, the collector will not properly work on Solaris when +dnl The collector might not properly work on IBM AIX when dnl built with gcc and -O. So we remove -O in the appropriate case. -dnl Not needed anymore on Solaris. -AC_MSG_CHECKING(whether Solaris gcc optimization fix is necessary) +AC_MSG_CHECKING(whether AIX gcc optimization fix is necessary) case "$host" in *aix*) if test "$GCC" = yes; then diff -Nru libgc-8.0.4/cord/cordprnt.c libgc-8.0.6/cord/cordprnt.c --- libgc-8.0.4/cord/cordprnt.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/cord/cordprnt.c 2021-11-25 21:36:27.000000000 +0000 @@ -52,7 +52,7 @@ static int ec_len(CORD_ec x) { - return(CORD_len(x[0].ec_cord) + (x[0].ec_bufptr - x[0].ec_buf)); + return (int)(CORD_len(x[0].ec_cord) + (x[0].ec_bufptr - x[0].ec_buf)); } /* Possible nonumeric precision values. */ @@ -232,7 +232,7 @@ } else { short * pos_ptr; pos_ptr = va_arg(args, short *); - *pos_ptr = ec_len(result); + *pos_ptr = (short)ec_len(result); } goto done; case 'r': diff -Nru libgc-8.0.4/cord/tests/cordtest.c libgc-8.0.6/cord/tests/cordtest.c --- libgc-8.0.4/cord/tests/cordtest.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/cord/tests/cordtest.c 2021-11-25 21:36:27.000000000 +0000 @@ -40,7 +40,8 @@ int test_fn(char c, void * client_data) { - if (client_data != (void *)13) ABORT("bad client data"); + if (client_data != (void *)(GC_word)13) + ABORT("bad client data"); if (count < 64*1024+1) { if ((count & 1) == 0) { if (c != 'b') ABORT("bad char"); @@ -81,7 +82,8 @@ if (CORD_len(x) != 128*1024+1) ABORT("bad length"); count = 0; - if (CORD_iter5(x, 64*1024-1, test_fn, CORD_NO_FN, (void *)13) == 0) { + if (CORD_iter5(x, 64*1024-1, test_fn, CORD_NO_FN, + (void *)(GC_word)13) == 0) { ABORT("CORD_iter5 failed"); } if (count != 64*1024 + 2) ABORT("CORD_iter5 failed"); @@ -89,7 +91,7 @@ count = 0; CORD_set_pos(p, x, 64*1024-1); while(CORD_pos_valid(p)) { - (void) test_fn(CORD_pos_fetch(p), (void *)13); + (void)test_fn(CORD_pos_fetch(p), (void *)(GC_word)13); CORD_next(p); } if (count != 64*1024 + 2) ABORT("Position based iteration failed"); @@ -113,7 +115,8 @@ if (CORD_len(x) != 128*1024+1) ABORT("bad length"); count = 0; - if (CORD_iter5(x, 64*1024-1, test_fn, CORD_NO_FN, (void *)13) == 0) { + if (CORD_iter5(x, 64*1024-1, test_fn, CORD_NO_FN, + (void *)(GC_word)13) == 0) { ABORT("CORD_iter5 failed"); } if (count != 64*1024 + 2) ABORT("CORD_iter5 failed"); @@ -128,7 +131,7 @@ while(CORD_pos_valid(p)) { char c = CORD_pos_fetch(p); - if ((unsigned char)c != i) + if ((size_t)(unsigned char)c != i) ABORT("Traversal of function node failed"); CORD_next(p); i++; diff -Nru libgc-8.0.4/cord/tests/de_win.c libgc-8.0.6/cord/tests/de_win.c --- libgc-8.0.4/cord/tests/de_win.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/cord/tests/de_win.c 2021-11-25 21:36:27.000000000 +0000 @@ -147,7 +147,7 @@ } /* Return the argument with all non-control-characters replaced by */ -/* blank, and all control characters c replaced by c + 32. */ +/* blank, and all control characters c replaced by c + 64. */ char * control_chars(char * text, size_t len) { char * result = (char *)GC_MALLOC_ATOMIC(len + 1); @@ -156,7 +156,7 @@ if (NULL == result) return NULL; for (i = 0; i < len; i++) { if (iscntrl(((unsigned char *)text)[i])) { - result[i] = text[i] + 0x40; + result[i] = (char)(text[i] + 0x40); } else { result[i] = ' '; } diff -Nru libgc-8.0.4/darwin_stop_world.c libgc-8.0.6/darwin_stop_world.c --- libgc-8.0.4/darwin_stop_world.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/darwin_stop_world.c 2021-11-25 21:36:27.000000000 +0000 @@ -196,10 +196,12 @@ /* else */ { mach_msg_type_number_t thread_state_count = GC_MACH_THREAD_STATE_COUNT; - /* Get the thread state (registers, etc) */ - kern_result = thread_get_state(thread, GC_MACH_THREAD_STATE, - (natural_t *)&state, - &thread_state_count); + /* Get the thread state (registers, etc.) */ + do { + kern_result = thread_get_state(thread, GC_MACH_THREAD_STATE, + (natural_t *)&state, + &thread_state_count); + } while (kern_result == KERN_ABORTED); } # ifdef DEBUG_THREADS GC_log_printf("thread_get_state returns value = %d\n", kern_result); diff -Nru libgc-8.0.4/debian/changelog libgc-8.0.6/debian/changelog --- libgc-8.0.4/debian/changelog 2020-12-06 11:44:00.000000000 +0000 +++ libgc-8.0.6/debian/changelog 2022-03-24 12:12:16.000000000 +0000 @@ -1,3 +1,25 @@ +libgc (1:8.0.6-1.1build1) jammy; urgency=high + + * No change rebuild for ppc64el baseline bump. + + -- Julian Andres Klode Thu, 24 Mar 2022 13:12:16 +0100 + +libgc (1:8.0.6-1.1) unstable; urgency=medium + + * Non-maintainer upload. ((Closes: #999740) + * New upstream version 8.0.6 + * Update to point to salsa + * Update symbols for 8.0.6 + * Drop enable-threads-on-hurd.diff and issue329.diff + + -- Ian Wienand Fri, 26 Nov 2021 09:12:33 +1100 + +libgc (1:8.0.4-3+alpha.1) unreleased; urgency=medium + + * Update symbols on Alpha (fixing FTBFS). + + -- Michael Cree Fri, 26 Mar 2021 08:19:12 +1300 + libgc (1:8.0.4-3) unstable; urgency=medium * Fix cross/native difference: explicitly disable usage of diff -Nru libgc-8.0.4/debian/control libgc-8.0.6/debian/control --- libgc-8.0.4/debian/control 2020-12-06 11:44:00.000000000 +0000 +++ libgc-8.0.6/debian/control 2022-03-24 12:12:16.000000000 +0000 @@ -1,5 +1,6 @@ Source: libgc -Maintainer: Christoph Egger +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Christoph Egger Uploaders: Debian GCC Maintainers Section: libs Priority: optional @@ -9,8 +10,7 @@ pkg-kde-tools Standards-Version: 4.5.1 Homepage: http://www.hboehm.info/gc/ -#Vcs-Git: git://anonscm.debian.org/collab-maint/libgc.git -#Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/libgc.git +Vcs-Git: https://salsa.debian.org/debian/libgc Package: libgc1 Architecture: any diff -Nru libgc-8.0.4/debian/libgc1.symbols libgc-8.0.6/debian/libgc1.symbols --- libgc-8.0.4/debian/libgc1.symbols 2020-10-27 13:07:51.000000000 +0000 +++ libgc-8.0.6/debian/libgc1.symbols 2021-11-25 21:57:11.000000000 +0000 @@ -180,7 +180,7 @@ GC_extend_size_map@Base 1:7.2d GC_fail_count@Base 1:7.2d (arch=!arm64 !nios2 !mips !mips64el !mipsel !riscv64 !s390 !s390x)GC_fault_handler@Base 1:7.2d - (arch=alpha sh4)GC_fault_handler_lock@Base 1:8.0 + (arch=sh4)GC_fault_handler_lock@Base 1:8.0 GC_finalize@Base 1:7.2d GC_finalize_all@Base 1:7.2d GC_finalize_on_demand@Base 1:7.2d @@ -289,7 +289,7 @@ GC_handle_fork@Base 1:7.4.2 GC_has_other_debug_info@Base 1:7.2d GC_has_static_roots@Base 1:7.2d - (arch=amd64 i386 ia64 m68k x32)GC_has_unmapped_memory@Base 1:8.0 + (arch=alpha amd64 i386 ia64 m68k x32)GC_has_unmapped_memory@Base 1:8.0 GC_have_errors@Base 1:7.2d GC_hblk_fl_from_blocks@Base 1:7.2d GC_hblkfreelist@Base 1:7.2d @@ -391,7 +391,7 @@ GC_move_disappearing_link@Base 1:7.4.2 GC_move_disappearing_link_inner@Base 1:7.4.2 GC_move_long_link@Base 1:7.4.2 - (arch=amd64 i386 ia64 m68k x32)GC_mprotect_dirty_init@Base 1:8.0 + (arch=alpha amd64 i386 ia64 m68k x32)GC_mprotect_dirty_init@Base 1:8.0 GC_n_attempts@Base 1:7.2d GC_n_heap_sects@Base 1:7.2d GC_n_kinds@Base 1:7.2d @@ -411,8 +411,8 @@ GC_new_proc@Base 1:7.2d GC_new_proc_inner@Base 1:7.2d GC_new_thread@Base 1:7.2d + GC_next_block@Base 1:8.0.6 GC_next_exclusion@Base 1:7.2d - GC_next_used_block@Base 1:7.2d GC_no_dls@Base 1:7.2d GC_non_gc_bytes@Base 1:7.2d GC_non_gc_bytes_at_gc@Base 1:7.4.2 @@ -677,7 +677,6 @@ GC_unix_get_mem@Base 1:7.2d GC_unix_mmap_get_mem@Base 1:7.6.4 GC_unmap@Base 1:8.0 - GC_unmap_end@Base 1:8.0 GC_unmap_gap@Base 1:8.0 GC_unmap_old@Base 1:8.0 GC_unmap_start@Base 1:8.0 diff -Nru libgc-8.0.4/debian/patches/enable-threads-on-hurd.diff libgc-8.0.6/debian/patches/enable-threads-on-hurd.diff --- libgc-8.0.4/debian/patches/enable-threads-on-hurd.diff 2020-04-05 10:03:18.000000000 +0000 +++ libgc-8.0.6/debian/patches/enable-threads-on-hurd.diff 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -Index: b/include/gc_config_macros.h -=================================================================== ---- a/include/gc_config_macros.h -+++ b/include/gc_config_macros.h -@@ -125,6 +125,10 @@ - # if defined(__rtems__) && (defined(i386) || defined(__i386__)) - # define GC_RTEMS_PTHREADS - # endif -+# if defined(__gnu_hurd__) -+# define GC_GNU_THREADS -+# define GC_PTHREADS -+# endif - #endif /* GC_THREADS */ - - #undef GC_PTHREADS diff -Nru libgc-8.0.4/debian/patches/issue329.diff libgc-8.0.6/debian/patches/issue329.diff --- libgc-8.0.4/debian/patches/issue329.diff 2020-12-06 11:44:00.000000000 +0000 +++ libgc-8.0.6/debian/patches/issue329.diff 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ ---- a/include/private/gc_priv.h -+++ b/include/private/gc_priv.h -@@ -166,6 +166,14 @@ typedef int GC_bool; - # define REGISTER register - #endif - -+#if defined(M68K) && defined(__GNUC__) -+ /* By default, __alignof__(word) is 2 on m68k. Use this attribute to */ -+ /* have proper word alignment (i.e. 4-byte on a 32-bit arch). */ -+# define GC_ATTR_WORD_ALIGNED __attribute__((__aligned__(sizeof(word)))) -+#else -+# define GC_ATTR_WORD_ALIGNED /* empty */ -+#endif -+ - #ifndef HEADERS_H - # include "gc_hdrs.h" - #endif ---- a/include/private/pthread_support.h -+++ b/include/private/pthread_support.h -@@ -132,7 +132,7 @@ typedef struct GC_Thread_Rep { - /* and detach. */ - - # ifdef THREAD_LOCAL_ALLOC -- struct thread_local_freelists tlfs; -+ struct thread_local_freelists tlfs GC_ATTR_WORD_ALIGNED; - # endif - } * GC_thread; - diff -Nru libgc-8.0.4/debian/patches/series libgc-8.0.6/debian/patches/series --- libgc-8.0.4/debian/patches/series 2020-12-06 11:44:00.000000000 +0000 +++ libgc-8.0.6/debian/patches/series 2021-11-25 21:54:55.000000000 +0000 @@ -1,2 +1 @@ -enable-threads-on-hurd.diff -issue329.diff +# intentionally left blank diff -Nru libgc-8.0.4/doc/README.OS2 libgc-8.0.6/doc/README.OS2 --- libgc-8.0.4/doc/README.OS2 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/README.OS2 2021-11-25 21:36:27.000000000 +0000 @@ -2,5 +2,5 @@ not been ported. The cord test program has. The supplied OS2_MAKEFILE assumes the IBM C Set/2 environment, but the code shouldn't. -Since we haven't figured out hoe to do perform partial links or to build static +Since we haven't figured out how to do partial linking or to build static libraries, clients currently need to link against a long list of executables. diff -Nru libgc-8.0.4/doc/README.amiga libgc-8.0.6/doc/README.amiga --- libgc-8.0.4/doc/README.amiga 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/README.amiga 2021-11-25 21:36:27.000000000 +0000 @@ -9,15 +9,15 @@ WHATS NEW: 1. - Made a pretty big effort in preventing GCs allocating-functions from returning - chip-mem. + Made a pretty big effort in preventing GC allocating-functions from + returning chip-mem. The lower part of the new file AmigaOS.c does this in various ways, mainly by wrapping GC_malloc, GC_malloc_atomic, GC_malloc_uncollectable, GC_malloc_atomic_uncollectable, GC_malloc_ignore_off_page and GC_malloc_atomic_ignore_off_page. GC_realloc is also wrapped, but doesn't do the same effort in preventing to return chip-mem. - Other allocating-functions (f.ex. GC_*_typed_) can probably be + Other allocating-functions (e.g., GC_*_typed) can probably be used without any problems, but beware that the warn hook will not be called. In case of problems, don't define GC_AMIGA_FASTALLOC. @@ -81,7 +81,7 @@ GC_AMIGA_FASTALLOC by letting the function go thru the new GC_amiga_allocwrapper_do function-pointer (see gc.h). Means that sending function-pointers, such as GC_malloc, GC_malloc_atomic, etc., - for later to be called like f.ex this, (*GC_malloc_function_pointer)(size), + for later to be called, e.g., like this, (*GC_malloc_function_pointer)(size), will not wrap the function. This is normally not a big problem, unless all allocation function is called like this, which will cause the atexit un-allocating function never to be called. Then you either @@ -91,7 +91,7 @@ There are probably better ways this problem could be handled, unfortunately, I didn't find any without rewriting or replacing a lot of the GC-code, which I really didn't want to. (Making new GC_malloc_* functions, and just - define f.ex GC_malloc as GC_amiga_malloc should work too). + defining, e.g., GC_malloc as GC_amiga_malloc should work too). New Amiga-specific function: @@ -99,16 +99,16 @@ void GC_amiga_set_toany(void (*func)(void)); 'func' is a function that will be called right before gc has to change - allocation-method from MEMF_FAST to MEMF_ANY. Ie. when it is likely + allocation-method from MEMF_FAST to MEMF_ANY. I.e., when it is likely it will return chip-mem. 2. A few small compiler-specific additions to make it compile with SAS/C again. -3. Updated and rewritten the smakefile, so that it works again and that +3. Updated and rewritten the SMakefile.amiga, so that it works again and that the "unnecessary" 'SCOPTIONS' files could be removed. Also included the cord-smakefile stuff in the main smakefile, so that the cord smakefile - could be removed too. By writing smake -f Smakefile.smk, both gc.lib and + could be removed too. By typing "smake -f SMakefile.amiga", both gc.lib and cord.lib will be made. @@ -246,10 +246,10 @@ In keeping with the porting philosophy outlined above, this port will not behave well with Amiga specific code. Especially not inter- -process comms via messages, and setting up public structures like +process communications via messages, and setting up public structures like Intuition objects or anything else in the system lists. For the time being the use of this library is limited to single threaded -ANSI/POSIX compliant or near-compliant code. (ie. Stick to stdio +ANSI/POSIX compliant or near-compliant code. (i.e., stick to stdio for now). Given this limitation there is currently no mechanism for allocating "CHIP" or "PUBLIC" memory under the garbage collector. I'll add this after giving it considerable thought. The major diff -Nru libgc-8.0.4/doc/README.cmake libgc-8.0.6/doc/README.cmake --- libgc-8.0.4/doc/README.cmake 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/README.cmake 2021-11-25 21:36:27.000000000 +0000 @@ -47,4 +47,4 @@ ----- The main input to cmake are the CMakeLists.txt files in each directory. For -help, goto cmake.org. +help, go to cmake.org. diff -Nru libgc-8.0.4/doc/README.darwin libgc-8.0.6/doc/README.darwin --- libgc-8.0.4/doc/README.darwin 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/README.darwin 2021-11-25 21:36:27.000000000 +0000 @@ -36,11 +36,6 @@ garbage collector, to create an initialization routine for each of them that calls GC_init(). Better safe than sorry. -The incremental collector is still a bit flaky on darwin. It seems to -work reliably with workarounds for a few possible bugs in place however -these workaround may not work correctly in all cases. There may also -be additional problems that I have not found. - Thread-local GC allocation will not work with threads that are not created using the GC-provided override of pthread_create(). Threads created without the GC-provided pthread_create() do not have the @@ -76,69 +71,11 @@ layout or stack pointer conventions laid out in the PPC Mach-O ABI, then this will likely crash the garbage collector. -The original incremental collector support unfortunately no longer works -on recent Darwin versions. It also relied on some undocumented kernel -structures. Mach, however, does have a very clean interface to exception -handing. The current implementation uses Mach's exception handling. +Mach has a very clean interface to exception handing. So, the current +implementation of the incremental collection uses Mach's exception handling. Much thanks goes to Andrew Stone, Dietmar Planitzer, Andrew Begel, Jeff Sturm, and Jesse Rosenstock for all their work on the Darwin/OS X port. -Brian Alliet - -== gc_cpp.h usage == - -Replacement of operator new and delete is apparently not supported with -dynamic libraries. This means that applications using gc_cpp.h -(including the built-in test) will probably not work correctly with -the collector in a dynamic library, unless special care is taken. - -See -http://article.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/1421 -for some details. - -- Hans Boehm (based on information from Andrew Begel) - - -== Older Information (Most of this no longer applies to the current code) == - -While the GC should work on MacOS X Server, MacOS X and Darwin, I only tested -it on MacOS X Server. -I've added a PPC assembly version of GC_push_regs(), thus the setjmp() hack is -no longer necessary. Incremental collection is supported via mprotect/signal. -The current solution isn't really optimal because the signal handler must decode -the faulting PPC machine instruction in order to find the correct heap address. -Further, it must poke around in the register state which the kernel saved away -in some obscure register state structure before it calls the signal handler - -needless to say the layout of this structure is no where documented. -Threads and dynamic libraries are not yet supported (adding dynamic library -support via the low-level dyld API shouldn't be that hard). - -The original MacOS X port was brought to you by Andrew Stone. - - -June, 1 2000 - -Dietmar Planitzer - -Note from Andrew Begel: - -One more fix to enable gc.a to link successfully into a shared library for -MacOS X. You have to add -fno-common to the CFLAGS in the Makefile. MacOSX -disallows common symbols in anything that eventually finds its way into a -shared library. (I don't completely understand why, but -fno-common seems to -work and doesn't mess up the garbage collector's functionality). - -Feb 26, 2003 - -Jeff Sturm and Jesse Rosenstock provided a patch that adds thread support. -GC_THREADS should be defined in the build and in clients. Real -dynamic library support is still missing, i.e. dynamic library data segments -are still not scanned. Code that stores pointers to the garbage collected -heap in statically allocated variables should not reside in a dynamic -library. This still doesn't appear to be 100% reliable. - -Mar 10, 2003 -Brian Alliet contributed dynamic library support for MacOSX. It could also -use more testing. diff -Nru libgc-8.0.4/doc/README.ews4800 libgc-8.0.6/doc/README.ews4800 --- libgc-8.0.4/doc/README.ews4800 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/README.ews4800 2021-11-25 21:36:27.000000000 +0000 @@ -24,7 +24,7 @@ *** Caution: The following information is empirical. *** 32-bit: - ELF file has an unique format. (See a.out(4) and end(3C).) + ELF file has a unique format. (See a.out(4) and end(3C).) &_start : text segment diff -Nru libgc-8.0.4/doc/README.macros libgc-8.0.6/doc/README.macros --- libgc-8.0.4/doc/README.macros 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/README.macros 2021-11-25 21:36:27.000000000 +0000 @@ -22,7 +22,7 @@ Many of the tested configuration macros are at least somewhat defined in either include/private/gcconfig.h or in Makefile.direct. Here is an attempt at documenting these macros: (Thanks to Walter Bright for suggesting -this. This is a work in progress) +this.) MACRO EXPLANATION ----- ----------- @@ -57,6 +57,10 @@ operator new[] and delete[] are separately overloadable. Used in gc_cpp.h. +GC_NO_INLINE_STD_NEW Tested by gc_cpp.cc and gc_cpp.h. MS Windows only. + Define the system-wide new and delete operators in gccpp.dll + instead of providing an inline version of the operators. + _DLL Tested by gc_config_macros.h. Defined by Visual C++ if runtime dynamic libraries are in use. Used (only if none of GC_DLL, GC_NOT_DLL, __GNUC__ are defined) to test whether diff -Nru libgc-8.0.4/doc/README.solaris2 libgc-8.0.6/doc/README.solaris2 --- libgc-8.0.4/doc/README.solaris2 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/README.solaris2 2021-11-25 21:36:27.000000000 +0000 @@ -61,7 +61,7 @@ I encountered "symbol : offset .... is non-aligned" errors. These appear to be traceable to the use of the GNU assembler with the Sun linker. The former appears to generate a relocation not understood by the latter. -The fix appears to be to use a consistent tool chain. (As a non-Solaris-expert +The fix appears to be to use a consistent toolchain. (As a non-Solaris-expert my solution involved hacking the libtool script, but I'm sure you can do something less ugly.) diff -Nru libgc-8.0.4/doc/README.win32 libgc-8.0.6/doc/README.win32 --- libgc-8.0.4/doc/README.win32 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/README.win32 2021-11-25 21:36:27.000000000 +0000 @@ -114,7 +114,7 @@ For unknown reason compiling under Windows 3.11 for NT (one attempt has been made) leads to broken executables. -Incremental collection is not supported. +Incremental collection is supported (except for MSDOS and OS/2). cord is not ported. diff -Nru libgc-8.0.4/doc/finalization.md libgc-8.0.6/doc/finalization.md --- libgc-8.0.4/doc/finalization.md 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/finalization.md 2021-11-25 21:36:27.000000000 +0000 @@ -51,7 +51,7 @@ actions, which are then explicitly run during an explicit call by the user's program. -# Topologically Ordered Finalization +## Topologically ordered finalization Our _conservative garbage collector_ supports a form of finalization (with `GC_register_finalizer`) in which objects are finalized in topological order. @@ -67,7 +67,7 @@ Cycles involving one or more finalizable objects are never finalized. -# Why topological ordering? +## Why topological ordering? It is important to keep in mind that the choice of finalization ordering matters only in relatively rare cases. In spite of the fact that it has @@ -123,7 +123,7 @@ reachable from another finalizer via a pointer chain is presumed to be accessible by the finalizer, and thus should not be finalized. -# Programming with topological finalization +## Programming with topological finalization Experience with Cedar has shown that cycles or long chains of finalizable objects are typically not a problem. Finalizable objects are typically rare. @@ -141,7 +141,7 @@ references are still left at process exit, they can be explicitly deallocated then. -# Getting around topological finalization ordering +## Getting around topological finalization ordering There are certain situations in which cycles between finalizable objects are genuinely unavoidable. Most notably, C++ compilers introduce self-cycles diff -Nru libgc-8.0.4/doc/gcdescr.md libgc-8.0.6/doc/gcdescr.md --- libgc-8.0.4/doc/gcdescr.md 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/gcdescr.md 2021-11-25 21:36:27.000000000 +0000 @@ -36,7 +36,7 @@ to be reachable from variables are again scanned similarly. 3. _Sweep phase_ Scans the heap for inaccessible, and hence unmarked, objects, and returns them to an appropriate free list for reuse. This is not - really a separate phase; even in non incremental mode this is operation + really a separate phase; even in non-incremental mode this operation is usually performed on demand during an allocation that discovers an empty free list. Thus the sweep phase is very unlikely to touch a page that would not have been touched shortly thereafter anyway. @@ -132,7 +132,7 @@ * Programs with a large root set size and little live heap memory will expand the heap to amortize the cost of scanning the roots. - * GC v5 actually collect more frequently in non-incremental mode. The large + * GC v5 actually collects more frequently in non-incremental mode. The large block allocator usually refuses to split large heap blocks once the garbage collection threshold is reached. This often has the effect of collecting well before the heap fills up, thus reducing fragmentation and working set @@ -203,18 +203,19 @@ objects, roots, and then mark everything reachable from them. `scan_ptr` is advanced through the heap until all uncollectible objects are pushed, and objects reachable from them are marked. At that point, the next call - to `GC_mark_some` calls `GC_push_roots` to push the roots. It the advances - the mark state to + to `GC_mark_some` calls `GC_push_roots` to push the roots. It, then, + advances the mark state to 3. `MS_ROOTS_PUSHED` asserting that once the mark stack is empty, all reachable objects are marked. Once in this state, we work only on emptying the mark stack. Once this is completed, the state changes to - 4. `MS_NONE` indicating that reachable objects are marked. The core mark - routine `GC_mark_from`, is called repeatedly by several of the sub-phases - when the mark stack starts to fill up. It is also called repeatedly - in `MS_ROOTS_PUSHED` state to empty the mark stack. The routine is designed - to only perform a limited amount of marking at each call, so that it can - also be used by the incremental collector. It is fairly carefully tuned, - since it usually consumes a large majority of the garbage collection time. + 4. `MS_NONE` indicating that reachable objects are marked. + +The core mark routine `GC_mark_from`, is called repeatedly by several of the +sub-phases when the mark stack starts to fill up. It is also called repeatedly +in `MS_ROOTS_PUSHED` state to empty the mark stack. The routine is designed +to only perform a limited amount of marking at each call, so that it can +also be used by the incremental collector. It is fairly carefully tuned, +since it usually consumes a large majority of the garbage collection time. The fact that it performs only a small amount of work per call also allows it to be used as the core routine of the parallel marker. In that case it is @@ -255,7 +256,7 @@ the page is not part of the garbage collected heap, a small integer _n_, indicating that the page is part of large object, starting at least _n_ pages back, or a pointer to a descriptor for the page. In the first case, - the candidate pointer `i` not a true pointer and can be safely ignored. + the candidate pointer is not a true pointer and can be safely ignored. In the last two cases, we can obtain a descriptor for the page containing the beginning of the object. * The starting address of the referenced object is computed. The page @@ -506,7 +507,7 @@ linked using the first word in the object. In most cases this means they require considerably less time. -Local free lists are treated buy most of the rest of the collector as though +Local free lists are treated by most of the rest of the collector as though they were in-use reachable data. This requires some care, since pointer-free objects are not normally traced, and hence a special tracing procedure is required to mark all objects on pointer-free and gcj local free lists. diff -Nru libgc-8.0.4/doc/gcinterface.md libgc-8.0.6/doc/gcinterface.md --- libgc-8.0.4/doc/gcinterface.md 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/gcinterface.md 2021-11-25 21:36:27.000000000 +0000 @@ -1,7 +1,7 @@ # C/C++ Interface On many platforms, a single-threaded garbage collector library can be built -to act as a plug-in `malloc` replacement. (Build with +to act as a plug-in `malloc` replacement. (Build it with `-DREDIRECT_MALLOC=GC_malloc -DIGNORE_FREE`.) This is often the best way to deal with third-party libraries which leak or prematurely free objects. `-DREDIRECT_MALLOC=GC_malloc` is intended primarily as an easy way to adapt @@ -55,15 +55,15 @@ does not appear to be reachable. (Objects allocated in this way are effectively treated as roots by the collector.) -**void * `GC_REALLOC`(void * _old_, size_t _new_size_)** - Allocate a new +**void * `GC_REALLOC`(void * _old_, size_t _new_size_)** - Allocates a new object of the indicated size and copy (a prefix of) the old object into the new object. The old object is reused in place if convenient. If the original object was allocated with `GC_MALLOC_ATOMIC`, the new object is subject to the same constraints. If it was allocated as an uncollectible object, then the new object is uncollectible, and the old object (if different) is deallocated. -**void `GC_FREE`(void * _dead_)** - Explicitly deallocate an object. Typically -not useful for small collectible objects. +**void `GC_FREE`(void * _dead_)** - Explicitly deallocates an object. +Typically not useful for small collectible objects. **void * `GC_MALLOC_IGNORE_OFF_PAGE`(size_t _nbytes_)** and **void * `GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE`(size_t _nbytes_)** - Analogous @@ -84,9 +84,9 @@ as possible. In GC v7.0, it was required if thread-local allocation is enabled in the collector build, and `malloc` is not redirected to `GC_malloc`. -**void `GC_gcollect`(void)** - Explicitly force a garbage collection. +**void `GC_gcollect`(void)** - Explicitly forces a garbage collection. -**void `GC_enable_incremental`(void)** - Cause the garbage collector +**void `GC_enable_incremental`(void)** - Causes the garbage collector to perform a small amount of work every few invocations of `GC_MALLOC` or the like, instead of performing an entire collection at once. This is likely to increase total running time. It will improve response on a platform that @@ -94,13 +94,13 @@ versions, Win32 if the collector was suitably built). On many platforms this interacts poorly with system calls that write to the garbage collected heap. -**void `GC_set_warn_proc`(GC_warn_proc)** - Replace the default procedure +**void `GC_set_warn_proc`(GC_warn_proc)** - Replaces the default procedure used by the collector to print warnings. The collector may otherwise write to `stderr`, most commonly because `GC_malloc` was used in a situation in which `GC_malloc_ignore_off_page` would have been more appropriate. See `gc.h` for details. -**void `GC_REGISTER_FINALIZER`(...)** - Register a function to be called when +**void `GC_REGISTER_FINALIZER`(...)** - Registers a function to be called when an object becomes inaccessible. This is often useful as a backup method for releasing system resources (e.g. closing files) when the object referencing them becomes inaccessible. It is not an acceptable method to perform actions @@ -189,8 +189,8 @@ This defines SGI-style allocators - * `alloc` - * `single_client_alloc` + * `traceable_alloc` + * `single_client_traceable_alloc` * `gc_alloc` * `single_client_gc_alloc` @@ -207,7 +207,7 @@ For details see `gc_cpp.h` file. Linking against `libgccpp` in addition to the `gc` library overrides `::new` -(and friends) to allocate traceable memory but uncollectible memory, making +(and friends) to allocate traceable but uncollectible memory, making it safe to refer to collectible objects from the resulting memory. ## C interface diff -Nru libgc-8.0.4/doc/leak.md libgc-8.0.6/doc/leak.md --- libgc-8.0.4/doc/leak.md 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/leak.md 2021-11-25 21:36:27.000000000 +0000 @@ -4,7 +4,7 @@ primary function of the collector is to report objects that were allocated (typically with `GC_MALLOC`), not deallocated (normally with `GC_FREE`), but are no longer accessible. Since the object is no longer accessible, there -in normally no way to deallocate the object at a later time; thus it can +is normally no way to deallocate the object at a later time; thus it can safely be assumed that the object has been "leaked". This is substantially different from counting leak detectors, which simply @@ -35,13 +35,15 @@ the garbage collector. 3. Arrange to call `GC_gcollect` at appropriate points to check for leaks. (For sufficiently long running programs, this will happen implicitly, but - probably not with sufficient frequency.) The second step can usually - be accomplished with the `-DREDIRECT_MALLOC=GC_malloc` option when the - collector is built, or by defining `malloc`, `calloc`, `realloc` and `free` - to call the corresponding garbage collector functions. But this, by itself, - will not yield very informative diagnostics, since the collector does not - keep track of information about how objects were allocated. The error - reports will include only object addresses. + probably not with sufficient frequency.) + +The second step can usually be accomplished with the +`-DREDIRECT_MALLOC=GC_malloc` option when the collector is built, or by +defining `malloc`, `calloc`, `realloc` and `free` to call the corresponding +garbage collector functions. But this, by itself, will not yield very +informative diagnostics, since the collector does not keep track of +information about how objects were allocated. The error reports will include +only object addresses. For more precise error reports, as much of the program as possible should use the all uppercase variants of these functions, after defining `GC_DEBUG`, and @@ -135,25 +137,28 @@ debug information. This will improve the quality of the leak reports. With this approach, it is no longer necessary to call `GC_` routines explicitly, though that can also improve the quality of the leak reports. - 4. Build the collector and install it in directory _foo_ as follows: - * `configure --prefix=_foo_ --enable-gc-debug --enable-redirect-malloc --disable-threads` - * `make` - * `make install` - - With a very recent collector on Linux, it may sometimes be safe to omit - the `--disable-threads`. But the combination of thread support and - `malloc` replacement is not yet rock solid. - 5. Set environment variables as follows: - * `LD_PRELOAD=`_foo_`/lib/libgc.so` - * `GC_FIND_LEAK` - - You may also want to set `GC_PRINT_STATS` (to confirm that the collector - is running) and/or `GC_LOOP_ON_ABORT` (to facilitate debugging from - another window if something goes wrong). + 4. Build the collector and install it in directory _foo_ as follows (it may + be safe to omit the `--disable-threads` option on Linux, but the combination + of thread support and `malloc` replacement is not yet rock solid): + + - `configure --prefix=_foo_ --enable-gc-debug --enable-redirect-malloc --disable-threads` + - `make` + - `make install` + + 5. Set environment variables as follows (the last two are optional, just to + confirm the collector is running, and to facilitate debugging from another + console window if something goes wrong, respectively): + + - `LD_PRELOAD=_foo_/lib/libgc.so` + - `GC_FIND_LEAK` + - `GC_PRINT_STATS` + - `GC_LOOP_ON_ABORT` + 6. Simply run `a.out` as you normally would. Note that if you run anything else (e.g. your editor) with those environment variables set, it will also be leak tested. This may or may not be useful and/or embarrassing. It can generate mountains of leak reports if the application was not designed - to avoid leaks, e.g. because it's always short-lived. This has not yet - been thoroughly tested on large applications, but it's known to do the right - thing on at least some small ones. + to avoid leaks, e.g. because it's always short-lived. + +This has not yet been thoroughly tested on large applications, but it's known +to do the right thing on at least some small ones. diff -Nru libgc-8.0.4/doc/overview.md libgc-8.0.6/doc/overview.md --- libgc-8.0.4/doc/overview.md 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/overview.md 2021-11-25 21:36:27.000000000 +0000 @@ -130,7 +130,7 @@ compensated for by decreased copying etc. if programs are written and tuned for garbage collection. -# Further Reading: +## Further reading **The beginnings of a frequently asked questions list for this collector are [here](http://www.hboehm.info/gc/faq.html)**. @@ -164,7 +164,7 @@ Boehm, H., and [M. Weiser](http://www.ubiq.com/hypertext/weiser/weiser.html), [Garbage Collection in an Uncooperative Environment](http://www.hboehm.info/spe_gc_paper/), -_Software Practice & Experience_, September 1988, pp. 807-820. +_Software Practice and Experience_, September 1988, pp. 807-820. Boehm, H., A. Demers, and S. Shenker, [Mostly Parallel Garbage Collection](http://www.hboehm.info/gc/papers/pldi91.ps.Z), @@ -239,7 +239,7 @@ Slides for Hans Boehm's [Allocation and GC Myths](http://www.hboehm.info/gc/myths.ps) talk. -# Current users: +## Current users Known current users of some variant of this collector include: @@ -300,7 +300,7 @@ [Asymptote LaTeX-compatible vector graphics language](http://asymptote.sf.net/). -# More information on the BDWGC primary site +## Information provided on the BDWGC site [A simple illustration of how to build and use the collector](simple_example.md). @@ -324,7 +324,7 @@ files of all garbage collector releases. It duplicates [Download](https://github.com/ivmai/bdwgc/wiki/Download) page on GitHub. -# More background information +## More background information [An attempt to establish a bound on space usage of conservative garbage collectors](http://www.hboehm.info/gc/bounds.html). @@ -352,7 +352,7 @@ [Related papers](http://www.hboehm.info/gc/papers/). -# Contacts and new release announcements +## Contacts and new release announcements GitHub and Stack Overflow are the major two places for communication. diff -Nru libgc-8.0.4/doc/porting.md libgc-8.0.6/doc/porting.md --- libgc-8.0.4/doc/porting.md 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/porting.md 2021-11-25 21:36:27.000000000 +0000 @@ -47,6 +47,7 @@ RISC variants.) On GNU-based systems, `cpp -dM empty_source_file.c` seems to generate a set of predefined macros. On some other systems, the "verbose" compiler option may do so, or the manual page may list them. + 2. A section that defines a small number of platform-specific macros, which are then used directly by the collector. For simple ports, this is where most of the effort is required. We describe the macros below. This section @@ -84,7 +85,7 @@ trace all memory between `DATASTART` and `DATAEND` for root pointers. On some platforms, this can be defined to a constant address, though experience has shown that to be risky. Ideally the linker will define - a symbol (e.g. `_data` whose address is the beginning of the data segment. + a symbol (e.g. `_data`) whose address is the beginning of the data segment. Sometimes the value can be computed using the `GC_SysVGetDataStart` function. Not used if either the next macro is defined, or if dynamic loading is supported, and the dynamic loading support defines a function @@ -114,8 +115,8 @@ three macros is defined, client code must explicitly set `GC_stackbottom` to an appropriate value before calling `GC_INIT` or any other `GC_` routine. * `LINUX_STACKBOTTOM` - May be defined instead of `STACKBOTTOM`. If defined, - then the cold end of the stack will be determined Currently we usually read - it from `/proc`. + then the cold end of the stack will be determined, we usually read it from + `/proc`. * `HEURISTIC1` - May be defined instead of `STACKBOTTOM`. `STACK_GRAN` should generally also be redefined. The cold end of the stack is determined by taking an address inside `GC_init`s frame, and rounding it up to the next @@ -154,7 +155,7 @@ For GC v7, if your platform supports `getcontext`, then defining the macro `UNIX_LIKE` for your OS in `gcconfig.h` (if it is not defined there yet) -is likely to solve the problem. otherwise, if you are using gcc, +is likely to solve the problem. Otherwise, if you are using gcc, `_builtin_unwind_init` will be used, and should work fine. If that is not applicable either, the implementation will try to use `setjmp`. This will work if your `setjmp` implementation saves all possibly pointer-valued registers @@ -226,7 +227,7 @@ `gcconfig.h`. * An appropriate versions of the functions `GC_register_dynamic_libraries` should be defined in `dyn_load.c`. This function should invoke - `GC_cond_add_roots(_region_start, region_end_, TRUE)` on each dynamic + `GC_cond_add_roots(region_start, region_end, TRUE)` on each dynamic library data section. Implementations that scan for writable data segments are error prone, @@ -244,7 +245,7 @@ For incremental and generational collection to work, `os_dep.c` must contain a suitable _virtual dirty bit_ implementation, which allows the collector -to track which heap pages (assumed to be a multiple of the collectors block +to track which heap pages (assumed to be a multiple of the collector's block size) have been written during a certain time interval. The collector provides several implementations, which might be adapted. The default (`DEFAULT_VDB`) is a placeholder which treats all pages as having been written. This ensures @@ -253,7 +254,7 @@ ## Stack traces for debug support -If stack traces in objects are need for debug support, `GC_dave_callers` and +If stack traces in objects are needed for debug support, `GC_save_callers` and `GC_print_callers` must be implemented. ## Disclaimer diff -Nru libgc-8.0.4/doc/scale.md libgc-8.0.6/doc/scale.md --- libgc-8.0.4/doc/scale.md 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/scale.md 2021-11-25 21:36:27.000000000 +0000 @@ -39,7 +39,8 @@ is performed by the thread that triggered the collection, together with _N_ - 1 dedicated threads, where _N_ is the number of processors detected by the collector. The dedicated threads are created once at initialization - time. A second effect of this flag is to switch to a more concurrent + time (and optionally recreated in child processes after forking). + A second effect of this flag is to switch to a more concurrent implementation of `GC_malloc_many`, so that free lists can be built, and memory can be cleared, by more than one thread concurrently. * Building the collector with `-DTHREAD_LOCAL_ALLOC` adds support for @@ -142,9 +143,10 @@ enabled in the marker. We used the C version of the benchmark. All measurements are in elapsed seconds on an unloaded machine. -Number of threads| 1 marker thread (secs.) | 2 marker threads (secs.) ----|---|--- -1 client| 10.45| 7.85 | 2 clients| 19.95| 12.3 +Number of client threads| 1 marker thread (secs.)| 2 marker threads (secs.) +---|------|----- + 1| 10.45| 7.85 + 2| 19.95| 12.3 The execution time for the single threaded case is slightly worse than with simple locking. However, even the single-threaded benchmark runs faster than diff -Nru libgc-8.0.4/doc/simple_example.md libgc-8.0.6/doc/simple_example.md --- libgc-8.0.4/doc/simple_example.md 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/doc/simple_example.md 2021-11-25 21:36:27.000000000 +0000 @@ -99,7 +99,8 @@ assert(*p == 0); *p = (int *) GC_REALLOC(q, 2 * sizeof(int)); if (i % 100000 == 0) - printf("Heap size = %d\n", GC_get_heap_size()); + printf("Heap size = %lu bytes\n", + (unsigned long)GC_get_heap_size()); } return 0; } diff -Nru libgc-8.0.4/dyn_load.c libgc-8.0.6/dyn_load.c --- libgc-8.0.4/dyn_load.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/dyn_load.c 2021-11-25 21:36:27.000000000 +0000 @@ -547,11 +547,15 @@ if (load_segs[j].start2 != 0) { WARN("More than one GNU_RELRO segment per load one\n",0); } else { - GC_ASSERT((word)end <= (word)load_segs[j].end); + GC_ASSERT((word)end <= + (((word)load_segs[j].end + GC_page_size - 1) & + ~(GC_page_size - 1))); /* Remove from the existing load segment */ load_segs[j].end2 = load_segs[j].end; load_segs[j].end = start; load_segs[j].start2 = end; + /* Note that start2 may be greater than end2 because of */ + /* p->p_memsz value multiple of page size. */ } break; } @@ -1214,7 +1218,7 @@ #endif /* HPUX */ #ifdef AIX -# pragma alloca +# include # include # include GC_INNER void GC_register_dynamic_libraries(void) diff -Nru libgc-8.0.4/extra/msvc_dbg.c libgc-8.0.6/extra/msvc_dbg.c --- libgc-8.0.4/extra/msvc_dbg.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/extra/msvc_dbg.c 2021-11-25 21:36:27.000000000 +0000 @@ -22,7 +22,7 @@ #if !defined(_M_AMD64) && defined(_MSC_VER) -/* X86_64 is currently missing some meachine-dependent code below. */ +/* X86_64 is currently missing some machine-dependent code below. */ #define GC_BUILD #include "private/msvc_dbg.h" diff -Nru libgc-8.0.4/extra/pcr_interface.c libgc-8.0.6/extra/pcr_interface.c --- libgc-8.0.4/extra/pcr_interface.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/extra/pcr_interface.c 2021-11-25 21:36:27.000000000 +0000 @@ -150,6 +150,8 @@ return PCR_ERes_okay; } +extern GC_bool GC_quiet; + PCR_ERes PCR_GC_Run(void) { diff -Nru libgc-8.0.4/finalize.c libgc-8.0.6/finalize.c --- libgc-8.0.4/finalize.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/finalize.c 2021-11-25 21:36:27.000000000 +0000 @@ -634,6 +634,10 @@ /* Possible finalization_marker procedures. Note that mark stack */ /* overflow is handled by the caller, and is not a disaster. */ +#if defined(_MSC_VER) && defined(I386) + GC_ATTR_NOINLINE + /* Otherwise some optimizer bug is tickled in VC for X86 (v19, at least). */ +#endif STATIC void GC_normal_finalize_mark_proc(ptr_t p) { GC_mark_stack_top = GC_push_obj(p, HDR(p), GC_mark_stack_top, diff -Nru libgc-8.0.4/gc_cpp.cc libgc-8.0.6/gc_cpp.cc --- libgc-8.0.4/gc_cpp.cc 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/gc_cpp.cc 2021-11-25 21:36:27.000000000 +0000 @@ -9,7 +9,7 @@ */ /************************************************************************* -This implementation module for gc_c++.h provides an implementation of +This implementation module for gc_cpp.h provides an implementation of the global operators "new" and "delete" that calls the Boehm allocator. All objects allocated by this implementation will be uncollectible but part of the root set of the collector. @@ -44,7 +44,7 @@ GC_ALLOCATOR_THROW_OR_ABORT(); } -#if !defined(_MSC_VER) && !defined(__DMC__) +#if !(defined(_MSC_VER) || defined(__DMC__)) || defined(GC_NO_INLINE_STD_NEW) # if !defined(GC_NEW_DELETE_THROW_NOT_NEEDED) \ && !defined(GC_NEW_DELETE_NEED_THROW) && GC_GNUC_PREREQ(4, 2) \ @@ -53,7 +53,13 @@ # endif # ifdef GC_NEW_DELETE_NEED_THROW -# define GC_DECL_NEW_THROW throw(std::bad_alloc) +# if __cplusplus >= 201703L || _MSVC_LANG >= 201703L + // The "dynamic exception" syntax had been deprecated in C++11 + // and was removed in C++17. +# define GC_DECL_NEW_THROW noexcept(false) +# else +# define GC_DECL_NEW_THROW throw(std::bad_alloc) +# endif # else # define GC_DECL_NEW_THROW /* empty */ # endif @@ -65,6 +71,23 @@ return obj; } +# ifdef _MSC_VER + // This new operator is used by VC++ in case of Debug builds. + void* operator new(size_t size, int /* nBlockUse */, + const char* szFileName, int nLine) + { +# ifdef GC_DEBUG + void* obj = GC_debug_malloc_uncollectable(size, szFileName, nLine); +# else + void* obj = GC_MALLOC_UNCOLLECTABLE(size); + (void)szFileName; (void)nLine; +# endif + if (0 == obj) + GC_ALLOCATOR_THROW_OR_ABORT(); + return obj; + } +# endif // _MSC_VER + void operator delete(void* obj) GC_NOEXCEPT { GC_FREE(obj); } @@ -77,12 +100,21 @@ return obj; } +# ifdef _MSC_VER + // This new operator is used by VC++ 7+ in Debug builds. + void* operator new[](size_t size, int nBlockUse, + const char* szFileName, int nLine) + { + return operator new(size, nBlockUse, szFileName, nLine); + } +# endif // _MSC_VER + void operator delete[](void* obj) GC_NOEXCEPT { GC_FREE(obj); } # endif // GC_OPERATOR_NEW_ARRAY -# if __cplusplus > 201103L // C++14 +# if __cplusplus >= 201402L || _MSVC_LANG >= 201402L // C++14 void operator delete(void* obj, size_t size) GC_NOEXCEPT { (void)size; // size is ignored GC_FREE(obj); @@ -96,4 +128,4 @@ # endif # endif // C++14 -#endif // !_MSC_VER +#endif // !_MSC_VER && !__DMC__ || GC_NO_INLINE_STD_NEW diff -Nru libgc-8.0.4/headers.c libgc-8.0.6/headers.c --- libgc-8.0.4/headers.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/headers.c 2021-11-25 21:36:27.000000000 +0000 @@ -122,9 +122,10 @@ bytes = ROUNDUP_GRANULE_SIZE(bytes); for (;;) { - scratch_free_ptr += bytes; - if ((word)scratch_free_ptr <= (word)GC_scratch_end_ptr) { + GC_ASSERT((word)GC_scratch_end_ptr >= (word)result); + if (bytes <= (word)GC_scratch_end_ptr - (word)result) { /* Unallocated space of scratch buffer has enough size. */ + scratch_free_ptr = result + bytes; return result; } @@ -132,8 +133,7 @@ bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(bytes); result = (ptr_t)GET_MEM(bytes_to_get); GC_add_to_our_memory(result, bytes_to_get); - /* Undo scratch free area pointer update; get memory directly. */ - scratch_free_ptr -= bytes; + /* No update of scratch free area pointer; get memory directly. */ if (result != NULL) { /* Update end point of last obtained area (needed only */ /* by GC_register_dynamic_libraries for some targets). */ @@ -149,10 +149,11 @@ if (NULL == result) { WARN("Out of memory - trying to allocate requested amount" " (%" WARN_PRIdPTR " bytes)...\n", (word)bytes); - scratch_free_ptr -= bytes; /* Undo free area pointer update */ bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(bytes); result = (ptr_t)GET_MEM(bytes_to_get); GC_add_to_our_memory(result, bytes_to_get); + if (result != NULL) + GC_scratch_last_end_ptr = result + bytes; return result; } /* Update scratch area pointers and retry. */ @@ -346,9 +347,7 @@ } } -/* Get the next valid block whose address is at least h */ -/* Return 0 if there is none. */ -GC_INNER struct hblk * GC_next_used_block(struct hblk *h) +GC_INNER struct hblk * GC_next_block(struct hblk *h, GC_bool allow_free) { REGISTER bottom_index * bi; REGISTER word j = ((word)h >> LOG_HBLKSIZE) & (BOTTOM_SZ-1); @@ -362,14 +361,15 @@ while (bi != 0 && bi -> key < hi) bi = bi -> asc_link; j = 0; } - while(bi != 0) { + + while (bi != 0) { while (j < BOTTOM_SZ) { hdr * hhdr = bi -> index[j]; if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) { j++; } else { - if (!HBLK_IS_FREE(hhdr)) { - return((struct hblk *) + if (allow_free || !HBLK_IS_FREE(hhdr)) { + return ((struct hblk *) (((bi -> key << LOG_BOTTOM_SZ) + j) << LOG_HBLKSIZE)); } else { @@ -383,9 +383,6 @@ return(0); } -/* Get the last (highest address) block whose address is */ -/* at most h. Return 0 if there is none. */ -/* Unlike the above, this may return a free block. */ GC_INNER struct hblk * GC_prev_block(struct hblk *h) { bottom_index * bi; diff -Nru libgc-8.0.4/include/ec.h libgc-8.0.6/include/ec.h --- libgc-8.0.4/include/ec.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/ec.h 2021-11-25 21:36:27.000000000 +0000 @@ -61,8 +61,8 @@ /* Append a character to an extensible cord. */ #define CORD_ec_append(x, c) \ - (((x)[0].ec_bufptr == (x)[0].ec_buf + CORD_BUFSZ ? \ - (CORD_ec_flush_buf(x), 0) : 0), \ + ((void)((x)[0].ec_bufptr == (x)[0].ec_buf + CORD_BUFSZ \ + ? (CORD_ec_flush_buf(x), 0) : 0), \ (void)(*(x)[0].ec_bufptr++ = (c))) /* Append a cord to an extensible cord. Structure remains shared with */ diff -Nru libgc-8.0.4/include/gc.h libgc-8.0.6/include/gc.h --- libgc-8.0.4/include/gc.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/gc.h 2021-11-25 21:36:27.000000000 +0000 @@ -24,7 +24,6 @@ * For better performance, also look at GC_MALLOC_ATOMIC, and * GC_enable_incremental. If you need an action to be performed * immediately before an object is collected, look at GC_register_finalizer. - * If you are using Solaris threads, look at the end of this file. * Everything else is best ignored unless you encounter performance * problems. */ @@ -90,11 +89,12 @@ #ifdef GC_THREADS GC_API GC_ATTR_DEPRECATED int GC_parallel; /* GC is parallelized for performance on */ - /* multiprocessors. Currently set only */ - /* implicitly if collector is built with */ - /* PARALLEL_MARK defined and if either: */ - /* Env variable GC_NPROC is set to > 1, or */ - /* GC_NPROC is not set and this is an MP. */ + /* multiprocessors. Set to a non-zero value */ + /* only implicitly if collector is built with */ + /* PARALLEL_MARK defined, and if either */ + /* GC_MARKERS (or GC_NPROCS) environment */ + /* variable is set to > 1, or multiple cores */ + /* (processors) are available. */ /* If GC_parallel is on (non-zero), incremental */ /* collection is only partially functional, */ /* and may not be desirable. The getter does */ @@ -1534,8 +1534,13 @@ /* the current thread (this means that the thread is not suspended and */ /* the thread's stack frames "belonging" to the functions in the */ /* "inactive" state are not scanned during garbage collections). It is */ -/* allowed for fn to call GC_call_with_gc_active() (even recursively), */ -/* thus temporarily toggling the collector's state back to "active". */ +/* assumed that the collector is already initialized and the current */ +/* thread is registered. It is allowed for fn to call */ +/* GC_call_with_gc_active() (even recursively), thus temporarily */ +/* toggling the collector's state back to "active". The latter */ +/* technique might be used to make stack scanning more precise (i.e. */ +/* scan only stack frames of functions that allocate garbage collected */ +/* memory and/or manipulate pointers to the garbage collected heap). */ GC_API void * GC_CALL GC_do_blocking(GC_fn_type /* fn */, void * /* client_data */) GC_ATTR_NONNULL(1); @@ -1893,8 +1898,8 @@ /* Required at least if GC is in a DLL. And doesn't hurt. */ #elif defined(_AIX) extern int _data[], _end[]; -# define GC_DATASTART ((void *)((ulong)_data)) -# define GC_DATAEND ((void *)((ulong)_end)) +# define GC_DATASTART ((void *)_data) +# define GC_DATAEND ((void *)_end) # define GC_INIT_CONF_ROOTS GC_add_roots(GC_DATASTART, GC_DATAEND) #elif (defined(HOST_ANDROID) || defined(__ANDROID__)) \ && defined(IGNORE_DYNAMIC_LOADING) @@ -2002,7 +2007,7 @@ /* Portable clients should call this at the program start-up. More */ /* over, some platforms require this call to be done strictly from the */ -/* primordial thread. */ +/* primordial thread. Multiple invocations are harmless. */ #define GC_INIT() { GC_INIT_CONF_DONT_EXPAND; /* pre-init */ \ GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT; \ GC_INIT_CONF_MAX_RETRIES; \ diff -Nru libgc-8.0.4/include/gc_allocator.h libgc-8.0.6/include/gc_allocator.h --- libgc-8.0.4/include/gc_allocator.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/gc_allocator.h 2021-11-25 21:36:27.000000000 +0000 @@ -44,7 +44,8 @@ #include // for placement new and bad_alloc #ifndef GC_ATTR_EXPLICIT -# if (__cplusplus >= 201103L) || defined(CPPCHECK) +# if __cplusplus >= 201103L && !defined(__clang__) || _MSVC_LANG >= 201103L \ + || defined(CPPCHECK) # define GC_ATTR_EXPLICIT explicit # else # define GC_ATTR_EXPLICIT /* empty */ @@ -65,7 +66,7 @@ # ifndef GC_NEW_ABORTS_ON_OOM # define GC_NEW_ABORTS_ON_OOM # endif -# elif __cplusplus >= 201103L +# elif __cplusplus >= 201103L || _MSVC_LANG >= 201103L # define GC_NOEXCEPT noexcept # else # define GC_NOEXCEPT throw() diff -Nru libgc-8.0.4/include/gc_config_macros.h libgc-8.0.6/include/gc_config_macros.h --- libgc-8.0.4/include/gc_config_macros.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/gc_config_macros.h 2021-11-25 21:36:27.000000000 +0000 @@ -83,13 +83,13 @@ #elif defined(GC_THREADS) # if defined(__linux__) # define GC_LINUX_THREADS +# elif defined(__OpenBSD__) +# define GC_OPENBSD_THREADS # elif defined(_PA_RISC1_1) || defined(_PA_RISC2_0) || defined(hppa) \ || defined(__HPPA) || (defined(__ia64) && defined(_HPUX_SOURCE)) # define GC_HPUX_THREADS # elif defined(__HAIKU__) # define GC_HAIKU_THREADS -# elif defined(__OpenBSD__) -# define GC_OPENBSD_THREADS # elif defined(__DragonFly__) || defined(__FreeBSD_kernel__) \ || (defined(__FreeBSD__) && !defined(SN_TARGET_ORBIS)) # define GC_FREEBSD_THREADS @@ -176,13 +176,22 @@ #if defined(GC_DLL) && !defined(GC_API) -# if defined(__MINGW32__) || defined(__CEGCC__) -# if defined(GC_BUILD) || defined(__MINGW32_DELAY_LOAD__) +# if defined(__CEGCC__) +# if defined(GC_BUILD) # define GC_API __declspec(dllexport) # else # define GC_API __declspec(dllimport) # endif +# elif defined(__MINGW32__) +# if defined(__cplusplus) && defined(GC_BUILD) +# define GC_API extern __declspec(dllexport) +# elif defined(GC_BUILD) || defined(__MINGW32_DELAY_LOAD__) +# define GC_API __declspec(dllexport) +# else +# define GC_API extern __declspec(dllimport) +# endif + # elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \ || defined(__CYGWIN__) # ifdef GC_BUILD diff -Nru libgc-8.0.4/include/gc_cpp.h libgc-8.0.6/include/gc_cpp.h --- libgc-8.0.4/include/gc_cpp.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/gc_cpp.h 2021-11-25 21:36:27.000000000 +0000 @@ -182,7 +182,7 @@ # ifndef GC_NEW_ABORTS_ON_OOM # define GC_NEW_ABORTS_ON_OOM # endif -# elif __cplusplus >= 201103L +# elif __cplusplus >= 201103L || _MSVC_LANG >= 201103L # define GC_NOEXCEPT noexcept # else # define GC_NOEXCEPT throw() @@ -306,14 +306,13 @@ void*) GC_NOEXCEPT; #endif +#ifndef GC_NO_INLINE_STD_NEW + #if defined(_MSC_VER) || defined(__DMC__) \ - || ((defined(__CYGWIN32__) || defined(__CYGWIN__) \ - || defined(__MINGW32__)) && !defined(GC_BUILD) && !defined(GC_NOT_DLL)) - // The following ensures that the system default operator new[] does not - // get undefined, which is what seems to happen on VC++ 6 for some reason - // if we define a multi-argument operator new[]. - // There seems to be no way to redirect new in this environment without - // including this everywhere. + || ((defined(__BORLANDC__) || defined(__CYGWIN__) \ + || defined(__CYGWIN32__) || defined(__MINGW32__) \ + || defined(__WATCOMC__)) \ + && !defined(GC_BUILD) && !defined(GC_NOT_DLL)) // Inlining done to avoid mix up of new and delete operators by VC++ 9 (due // to arbitrary ordering during linking). @@ -343,7 +342,7 @@ GC_FREE(obj); } -# if __cplusplus > 201103L // C++14 +# if __cplusplus >= 201402L || _MSVC_LANG >= 201402L // C++14 inline void operator delete(void* obj, size_t size) GC_NOEXCEPT { (void)size; // size is ignored GC_FREE(obj); @@ -390,6 +389,24 @@ #endif // _MSC_VER +#elif defined(_MSC_VER) + // The following ensures that the system default operator new[] does not + // get undefined, which is what seems to happen on VC++ 6 for some reason + // if we define a multi-argument operator new[]. + // There seems to be no way to redirect new in this environment without + // including this everywhere. +# ifdef GC_OPERATOR_NEW_ARRAY + void *operator new[](size_t size); + void operator delete[](void* obj); +# endif + + void* operator new(size_t size); + void operator delete(void* obj); + + void* operator new(size_t size, int /* nBlockUse */, + const char * szFileName, int nLine); +#endif // GC_NO_INLINE_STD_NEW && _MSC_VER + #ifdef GC_OPERATOR_NEW_ARRAY // The operator new for arrays, identical to the above. inline void* operator new[](size_t size, GC_NS_QUALIFY(GCPlacement) gcp, diff -Nru libgc-8.0.4/include/gc_pthread_redirects.h libgc-8.0.6/include/gc_pthread_redirects.h --- libgc-8.0.4/include/gc_pthread_redirects.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/gc_pthread_redirects.h 2021-11-25 21:36:27.000000000 +0000 @@ -18,6 +18,9 @@ /* Our pthread support normally needs to intercept a number of thread */ /* calls. We arrange to do that here, if appropriate. */ +#ifndef GC_PTHREAD_REDIRECTS_H +#define GC_PTHREAD_REDIRECTS_H + /* Included from gc.h only. Included only if GC_PTHREADS. */ #if defined(GC_H) && defined(GC_PTHREADS) @@ -117,3 +120,5 @@ #endif /* !GC_NO_THREAD_REDIRECTS */ #endif /* GC_PTHREADS */ + +#endif /* GC_PTHREAD_REDIRECTS_H */ diff -Nru libgc-8.0.4/include/gc_typed.h libgc-8.0.6/include/gc_typed.h --- libgc-8.0.4/include/gc_typed.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/gc_typed.h 2021-11-25 21:36:27.000000000 +0000 @@ -105,8 +105,9 @@ /* Returned object is cleared. */ #ifdef GC_DEBUG -# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) GC_MALLOC(bytes) -# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) GC_MALLOC((n) * (bytes)) +# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) ((void)(d), GC_MALLOC(bytes)) +# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \ + ((void)(d), GC_MALLOC((n) * (bytes))) #else # define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) \ GC_malloc_explicitly_typed(bytes, d) diff -Nru libgc-8.0.4/include/gc_version.h libgc-8.0.6/include/gc_version.h --- libgc-8.0.4/include/gc_version.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/gc_version.h 2021-11-25 21:36:27.000000000 +0000 @@ -30,7 +30,7 @@ /* it to keep the old-style build process working. */ #define GC_TMP_VERSION_MAJOR 8 #define GC_TMP_VERSION_MINOR 0 -#define GC_TMP_VERSION_MICRO 4 /* 8.0.4 */ +#define GC_TMP_VERSION_MICRO 6 /* 8.0.6 */ #ifdef GC_VERSION_MAJOR # if GC_TMP_VERSION_MAJOR != GC_VERSION_MAJOR \ diff -Nru libgc-8.0.4/include/include.am libgc-8.0.6/include/include.am --- libgc-8.0.4/include/include.am 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/include.am 2021-11-25 21:36:27.000000000 +0000 @@ -29,9 +29,6 @@ # headers which are not installed # dist_noinst_HEADERS += \ - include/cord.h \ - include/cord_pos.h \ - include/ec.h \ include/gc_alloc_ptrs.h \ include/new_gc_alloc.h \ include/private/darwin_semaphore.h \ diff -Nru libgc-8.0.4/include/new_gc_alloc.h libgc-8.0.6/include/new_gc_alloc.h --- libgc-8.0.4/include/new_gc_alloc.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/new_gc_alloc.h 2021-11-25 21:36:27.000000000 +0000 @@ -74,6 +74,8 @@ // We can't include gc_priv.h, since that pulls in way too much stuff. #include "gc_alloc_ptrs.h" +#include "gc_mark.h" // for GC_generic_malloc + #define GC_generic_malloc_words_small(lw, k) \ GC_generic_malloc((lw) * sizeof(GC_word), k) @@ -153,14 +155,15 @@ if (0 == op) GC_ALLOCATOR_THROW_OR_ABORT(); + GC_word non_gc_bytes = GC_get_non_gc_bytes(); GC_bytes_recently_allocd += GC_uncollectable_bytes_recently_allocd; - GC_non_gc_bytes += - GC_uncollectable_bytes_recently_allocd; + non_gc_bytes += GC_uncollectable_bytes_recently_allocd; GC_uncollectable_bytes_recently_allocd = 0; GC_bytes_recently_freed += GC_uncollectable_bytes_recently_freed; - GC_non_gc_bytes -= GC_uncollectable_bytes_recently_freed; + non_gc_bytes -= GC_uncollectable_bytes_recently_freed; GC_uncollectable_bytes_recently_freed = 0; + GC_set_non_gc_bytes(non_gc_bytes); GC_incr_bytes_allocd(GC_bytes_recently_allocd); GC_bytes_recently_allocd = 0; diff -Nru libgc-8.0.4/include/private/gc_locks.h libgc-8.0.6/include/private/gc_locks.h --- libgc-8.0.4/include/private/gc_locks.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/private/gc_locks.h 2021-11-25 21:36:27.000000000 +0000 @@ -183,6 +183,7 @@ EXTERN_C_BEGIN GC_EXTERN pthread_mutex_t GC_allocate_ml; # ifdef GC_ASSERTIONS + GC_INNER void GC_lock(void); # define UNCOND_LOCK() { GC_ASSERT(I_DONT_HOLD_LOCK()); \ GC_lock(); SET_LOCK_HOLDER(); } # define UNCOND_UNLOCK() \ @@ -192,6 +193,7 @@ # if defined(NO_PTHREAD_TRYLOCK) # define UNCOND_LOCK() pthread_mutex_lock(&GC_allocate_ml) # else + GC_INNER void GC_lock(void); # define UNCOND_LOCK() \ { if (0 != pthread_mutex_trylock(&GC_allocate_ml)) \ GC_lock(); } @@ -225,7 +227,6 @@ # define EXIT_GC() (void)(GC_collecting = FALSE) # endif # endif - GC_INNER void GC_lock(void); # endif /* GC_PTHREADS */ # if defined(GC_ALWAYS_MULTITHREADED) \ && (defined(USE_PTHREAD_LOCKS) || defined(USE_SPIN_LOCK)) diff -Nru libgc-8.0.4/include/private/gc_priv.h libgc-8.0.6/include/private/gc_priv.h --- libgc-8.0.4/include/private/gc_priv.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/private/gc_priv.h 2021-11-25 21:36:27.000000000 +0000 @@ -26,7 +26,8 @@ # define GC_BUILD #endif -#if (defined(__linux__) || defined(__GLIBC__) || defined(__GNU__)) \ +#if (defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) \ + || (defined(__CYGWIN__) && !defined(USE_MMAP))) \ && !defined(_GNU_SOURCE) /* Can't test LINUX, since this must be defined before other includes. */ # define _GNU_SOURCE 1 @@ -166,6 +167,14 @@ # define REGISTER register #endif +#if defined(M68K) && defined(__GNUC__) + /* By default, __alignof__(word) is 2 on m68k. Use this attribute to */ + /* have proper word alignment (i.e. 4-byte on a 32-bit arch). */ +# define GC_ATTR_WORD_ALIGNED __attribute__((__aligned__(sizeof(word)))) +#else +# define GC_ATTR_WORD_ALIGNED /* empty */ +#endif + #ifndef HEADERS_H # include "gc_hdrs.h" #endif @@ -1231,8 +1240,8 @@ /* be pointers are also put here. */ /* The main fields should precede any */ /* conditionally included fields, so that */ -/* gc_inl.h will work even if a different set */ -/* of macros is defined when the client is */ +/* gc_inline.h will work even if a different */ +/* set of macros is defined when the client is */ /* compiled. */ struct _GC_arrays { @@ -1299,6 +1308,10 @@ # ifdef USE_MUNMAP # define GC_unmapped_bytes GC_arrays._unmapped_bytes word _unmapped_bytes; +# ifdef COUNT_UNMAPPED_REGIONS +# define GC_num_unmapped_regions GC_arrays._num_unmapped_regions + signed_word _num_unmapped_regions; +# endif # else # define GC_unmapped_bytes 0 # endif @@ -1538,8 +1551,14 @@ #endif #if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) - struct _SYSTEM_INFO; - GC_EXTERN struct _SYSTEM_INFO GC_sysinfo; +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +# define NOSERVICE + EXTERN_C_END +# include + EXTERN_C_BEGIN + GC_EXTERN SYSTEM_INFO GC_sysinfo; GC_INNER GC_bool GC_is_heap_base(void *p); #endif @@ -1662,12 +1681,16 @@ word client_data); /* Invoke fn(hbp, client_data) for each */ /* allocated heap block. */ -GC_INNER struct hblk * GC_next_used_block(struct hblk * h); - /* Return first in-use block >= h */ +GC_INNER struct hblk * GC_next_block(struct hblk *h, GC_bool allow_free); + /* Get the next block whose address is at least */ + /* h. Returned block is managed by GC. The */ + /* block must be in use unless allow_free is */ + /* true. Return 0 if there is no such block. */ GC_INNER struct hblk * GC_prev_block(struct hblk * h); - /* Return last block <= h. Returned block */ - /* is managed by GC, but may or may not be in */ - /* use. */ + /* Get the last (highest address) block whose */ + /* address is at most h. Returned block is */ + /* managed by GC, but may or may not be in use. */ + /* Return 0 if there is no such block. */ GC_INNER void GC_mark_init(void); GC_INNER void GC_clear_marks(void); /* Clear mark bits for all heap objects. */ @@ -1861,10 +1884,13 @@ /* Reuse the memory region by the heap. */ /* Heap block layout maps: */ -GC_INNER GC_bool GC_add_map_entry(size_t sz); +#ifdef MARK_BIT_PER_GRANULE + GC_INNER GC_bool GC_add_map_entry(size_t sz); /* Add a heap block map for objects of */ /* size sz to obj_map. */ /* Return FALSE on failure. */ +#endif + GC_INNER void GC_register_displacement_inner(size_t offset); /* Version of GC_register_displacement */ /* that assumes lock is already held. */ @@ -2130,7 +2156,13 @@ GC_INNER void GC_remap(ptr_t start, size_t bytes); GC_INNER void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2, size_t bytes2); -#endif + + /* Compute end address for an unmap operation on the indicated block. */ + GC_INLINE ptr_t GC_unmap_end(ptr_t start, size_t bytes) + { + return (ptr_t)((word)(start + bytes) & ~(GC_page_size - 1)); + } +#endif /* USE_MUNMAP */ #ifdef CAN_HANDLE_FORK GC_EXTERN int GC_handle_fork; @@ -2182,6 +2214,17 @@ /* pointer-free system call buffers in the heap are */ /* not protected. */ +# ifdef CAN_HANDLE_FORK +# if defined(PROC_VDB) + GC_INNER void GC_dirty_update_child(void); + /* Update pid-specific resources (like /proc file */ + /* descriptors) needed by the dirty bits implementation */ + /* after fork in the child process. */ +# else +# define GC_dirty_update_child() (void)0 +# endif +# endif /* CAN_HANDLE_FORK */ + GC_INNER GC_bool GC_dirty_init(void); /* Returns true if dirty bits are maintained (otherwise */ /* it is OK to be called again if the client invokes */ @@ -2642,7 +2685,6 @@ /* Do we need the GC_find_limit machinery to find the end of a */ /* data segment. */ #if defined(HEURISTIC2) || defined(SEARCH_FOR_DATA_START) \ - || (!defined(STACKBOTTOM) && defined(HEURISTIC2)) \ || ((defined(SVR4) || defined(AIX) || defined(DGUX) \ || (defined(LINUX) && defined(SPARC))) && !defined(PCR)) # define NEED_FIND_LIMIT diff -Nru libgc-8.0.4/include/private/gcconfig.h libgc-8.0.6/include/private/gcconfig.h --- libgc-8.0.4/include/private/gcconfig.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/private/gcconfig.h 2021-11-25 21:36:27.000000000 +0000 @@ -160,7 +160,8 @@ # if defined(__aarch64__) # define AARCH64 # if !defined(LINUX) && !defined(DARWIN) && !defined(FREEBSD) \ - && !defined(NETBSD) && !defined(NN_BUILD_TARGET_PLATFORM_NX) + && !defined(NETBSD) && !defined(NN_BUILD_TARGET_PLATFORM_NX) \ + && !defined(OPENBSD) # define NOSYS # define mach_type_known # endif @@ -196,6 +197,10 @@ # define ARM32 # define mach_type_known # endif +# if defined(OPENBSD) && defined(__aarch64__) +# define AARCH64 +# define mach_type_known +# endif # if defined(OPENBSD) && defined(__sh__) # define SH # define mach_type_known @@ -883,7 +888,8 @@ && !(defined(POWERPC) && defined(DARWIN)) /* for MacOS X 10.3.9 */ \ && !defined(RTEMS) \ && !defined(__ARMCC_VERSION) /* does not exist in armcc gnu emu */ \ - && !defined(__clang__) /* since no-op in clang (3.0) */ + && (!defined(__clang__) \ + || (GC_CLANG_PREREQ(8, 0) && defined(HOST_ANDROID))) # define HAVE_BUILTIN_UNWIND_INIT # endif @@ -943,7 +949,10 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM -# define MPROTECT_VDB +# define COUNT_UNMAPPED_REGIONS +# if !defined(REDIRECT_MALLOC) +# define MPROTECT_VDB +# endif # ifdef __ELF__ # define DYNAMIC_LOADING EXTERN_C_END @@ -1033,6 +1042,7 @@ # else # define LINUX_STACKBOTTOM # endif +# define COUNT_UNMAPPED_REGIONS # define DYNAMIC_LOADING # define SEARCH_FOR_DATA_START extern int _end[]; @@ -1078,17 +1088,7 @@ # define OS_TYPE "OPENBSD" # define ALIGNMENT 4 # ifndef GC_OPENBSD_THREADS - EXTERN_C_END -# include -# include - EXTERN_C_BEGIN - /* USRSTACK is defined in but that is */ - /* protected by _KERNEL in file. */ -# ifdef USRSTACK -# define STACKBOTTOM ((ptr_t)USRSTACK) -# else -# define HEURISTIC2 -# endif +# define HEURISTIC2 # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) @@ -1288,6 +1288,7 @@ # elif !defined(CPPCHECK) # error Linux SPARC a.out not supported # endif +# define COUNT_UNMAPPED_REGIONS extern int _end[]; extern int _etext[]; # define DATAEND ((ptr_t)(_end)) @@ -1304,15 +1305,7 @@ # ifdef OPENBSD # define OS_TYPE "OPENBSD" # ifndef GC_OPENBSD_THREADS - EXTERN_C_END -# include -# include - EXTERN_C_BEGIN -# ifdef USRSTACK -# define STACKBOTTOM ((ptr_t)USRSTACK) -# else -# define HEURISTIC2 -# endif +# define HEURISTIC2 # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) @@ -1468,7 +1461,8 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM -# if !defined(GC_LINUX_THREADS) || !defined(REDIRECT_MALLOC) +# define COUNT_UNMAPPED_REGIONS +# if !defined(REDIRECT_MALLOC) # define MPROTECT_VDB # else /* We seem to get random errors in incremental mode, */ @@ -1545,6 +1539,8 @@ # endif # ifdef CYGWIN32 # define OS_TYPE "CYGWIN32" +# define WOW64_THREAD_CONTEXT_WORKAROUND +# define RETRY_GET_THREAD_CONTEXT # define DATASTART ((ptr_t)GC_DATASTART) /* From gc.h */ # define DATAEND ((ptr_t)GC_DATAEND) # undef STACK_GRAN @@ -1575,6 +1571,8 @@ # endif # ifdef MSWIN32 # define OS_TYPE "MSWIN32" +# define WOW64_THREAD_CONTEXT_WORKAROUND +# define RETRY_GET_THREAD_CONTEXT /* STACKBOTTOM and DATASTART are handled specially in */ /* os_dep.c. */ # define MPROTECT_VDB @@ -1601,15 +1599,7 @@ # ifdef OPENBSD # define OS_TYPE "OPENBSD" # ifndef GC_OPENBSD_THREADS - EXTERN_C_END -# include -# include - EXTERN_C_BEGIN -# ifdef USRSTACK -# define STACKBOTTOM ((ptr_t)USRSTACK) -# else # define HEURISTIC2 -# endif # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) @@ -1747,6 +1737,7 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define DYNAMIC_LOADING +# define COUNT_UNMAPPED_REGIONS extern int _end[]; # pragma weak __data_start extern int __data_start[]; @@ -1847,20 +1838,13 @@ # endif # ifdef OPENBSD # define OS_TYPE "OPENBSD" -# define ALIGNMENT 4 +# define CPP_WORDSZ 64 /* all OpenBSD/mips platforms are 64-bit */ +# define ALIGNMENT 8 # ifndef GC_OPENBSD_THREADS - EXTERN_C_END -# include -# include - EXTERN_C_BEGIN -# ifdef USRSTACK -# define STACKBOTTOM ((ptr_t)USRSTACK) -# else -# define HEURISTIC2 -# endif +# define HEURISTIC2 # endif - extern int _fdata[]; -# define DATASTART ((ptr_t)_fdata) + extern int __data_start[]; +# define DATASTART ((ptr_t)__data_start) extern int _end[]; # define DATAEND ((ptr_t)(&_end)) # define DYNAMIC_LOADING @@ -1898,6 +1882,7 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define DYNAMIC_LOADING +# define COUNT_UNMAPPED_REGIONS extern int _end[]; extern int __data_start[]; # define DATASTART ((ptr_t)(__data_start)) @@ -1916,6 +1901,7 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define DYNAMIC_LOADING +# define COUNT_UNMAPPED_REGIONS extern int _end[]; extern int __data_start[]; # define DATASTART ((ptr_t)(__data_start)) @@ -1946,6 +1932,9 @@ # define OS_TYPE "HPUX" extern int __data_start[]; # define DATASTART ((ptr_t)(__data_start)) +# ifdef USE_MMAP +# define USE_MMAP_ANON +# endif # ifdef USE_HPUX_FIXED_STACKBOTTOM /* The following appears to work for 7xx systems running HP/UX */ /* 9.xx. Furthermore, it might result in much faster */ @@ -1954,13 +1943,22 @@ /* default, since it may not work on older machine/OS */ /* combinations. (Thanks to Raymond X.T. Nijssen for uncovering */ /* this.) */ + /* This technique also doesn't work with HP/UX 11.xx. The */ + /* stack size is settable using the kernel maxssiz variable, */ + /* and in 11.23 and latter, the size can be set dynamically. */ + /* It also doesn't handle SHMEM_MAGIC binaries which have */ + /* stack and data in the first quadrant. */ # define STACKBOTTOM ((ptr_t)0x7b033000) /* from /etc/conf/h/param.h */ -# else +# elif defined(USE_ENVIRON_POINTER) /* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2 */ /* to this. Note that the GC must be initialized before the */ - /* first putenv call. */ + /* first putenv call. Unfortunately, some clients do not obey. */ extern char ** environ; # define STACKBOTTOM ((ptr_t)environ) +# elif !defined(HEURISTIC2) + /* This uses pst_vm_status support. */ +# define HPUX_MAIN_STACKBOTTOM +# define NEED_FIND_LIMIT # endif # define DYNAMIC_LOADING EXTERN_C_END @@ -1977,6 +1975,7 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # define DYNAMIC_LOADING # define SEARCH_FOR_DATA_START extern int _end[]; @@ -1985,15 +1984,7 @@ # ifdef OPENBSD # define OS_TYPE "OPENBSD" # ifndef GC_OPENBSD_THREADS - EXTERN_C_END -# include -# include - EXTERN_C_BEGIN -# ifdef USRSTACK -# define STACKBOTTOM ((ptr_t)USRSTACK) -# else -# define HEURISTIC2 -# endif +# define HEURISTIC2 # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) @@ -2021,15 +2012,7 @@ # define OS_TYPE "OPENBSD" # define ELF_CLASS ELFCLASS64 # ifndef GC_OPENBSD_THREADS - EXTERN_C_END -# include -# include - EXTERN_C_BEGIN -# ifdef USRSTACK -# define STACKBOTTOM ((ptr_t)USRSTACK) -# else # define HEURISTIC2 -# endif # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) @@ -2088,6 +2071,7 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # ifdef __ELF__ # define SEARCH_FOR_DATA_START # define DYNAMIC_LOADING @@ -2096,9 +2080,11 @@ # endif extern int _end[]; # define DATAEND ((ptr_t)(_end)) -# define MPROTECT_VDB +# if !defined(REDIRECT_MALLOC) +# define MPROTECT_VDB /* Has only been superficially tested. May not */ /* work on all versions. */ +# endif # endif # endif @@ -2120,6 +2106,9 @@ # define OS_TYPE "HPUX" extern int __data_start[]; # define DATASTART ((ptr_t)(__data_start)) +# ifdef USE_MMAP +# define USE_MMAP_ANON +# endif /* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2 */ /* to this. Note that the GC must be initialized before the */ /* first putenv call. */ @@ -2153,6 +2142,7 @@ /* backing store. */ extern ptr_t GC_register_stackbottom; # define BACKING_STORE_BASE GC_register_stackbottom +# define COUNT_UNMAPPED_REGIONS # define SEARCH_FOR_DATA_START # ifdef __GNUC__ # define DYNAMIC_LOADING @@ -2161,8 +2151,10 @@ /* statically linked executables and an undefined reference */ /* to _DYNAMIC */ # endif -# define MPROTECT_VDB +# if !defined(REDIRECT_MALLOC) +# define MPROTECT_VDB /* Requires Linux 2.3.47 or later. */ +# endif extern int _end[]; # define DATAEND ((ptr_t)(_end)) # ifdef __GNUC__ @@ -2183,17 +2175,6 @@ # endif /* __INTEL_COMPILER */ # endif # endif -# ifdef CYGWIN32 -# define OS_TYPE "CYGWIN32" -# define DATASTART ((ptr_t)GC_DATASTART) /* From gc.h */ -# define DATAEND ((ptr_t)GC_DATAEND) -# undef STACK_GRAN -# define STACK_GRAN 0x10000 -# ifdef USE_MMAP -# define NEED_FIND_LIMIT -# define USE_MMAP_ANON -# endif -# endif # ifdef MSWIN32 /* FIXME: This is a very partial guess. There is no port, yet. */ # define OS_TYPE "MSWIN32" @@ -2260,6 +2241,7 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # define DYNAMIC_LOADING extern int __data_start[] __attribute__((__weak__)); # define DATASTART ((ptr_t)(__data_start)) @@ -2285,6 +2267,7 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # define DYNAMIC_LOADING # if defined(HOST_ANDROID) # define SEARCH_FOR_DATA_START @@ -2304,7 +2287,9 @@ # define DATAEND ((ptr_t)get_end()) # define STACKBOTTOM ((ptr_t)0x16fdfffff) # define USE_MMAP_ANON -# define MPROTECT_VDB + /* MPROTECT_VDB causes use of non-public API like exc_server, */ + /* this could be a reason for blocking the client application in */ + /* the store. */ EXTERN_C_END # include EXTERN_C_BEGIN @@ -2337,6 +2322,18 @@ # define ELF_CLASS ELFCLASS64 # define DYNAMIC_LOADING # endif +# ifdef OPENBSD +# define OS_TYPE "OPENBSD" +# define ELF_CLASS ELFCLASS64 +# ifndef GC_OPENBSD_THREADS +# define HEURISTIC2 +# endif + extern int __data_start[]; +# define DATASTART ((ptr_t)__data_start) + extern int _end[]; +# define DATAEND ((ptr_t)(&_end)) +# define DYNAMIC_LOADING +# endif # ifdef NINTENDO_SWITCH extern int __bss_end[]; # define NO_HANDLE_FORK 1 @@ -2345,6 +2342,13 @@ void *switch_get_stack_bottom(void); # define STACKBOTTOM ((ptr_t)switch_get_stack_bottom()) # endif +# ifdef MSWIN32 /* UWP */ +# define OS_TYPE "MSWIN32" + /* TODO: Enable GWW_VDB and/or MPROTECT_VDB */ +# ifndef DATAEND +# define DATAEND /* not needed */ +# endif +# endif # ifdef NOSYS /* __data_start is usually defined in the target linker script. */ extern int __data_start[]; @@ -2377,6 +2381,7 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # undef STACK_GRAN # define STACK_GRAN 0x10000000 # ifdef __ELF__ @@ -2435,7 +2440,7 @@ # define DATAEND ((ptr_t)get_end()) # define STACKBOTTOM ((ptr_t)0x30000000) # define USE_MMAP_ANON -# define MPROTECT_VDB + /* MPROTECT_VDB causes use of non-public API. */ EXTERN_C_END # include EXTERN_C_BEGIN @@ -2450,15 +2455,7 @@ # ifdef OPENBSD # define OS_TYPE "OPENBSD" # ifndef GC_OPENBSD_THREADS - EXTERN_C_END -# include -# include - EXTERN_C_BEGIN -# ifdef USRSTACK -# define STACKBOTTOM ((ptr_t)USRSTACK) -# else -# define HEURISTIC2 -# endif +# define HEURISTIC2 # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) @@ -2481,6 +2478,13 @@ void *n3ds_get_stack_bottom(void); # define STACKBOTTOM ((ptr_t)n3ds_get_stack_bottom()) # endif +# ifdef MSWIN32 /* UWP */ +# define OS_TYPE "MSWIN32" + /* TODO: Enable GWW_VDB and/or MPROTECT_VDB */ +# ifndef DATAEND +# define DATAEND /* not needed */ +# endif +# endif # ifdef NOSYS /* __data_start is usually defined in the target linker script. */ extern int __data_start[]; @@ -2498,6 +2502,7 @@ # define OS_TYPE "LINUX" # define DYNAMIC_LOADING # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # define SEARCH_FOR_DATA_START extern int _end[]; # define DATAEND ((ptr_t)(_end)) @@ -2513,6 +2518,7 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # define DYNAMIC_LOADING # define SEARCH_FOR_DATA_START extern int _end[]; @@ -2528,15 +2534,7 @@ # ifdef OPENBSD # define OS_TYPE "OPENBSD" # ifndef GC_OPENBSD_THREADS - EXTERN_C_END -# include -# include - EXTERN_C_BEGIN -# ifdef USRSTACK -# define STACKBOTTOM ((ptr_t)USRSTACK) -# else -# define HEURISTIC2 -# endif +# define HEURISTIC2 # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) @@ -2560,6 +2558,7 @@ # define OS_TYPE "LINUX" # define DYNAMIC_LOADING # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # define SEARCH_FOR_DATA_START extern int _end[]; # define DATAEND ((ptr_t)(_end)) @@ -2572,6 +2571,7 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # undef STACK_GRAN # define STACK_GRAN 0x10000000 # define DYNAMIC_LOADING @@ -2606,15 +2606,7 @@ # define OS_TYPE "OPENBSD" # define ELF_CLASS ELFCLASS64 # ifndef GC_OPENBSD_THREADS - EXTERN_C_END -# include -# include - EXTERN_C_BEGIN -# ifdef USRSTACK -# define STACKBOTTOM ((ptr_t)USRSTACK) -# else # define HEURISTIC2 -# endif # endif extern int __data_start[]; extern int _end[]; @@ -2625,13 +2617,14 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM -# if !defined(GC_LINUX_THREADS) || !defined(REDIRECT_MALLOC) +# if !defined(REDIRECT_MALLOC) # define MPROTECT_VDB # else /* We seem to get random errors in incremental mode, */ /* possibly because Linux threads is itself a malloc client */ /* and can't deal with the signals. */ # endif +# define COUNT_UNMAPPED_REGIONS # ifdef __ELF__ # define DYNAMIC_LOADING EXTERN_C_END @@ -2700,6 +2693,11 @@ /* SIGTSTP and SIGCONT could be used alternatively. */ # endif # define FREEBSD_STACKBOTTOM +# if defined(__DragonFly__) + /* DragonFly BSD still has vm.max_proc_mmap, according to */ + /* its mmap(2) man page. */ +# define COUNT_UNMAPPED_REGIONS +# endif # ifdef __ELF__ # define DYNAMIC_LOADING # endif @@ -2776,6 +2774,13 @@ # define HEAP_START DATAEND # endif # endif +# ifdef CYGWIN32 +# define OS_TYPE "CYGWIN32" +# define RETRY_GET_THREAD_CONTEXT +# ifdef USE_MMAP +# define USE_MMAP_ANON +# endif +# endif # ifdef MSWIN_XBOX1 # define NO_GETENV # define DATASTART (ptr_t)ALIGNMENT @@ -2797,6 +2802,7 @@ # endif # ifdef MSWIN32 # define OS_TYPE "MSWIN32" +# define RETRY_GET_THREAD_CONTEXT /* STACKBOTTOM and DATASTART are handled specially in */ /* os_dep.c. */ # if !defined(__GNUC__) || defined(__INTEL_COMPILER) \ @@ -2819,9 +2825,12 @@ # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # define MPROTECT_VDB # ifdef __ELF__ -# define DYNAMIC_LOADING +# if !defined(REDIRECT_MALLOC) +# define MPROTECT_VDB +# endif EXTERN_C_END # include EXTERN_C_BEGIN @@ -2851,6 +2860,7 @@ extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # define DYNAMIC_LOADING # endif # endif @@ -2869,6 +2879,7 @@ extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # define DYNAMIC_LOADING # endif # endif @@ -2879,9 +2890,10 @@ # define ALIGNMENT (CPP_WORDSZ/8) # ifdef LINUX # define OS_TYPE "LINUX" - extern int __data_start[]; + extern int __data_start[] __attribute__((__weak__)); # define DATASTART ((ptr_t)__data_start) # define LINUX_STACKBOTTOM +# define COUNT_UNMAPPED_REGIONS # define DYNAMIC_LOADING # endif # endif /* RISCV */ @@ -2891,6 +2903,10 @@ # define USE_LIBC_PRIVATES #endif +#ifdef NO_RETRY_GET_THREAD_CONTEXT +# undef RETRY_GET_THREAD_CONTEXT +#endif + #if defined(LINUX_STACKBOTTOM) && defined(NO_PROC_STAT) \ && !defined(USE_LIBC_PRIVATES) /* This combination will fail, since we have no way to get */ @@ -3100,8 +3116,12 @@ # undef USE_MMAP #endif -#if defined(LINUX) || defined(FREEBSD) || defined(SOLARIS) || defined(IRIX5) \ - || ((defined(USE_MMAP) || defined(USE_MUNMAP)) && !defined(USE_WINALLOC)) +#if defined(DARWIN) || defined(FREEBSD) || defined(HAIKU) \ + || defined(IRIX5) || defined(LINUX) || defined(NETBSD) \ + || defined(OPENBSD) || defined(SOLARIS) \ + || ((defined(CYGWIN32) || defined(USE_MMAP) || defined(USE_MUNMAP)) \ + && !defined(USE_WINALLOC)) + /* Try both sbrk and mmap, in that order. */ # define MMAP_SUPPORTED #endif @@ -3115,6 +3135,20 @@ # define MUNMAP_THRESHOLD 2 #endif +#if defined(USE_MUNMAP) && defined(COUNT_UNMAPPED_REGIONS) \ + && !defined(GC_UNMAPPED_REGIONS_SOFT_LIMIT) + /* The default limit of vm.max_map_count on Linux is ~65530. */ + /* There is approximately one mapped region to every unmapped region. */ + /* Therefore if we aim to use up to half of vm.max_map_count for the */ + /* GC (leaving half for the rest of the process) then the number of */ + /* unmapped regions should be one quarter of vm.max_map_count. */ +# if defined(__DragonFly__) +# define GC_UNMAPPED_REGIONS_SOFT_LIMIT (1000000 / 4) +# else +# define GC_UNMAPPED_REGIONS_SOFT_LIMIT 16384 +# endif +#endif + #if defined(GC_DISABLE_INCREMENTAL) || defined(DEFAULT_VDB) # undef GWW_VDB # undef MPROTECT_VDB @@ -3146,6 +3180,11 @@ /* PARALLEL_MARK does not cause undef MPROTECT_VDB any longer. */ +#if defined(USE_PROC_FOR_LIBRARIES) && defined(GC_LINUX_THREADS) + /* Incremental GC is incompatible with /proc roots. */ +# undef MPROTECT_VDB +#endif + #if defined(MPROTECT_VDB) && defined(GC_PREFER_MPROTECT_VDB) /* Choose MPROTECT_VDB manually (if multiple strategies available). */ # undef PCR_VDB @@ -3158,6 +3197,10 @@ # undef MPROTECT_VDB #endif +#if defined(MPROTECT_VDB) && !defined(MSWIN32) && !defined(MSWINCE) +# include /* for SA_SIGINFO, SIGBUS */ +#endif + #if defined(SIGBUS) && !defined(HAVE_SIGBUS) && !defined(CPPCHECK) # define HAVE_SIGBUS #endif @@ -3166,7 +3209,8 @@ # define NO_SA_SIGACTION #endif -#if defined(NO_SA_SIGACTION) && defined(MPROTECT_VDB) && !defined(DARWIN) \ +#if (defined(NO_SA_SIGACTION) || defined(GC_NO_SIGSETJMP)) \ + && defined(MPROTECT_VDB) && !defined(DARWIN) \ && !defined(MSWIN32) && !defined(MSWINCE) # undef MPROTECT_VDB #endif diff -Nru libgc-8.0.4/include/private/pthread_support.h libgc-8.0.6/include/private/pthread_support.h --- libgc-8.0.4/include/private/pthread_support.h 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/include/private/pthread_support.h 2021-11-25 21:36:27.000000000 +0000 @@ -132,7 +132,7 @@ /* and detach. */ # ifdef THREAD_LOCAL_ALLOC - struct thread_local_freelists tlfs; + struct thread_local_freelists tlfs GC_ATTR_WORD_ALIGNED; # endif } * GC_thread; diff -Nru libgc-8.0.4/mallocx.c libgc-8.0.6/mallocx.c --- libgc-8.0.4/mallocx.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/mallocx.c 2021-11-25 21:36:27.000000000 +0000 @@ -349,10 +349,9 @@ struct hblk * hbp; hdr * hhdr; - rlh += lg; - while ((hbp = *rlh) != 0) { + while ((hbp = rlh[lg]) != NULL) { hhdr = HDR(hbp); - *rlh = hhdr -> hb_next; + rlh[lg] = hhdr -> hb_next; GC_ASSERT(hhdr -> hb_sz == lb); hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no; # ifdef PARALLEL_MARK @@ -416,6 +415,9 @@ /* GC lock is needed for reclaim list access. We */ /* must decrement fl_builder_count before reacquiring */ /* the lock. Hopefully this path is rare. */ + + rlh = ok -> ok_reclaim_list; /* reload rlh after locking */ + if (NULL == rlh) break; } # endif } diff -Nru libgc-8.0.4/mark.c libgc-8.0.6/mark.c --- libgc-8.0.4/mark.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/mark.c 2021-11-25 21:36:27.000000000 +0000 @@ -123,7 +123,7 @@ /* Are there collectible marked objects in the heap? */ /* Is a collection in progress? Note that this can return true in the */ -/* nonincremental case, if a collection has been abandoned and the */ +/* non-incremental case, if a collection has been abandoned and the */ /* mark state is now MS_INVALID. */ GC_INNER GC_bool GC_collection_in_progress(void) { @@ -502,7 +502,8 @@ /* to the exception case; our results are invalid and we have */ /* to start over. This cannot be prevented since we can't */ /* block in DllMain. */ - if (GC_started_thread_while_stopped()) goto handle_ex; + if (GC_started_thread_while_stopped()) + goto handle_thr_start; # endif rm_handler: return ret_val; @@ -539,7 +540,7 @@ goto handle_ex; # if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) if (GC_started_thread_while_stopped()) - goto handle_ex; + goto handle_thr_start; # endif rm_handler: /* Uninstall the exception handler */ @@ -553,10 +554,17 @@ /* thread that is in the process of exiting, and disappears */ /* while we are marking it. This seems extremely difficult to */ /* avoid otherwise. */ - if (GC_incremental) { - WARN("Incremental GC incompatible with /proc roots\n", 0); - /* I'm not sure if this could still work ... */ - } +# ifndef DEFAULT_VDB + if (GC_auto_incremental) { + static GC_bool is_warned = FALSE; + + if (!is_warned) { + is_warned = TRUE; + WARN("Incremental GC incompatible with /proc roots\n", 0); + } + /* I'm not sure if this could still work ... */ + } +# endif GC_setup_temporary_fault_handler(); if(SETJMP(GC_jmp_buf) != 0) goto handle_ex; ret_val = GC_mark_some_inner(cold_gc_frame); @@ -578,6 +586,10 @@ " memory mapping disappeared\n", 0); } } +# if (defined(MSWIN32) || defined(MSWINCE)) && defined(GC_WIN32_THREADS) \ + && !defined(GC_PTHREADS) + handle_thr_start: +# endif /* We have bad roots on the stack. Discard mark stack. */ /* Rescan from marked objects. Redetermine roots. */ # ifdef REGISTER_LIBRARIES_EARLY @@ -1270,7 +1282,7 @@ /* TODO: Assert correct memory flags if GWW_VDB */ if (page_offset != 0) displ = GC_page_size - page_offset; - recycled_bytes = (bytes - displ) & ~(GC_page_size - 1); + recycled_bytes = bytes > displ ? (bytes - displ) & ~(GC_page_size-1) : 0; GC_COND_LOG_PRINTF("Recycle %lu/%lu scratch-allocated bytes at %p\n", (unsigned long)recycled_bytes, (unsigned long)bytes, ptr); @@ -1521,7 +1533,7 @@ word bytes_allocd; word arg1; word arg2; -} GC_trace_buf[TRACE_ENTRIES]; +} GC_trace_buf[TRACE_ENTRIES] = { { NULL, 0, 0, 0, 0 } }; int GC_trace_buf_ptr = 0; @@ -1962,8 +1974,8 @@ hdr * hhdr = HDR(h); if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr) || HBLK_IS_FREE(hhdr), FALSE)) { - h = GC_next_used_block(h); - if (h == 0) return(0); + h = GC_next_block(h, FALSE); + if (NULL == h) return NULL; hhdr = GC_find_header((ptr_t)h); } else { # ifdef LINT2 @@ -1984,8 +1996,8 @@ for (;;) { if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr) || HBLK_IS_FREE(hhdr), FALSE)) { - h = GC_next_used_block(h); - if (h == 0) return(0); + h = GC_next_block(h, FALSE); + if (NULL == h) return NULL; hhdr = GC_find_header((ptr_t)h); } else { # ifdef LINT2 @@ -2025,8 +2037,8 @@ for (;;) { if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr) || HBLK_IS_FREE(hhdr), FALSE)) { - h = GC_next_used_block(h); - if (h == 0) return(0); + h = GC_next_block(h, FALSE); + if (NULL == h) return NULL; hhdr = GC_find_header((ptr_t)h); } else { # ifdef LINT2 diff -Nru libgc-8.0.4/mark_rts.c libgc-8.0.6/mark_rts.c --- libgc-8.0.4/mark_rts.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/mark_rts.c 2021-11-25 21:36:27.000000000 +0000 @@ -502,8 +502,11 @@ GC_INNER ptr_t GC_approx_sp(void) { volatile word sp; -# if defined(CPPCHECK) || (__GNUC__ >= 4 /* GC_GNUC_PREREQ(4, 0) */ \ - && !defined(STACK_NOT_SCANNED)) +# if defined(S390) && !defined(CPPCHECK) && (__clang_major__ < 8) + /* Workaround a crash in SystemZTargetLowering of libLLVM-3.8. */ + sp = (word)&sp; +# elif defined(CPPCHECK) || (__GNUC__ >= 4 /* GC_GNUC_PREREQ(4, 0) */ \ + && !defined(STACK_NOT_SCANNED)) /* TODO: Use GC_GNUC_PREREQ after fixing a bug in cppcheck. */ sp = (word)__builtin_frame_address(0); # else diff -Nru libgc-8.0.4/misc.c libgc-8.0.6/misc.c --- libgc-8.0.4/misc.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/misc.c 2021-11-25 21:36:27.000000000 +0000 @@ -830,7 +830,7 @@ if (hU32) { FARPROC pfn = GetProcAddress(hU32, "MessageBoxA"); if (pfn) - (void)(*(int (WINAPI *)(HWND, LPCSTR, LPCSTR, UINT))pfn)( + (void)(*(int (WINAPI *)(HWND, LPCSTR, LPCSTR, UINT))(word)pfn)( NULL /* hWnd */, msg, caption, flags); (void)FreeLibrary(hU32); } @@ -957,14 +957,14 @@ # else { # ifndef MSWINCE - BOOL (WINAPI *pfn)(LPCRITICAL_SECTION, DWORD) = 0; + FARPROC pfn = 0; HMODULE hK32 = GetModuleHandle(TEXT("kernel32.dll")); if (hK32) - pfn = (BOOL (WINAPI *)(LPCRITICAL_SECTION, DWORD)) - GetProcAddress(hK32, - "InitializeCriticalSectionAndSpinCount"); + pfn = GetProcAddress(hK32, + "InitializeCriticalSectionAndSpinCount"); if (pfn) { - pfn(&GC_allocate_ml, SPIN_COUNT); + (*(BOOL (WINAPI *)(LPCRITICAL_SECTION, DWORD))(word)pfn)( + &GC_allocate_ml, SPIN_COUNT); } else # endif /* !MSWINCE */ /* else */ InitializeCriticalSection(&GC_allocate_ml); @@ -1087,15 +1087,12 @@ } } # endif -# ifndef GC_DISABLE_INCREMENTAL +# if !defined(GC_DISABLE_INCREMENTAL) && !defined(NO_CLOCK) { char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET"); if (0 != time_limit_string) { long time_limit = atol(time_limit_string); - if (time_limit < 5) { - WARN("GC_PAUSE_TIME_TARGET environment variable value too small " - "or bad syntax: Ignoring\n", 0); - } else { + if (time_limit > 0) { GC_time_limit = time_limit; } } @@ -1186,7 +1183,7 @@ # if defined(USE_PROC_FOR_LIBRARIES) && defined(GC_LINUX_THREADS) WARN("USE_PROC_FOR_LIBRARIES + GC_LINUX_THREADS performs poorly.\n", 0); /* If thread stacks are cached, they tend to be scanned in */ - /* entirety as part of the root set. This wil grow them to */ + /* entirety as part of the root set. This will grow them to */ /* maximum size, and is generally not desirable. */ # endif # if defined(SEARCH_FOR_DATA_START) @@ -1233,6 +1230,7 @@ # ifndef GC_DISABLE_INCREMENTAL if (GC_incremental || 0 != GETENV("GC_ENABLE_INCREMENTAL")) { # if defined(BASE_ATOMIC_OPS_EMULATED) || defined(CHECKSUMS) \ + || defined(REDIRECT_MALLOC) || defined(REDIRECT_MALLOC_IN_HEADER) \ || defined(SMALL_CONFIG) /* TODO: Implement CHECKSUMS for manual VDB. */ # else @@ -1379,7 +1377,8 @@ LOCK(); } else { # if !defined(BASE_ATOMIC_OPS_EMULATED) && !defined(CHECKSUMS) \ - && !defined(SMALL_CONFIG) + && !defined(REDIRECT_MALLOC) \ + && !defined(REDIRECT_MALLOC_IN_HEADER) && !defined(SMALL_CONFIG) if (manual_vdb_allowed) { GC_manual_vdb = TRUE; GC_incremental = TRUE; @@ -1708,10 +1707,16 @@ # define WRITE(level, buf, len) switch_log_write(buf, len) #else -# if !defined(AMIGA) && !defined(MSWIN_XBOX1) && !defined(SN_TARGET_ORBIS) \ - && !defined(SN_TARGET_PSP2) && !defined(__CC_ARM) -# include -# endif + +# if !defined(SN_TARGET_ORBIS) && !defined(SN_TARGET_PSP2) +# if !defined(AMIGA) && !defined(MSWIN_XBOX1) \ + && !defined(__CC_ARM) +# include +# endif +# if !defined(ECOS) && !defined(NOSYS) +# include +# endif +# endif /* !SN_TARGET_ORBIS && !SN_TARGET_PSP2 */ STATIC int GC_write(int fd, const char *buf, size_t len) { @@ -1738,6 +1743,8 @@ # endif if (-1 == result) { + if (EAGAIN == errno) /* Resource temporarily unavailable */ + continue; RESTORE_CANCEL(cancel_state); return(result); } @@ -1793,8 +1800,13 @@ (void)WRITE(GC_stdout, buf, strlen(buf)); /* Ignore errors silently. */ # else - if (WRITE(GC_stdout, buf, strlen(buf)) < 0) + if (WRITE(GC_stdout, buf, strlen(buf)) < 0 +# if defined(CYGWIN32) + && GC_stdout != GC_DEFAULT_STDOUT_FD +# endif + ) { ABORT("write to stdout failed"); + } # endif } } @@ -1815,8 +1827,13 @@ # ifdef NACL (void)WRITE(GC_log, buf, strlen(buf)); # else - if (WRITE(GC_log, buf, strlen(buf)) < 0) + if (WRITE(GC_log, buf, strlen(buf)) < 0 +# if defined(CYGWIN32) + && GC_log != GC_DEFAULT_STDERR_FD +# endif + ) { ABORT("write to GC log failed"); + } # endif } @@ -2201,14 +2218,6 @@ #endif /* !THREADS */ -/* Wrapper for functions that are likely to block (or, at least, do not */ -/* allocate garbage collected memory and/or manipulate pointers to the */ -/* garbage collected heap) for an appreciable length of time. */ -/* In the single threaded case, GC_do_blocking() (together */ -/* with GC_call_with_gc_active()) might be used to make stack scanning */ -/* more precise (i.e. scan only stack frames of functions that allocate */ -/* garbage collected memory and/or manipulate pointers to the garbage */ -/* collected heap). */ GC_API void * GC_CALL GC_do_blocking(GC_fn_type fn, void * client_data) { struct blocking_data my_data; diff -Nru libgc-8.0.4/new_hblk.c libgc-8.0.6/new_hblk.c --- libgc-8.0.4/new_hblk.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/new_hblk.c 2021-11-25 21:36:27.000000000 +0000 @@ -18,7 +18,7 @@ /* * This file contains the functions: * ptr_t GC_build_flXXX(h, old_fl) - * void GC_new_hblk(size) + * void GC_new_hblk(size, kind) */ #include diff -Nru libgc-8.0.4/os_dep.c libgc-8.0.6/os_dep.c --- libgc-8.0.4/os_dep.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/os_dep.c 2021-11-25 21:36:27.000000000 +0000 @@ -303,10 +303,12 @@ GC_ASSERT(*p == 'r' || *p == '-'); *prot = (char *)p; /* Skip past protection field to offset field */ - while (!isspace(*p)) ++p; while (isspace(*p)) ++p; + while (!isspace(*p)) ++p; + while (isspace(*p)) p++; GC_ASSERT(isxdigit(*p)); /* Skip past offset field, which we ignore */ - while (!isspace(*p)) ++p; while (isspace(*p)) ++p; + while (!isspace(*p)) ++p; + while (isspace(*p)) p++; maj_dev_start = p; GC_ASSERT(isxdigit(*maj_dev_start)); *maj_dev = strtoul((char *)maj_dev_start, NULL, 16); @@ -429,8 +431,12 @@ { ptr_t data_end = DATAEND; -# if (defined(LINUX) || defined(HURD)) && !defined(IGNORE_PROG_DATA_START) +# if (defined(LINUX) || defined(HURD)) && defined(USE_PROG_DATA_START) /* Try the easy approaches first: */ + /* However, this may lead to wrong data start value if libgc */ + /* code is put into a shared library (directly or indirectly) */ + /* which is linked with -Bsymbolic-functions option. Thus, */ + /* the following is not used by default. */ if (COVERT_DATAFLOW(__data_start) != 0) { GC_data_start = (ptr_t)(__data_start); } else { @@ -967,6 +973,7 @@ /* the smallest location q s.t. [q,p) is addressable (!up). */ /* We assume that p (up) or p-1 (!up) is addressable. */ /* Requires allocation lock. */ + GC_ATTR_NO_SANITIZE_ADDR STATIC ptr_t GC_find_limit_with_bound(ptr_t p, GC_bool up, ptr_t bound) { static volatile ptr_t result; @@ -1018,6 +1025,29 @@ } # endif /* NEED_FIND_LIMIT || USE_PROC_FOR_LIBRARIES */ +#ifdef HPUX_MAIN_STACKBOTTOM +# include +# include + + STATIC ptr_t GC_hpux_main_stack_base(void) + { + struct pst_vm_status vm_status; + int i = 0; + + while (pstat_getprocvm(&vm_status, sizeof(vm_status), 0, i++) == 1) { + if (vm_status.pst_type == PS_STACK) + return (ptr_t)vm_status.pst_vaddr; + } + + /* Old way to get the stack bottom. */ +# ifdef STACK_GROWS_UP + return (ptr_t)GC_find_limit(GC_approx_sp(), /* up= */ FALSE); +# else /* not HP_PA */ + return (ptr_t)GC_find_limit(GC_approx_sp(), TRUE); +# endif + } +#endif /* HPUX_MAIN_STACKBOTTOM */ + #ifdef HPUX_STACKBOTTOM #include @@ -1257,10 +1287,12 @@ # else result = (ptr_t)((word)GC_approx_sp() & ~STACKBOTTOM_ALIGNMENT_M1); # endif +# elif defined(HPUX_MAIN_STACKBOTTOM) + result = GC_hpux_main_stack_base(); # elif defined(LINUX_STACKBOTTOM) - result = GC_linux_main_stack_base(); + result = GC_linux_main_stack_base(); # elif defined(FREEBSD_STACKBOTTOM) - result = GC_freebsd_main_stack_base(); + result = GC_freebsd_main_stack_base(); # elif defined(HEURISTIC2) { ptr_t sp = GC_approx_sp(); @@ -1613,10 +1645,10 @@ typedef UINT (WINAPI * GetWriteWatch_type)( DWORD, PVOID, GC_ULONG_PTR /* SIZE_T */, PVOID *, GC_ULONG_PTR *, PULONG); - static GetWriteWatch_type GetWriteWatch_func; + static FARPROC GetWriteWatch_func; static DWORD GetWriteWatch_alloc_flag; -# define GC_GWW_AVAILABLE() (GetWriteWatch_func != NULL) +# define GC_GWW_AVAILABLE() (GetWriteWatch_func != 0) static void detect_GetWriteWatch(void) { @@ -1658,8 +1690,7 @@ hK32 = GetModuleHandle(TEXT("kernel32.dll")); # endif if (hK32 != (HMODULE)0 && - (GetWriteWatch_func = (GetWriteWatch_type)GetProcAddress(hK32, - "GetWriteWatch")) != NULL) { + (GetWriteWatch_func = GetProcAddress(hK32, "GetWriteWatch")) != 0) { /* Also check whether VirtualAlloc accepts MEM_WRITE_WATCH, */ /* as some versions of kernel32.dll have one but not the */ /* other, making the feature completely broken. */ @@ -1671,26 +1702,25 @@ GC_ULONG_PTR count = 16; DWORD page_size; /* Check that it actually works. In spite of some */ - /* documentation it actually seems to exist on W2K. */ + /* documentation it actually seems to exist on Win2K. */ /* This test may be unnecessary, but ... */ - if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET, - page, GC_page_size, - pages, - &count, - &page_size) != 0) { + if ((*(GetWriteWatch_type)(word)GetWriteWatch_func)( + WRITE_WATCH_FLAG_RESET, page, + GC_page_size, pages, &count, + &page_size) != 0) { /* GetWriteWatch always fails. */ - GetWriteWatch_func = NULL; + GetWriteWatch_func = 0; } else { GetWriteWatch_alloc_flag = MEM_WRITE_WATCH; } VirtualFree(page, 0 /* dwSize */, MEM_RELEASE); } else { /* GetWriteWatch will be useless. */ - GetWriteWatch_func = NULL; + GetWriteWatch_func = 0; } } # ifndef SMALL_CONFIG - if (GetWriteWatch_func == NULL) { + if (!GetWriteWatch_func) { GC_COND_LOG_PRINTF("Did not find a usable GetWriteWatch()\n"); } else { GC_COND_LOG_PRINTF("Using GetWriteWatch()\n"); @@ -1719,7 +1749,7 @@ /* assembly code to do that right. */ GC_INNER GC_bool GC_wnt = FALSE; - /* This is a Windows NT derivative, i.e. NT, W2K, XP or later. */ + /* This is a Windows NT derivative, i.e. NT, Win2K, XP or later. */ GC_INNER void GC_init_win32(void) { @@ -2514,13 +2544,6 @@ return result; } -/* Compute end address for an unmap operation on the indicated */ -/* block. */ -STATIC ptr_t GC_unmap_end(ptr_t start, size_t bytes) -{ - return (ptr_t)((word)(start + bytes) & ~(GC_page_size - 1)); -} - /* Under Win32/WinCE we commit (map) and decommit (unmap) */ /* memory using VirtualAlloc and VirtualFree. These functions */ /* work on individual allocations of virtual memory, made */ @@ -2560,9 +2583,12 @@ /* We immediately remap it to prevent an intervening mmap from */ /* accidentally grabbing the same address space. */ { -# ifdef CYGWIN32 - /* Calling mmap() with the new protection flags on an */ - /* existing memory map with MAP_FIXED is broken on Cygwin. */ +# if defined(AIX) || defined(CYGWIN32) || defined(HAIKU) \ + || defined(HPUX) + /* On AIX, mmap(PROT_NONE) fails with ENOMEM unless the */ + /* environment variable XPG_SUS_ENV is set to ON. */ + /* On Cygwin, calling mmap() with the new protection flags on */ + /* an existing memory map with MAP_FIXED is broken. */ /* However, calling mprotect() on the given address range */ /* with PROT_NONE seems to work fine. */ if (mprotect(start_addr, len, PROT_NONE)) @@ -2688,7 +2714,8 @@ # else if (len != 0) { /* Immediately remap as above. */ -# ifdef CYGWIN32 +# if defined(AIX) || defined(CYGWIN32) || defined(HAIKU) \ + || defined(HPUX) if (mprotect(start_addr, len, PROT_NONE)) ABORT("mprotect(PROT_NONE) failed"); # else @@ -2874,8 +2901,8 @@ count = GC_GWW_BUF_LEN; /* GetWriteWatch is documented as returning non-zero when it */ /* fails, but the documentation doesn't explicitly say why it */ - /* would fail or what its behaviour will be if it fails. */ - /* It does appear to fail, at least on recent W2K instances, if */ + /* would fail or what its behavior will be if it fails. It */ + /* does appear to fail, at least on recent Win2K instances, if */ /* the underlying memory was not allocated with the appropriate */ /* flag. This is common if GC_enable_incremental is called */ /* shortly after GC initialization. To avoid modifying the */ @@ -2886,12 +2913,11 @@ /* loop condition. Since each partial call will reset the */ /* status of some pages, this should eventually terminate even */ /* in the overflow case. */ - if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET, - GC_heap_sects[i].hs_start, - GC_heap_sects[i].hs_bytes, - pages, - &count, - &page_size) != 0) { + if ((*(GetWriteWatch_type)(word)GetWriteWatch_func)( + WRITE_WATCH_FLAG_RESET, + GC_heap_sects[i].hs_start, + GC_heap_sects[i].hs_bytes, + pages, &count, &page_size) != 0) { static int warn_count = 0; struct hblk * start = (struct hblk *)GC_heap_sects[i].hs_start; static struct hblk *last_warned = 0; @@ -3073,11 +3099,13 @@ #ifndef DARWIN STATIC SIG_HNDLR_PTR GC_old_segv_handler = 0; /* Also old MSWIN32 ACCESS_VIOLATION filter */ -# if !defined(MSWIN32) && !defined(MSWINCE) +# if defined(FREEBSD) || defined(HPUX) || defined(HURD) || defined(LINUX) STATIC SIG_HNDLR_PTR GC_old_bus_handler = 0; -# if defined(FREEBSD) || defined(HURD) || defined(HPUX) +# ifndef LINUX STATIC GC_bool GC_old_bus_handler_used_si = FALSE; # endif +# endif +# if !defined(MSWIN32) && !defined(MSWINCE) STATIC GC_bool GC_old_segv_handler_used_si = FALSE; # endif /* !MSWIN32 */ #endif /* !DARWIN */ @@ -3116,7 +3144,8 @@ # ifndef SEGV_ACCERR # define SEGV_ACCERR 2 # endif -# if defined(AARCH64) || defined(ARM32) || defined(MIPS) +# if defined(AARCH64) || defined(ARM32) || defined(MIPS) \ + || __FreeBSD__ >= 7 # define CODE_OK (si -> si_code == SEGV_ACCERR) # elif defined(POWERPC) # define AIM /* Pretend that we're AIM. */ @@ -3359,9 +3388,6 @@ # endif } else { GC_old_bus_handler = (SIG_HNDLR_PTR)(signed_word)oldact.sa_handler; -# if !defined(LINUX) - GC_old_bus_handler_used_si = FALSE; -# endif } if (GC_old_bus_handler == (SIG_HNDLR_PTR)(signed_word)SIG_IGN) { WARN("Previously ignored bus error!?\n", 0); @@ -3519,32 +3545,57 @@ # include # endif +# ifndef THREADS + static pid_t saved_proc_pid; /* pid used to compose /proc file name */ +# endif + # define INITIAL_BUF_SZ 16384 STATIC size_t GC_proc_buf_size = INITIAL_BUF_SZ; STATIC char *GC_proc_buf = NULL; - STATIC int GC_proc_fd = 0; + STATIC int GC_proc_fd = -1; -GC_INNER GC_bool GC_dirty_init(void) -{ + static GC_bool proc_dirty_open_files(void) + { char buf[40]; + pid_t pid = getpid(); - if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) { - memset(GC_written_pages, 0xff, sizeof(page_hash_table)); - GC_VERBOSE_LOG_PRINTF( - "Allocated %lu bytes: all pages may have been written\n", - (unsigned long)(GC_bytes_allocd + GC_bytes_allocd_before_gc)); - } - - (void)snprintf(buf, sizeof(buf), "/proc/%ld/pagedata", (long)getpid()); + (void)snprintf(buf, sizeof(buf), "/proc/%ld/pagedata", (long)pid); buf[sizeof(buf) - 1] = '\0'; GC_proc_fd = open(buf, O_RDONLY); - if (GC_proc_fd < 0) { + if (-1 == GC_proc_fd) { WARN("/proc open failed; cannot enable GC incremental mode\n", 0); return FALSE; } if (syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC) == -1) WARN("Could not set FD_CLOEXEC for /proc\n", 0); +# ifndef THREADS + saved_proc_pid = pid; /* updated on success only */ +# endif + return TRUE; + } + +# ifdef CAN_HANDLE_FORK + GC_INNER void GC_dirty_update_child(void) + { + if (-1 == GC_proc_fd) + return; /* GC incremental mode is off */ + + close(GC_proc_fd); + if (!proc_dirty_open_files()) + GC_incremental = FALSE; /* should be safe to turn it off */ + } +# endif /* CAN_HANDLE_FORK */ +GC_INNER GC_bool GC_dirty_init(void) +{ + if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) { + memset(GC_written_pages, 0xff, sizeof(page_hash_table)); + GC_VERBOSE_LOG_PRINTF( + "Allocated %lu bytes: all pages may have been written\n", + (unsigned long)(GC_bytes_allocd + GC_bytes_allocd_before_gc)); + } + if (!proc_dirty_open_files()) + return FALSE; GC_proc_buf = GC_scratch_alloc(GC_proc_buf_size); if (GC_proc_buf == NULL) ABORT("Insufficient space for /proc read"); @@ -3558,6 +3609,23 @@ char * bufp = GC_proc_buf; int i; +# ifndef THREADS + /* If the current pid differs from the saved one, then we are in */ + /* the forked (child) process, the current /proc file should be */ + /* closed, the new one should be opened with the updated path. */ + /* Note, this is not needed for multi-threaded case because */ + /* fork_child_proc() reopens the file right after fork. */ + if (getpid() != saved_proc_pid + && (-1 == GC_proc_fd /* no need to retry */ + || (close(GC_proc_fd), !proc_dirty_open_files()))) { + /* Failed to reopen the file. Punt! */ + if (!output_unneeded) + memset(GC_grungy_pages, 0xff, sizeof(page_hash_table)); + memset(GC_written_pages, 0xff, sizeof(page_hash_table)); + return; + } +# endif + BZERO(GC_grungy_pages, sizeof(GC_grungy_pages)); if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) { /* Retry with larger buffer. */ @@ -3734,6 +3802,8 @@ /* side of labeling pages as dirty (and this implementation does). */ GC_INNER GC_bool GC_page_was_dirty(struct hblk *h) { + word index; + # ifdef PCR_VDB if (!GC_manual_vdb) { if ((word)h < (word)GC_vd_base @@ -3745,9 +3815,16 @@ # elif defined(DEFAULT_VDB) if (!GC_manual_vdb) return TRUE; +# elif defined(PROC_VDB) + /* Unless manual VDB is on, the bitmap covers all process memory. */ + if (GC_manual_vdb) # endif - return NULL == HDR(h) - || get_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h)); + { + if (NULL == HDR(h)) + return TRUE; + } + index = PHT_HASH(h); + return get_pht_entry_from_index(GC_grungy_pages, index); } # if defined(CHECKSUMS) || defined(PROC_VDB) @@ -3755,12 +3832,21 @@ GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk *h) { # if defined(GWW_VDB) || defined(PROC_VDB) + word index; + # ifdef MPROTECT_VDB if (!GC_GWW_AVAILABLE()) return TRUE; # endif - return NULL == HDR(h) - || get_pht_entry_from_index(GC_written_pages, PHT_HASH(h)); +# if defined(PROC_VDB) + if (GC_manual_vdb) +# endif + { + if (NULL == HDR(h)) + return TRUE; + } + index = PHT_HASH(h); + return get_pht_entry_from_index(GC_written_pages, index); # else /* TODO: implement me for MANUAL_VDB. */ (void)h; @@ -4622,7 +4708,11 @@ #endif for (; !((word)fp HOTTER_THAN (word)frame) - && !((word)GC_stackbottom HOTTER_THAN (word)fp) +# ifndef THREADS + && !((word)GC_stackbottom HOTTER_THAN (word)fp) +# elif defined(STACK_GROWS_UP) + && fp != NULL +# endif && nframes < NFRAMES; fp = (struct frame *)((long) fp -> FR_SAVFP + BIAS), nframes++) { # if NARGS > 0 diff -Nru libgc-8.0.4/pthread_support.c libgc-8.0.6/pthread_support.c --- libgc-8.0.4/pthread_support.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/pthread_support.c 2021-11-25 21:36:27.000000000 +0000 @@ -1123,7 +1123,10 @@ /* Turn off parallel marking in the child, since we are probably */ /* just going to exec, and we would have to restart mark threads. */ GC_parallel = FALSE; -# endif /* PARALLEL_MARK */ +# endif +# ifndef GC_DISABLE_INCREMENTAL + GC_dirty_update_child(); +# endif RESTORE_CANCEL(fork_cancel_state); UNLOCK(); /* Even though after a fork the child only inherits the single */ @@ -1242,11 +1245,7 @@ } } -# ifndef GC_DARWIN_THREADS - GC_stop_init(); -# endif - - /* Set GC_nprocs. */ + /* Set GC_nprocs and available_markers_m1. */ { char * nprocs_string = GETENV("GC_NPROCS"); GC_nprocs = -1; @@ -1295,6 +1294,43 @@ # endif } GC_COND_LOG_PRINTF("Number of processors = %d\n", GC_nprocs); + +# if defined(BASE_ATOMIC_OPS_EMULATED) && !defined(GC_DARWIN_THREADS) \ + && !defined(GC_OPENBSD_UTHREADS) && !defined(NACL) \ + && !defined(SN_TARGET_ORBIS) && !defined(SN_TARGET_PSP2) + /* Ensure the process is running on just one CPU core. */ + /* This is needed because the AO primitives emulated with */ + /* locks cannot be used inside signal handlers. */ + { + cpu_set_t mask; + int cpu_set_cnt = 0; + int cpu_lowest_set = 0; + int i = GC_nprocs > 1 ? GC_nprocs : 2; /* check at least 2 cores */ + + if (sched_getaffinity(0 /* current process */, + sizeof(mask), &mask) == -1) + ABORT_ARG1("sched_getaffinity failed", ": errno= %d", errno); + while (i-- > 0) + if (CPU_ISSET(i, &mask)) { + cpu_lowest_set = i; + cpu_set_cnt++; + } + if (0 == cpu_set_cnt) + ABORT("sched_getaffinity returned empty mask"); + if (cpu_set_cnt > 1) { + CPU_ZERO(&mask); + CPU_SET(cpu_lowest_set, &mask); /* select just one CPU */ + if (sched_setaffinity(0, sizeof(mask), &mask) == -1) + ABORT_ARG1("sched_setaffinity failed", ": errno= %d", errno); + WARN("CPU affinity mask is set to %p\n", (word)1 << cpu_lowest_set); + } + } +# endif /* BASE_ATOMIC_OPS_EMULATED */ + +# ifndef GC_DARWIN_THREADS + GC_stop_init(); +# endif + # ifdef PARALLEL_MARK if (available_markers_m1 <= 0) { /* Disable parallel marking. */ @@ -1827,7 +1863,7 @@ int result; int detachstate; word my_flags = 0; - struct start_info * si; + struct start_info si; DCL_LOCK_STATE; /* This is otherwise saved only in an area mmapped by the thread */ /* library, which isn't visible to the collector. */ @@ -1837,21 +1873,13 @@ /* responsibility. */ INIT_REAL_SYMS(); - LOCK(); - si = (struct start_info *)GC_INTERNAL_MALLOC(sizeof(struct start_info), - NORMAL); - UNLOCK(); if (!EXPECT(parallel_initialized, TRUE)) GC_init_parallel(); - if (EXPECT(0 == si, FALSE) && - (si = (struct start_info *) - (*GC_get_oom_fn())(sizeof(struct start_info))) == 0) - return(ENOMEM); - if (sem_init(&(si -> registered), GC_SEM_INIT_PSHARED, 0) != 0) + if (sem_init(&si.registered, GC_SEM_INIT_PSHARED, 0) != 0) ABORT("sem_init failed"); - si -> start_routine = start_routine; - si -> arg = arg; + si.start_routine = start_routine; + si.arg = arg; LOCK(); if (!EXPECT(GC_thr_initialized, TRUE)) GC_thr_init(); @@ -1891,19 +1919,19 @@ pthread_attr_getdetachstate(attr, &detachstate); } if (PTHREAD_CREATE_DETACHED == detachstate) my_flags |= DETACHED; - si -> flags = my_flags; + si.flags = my_flags; UNLOCK(); # ifdef DEBUG_THREADS GC_log_printf("About to start new thread from thread %p\n", (void *)pthread_self()); # endif set_need_to_lock(); - result = REAL_FUNC(pthread_create)(new_thread, attr, GC_start_routine, si); + result = REAL_FUNC(pthread_create)(new_thread, attr, GC_start_routine, + &si); /* Wait until child has been added to the thread table. */ - /* This also ensures that we hold onto si until the child is done */ - /* with it. Thus it doesn't matter whether it is otherwise */ - /* visible to the collector. */ + /* This also ensures that we hold onto the stack-allocated si until */ + /* the child is done with it. */ if (0 == result) { IF_CANCEL(int cancel_state;) @@ -1913,7 +1941,7 @@ # endif DISABLE_CANCEL(cancel_state); /* pthread_create is not a cancellation point. */ - while (0 != sem_wait(&(si -> registered))) { + while (0 != sem_wait(&si.registered)) { # if defined(GC_HAIKU_THREADS) /* To workaround some bug in Haiku semaphores. */ if (EACCES == errno) continue; @@ -1922,11 +1950,7 @@ } RESTORE_CANCEL(cancel_state); } - sem_destroy(&(si -> registered)); - LOCK(); - GC_INTERNAL_FREE(si); - UNLOCK(); - + sem_destroy(&si.registered); return(result); } #endif /* !SN_TARGET_ORBIS && !SN_TARGET_PSP2 */ @@ -2111,22 +2135,25 @@ } } -#else /* !USE_SPIN_LOCK */ +#elif defined(USE_PTHREAD_LOCKS) -GC_INNER void GC_lock(void) -{ -#ifndef NO_PTHREAD_TRYLOCK - if (1 == GC_nprocs || is_collecting()) { +# ifndef NO_PTHREAD_TRYLOCK + GC_INNER void GC_lock(void) + { + if (1 == GC_nprocs || is_collecting()) { pthread_mutex_lock(&GC_allocate_ml); - } else { + } else { GC_generic_lock(&GC_allocate_ml); + } } -#else /* !NO_PTHREAD_TRYLOCK */ - pthread_mutex_lock(&GC_allocate_ml); -#endif /* !NO_PTHREAD_TRYLOCK */ -} +# elif defined(GC_ASSERTIONS) + GC_INNER void GC_lock(void) + { + pthread_mutex_lock(&GC_allocate_ml); + } +# endif -#endif /* !USE_SPIN_LOCK */ +#endif /* !USE_SPIN_LOCK && USE_PTHREAD_LOCKS */ #ifdef PARALLEL_MARK diff -Nru libgc-8.0.4/tests/disclaim_test.c libgc-8.0.6/tests/disclaim_test.c --- libgc-8.0.4/tests/disclaim_test.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/tests/disclaim_test.c 2021-11-25 21:36:27.000000000 +0000 @@ -84,7 +84,7 @@ } my_assert(memeq(p, 0, (size_t)1 << i)); memset(p, 0x56, (size_t)1 << i); - *(unsigned char *)p = i; + *(unsigned char *)p = (unsigned char)i; } } diff -Nru libgc-8.0.4/tests/disclaim_weakmap_test.c libgc-8.0.6/tests/disclaim_weakmap_test.c --- libgc-8.0.4/tests/disclaim_weakmap_test.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/tests/disclaim_weakmap_test.c 2021-11-25 21:36:27.000000000 +0000 @@ -98,7 +98,7 @@ my_assert(len % sizeof(GC_word) == 0); for (i = 0; i < len / sizeof(GC_word); ++i) { - acc = (2003 * acc + ((GC_word *)src)[i]) / 3; + acc = (unsigned)((2003 * (GC_word)acc + ((GC_word *)src)[i]) / 3); } return acc; } diff -Nru libgc-8.0.4/tests/smash_test.c libgc-8.0.6/tests/smash_test.c --- libgc-8.0.4/tests/smash_test.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/tests/smash_test.c 2021-11-25 21:36:27.000000000 +0000 @@ -13,6 +13,8 @@ char * A[COUNT]; +char * volatile q; + int main(void) { int i; @@ -23,8 +25,17 @@ for (i = 0; i < COUNT; ++i) { A[i] = p = (char*)GC_MALLOC(SIZE); - if (i%3000 == 0) GC_gcollect(); - if (i%5678 == 0 && p != 0) p[SIZE + i/2000] = 42; + if (i%3000 == 0) { + q = NULL; + GC_gcollect(); + } else if (i%5678 == 0 && p != 0) { + /* Write a byte past the end of the allocated object */ + /* but not beyond the last word of the object's memory. */ + /* A volatile intermediate pointer variable is used to */ + /* avoid a compiler complain of out-of-bounds access. */ + q = &p[(SIZE + i/2000) /* 42 */]; + *q = 42; + } } return 0; } diff -Nru libgc-8.0.4/tests/subthread_create.c libgc-8.0.6/tests/subthread_create.c --- libgc-8.0.4/tests/subthread_create.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/tests/subthread_create.c 2021-11-25 21:36:27.000000000 +0000 @@ -58,7 +58,7 @@ DWORD WINAPI entry(LPVOID arg) #endif { - int thread_num = AO_fetch_and_add1(&thread_created_cnt); + int thread_num = (int)AO_fetch_and_add1(&thread_created_cnt); GC_word my_depth = (GC_word)arg + 1; if (my_depth <= MAX_SUBTHREAD_DEPTH diff -Nru libgc-8.0.4/tests/test_cpp.cc libgc-8.0.6/tests/test_cpp.cc --- libgc-8.0.4/tests/test_cpp.cc 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/tests/test_cpp.cc 2021-11-25 21:36:27.000000000 +0000 @@ -14,7 +14,7 @@ usage: test_cpp number-of-iterations This program tries to test the specific C++ functionality provided by -gc_c++.h that isn't tested by the more general test routines of the +gc_cpp.h that isn't tested by the more general test routines of the collector. A recommended value for number-of-iterations is 10, which will take a @@ -76,7 +76,8 @@ exit( 1 ); } #ifndef GC_ATTR_EXPLICIT -# if (__cplusplus >= 201103L) || defined(CPPCHECK) +# if __cplusplus >= 201103L && !defined(__clang__) || _MSVC_LANG >= 201103L \ + || defined(CPPCHECK) # define GC_ATTR_EXPLICIT explicit # else # define GC_ATTR_EXPLICIT /* empty */ diff -Nru libgc-8.0.4/win32_threads.c libgc-8.0.6/win32_threads.c --- libgc-8.0.4/win32_threads.c 2019-03-02 08:54:41.000000000 +0000 +++ libgc-8.0.6/win32_threads.c 2021-11-25 21:36:27.000000000 +0000 @@ -74,6 +74,26 @@ #endif /* !GC_PTHREADS && !MSWINCE */ +/* PUSHED_REGS_COUNT is the number of copied registers in copy_ptr_regs. */ +static ptr_t copy_ptr_regs(word *regs, const CONTEXT *pcontext); +#if defined(I386) +# ifdef WOW64_THREAD_CONTEXT_WORKAROUND +# define PUSHED_REGS_COUNT 9 +# else +# define PUSHED_REGS_COUNT 7 +# endif +#elif defined(X86_64) || defined(SHx) +# define PUSHED_REGS_COUNT 15 +#elif defined(ARM32) +# define PUSHED_REGS_COUNT 13 +#elif defined(AARCH64) +# define PUSHED_REGS_COUNT 30 +#elif defined(MIPS) || defined(ALPHA) +# define PUSHED_REGS_COUNT 28 +#elif defined(PPC) +# define PUSHED_REGS_COUNT 29 +#endif + /* DllMain-based thread registration is currently incompatible */ /* with thread-local allocation, pthreads and WinCE. */ #if (defined(GC_DLL) || defined(GC_INSIDE_DLL)) \ @@ -254,6 +274,14 @@ # ifdef THREAD_LOCAL_ALLOC struct thread_local_freelists tlfs; # endif + +# ifdef RETRY_GET_THREAD_CONTEXT + ptr_t context_sp; + word context_regs[PUSHED_REGS_COUNT]; + /* Populated as part of GC_suspend() as */ + /* resume/suspend loop may be needed for the */ + /* call to GetThreadContext() to succeed. */ +# endif }; typedef struct GC_Thread_Rep * GC_thread; @@ -320,7 +348,7 @@ /* And now the version used if GC_win32_dll_threads is not set. */ /* This is a chained hash table, with much of the code borrowed */ -/* From the Posix implementation. */ +/* from the Posix implementation. */ #ifndef THREAD_TABLE_SZ # define THREAD_TABLE_SZ 256 /* Power of 2 (for speed). */ #endif @@ -329,8 +357,8 @@ STATIC GC_thread GC_threads[THREAD_TABLE_SZ]; /* It may not be safe to allocate when we register the first thread. */ -/* Thus we allocated one statically. It does not contain any field we */ -/* need to push ("next" and "status" fields are unused). */ +/* Thus we allocated one statically. It does not contain any pointer */ +/* field we need to push ("next" and "status" fields are unused). */ static struct GC_Thread_Rep first_thread; static GC_bool first_thread_used = FALSE; @@ -670,6 +698,10 @@ /* see GC_stop_world() for the information. */ t -> stack_base = 0; t -> id = 0; + t -> suspended = FALSE; +# ifdef RETRY_GET_THREAD_CONTEXT + t -> context_sp = NULL; +# endif AO_store_release(&t->tm.in_use, FALSE); } else # endif @@ -1166,41 +1198,101 @@ # endif } +#ifdef WOW64_THREAD_CONTEXT_WORKAROUND +# ifndef CONTEXT_EXCEPTION_ACTIVE +# define CONTEXT_EXCEPTION_ACTIVE 0x08000000 +# define CONTEXT_EXCEPTION_REQUEST 0x40000000 +# define CONTEXT_EXCEPTION_REPORTING 0x80000000 +# endif + static BOOL isWow64; /* Is running 32-bit code on Win64? */ +# define GET_THREAD_CONTEXT_FLAGS (isWow64 \ + ? CONTEXT_INTEGER | CONTEXT_CONTROL \ + | CONTEXT_EXCEPTION_REQUEST | CONTEXT_SEGMENTS \ + : CONTEXT_INTEGER | CONTEXT_CONTROL) +#else +# define GET_THREAD_CONTEXT_FLAGS (CONTEXT_INTEGER | CONTEXT_CONTROL) +#endif /* !WOW64_THREAD_CONTEXT_WORKAROUND */ + /* Suspend the given thread, if it's still active. */ STATIC void GC_suspend(GC_thread t) { # ifndef MSWINCE - /* Apparently the Windows 95 GetOpenFileName call creates */ - /* a thread that does not properly get cleaned up, and */ - /* SuspendThread on its descriptor may provoke a crash. */ - /* This reduces the probability of that event, though it still */ - /* appears there's a race here. */ DWORD exitCode; # endif +# ifdef RETRY_GET_THREAD_CONTEXT + int retry_cnt = 0; +# define MAX_SUSPEND_THREAD_RETRIES (1000 * 1000) +# endif + UNPROTECT_THREAD(t); -# ifndef MSWINCE - if (GetExitCodeThread(t -> handle, &exitCode) && - exitCode != STILL_ACTIVE) { + GC_acquire_dirty_lock(); + +# ifdef MSWINCE + /* SuspendThread() will fail if thread is running kernel code. */ + while (SuspendThread(THREAD_HANDLE(t)) == (DWORD)-1) { + GC_release_dirty_lock(); + Sleep(10); /* in millis */ + GC_acquire_dirty_lock(); + } +# elif defined(RETRY_GET_THREAD_CONTEXT) + for (;;) { + /* Apparently the Windows 95 GetOpenFileName call creates */ + /* a thread that does not properly get cleaned up, and */ + /* SuspendThread on its descriptor may provoke a crash. */ + /* This reduces the probability of that event, though it still */ + /* appears there is a race here. */ + if (GetExitCodeThread(t -> handle, &exitCode) + && exitCode != STILL_ACTIVE) { + GC_release_dirty_lock(); +# ifdef GC_PTHREADS + t -> stack_base = 0; /* prevent stack from being pushed */ +# else + /* This breaks pthread_join on Cygwin, which is guaranteed to */ + /* only see user threads. */ + GC_ASSERT(GC_win32_dll_threads); + GC_delete_gc_thread_no_free(t); +# endif + return; + } + + if (SuspendThread(t->handle) != (DWORD)-1) { + CONTEXT context; + + context.ContextFlags = GET_THREAD_CONTEXT_FLAGS; + if (GetThreadContext(t->handle, &context)) { + /* TODO: WoW64 extra workaround: if CONTEXT_EXCEPTION_ACTIVE */ + /* then Sleep(1) and retry. */ + t->context_sp = copy_ptr_regs(t->context_regs, &context); + break; /* success; the context pointer registers are saved */ + } + + /* Resume the thread, try to suspend it in a better location. */ + if (ResumeThread(t->handle) == (DWORD)-1) + ABORT("ResumeThread failed in suspend loop"); + } + if (retry_cnt > 1) { + GC_release_dirty_lock(); + Sleep(0); /* yield */ + GC_acquire_dirty_lock(); + } + if (++retry_cnt >= MAX_SUSPEND_THREAD_RETRIES) + ABORT("SuspendThread loop failed"); /* something must be wrong */ + } +# else + if (GetExitCodeThread(t -> handle, &exitCode) + && exitCode != STILL_ACTIVE) { + GC_release_dirty_lock(); # ifdef GC_PTHREADS t -> stack_base = 0; /* prevent stack from being pushed */ # else - /* this breaks pthread_join on Cygwin, which is guaranteed to */ - /* only see user pthreads */ GC_ASSERT(GC_win32_dll_threads); GC_delete_gc_thread_no_free(t); # endif return; } -# endif - GC_acquire_dirty_lock(); -# ifdef MSWINCE - /* SuspendThread() will fail if thread is running kernel code. */ - while (SuspendThread(THREAD_HANDLE(t)) == (DWORD)-1) - Sleep(10); /* in millis */ -# else if (SuspendThread(t -> handle) == (DWORD)-1) ABORT("SuspendThread failed"); -# endif /* !MSWINCE */ +# endif t -> suspended = (unsigned char)TRUE; GC_release_dirty_lock(); if (GC_on_thread_event) @@ -1386,89 +1478,25 @@ && !(last_info.Protect & PAGE_GUARD); } -#if defined(I386) - static BOOL isWow64; /* Is running 32-bit code on Win64? */ -#endif - -STATIC word GC_push_stack_for(GC_thread thread, DWORD me) -{ - ptr_t sp, stack_min; - - struct GC_traced_stack_sect_s *traced_stack_sect = - thread -> traced_stack_sect; - if (thread -> id == me) { - GC_ASSERT(thread -> thread_blocked_sp == NULL); - sp = GC_approx_sp(); - } else if ((sp = thread -> thread_blocked_sp) == NULL) { - /* Use saved sp value for blocked threads. */ - /* For unblocked threads call GetThreadContext(). */ - CONTEXT context; -# if defined(I386) -# ifndef CONTEXT_EXCEPTION_ACTIVE -# define CONTEXT_EXCEPTION_ACTIVE 0x08000000 -# define CONTEXT_EXCEPTION_REQUEST 0x40000000 -# define CONTEXT_EXCEPTION_REPORTING 0x80000000 -# endif - - if (isWow64) { - context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL - | CONTEXT_EXCEPTION_REQUEST - | CONTEXT_SEGMENTS; - } else -# endif - /* else */ { - context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; - } - if (!GetThreadContext(THREAD_HANDLE(thread), &context)) - ABORT("GetThreadContext failed"); - - /* Push all registers that might point into the heap. Frame */ - /* pointer registers are included in case client code was */ - /* compiled with the 'omit frame pointer' optimization. */ -# define PUSH1(reg) GC_push_one((word)context.reg) +/* Copy all registers that might point into the heap. Frame */ +/* pointer registers are included in case client code was */ +/* compiled with the 'omit frame pointer' optimization. */ +/* The context register values are stored to regs argument */ +/* which is expected to be of PUSHED_REGS_COUNT length exactly. */ +/* The functions returns the context stack pointer value. */ +static ptr_t copy_ptr_regs(word *regs, const CONTEXT *pcontext) { + ptr_t sp; + int cnt = 0; +# define context (*pcontext) +# define PUSH1(reg) (regs[cnt++] = (word)pcontext->reg) # define PUSH2(r1,r2) (PUSH1(r1), PUSH1(r2)) # define PUSH4(r1,r2,r3,r4) (PUSH2(r1,r2), PUSH2(r3,r4)) # if defined(I386) +# ifdef WOW64_THREAD_CONTEXT_WORKAROUND + PUSH2(ContextFlags, SegFs); /* cannot contain pointers */ +# endif PUSH4(Edi,Esi,Ebx,Edx), PUSH2(Ecx,Eax), PUSH1(Ebp); - /* WoW64 workaround. */ - if (isWow64 - && (context.ContextFlags & CONTEXT_EXCEPTION_REPORTING) != 0 - && (context.ContextFlags & (CONTEXT_EXCEPTION_ACTIVE - /* | CONTEXT_SERVICE_ACTIVE */)) != 0) { - LDT_ENTRY selector; - PNT_TIB tib; - - if (!GetThreadSelectorEntry(THREAD_HANDLE(thread), context.SegFs, - &selector)) - ABORT("GetThreadSelectorEntry failed"); - tib = (PNT_TIB)(selector.BaseLow - | (selector.HighWord.Bits.BaseMid << 16) - | (selector.HighWord.Bits.BaseHi << 24)); - /* GetThreadContext() might return stale register values, so */ - /* we scan the entire stack region (down to the stack limit). */ - /* There is no 100% guarantee that all the registers are pushed */ - /* but we do our best (the proper solution would be to fix it */ - /* inside Windows OS). */ - sp = (ptr_t)tib->StackLimit; -# ifdef DEBUG_THREADS - GC_log_printf("TIB stack limit/base: %p .. %p\n", - (void *)tib->StackLimit, (void *)tib->StackBase); -# endif - GC_ASSERT(!((word)thread->stack_base - COOLER_THAN (word)tib->StackBase)); - } else { -# ifdef DEBUG_THREADS - { - static GC_bool logged; - if (isWow64 && !logged - && (context.ContextFlags & CONTEXT_EXCEPTION_REPORTING) == 0) { - GC_log_printf("CONTEXT_EXCEPTION_REQUEST not supported\n"); - logged = TRUE; - } - } -# endif - sp = (ptr_t)context.Esp; - } + sp = (ptr_t)context.Esp; # elif defined(X86_64) PUSH4(Rax,Rcx,Rdx,Rbx); PUSH2(Rbp, Rsi); PUSH1(Rdi); PUSH4(R8, R9, R10, R11); PUSH4(R12, R13, R14, R15); @@ -1505,9 +1533,111 @@ PUSH4(IntA0,IntA1,IntA2,IntA3), PUSH4(IntA4,IntA5,IntT8,IntT9); PUSH4(IntT10,IntT11,IntT12,IntAt); sp = (ptr_t)context.IntSp; -# elif !defined(CPPCHECK) +# elif defined(CPPCHECK) + sp = (ptr_t)(word)cnt; /* to workaround "cnt not used" false positive */ +# else # error Architecture is not supported # endif +# undef context + GC_ASSERT(cnt == PUSHED_REGS_COUNT); + return sp; +} + +STATIC word GC_push_stack_for(GC_thread thread, DWORD me) +{ + ptr_t sp, stack_min; + + struct GC_traced_stack_sect_s *traced_stack_sect = + thread -> traced_stack_sect; + if (thread -> id == me) { + GC_ASSERT(thread -> thread_blocked_sp == NULL); + sp = GC_approx_sp(); + } else if ((sp = thread -> thread_blocked_sp) == NULL) { + /* Use saved sp value for blocked threads. */ + int i = 0; +# ifdef RETRY_GET_THREAD_CONTEXT + /* We cache context when suspending the thread since it may */ + /* require looping. */ + word *regs = thread->context_regs; + + if (thread->suspended) { + sp = thread->context_sp; + } else +# else + word regs[PUSHED_REGS_COUNT]; +# endif + + /* else */ { + CONTEXT context; + + /* For unblocked threads call GetThreadContext(). */ + context.ContextFlags = GET_THREAD_CONTEXT_FLAGS; + if (GetThreadContext(THREAD_HANDLE(thread), &context)) { + sp = copy_ptr_regs(regs, &context); + } else { +# ifdef RETRY_GET_THREAD_CONTEXT + /* At least, try to use the stale context if saved. */ + sp = thread->context_sp; + if (NULL == sp) { + /* Skip the current thread, anyway its stack will */ + /* be pushed when the world is stopped. */ + return 0; + } +# else + ABORT("GetThreadContext failed"); +# endif + } + } + +# ifdef WOW64_THREAD_CONTEXT_WORKAROUND + i += 2; /* skip ContextFlags and SegFs */ +# endif + for (; i < PUSHED_REGS_COUNT; i++) + GC_push_one(regs[i]); + +# ifdef WOW64_THREAD_CONTEXT_WORKAROUND + /* WoW64 workaround. */ + if (isWow64) { + DWORD ContextFlags = (DWORD)regs[0]; + WORD SegFs = (WORD)regs[1]; + + if ((ContextFlags & CONTEXT_EXCEPTION_REPORTING) != 0 + && (ContextFlags & (CONTEXT_EXCEPTION_ACTIVE + /* | CONTEXT_SERVICE_ACTIVE */)) != 0) { + LDT_ENTRY selector; + PNT_TIB tib; + + if (!GetThreadSelectorEntry(THREAD_HANDLE(thread), SegFs, &selector)) + ABORT("GetThreadSelectorEntry failed"); + tib = (PNT_TIB)(selector.BaseLow + | (selector.HighWord.Bits.BaseMid << 16) + | (selector.HighWord.Bits.BaseHi << 24)); +# ifdef DEBUG_THREADS + GC_log_printf("TIB stack limit/base: %p .. %p\n", + (void *)tib->StackLimit, (void *)tib->StackBase); +# endif + GC_ASSERT(!((word)thread->stack_base + COOLER_THAN (word)tib->StackBase)); + + /* GetThreadContext() might return stale register values, */ + /* so we scan the entire stack region (down to the stack */ + /* limit). There is no 100% guarantee that all the */ + /* registers are pushed but we do our best (the proper */ + /* solution would be to fix it inside Windows OS). */ + sp = (ptr_t)tib->StackLimit; + } /* else */ +# ifdef DEBUG_THREADS + else { + static GC_bool logged; + if (!logged + && (ContextFlags & CONTEXT_EXCEPTION_REPORTING) == 0) { + GC_log_printf("CONTEXT_EXCEPTION_REQUEST not supported\n"); + logged = TRUE; + } + } +# endif + } +# endif /* WOW64_THREAD_CONTEXT_WORKAROUND */ } /* ! current thread */ /* Set stack_min to the lowest address in the thread stack, */ @@ -1592,6 +1722,8 @@ return thread->stack_base - sp; /* stack grows down */ } +/* We hold allocation lock. Should do exactly the right thing if the */ +/* world is stopped. Should not fail if it isn't. */ GC_INNER void GC_push_all_stacks(void) { DWORD thread_id = GetCurrentThreadId(); @@ -2478,9 +2610,6 @@ GC_INNER void GC_thr_init(void) { struct GC_stack_base sb; -# ifdef GC_ASSERTIONS - int sb_result; -# endif GC_ASSERT(I_HOLD_LOCK()); if (GC_thr_initialized) return; @@ -2504,26 +2633,26 @@ } # endif -# if defined(I386) +# ifdef WOW64_THREAD_CONTEXT_WORKAROUND /* Set isWow64 flag. */ { HMODULE hK32 = GetModuleHandle(TEXT("kernel32.dll")); if (hK32) { FARPROC pfn = GetProcAddress(hK32, "IsWow64Process"); if (pfn - && !(*(BOOL (WINAPI*)(HANDLE, BOOL*))pfn)(GetCurrentProcess(), - &isWow64)) + && !(*(BOOL (WINAPI*)(HANDLE, BOOL*))(word)pfn)( + GetCurrentProcess(), &isWow64)) isWow64 = FALSE; /* IsWow64Process failed */ } } # endif /* Add the initial thread, so we can stop it. */ -# ifdef GC_ASSERTIONS - sb_result = + sb.mem_base = GC_stackbottom; + GC_ASSERT(sb.mem_base != NULL); +# ifdef IA64 + sb.reg_base = GC_register_stackbottom; # endif - GC_get_stack_base(&sb); - GC_ASSERT(sb_result == GC_SUCCESS); # if defined(PARALLEL_MARK) {