فهرست منبع

Update to bdwgc 8.3.0.04d7f70

Brucey 2 سال پیش
والد
کامیت
a382eda793
100فایلهای تغییر یافته به همراه4162 افزوده شده و 2271 حذف شده
  1. 177 0
      blitz.mod/bdwgc/.appveyor.yml
  2. 16 0
      blitz.mod/bdwgc/.gitattributes
  3. 174 0
      blitz.mod/bdwgc/.gitignore
  4. 868 0
      blitz.mod/bdwgc/.travis.yml
  5. 12 0
      blitz.mod/bdwgc/AUTHORS
  6. 222 97
      blitz.mod/bdwgc/CMakeLists.txt
  7. 618 48
      blitz.mod/bdwgc/ChangeLog
  8. 2 2
      blitz.mod/bdwgc/LICENSE
  9. 33 33
      blitz.mod/bdwgc/Makefile.am
  10. 133 129
      blitz.mod/bdwgc/Makefile.direct
  11. 17 16
      blitz.mod/bdwgc/NT_MAKEFILE
  12. 0 64
      blitz.mod/bdwgc/OS2_MAKEFILE
  13. 0 47
      blitz.mod/bdwgc/PCR-Makefile
  14. 21 21
      blitz.mod/bdwgc/README.md
  15. 0 174
      blitz.mod/bdwgc/SMakefile.amiga
  16. 12 13
      blitz.mod/bdwgc/WCC_MAKEFILE
  17. 87 73
      blitz.mod/bdwgc/allchblk.c
  18. 217 215
      blitz.mod/bdwgc/alloc.c
  19. 22 11
      blitz.mod/bdwgc/backgraph.c
  20. 24 19
      blitz.mod/bdwgc/blacklst.c
  21. 0 11
      blitz.mod/bdwgc/build/s60v3/bld.inf
  22. 0 78
      blitz.mod/bdwgc/build/s60v3/libgc.mmp
  23. 5 4
      blitz.mod/bdwgc/checksums.c
  24. 147 81
      blitz.mod/bdwgc/configure.ac
  25. 1 1
      blitz.mod/bdwgc/cord/cord.am
  26. 153 167
      blitz.mod/bdwgc/cord/cordbscs.c
  27. 27 18
      blitz.mod/bdwgc/cord/cordprnt.c
  28. 79 103
      blitz.mod/bdwgc/cord/cordxtra.c
  29. 33 9
      blitz.mod/bdwgc/cord/tests/cordtest.c
  30. 35 35
      blitz.mod/bdwgc/cord/tests/de.c
  31. 1 1
      blitz.mod/bdwgc/cord/tests/de_cmds.h
  32. 43 45
      blitz.mod/bdwgc/cord/tests/de_win.c
  33. 1 1
      blitz.mod/bdwgc/cord/tests/de_win.h
  34. 1 1
      blitz.mod/bdwgc/cord/tests/de_win.rc
  35. 65 62
      blitz.mod/bdwgc/darwin_stop_world.c
  36. 80 60
      blitz.mod/bdwgc/dbg_mlc.c
  37. 24 66
      blitz.mod/bdwgc/digimars.mak
  38. 0 6
      blitz.mod/bdwgc/doc/README.OS2
  39. 17 6
      blitz.mod/bdwgc/doc/README.cmake
  40. 4 4
      blitz.mod/bdwgc/doc/README.environment
  41. 84 63
      blitz.mod/bdwgc/doc/README.macros
  42. 0 11
      blitz.mod/bdwgc/doc/README.symbian
  43. 1 1
      blitz.mod/bdwgc/doc/debugging.md
  44. 1 1
      blitz.mod/bdwgc/doc/gcdescr.md
  45. 4 4
      blitz.mod/bdwgc/doc/gcinterface.md
  46. 15 15
      blitz.mod/bdwgc/doc/leak.md
  47. 36 19
      blitz.mod/bdwgc/doc/overview.md
  48. 0 0
      blitz.mod/bdwgc/doc/platforms/README.aix
  49. 13 7
      blitz.mod/bdwgc/doc/platforms/README.amiga
  50. 0 0
      blitz.mod/bdwgc/doc/platforms/README.arm_cross
  51. 0 0
      blitz.mod/bdwgc/doc/platforms/README.darwin
  52. 0 0
      blitz.mod/bdwgc/doc/platforms/README.dgux386
  53. 0 0
      blitz.mod/bdwgc/doc/platforms/README.emscripten
  54. 0 0
      blitz.mod/bdwgc/doc/platforms/README.ews4800
  55. 0 0
      blitz.mod/bdwgc/doc/platforms/README.hp
  56. 0 0
      blitz.mod/bdwgc/doc/platforms/README.linux
  57. 9 28
      blitz.mod/bdwgc/doc/platforms/README.mac
  58. 13 0
      blitz.mod/bdwgc/doc/platforms/README.os2
  59. 0 0
      blitz.mod/bdwgc/doc/platforms/README.sgi
  60. 1 1
      blitz.mod/bdwgc/doc/platforms/README.solaris2
  61. 65 0
      blitz.mod/bdwgc/doc/platforms/README.symbian
  62. 0 0
      blitz.mod/bdwgc/doc/platforms/README.uts
  63. 6 6
      blitz.mod/bdwgc/doc/platforms/README.win32
  64. 3 3
      blitz.mod/bdwgc/doc/platforms/README.win64
  65. 1 1
      blitz.mod/bdwgc/doc/porting.md
  66. 4 3
      blitz.mod/bdwgc/doc/scale.md
  67. 3 3
      blitz.mod/bdwgc/doc/simple_example.md
  68. 4 2
      blitz.mod/bdwgc/doc/tree.md
  69. 53 42
      blitz.mod/bdwgc/dyn_load.c
  70. 1 1
      blitz.mod/bdwgc/extra/AmigaOS.c
  71. 1 2
      blitz.mod/bdwgc/extra/gc.c
  72. 5 5
      blitz.mod/bdwgc/extra/msvc_dbg.c
  73. 1 1
      blitz.mod/bdwgc/extra/pcr_interface.c
  74. 2 2
      blitz.mod/bdwgc/extra/real_malloc.c
  75. 96 56
      blitz.mod/bdwgc/finalize.c
  76. 14 8
      blitz.mod/bdwgc/fnlz_mlc.c
  77. 2 2
      blitz.mod/bdwgc/gc_badalc.cc
  78. 3 3
      blitz.mod/bdwgc/gc_cpp.cc
  79. 2 2
      blitz.mod/bdwgc/gc_dlopen.c
  80. 14 11
      blitz.mod/bdwgc/gcj_mlc.c
  81. 41 30
      blitz.mod/bdwgc/headers.c
  82. 36 36
      blitz.mod/bdwgc/include/gc/cord.h
  83. 7 7
      blitz.mod/bdwgc/include/gc/cord_pos.h
  84. 4 6
      blitz.mod/bdwgc/include/gc/ec.h
  85. 101 80
      blitz.mod/bdwgc/include/gc/gc.h
  86. 3 3
      blitz.mod/bdwgc/include/gc/gc_allocator.h
  87. 6 6
      blitz.mod/bdwgc/include/gc/gc_backptr.h
  88. 2 2
      blitz.mod/bdwgc/include/gc/gc_config_macros.h
  89. 37 38
      blitz.mod/bdwgc/include/gc/gc_cpp.h
  90. 1 1
      blitz.mod/bdwgc/include/gc/gc_disclaim.h
  91. 1 1
      blitz.mod/bdwgc/include/gc/gc_gcj.h
  92. 11 9
      blitz.mod/bdwgc/include/gc/gc_inline.h
  93. 57 11
      blitz.mod/bdwgc/include/gc/gc_mark.h
  94. 2 2
      blitz.mod/bdwgc/include/gc/gc_pthread_redirects.h
  95. 7 7
      blitz.mod/bdwgc/include/gc/gc_tiny_fl.h
  96. 1 1
      blitz.mod/bdwgc/include/gc/gc_typed.h
  97. 1 1
      blitz.mod/bdwgc/include/gc/gc_version.h
  98. 2 1
      blitz.mod/bdwgc/include/gc/javaxfc.h
  99. 13 2
      blitz.mod/bdwgc/include/gc/leak_detector.h
  100. 1 3
      blitz.mod/bdwgc/include/include.am

+ 177 - 0
blitz.mod/bdwgc/.appveyor.yml

@@ -0,0 +1,177 @@
+version: 8.3.0-{build}
+
+image:
+- Visual Studio 2019
+
+environment:
+  STUDIO_VERSION_EDITION: Studio\2019\Community
+  CMAKE_CONFIG: Debug
+  TEST_TARGET: check
+  matrix:
+  - TARGET: cmake
+    CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=OFF -Dbuild_tests=ON -Denable_cplusplus=ON -Denable_gc_assertions=ON -Werror=deprecated -Dwithout_libatomic_ops=ON
+  - TARGET: cmake
+    CMAKE_OPTIONS: -Dbuild_tests=ON -Denable_cplusplus=ON -Denable_throw_bad_alloc_library=OFF -Denable_gc_assertions=ON -Denable_gc_debug=ON -Denable_threads=OFF
+  - TARGET: cmake
+    CFLAGS_EXTRA: -DNO_MSGBOX_ON_ERROR -DNO_MPROTECT_VDB -DGC_READ_ENV_FILE
+    CMAKE_CONFIG: Release
+    CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -Dbuild_tests=ON -Denable_cplusplus=ON -Denable_large_config=ON -Ddisable_gc_debug=ON
+  - TARGET: cmake
+    CMAKE_CONFIG: Release
+    CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=MinSizeRel -Denable_parallel_mark=OFF
+  - TARGET: cmake
+    CMAKE_OPTIONS: -Denable_gc_assertions=ON -Denable_thread_local_alloc=OFF -Ddisable_single_obj_compilation=ON
+  - TARGET: cmake
+    CFLAGS_EXTRA: -DGC_DISABLE_INCREMENTAL
+    CMAKE_OPTIONS: -Denable_gc_assertions=ON -Denable_gcj_support=OFF -Denable_parallel_mark=OFF -Denable_thread_local_alloc=OFF
+  - TARGET: cmake
+    CMAKE_OPTIONS: -A Win32 -Dbuild_tests=ON -Denable_cplusplus=ON -Denable_gc_assertions=ON -Denable_large_config=ON
+  - TARGET: cmake
+    CMAKE_OPTIONS: -A ARM -Denable_cplusplus=ON -Denable_gc_assertions=ON
+  - TARGET: cmake
+    CMAKE_OPTIONS: -A ARM64 -DCMAKE_BUILD_TYPE=Release -Denable_cplusplus=ON
+    CMAKE_CONFIG: Release
+  - TARGET: nmake
+    ARCH: x86
+    NMAKE_OPTIONS: enable_static=1
+  - TARGET: nmake
+    ARCH: x64
+    CFLAGS_EXTRA: /J
+  - TARGET: nmake
+    ARCH: x86
+    NMAKE_OPTIONS: nodebug=1
+  - TARGET: nmake
+    ARCH: x64
+    NMAKE_OPTIONS: disable_threads=1
+  - TARGET: djgpp-no-make
+    CFLAGS_EXTRA: -O3 -DALL_INTERIOR_POINTERS -DNO_EXECUTE_PERMISSION -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE -DGC_GCJ_SUPPORT
+  - TARGET: dmc
+    CFLAGS_EXTRA: -s
+  - TARGET: mingw
+  - TARGET: mingw
+    CFLAGS_EXTRA: -D GC_THREADS -D THREAD_LOCAL_ALLOC -D PARALLEL_MARK -D GC_ASSERTIONS -D EMPTY_GETENV_RESULTS -D GC_GCJ_SUPPORT -D USE_MUNMAP -D LARGE_CONFIG -D NO_MSGBOX_ON_ERROR
+  - TARGET: mingw
+    CFLAGS_EXTRA: -O3 -march=native -D GC_THREADS -D GC_GCJ_SUPPORT -D GC_TIME_LIMIT=10 -D WINXP_USE_PERF_COUNTER -D NO_MSGBOX_ON_ERROR
+  - TARGET: mingw-shared-no-make
+    CFLAGS_EXTRA: -D GC_THREADS -D GC_ASSERTIONS -D ENABLE_DISCLAIM -D GC_GCJ_SUPPORT -D GC_PREFER_MPROTECT_VDB -D GC_CALL=__stdcall -D GC_CALLBACK=__fastcall -D CONSOLE_LOG -D NO_MSGBOX_ON_ERROR
+  - TARGET: wcc
+    WCC_SYSTEM: OS2
+    CFLAGS_EXTRA: -DGC_ASSERTIONS
+    ENABLE_STATIC_OPT: "ENABLE_STATIC=1"
+    TEST_TARGET: check-deps
+    WCC_INC_SUBDIR: os2
+  - TARGET: wcc
+    WCC_SYSTEM: MSWIN32
+    CFLAGS_EXTRA: -DCONSOLE_LOG -DUSE_MMAP -DUSE_MUNMAP
+    WCC_INC_SUBDIR: nt
+  - TARGET: mingw-w64
+    CFLAGS_EXTRA: -D NO_MSGBOX_ON_ERROR
+  - TARGET: mingw-w64
+    CFLAGS_EXTRA: -D GC_THREADS -D THREAD_LOCAL_ALLOC -D PARALLEL_MARK -D GC_ASSERTIONS -D GC_GCJ_SUPPORT -D NO_RETRY_GET_THREAD_CONTEXT
+  - TARGET: cygwin
+    CONF_OPTIONS: --enable-cplusplus
+    CFLAGS_EXTRA: -D GCTEST_PRINT_VERBOSE
+  - TARGET: cygwin64
+    CONF_OPTIONS: --disable-threads
+    CFLAGS_EXTRA: -std=c11 -D USE_WINALLOC
+  - TARGET: cygwin64
+    CONF_OPTIONS: --enable-cplusplus
+    CFLAGS_EXTRA: -D GCTEST_PRINT_VERBOSE
+  - TARGET: cygwin
+    CONF_OPTIONS: --enable-cplusplus --disable-munmap --enable-gc-assertions --enable-redirect-malloc
+  - TARGET: cygwin64
+    CFLAGS_EXTRA: -D GC_ALWAYS_MULTITHREADED -D LINT2 -D TEST_MANUAL_VDB
+    CONF_OPTIONS: --enable-cplusplus --enable-gc-assertions --disable-shared
+
+clone_depth: 50
+
+install:
+- cmd: git clone --depth=50 https://github.com/ivmai/libatomic_ops.git
+
+build_script:
+- cmd: if [%TARGET%]==[cmake] (
+    mkdir out && cd out
+    && cmake %CMAKE_OPTIONS% -Denable_werror=ON -DCFLAGS_EXTRA="%CFLAGS_EXTRA%" ..
+    && cmake --build . --config %CMAKE_CONFIG% --verbose )
+- cmd: if [%TARGET%]==[nmake] (
+    "C:\Program Files (x86)\Microsoft Visual %STUDIO_VERSION_EDITION%\VC\Auxiliary\Build\vcvarsall.bat" %ARCH%
+    && nmake /f NT_MAKEFILE %NMAKE_OPTIONS% CFLAGS_EXTRA="/WX %CFLAGS_EXTRA%" )
+- cmd: if [%TARGET%]==[cygwin] (
+    C:\cygwin\bin\bash -e -l -c
+      "cd /cygdrive/c/projects/bdwgc && ./autogen.sh
+       && ./configure %CONF_OPTIONS% --enable-werror && cat include/config.h
+       && make -j CFLAGS_EXTRA='%CFLAGS_EXTRA%'" )
+- cmd: if [%TARGET%]==[cygwin64] (
+    C:\cygwin64\bin\bash -e -l -c
+      "cd /cygdrive/c/projects/bdwgc && ./autogen.sh
+       && ./configure %CONF_OPTIONS% --enable-werror && cat include/config.h
+       && make -j CFLAGS_EXTRA='%CFLAGS_EXTRA%'" )
+- cmd: if [%TARGET%]==[djgpp-no-make] (
+    appveyor DownloadFile "https://github.com/andrewwutw/build-djgpp/releases/download/v3.1/djgpp-mingw-gcc1020-standalone.zip"
+    && 7z x -o.. djgpp-mingw-gcc1020-standalone.zip > nul
+    && ..\djgpp\setenv.bat
+    && gcc -I include -Werror -Wall -Wextra -Wpedantic %CFLAGS_EXTRA% -c extra/gc.c )
+- cmd: if [%TARGET%]==[dmc] (
+    appveyor DownloadFile "http://ftp.digitalmars.com/Digital_Mars_C++/Patch/dm857c.zip"
+    && 7z x -o.. dm857c.zip > nul && set "path=%cd%\..\dm\bin;%path%"
+    && make -f digimars.mak CFLAGS_EXTRA="-wx %CFLAGS_EXTRA%" )
+- cmd: if [%TARGET%]==[mingw] (
+    C:\MinGW\msys\1.0\bin\bash -e -l -c
+      "cd /c/projects/bdwgc
+       && make -j -f Makefile.direct CC=gcc CFLAGS_EXTRA='-Werror -Wall -Wextra -Wpedantic %CFLAGS_EXTRA%'" )
+- cmd: if [%TARGET%]==[mingw-shared-no-make] (
+    C:\MinGW\msys\1.0\bin\bash -e -l -c
+      "cd /c/projects/bdwgc
+       && gcc -I include -D GC_BUILTIN_ATOMIC -D GC_DLL -Werror -Wall -Wextra -Wpedantic %CFLAGS_EXTRA% -shared -o gc.dll extra/gc.c" )
+- cmd: if [%TARGET%]==[mingw-w64] (
+    C:\msys64\usr\bin\bash -e -l -c
+      "cd /c/projects/bdwgc
+       && make -j -f Makefile.direct CC=gcc CFLAGS_EXTRA='-Werror -Wall -Wextra -Wpedantic %CFLAGS_EXTRA%'" )
+- cmd: if [%TARGET%]==[wcc] (
+    appveyor DownloadFile "https://master.dl.sourceforge.net/project/openwatcom/open-watcom-2.0-2017-11-01/ow-snapshot.7z"
+    && 7z x -o..\watcom ow-snapshot.7z > nul
+    && set "watcom=%cd%\..\watcom" && set "path=%cd%\..\watcom\binnt64"
+    && set "include=%cd%\..\watcom\h\%WCC_INC_SUBDIR%;%cd%\..\watcom\h"
+    && wmake -f WCC_MAKEFILE SYSTEM=%WCC_SYSTEM% %ENABLE_STATIC_OPT% CFLAGS_EXTRA="-we %CFLAGS_EXTRA%" )
+
+test_script:
+- cmd: if [%TARGET%]==[cmake] ( ctest --build-config %CMAKE_CONFIG% -j4 -V )
+- cmd: if [%TARGET%]==[nmake] (
+    "C:\Program Files (x86)\Microsoft Visual %STUDIO_VERSION_EDITION%\VC\Auxiliary\Build\vcvarsall.bat" %ARCH%
+    && nmake /f NT_MAKEFILE %TEST_TARGET% %NMAKE_OPTIONS% CFLAGS_EXTRA="/WX %CFLAGS_EXTRA%"
+    && nmake /f NT_MAKEFILE clean )
+- cmd: if [%TARGET%]==[cygwin] (
+    C:\cygwin\bin\bash -e -l -c
+      "cd /cygdrive/c/projects/bdwgc
+       && make -j check-without-test-driver CFLAGS_EXTRA='%CFLAGS_EXTRA%'" )
+- cmd: if [%TARGET%]==[cygwin64] (
+    C:\cygwin64\bin\bash -e -l -c
+      "cd /cygdrive/c/projects/bdwgc
+       && make -j check-without-test-driver CFLAGS_EXTRA='%CFLAGS_EXTRA%'" )
+- cmd: if [%TARGET%]==[djgpp-no-make] (
+    ..\djgpp\setenv.bat
+    && gcc -I include -Werror -Wall -Wextra -Wpedantic %CFLAGS_EXTRA% -o cordtest.exe cord/tests/cordtest.c cord/*.c gc.o
+    && gcc -I include -Werror -Wall -Wextra -Wpedantic %CFLAGS_EXTRA% -v -o gctest.exe tests/gctest.c gc.o )
+- cmd: if [%TARGET%]==[dmc] (
+    set "path=%cd%\..\dm\bin;%path%"
+    && make -f digimars.mak %TEST_TARGET% CFLAGS_EXTRA="-wx %CFLAGS_EXTRA%"
+    && type gctest.gc.log cpptest.gc.log
+    && make -f digimars.mak clean )
+- cmd: if [%TARGET%]==[mingw] (
+    C:\MinGW\msys\1.0\bin\bash -e -l -c
+      "cd /c/projects/bdwgc
+       && make -j -f Makefile.direct %TEST_TARGET% CC=gcc CFLAGS_EXTRA='-DGC_NOT_DLL -Werror -Wall -Wextra -Wpedantic %CFLAGS_EXTRA%'" )
+- cmd: if [%TARGET%]==[mingw-shared-no-make] (
+    C:\MinGW\msys\1.0\bin\bash -e -l -c
+      "cd /c/projects/bdwgc
+       && gcc -I include -D GC_BUILTIN_ATOMIC -D GC_DLL -Werror -Wall -Wextra -Wpedantic %CFLAGS_EXTRA% -o gctest.exe tests/gctest.c gc.dll
+       && gctest.exe" )
+- cmd: if [%TARGET%]==[mingw-w64] (
+    C:\msys64\usr\bin\bash -e -l -c
+      "cd /c/projects/bdwgc
+       && make -j -f Makefile.direct %TEST_TARGET% CC=gcc CFLAGS_EXTRA='-Werror -Wall -Wextra -Wpedantic %CFLAGS_EXTRA%'" )
+- cmd: if [%TARGET%]==[wcc] (
+    set "watcom=%cd%\..\watcom" && set "beginlibpath=%cd%\..\watcom\binp\dll"
+    && set "path=%cd%\..\watcom\binnt64;%cd%\..\watcom\binnt"
+    && wmake -f WCC_MAKEFILE %TEST_TARGET% SYSTEM=%WCC_SYSTEM% %ENABLE_STATIC_OPT% CFLAGS_EXTRA="-we %CFLAGS_EXTRA%"
+    && wmake -f WCC_MAKEFILE clean )

+ 16 - 0
blitz.mod/bdwgc/.gitattributes

@@ -0,0 +1,16 @@
+# Git repo attributes.
+
+# Ensure shell and configure-related files have LF enforced.
+*.ac text eol=lf
+*.am text eol=lf
+*.m4 text eol=lf
+*.sh text eol=lf
+
+# Ensure all text files have normalized line endings in the repository.
+* text=auto
+
+# These files should use CR/LF line ending:
+/digimars.mak -text
+
+# Note: "core.eol" configuration variable controls which line endings to use
+# for the normalized files in the working directory (the default is native).

+ 174 - 0
blitz.mod/bdwgc/.gitignore

@@ -0,0 +1,174 @@
+# Ignored files in bdwgc Git repo.
+
+# Binary files (in root dir, cord, tests):
+*.dll
+*.exe
+*.gcda
+*.gch
+*.gcno
+*.la
+*.lib
+*.lo
+*.o
+*.obj
+
+*.gc.log
+.dirstamp
+/*.a
+/*_bench.log
+/*_bench.trs
+/*_test
+/*test.log
+/*test.trs
+/.libs/
+/Makefile
+/add_gc_prefix
+/atomicopstest
+/base_lib
+/bdw-gc.pc
+/c++
+/config.cache
+/config.log
+/config.status
+/cord/cordtest
+/cord/de
+/cord/de_win.rbj
+/cord/de_win.res
+/cord/tests/de_win.rbj
+/cord/tests/de_win.res
+/cords
+/cordtest
+/core
+/cpptest
+/de
+/de.dir/
+/disclaim_bench
+/disclaimtest
+/dont_ar_1
+/dont_ar_3
+/dont_ar_4
+/gc-*
+/gc.log
+/gcname
+/gctest
+/gctest_dyn_link
+/gctest_irix_dyn_link
+/hugetest
+/if_mach
+/if_not_there
+/initfromthreadtest
+/leaktest
+/lib*.so
+/libtool
+/middletest
+/realloctest
+/smashtest
+/staticrootstest
+/subthreadcreatetest
+/sunos5gc.so
+/test-suite.log
+/test_atomic_ops
+/test_atomic_ops.log
+/test_atomic_ops.trs
+/test_cpp
+/test_cpp.cpp
+/test_cpp.log
+/test_cpp.trs
+/threadkeytest
+/threadleaktest
+/threadlibs
+/tracetest
+/weakmaptest
+
+/out/
+
+# Config, dependency and stamp files generated by configure:
+.deps/
+/include/config.h
+config.h.in~
+stamp-h1
+
+# External library (without trailing slash to allow symlinks):
+/libatomic_ops*
+/pthreads-w32*
+
+# These files are generated by autoreconf:
+/Makefile.in
+/aclocal.m4
+/autom4te.cache/
+/compile
+/config.guess
+/config.sub
+/configure
+/depcomp
+/include/config.h.in
+/install-sh
+/ltmain.sh
+/m4/libtool.m4
+/m4/ltoptions.m4
+/m4/ltsugar.m4
+/m4/ltversion.m4
+/m4/lt~obsolete.m4
+/missing
+/mkinstalldirs
+/test-driver
+
+# These files are generated by CMake:
+*.tlog
+/*.vcxproj
+/*.vcxproj.filters
+/CMakeCache.txt
+/CMakeFiles/
+/DartConfiguration.tcl
+/Testing/Temporary/
+/cord/CMakeFiles/
+/cord/Makefile
+/gc.sln
+/tests/*.vcxproj
+/tests/*.vcxproj.filters
+/tests/*test
+/tests/CMakeFiles/
+/tests/Makefile
+/tests/test_cpp
+CTestTestfile.cmake
+cmake_install.cmake
+
+# Rarely generated files (mostly by some Win/DOS compilers):
+/*.copied.c
+/*.csm
+/*.err
+/*.i
+/*.lb1
+/*.lnk
+/*.map
+/*.out
+/*.rbj
+/*.res
+/*.stackdump
+/*.sym
+/*.tmp
+*.bsc
+*.dll.manifest
+*.exp
+*.idb
+*.ilk
+*.pdb
+*.sbr
+*.tds
+gc.def
+
+# Stuff from VS build system and IDE
+*.vcproj.*.user
+.vs/
+
+# Code analysis tools:
+*.c.gcov
+*.cc.gcov
+*.h.gcov
+*.sancov
+/.sv*-dir
+/cov-int
+/coverage.info
+/pvs-project.log
+/pvs-project.tasks
+/strace_out

+ 868 - 0
blitz.mod/bdwgc/.travis.yml

@@ -0,0 +1,868 @@
+language: cpp
+os: linux
+
+jobs:
+  include:
+  - compiler: clang
+    env:
+    - CONF_OPTIONS="--enable-cplusplus"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: gcc
+    env:
+    - CONF_OPTIONS="--enable-cplusplus"
+  - os: osx
+    env:
+    - CONF_OPTIONS="--enable-cplusplus"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - env:
+    - COVERITY_SCAN_BRANCH=1
+    addons:
+      coverity_scan:
+        project:
+          name: ivmai/bdwgc
+          version: 8.3.0
+        notification_email: [email protected]
+        branch_pattern: master
+        build_command_prepend: "./configure --enable-cplusplus --disable-shared --enable-single-obj-compilation"
+        build_command: make -j check CFLAGS_EXTRA=-DLINT2
+  - addons:
+      apt:
+        packages:
+        - lcov
+    compiler: gcc
+    env:
+    - CONF_OPTIONS="--enable-gcov --enable-single-obj-compilation --enable-cplusplus --disable-shared --enable-gc-assertions"
+    - CFLAGS_EXTRA="-D USE_CUSTOM_SPECIFIC"
+    - CC_FOR_CHECK=g++
+    - MAKEFILE_TARGETS="all"
+    - MAKEFILE_TARGETS_CHECK="check"
+    - NO_CLONE_LIBATOMIC_OPS=true
+    - REPORT_COVERAGE=true
+    - TESTS_CUSTOM_RUN=true
+  - env:
+    - MAKEFILE_TARGETS="dist"
+  - os: osx
+    env:
+    - CSA_CHECK=true
+    - CFLAGS_EXTRA="-m32"
+  - compiler: clang
+    language: c
+    env:
+    - CSA_CHECK=true
+    - CFLAGS_EXTRA="-D ALL_INTERIOR_POINTERS -D CHECKSUMS -D DBG_HDRS_ALL -D DEBUG_THREADS -D ENABLE_TRACE -D GC_ALWAYS_MULTITHREADED -D GC_ASSERTIONS -D GC_ATOMIC_UNCOLLECTABLE -D GC_ENABLE_SUSPEND_THREAD -D GC_GCJ_SUPPORT -D GC_PRINT_BACK_HEIGHT -D GC_THREADS -D HANDLE_FORK -D JAVA_FINALIZATION -D KEEP_BACK_PTRS -D MAKE_BACK_GRAPH -D PARALLEL_MARK -D PRINT_BLACK_LIST -D THREAD_LOCAL_ALLOC -D USE_MMAP -D USE_MUNMAP"
+  - env:
+    - CPPCHECK_ENABLE="--enable=unusedFunction -I libatomic_ops/src extra/gc.c tests/*.c"
+  - env:
+    - CPPCHECK_ENABLE="--enable=unusedFunction --force -D GC_BUILTIN_ATOMIC *.cc cord/*.c cord/tests/*.c tests/*.c tests/*.cc"
+    - CPPCHECK_OUT_FILTER="Z"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - env:
+    - CPPCHECK_ENABLE="-j4 --enable=information,performance,portability,style,warning --force -U GC_PRIVATE_H -I libatomic_ops/src *.c"
+  - env:
+    - CPPCHECK_ENABLE="-j4 --enable=information,performance,portability,style,warning --force -U GC_PRIVATE_H -I libatomic_ops/src *.cc cord/*.c cord/tests/*.c extra/AmigaOS.c extra/MacOS.c extra/msvc_dbg.c extra/symbian.cpp tests/*.c tests/*.cc tools/*.c"
+  - arch: arm64
+    compiler: clang
+  - arch: arm64
+    compiler: gcc
+  - addons:
+      apt:
+        packages:
+        - clang-12
+        sources:
+        - ubuntu-toolchain-r-test
+    arch: arm64
+    compiler: clang-12
+    dist: focal
+    env:
+    - CC=clang-12
+    - CXX=clang++-12
+    - CFLAGS_EXTRA="-O3"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-cplusplus --disable-shared"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - g++-11
+        sources:
+        - ubuntu-toolchain-r-test
+    arch: arm64
+    compiler: g++-11
+    dist: bionic
+    env:
+    - CC=gcc-11
+    - CXX=g++-11
+    - CFLAGS_EXTRA="-O3 -D SIMULATE_LOST_SIGNALS"
+    - CONF_OPTIONS="--enable-cplusplus --disable-gcj-support"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - musl-tools
+    arch: arm64
+    compiler: musl-gcc
+    language: c
+    env:
+    - CFLAGS_EXTRA="-O3 -D SOFT_VDB"
+    - CONF_OPTIONS="--enable-gc-assertions"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - arch: arm64
+    compiler: gcc
+    env:
+    - CONF_OPTIONS="--disable-threads"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - arch: arm64
+    addons:
+      apt:
+        packages:
+        - libatomic-ops-dev
+    compiler: gcc
+    env:
+    - CONF_OPTIONS="--with-libatomic-ops=yes --enable-gc-assertions --enable-cplusplus --disable-munmap"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - clang-12
+        sources:
+        - ubuntu-toolchain-r-test
+    arch: arm64
+    compiler: clang-12
+    dist: focal
+    language: c
+    env:
+    - CFLAGS_EXTRA="-fsanitize=memory,undefined -fno-omit-frame-pointer"
+    - CONF_OPTIONS="--enable-static"
+    - NO_CLONE_LIBATOMIC_OPS=true
+    - TESTS_CUSTOM_RUN=true
+  - arch: arm64
+    compiler: clang
+    env:
+    - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=MinSizeRel -Dbuild_tests=ON -DBUILD_SHARED_LIBS=OFF -Denable_cplusplus=ON -Denable_gc_assertions=ON"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - arch: arm64
+    compiler: gcc
+    env:
+    - MAKEFILE_NAME=Makefile.direct
+    - MAKEFILE_TARGETS="check cord/de"
+  - arch: ppc64le
+    compiler: clang
+  - arch: ppc64le
+    compiler: gcc
+    env:
+    - CONF_OPTIONS="--disable-disclaim"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - clang-12
+        sources:
+        - ubuntu-toolchain-r-test
+    arch: ppc64le
+    compiler: clang-12
+    dist: focal
+    env:
+    - CC=clang-12
+    - CXX=clang++-12
+    - CFLAGS_EXTRA="-O3 -D _FORTIFY_SOURCE=2 -D FORCE_MPROTECT_BEFORE_MADVISE"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-cplusplus --enable-static"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - g++-11
+        sources:
+        - ubuntu-toolchain-r-test
+    arch: ppc64le
+    compiler: g++-11
+    dist: bionic
+    env:
+    - CC=gcc-11
+    - CXX=g++-11
+    - CFLAGS_EXTRA="-O3 -D NO_MPROTECT_VDB"
+    - CONF_OPTIONS="--enable-cplusplus"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - clang-12
+        sources:
+        - ubuntu-toolchain-r-test
+    arch: ppc64le
+    compiler: clang-12
+    dist: focal
+    language: c
+    env:
+    - CFLAGS_EXTRA="-fsanitize=memory,undefined -fno-omit-frame-pointer"
+    - CONF_OPTIONS="--disable-shared"
+    - NO_CLONE_LIBATOMIC_OPS=true
+    - TESTS_CUSTOM_RUN=true
+  - arch: ppc64le
+    compiler: clang
+    env:
+    - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -Dbuild_tests=ON -Denable_cplusplus=ON -Denable_gc_assertions=ON"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - arch: ppc64le
+    compiler: clang
+    env:
+    - MAKEFILE_NAME=Makefile.direct
+    - MAKEFILE_TARGETS="check cord/de"
+  - arch: s390x
+    compiler: clang
+  - arch: s390x
+    compiler: gcc
+  - addons:
+      apt:
+        packages:
+        - clang-12
+        sources:
+        - ubuntu-toolchain-r-test
+    arch: s390x
+    compiler: clang-12
+    dist: focal
+    env:
+    - CC=clang-12
+    - CXX=clang++-12
+    - CFLAGS_EXTRA="-O3 -flto -D _FORTIFY_SOURCE=2 -D NO_RETRY_SIGNALS"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-cplusplus"
+  - addons:
+      apt:
+        packages:
+        - g++-11
+        sources:
+        - ubuntu-toolchain-r-test
+    arch: s390x
+    compiler: g++-11
+    dist: bionic
+    env:
+    - CC=gcc-11
+    - CXX=g++-11
+    - CFLAGS_EXTRA="-O3 -flto=auto -D _FORTIFY_SOURCE=2 -D PREFER_MMAP_PROT_NONE"
+    - CONF_OPTIONS="--enable-cplusplus --disable-shared"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - arch: s390x
+    compiler: gcc
+    env:
+    - MAKEFILE_NAME=Makefile.direct
+    - MAKEFILE_TARGETS="check cord/de"
+  - os: freebsd
+    compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-O3 -D _FORTIFY_SOURCE=2"
+    - CONF_OPTIONS="--enable-cplusplus --enable-gc-assertions"
+    - MAKE_NPROC=8
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - os: freebsd
+    env:
+    - CONF_OPTIONS="--enable-cplusplus"
+    - MAKE_NPROC=8
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - os: freebsd
+    env:
+    - CONF_OPTIONS="--enable-gc-assertions --disable-shared"
+    - MAKE_NPROC=8
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - os: freebsd
+    env:
+    - CMAKE_BUILD_OPTIONS="--verbose"
+    - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -Denable_cplusplus=ON"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - os: freebsd
+    compiler: clang
+    env:
+    - MAKEFILE_NAME=Makefile.direct
+    - MAKEFILE_TARGETS="check cord/de"
+    - MAKE_NPROC=8
+  - addons:
+      apt:
+        packages:
+        - g++-11
+        sources:
+        - ubuntu-toolchain-r-test
+    compiler: g++-11
+    dist: bionic
+    env:
+    - CC=gcc-11
+    - CXX=g++-11
+    - CFLAGS_EXTRA="-O3 -march=native"
+    - CONF_OPTIONS="--enable-cplusplus"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-D _FORTIFY_SOURCE=2"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-cplusplus --enable-static"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - gcc-multilib
+    compiler: clang
+    env:
+    - CFLAGS_EXTRA="-m32 -funsigned-char -D _FORTIFY_SOURCE=2"
+    - CONF_OPTIONS="--enable-gc-assertions"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - gcc-multilib
+    compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-m32 -D _FORTIFY_SOURCE=2"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-mmap"
+  - os: osx
+    env:
+    - CFLAGS_EXTRA="-m32 -D _FORTIFY_SOURCE=2"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-cplusplus"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: gcc
+    env:
+    - CONF_OPTIONS="--disable-threads --enable-checksums --disable-munmap --enable-cplusplus"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-D _FORTIFY_SOURCE=2 -D DBG_HDRS_ALL -D SHORT_DBG_HDRS"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-cplusplus"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - os: osx
+    env:
+    - CFLAGS_EXTRA="-D DBG_HDRS_ALL -D SHORT_DBG_HDRS -D LINT2"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-cplusplus --enable-handle-fork=manual --disable-throw-bad-alloc-library"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-D DEBUG_ADD_DEL_ROOTS -D DEBUG_THREADS -D GC_DEBUG -D GC_LOG_TO_FILE_ALWAYS"
+    - CONF_OPTIONS="--enable-cplusplus"
+  - compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-D BSD_TIME -D DEFAULT_STACK_MAYBE_SMALL -D ENABLE_TRACE -D EMPTY_GETENV_RESULTS -D GC_ALWAYS_MULTITHREADED -D GC_NETBSD_THREADS_WORKAROUND -D CPPCHECK"
+    - CONF_OPTIONS="--enable-cplusplus --enable-gc-assertions"
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-march=native -D _FORTIFY_SOURCE=2 -D DEFAULT_VDB -D TEST_WITH_SYSTEM_MALLOC"
+    - CONF_OPTIONS="--without-libatomic-ops --enable-cplusplus --disable-handle-fork"
+  - addons:
+      apt:
+        packages:
+        - libatomic-ops-dev
+    compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-D _FORTIFY_SOURCE=2 -D TEST_PAGES_EXECUTABLE"
+    - CONF_OPTIONS="--with-libatomic-ops=yes --enable-gc-assertions --enable-cplusplus --disable-throw-bad-alloc-library"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - os: osx
+    env:
+    - CFLAGS_EXTRA="-march=native -D _FORTIFY_SOURCE=2 -D AO_DISABLE_GCC_ATOMICS"
+    - CONF_OPTIONS="--without-libatomic-ops --enable-munmap --enable-cplusplus --enable-static"
+  - compiler: gcc
+    env:
+    - CONF_CFLAGS="-D _FORTIFY_SOURCE=2 -D AO_USE_PTHREAD_DEFS"
+    - CONF_OPTIONS="--without-libatomic-ops --enable-gc-assertions --enable-cplusplus --enable-static"
+  - compiler: clang
+    env:
+    - CONF_CFLAGS="-D AO_USE_PTHREAD_DEFS"
+    - CONF_OPTIONS="--without-libatomic-ops"
+  - addons:
+      apt:
+        packages:
+        - libatomic-ops-dev
+    compiler: gcc
+    env:
+    - CONF_CFLAGS="-D AO_USE_PTHREAD_DEFS"
+    - CONF_OPTIONS="--with-libatomic-ops=yes --enable-cplusplus"
+    - CFLAGS_EXTRA="-D GC_NO_FINALIZATION"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - libatomic-ops-dev
+    compiler: clang
+    env:
+    - CONF_CFLAGS="-D AO_USE_PTHREAD_DEFS"
+    - CONF_OPTIONS="--with-libatomic-ops=yes --enable-gc-assertions --enable-cplusplus --disable-shared --enable-static"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-funsigned-char -D _FORTIFY_SOURCE=2 -D DONT_ADD_BYTE_AT_END -D GC_TIME_LIMIT=3"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-cplusplus"
+  - addons:
+      apt:
+        packages:
+        - gcc-multilib
+    compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-m32 -D _FORTIFY_SOURCE=2 -D MARK_BIT_PER_OBJ -D USE_CUSTOM_SPECIFIC"
+    - CONF_OPTIONS="--enable-gc-assertions"
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-D MARK_BIT_PER_OBJ"
+    - CONF_OPTIONS="--enable-cplusplus"
+  - compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-D _FORTIFY_SOURCE=2 -D NO_CLOCK -D POINTER_MASK=~0xf"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-cplusplus --enable-handle-fork=manual"
+  - compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-D PROC_VDB -D GC_NO_SYS_FAULT_H -D NO_INCREMENTAL -D DEBUG_DIRTY_BITS"
+    - CONF_OPTIONS="--enable-cplusplus --disable-docs"
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-D _FORTIFY_SOURCE=2 -D TEST_MANUAL_VDB"
+    - CONF_OPTIONS="--enable-gc-assertions --disable-parallel-mark"
+  - compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-D TEST_MANUAL_VDB"
+    - CONF_OPTIONS="--enable-gc-assertions --disable-munmap"
+  - compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-D _FORTIFY_SOURCE=2 -D FIND_LEAK -D SKIP_LEAKED_OBJECTS_PRINTING"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-cplusplus"
+  - compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-D SMALL_CONFIG -D NO_GETENV"
+    - CONF_OPTIONS="--enable-cplusplus"
+  - compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-std=c11 -D _FORTIFY_SOURCE=2 -D GC_NO_SIGSETJMP"
+    - CONF_OPTIONS="--disable-threads --enable-gc-assertions"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: clang
+    env:
+    - CONF_OPTIONS="--disable-thread-local-alloc --enable-cplusplus --enable-static"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-O3 -flto -D _FORTIFY_SOURCE=2"
+    - CONF_OPTIONS="--disable-parallel-mark --disable-thread-local-alloc --enable-gc-assertions --enable-cplusplus"
+  - compiler: gcc
+    env:
+    - CONF_OPTIONS="--enable-gc-debug --enable-cplusplus"
+  - compiler: gcc
+    env:
+    - CONF_OPTIONS="--disable-gc-debug --enable-cplusplus"
+  - compiler: clang
+    env:
+    - CONF_OPTIONS="--enable-large-config --enable-cplusplus --disable-shared --enable-static"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - os: osx
+    env:
+    - CFLAGS_EXTRA="-D TEST_HANDLE_FORK"
+    - CONF_OPTIONS="--enable-cplusplus --disable-shared --enable-static"
+  - os: osx
+    env:
+    - CONF_OPTIONS="--enable-large-config --enable-cplusplus --disable-handle-fork"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - gcc-multilib
+    compiler: gcc
+    env:
+    - CONF_OPTIONS="--enable-large-config --disable-munmap"
+    - CFLAGS_EXTRA="-m32"
+  - compiler: gcc
+    env:
+    - CONF_OPTIONS="--enable-large-config --enable-cplusplus --enable-gc-assertions --enable-static"
+    - CFLAGS_EXTRA="-D LINT2 -D NO_VDB_FOR_STATIC_ROOTS"
+  - compiler: gcc
+    env:
+    - CONF_OPTIONS="--enable-large-config --enable-redirect-malloc --disable-threads"
+    - CFLAGS_EXTRA="-O3"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - gcc-multilib
+    compiler: clang
+    env:
+    - CONF_OPTIONS="--enable-redirect-malloc --enable-static --disable-threads"
+    - CFLAGS_EXTRA="-m32"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - os: osx
+    env:
+    - CONF_OPTIONS="--enable-redirect-malloc --enable-cplusplus --enable-static --disable-threads"
+    - CFLAGS_EXTRA="-m32"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: gcc
+    env:
+    - CFLAGS_EXTRA="-D _FORTIFY_SOURCE=2"
+    - CONF_OPTIONS="--enable-redirect-malloc --enable-gc-debug --enable-cplusplus --enable-gc-assertions"
+  - compiler: clang
+    env:
+    - CONF_OPTIONS="--disable-threads --enable-cplusplus"
+    - CFLAGS_EXTRA="-O3 -march=native"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: gcc
+    env:
+    - CONF_OPTIONS="--disable-static --disable-threads --enable-cplusplus"
+    - CFLAGS_EXTRA="-O3 -march=native -D GC_PREFER_MPROTECT_VDB"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - os: osx
+    env:
+    - CONF_OPTIONS="--disable-threads --enable-cplusplus"
+    - CFLAGS_EXTRA="-O3 -march=native"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: clang
+    env:
+    - CMAKE_OPTIONS="-Denable_cplusplus=ON -Denable_gc_assertions=ON"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - libatomic-ops-dev
+    compiler: clang
+    env:
+    - CMAKE_OPTIONS="-Denable_cplusplus=ON -Denable_munmap=OFF -Dwith_libatomic_ops=ON"
+  - compiler: gcc
+    env:
+    - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -Denable_cplusplus=ON -Denable_large_config=ON"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: gcc
+    env:
+    - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=OFF -Denable_gc_debug=ON -Dwithout_libatomic_ops=ON"
+  - compiler: gcc
+    env:
+    - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -Denable_threads=OFF"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - os: osx
+    env:
+    - CMAKE_BUILD_OPTIONS="--verbose"
+    - CMAKE_OPTIONS="-Denable_cplusplus=ON"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - os: osx
+    env:
+    - CMAKE_BUILD_OPTIONS="--verbose"
+    - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -Denable_cplusplus=ON -Denable_gc_assertions=ON -Denable_large_config=ON"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: clang
+    env:
+    - MAKEFILE_NAME=Makefile.direct
+    - MAKEFILE_TARGETS="check cord/de"
+  - compiler: gcc
+    env:
+    - MAKEFILE_NAME=Makefile.direct
+    - MAKEFILE_TARGETS="check cord/de"
+  - os: osx
+    env:
+    - MAKEFILE_NAME=Makefile.direct
+    - MAKEFILE_TARGETS="check cord/de"
+  - addons:
+      apt:
+        packages:
+        - musl-tools
+    compiler: musl-gcc
+    language: c
+    env:
+    - CONF_OPTIONS="--disable-parallel-mark --enable-gc-assertions"
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-fsanitize=address -fno-common -fno-omit-frame-pointer"
+    - CONF_OPTIONS="--enable-cplusplus --enable-static"
+    - NO_CLONE_LIBATOMIC_OPS=true
+    - TESTS_CUSTOM_RUN=true
+  - addons:
+      apt:
+        packages:
+        - gcc-5
+        sources:
+        - ubuntu-toolchain-r-test
+    compiler: gcc-5
+    language: c
+    env:
+    - CFLAGS_EXTRA="-fsanitize=address -O0"
+    - CONF_OPTIONS="--enable-gc-assertions"
+    - LDFLAGS="-fuse-ld=gold"
+  - os: osx
+    env:
+    - CFLAGS_EXTRA="-fsanitize=address -m32 -fno-omit-frame-pointer"
+    - CONF_OPTIONS="--disable-shared --enable-cplusplus"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: clang
+    language: c
+    env:
+    - CFLAGS_EXTRA="-fsanitize=memory -fno-omit-frame-pointer -std=gnu11"
+    - CONF_OPTIONS="--enable-static"
+    - TESTS_CUSTOM_RUN=true
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-fsanitize=undefined -fno-common -fno-omit-frame-pointer"
+    - TESTS_CUSTOM_RUN=true
+    - CONF_OPTIONS="--enable-cplusplus --enable-static"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - gcc-11
+        sources:
+        - ubuntu-toolchain-r-test
+    compiler: gcc-11
+    dist: bionic
+    env:
+    - CFLAGS_EXTRA="-fsanitize=thread -fno-omit-frame-pointer"
+    - CONF_OPTIONS="--enable-gc-assertions"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - clang-12
+        sources:
+        - ubuntu-toolchain-r-test
+    compiler: clang-12
+    dist: focal
+    language: c
+    env:
+    - CFLAGS_EXTRA="-O3 -fsanitize=thread -fno-omit-frame-pointer"
+    - CONF_OPTIONS="--enable-static"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-fsanitize=thread -D NO_INCREMENTAL -fno-omit-frame-pointer -D TEST_FORK_WITHOUT_ATFORK"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-handle-fork=manual"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-fsanitize=thread -D NO_INCREMENTAL -fno-omit-frame-pointer -D TEST_FORK_WITHOUT_ATFORK"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-gc-debug --enable-handle-fork=manual --enable-large-config --without-libatomic-ops"
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-fsanitize=thread -fno-omit-frame-pointer -D NTHREADS=10"
+    - CONF_OPTIONS="--disable-parallel-mark"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-fsanitize=thread -D NO_INCREMENTAL -fno-omit-frame-pointer -D NTHREADS=0"
+    - CONF_OPTIONS="--disable-parallel-mark --disable-thread-local-alloc --disable-shared --enable-gc-assertions --without-libatomic-ops"
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-O3 -march=native"
+    - CONF_OPTIONS="--enable-cplusplus --enable-static --enable-single-obj-compilation"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - gcc-multilib
+    compiler: clang
+    env:
+    - CFLAGS_EXTRA="-m32 -D _FORTIFY_SOURCE=2 -D GC_DISABLE_INCREMENTAL -std=gnu11"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-gc-debug"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - gcc-8
+        - g++-8
+        sources:
+        - ubuntu-toolchain-r-test
+    compiler: gcc-8
+    language: c
+    env:
+    - CXX=g++-8
+    - CONF_OPTIONS="--enable-cplusplus --enable-gc-assertions --enable-static"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - gcc-8
+        - gcc-8-multilib
+        - gcc-multilib
+        sources:
+        - ubuntu-toolchain-r-test
+    compiler: gcc-8
+    language: c
+    env:
+    - CFLAGS_EXTRA="-m32 -O3 -std=gnu11"
+    - CONF_OPTIONS="--disable-shared --enable-static --enable-single-obj-compilation"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - addons:
+      apt:
+        packages:
+        - gcc-8
+        - gcc-8-multilib
+        - gcc-multilib
+        sources:
+        - ubuntu-toolchain-r-test
+    compiler: gcc-8
+    language: c
+    env:
+    - CFLAGS_EXTRA="-mx32 -march=native -D _FORTIFY_SOURCE=2"
+    - CONF_OPTIONS="--enable-large-config --enable-gc-assertions"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-x c++"
+    - CONF_OPTIONS="--enable-gc-assertions --enable-cplusplus --enable-gc-debug --disable-shared"
+    - MAKEFILE_TARGETS="all"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: gcc
+    env:
+    - CC_FOR_CHECK=g++
+    - CONF_OPTIONS="--enable-gc-assertions"
+    - MAKEFILE_TARGETS="all"
+    - MAKEFILE_TARGETS_CHECK="check"
+    - NO_CLONE_LIBATOMIC_OPS=true
+  - compiler: clang
+    env:
+    - CFLAGS_EXTRA="-O3 -Wall -Wextra -Werror -x c++"
+    - MAKEFILE_NAME=Makefile.direct
+    - MAKEFILE_TARGETS="cords"
+  - compiler: gcc
+    env:
+    - CC_FOR_CHECK=g++
+    - CFLAGS_EXTRA="-O3 -Wall -Wextra -Werror -D TEST_MANUAL_VDB"
+    - MAKEFILE_NAME=Makefile.direct
+    - MAKEFILE_TARGETS="cords"
+    - MAKEFILE_TARGETS_CHECK="cord/de check"
+  - addons:
+      apt:
+        packages:
+        - g++-mingw-w64
+        - gcc-mingw-w64
+    compiler: x86_64-w64-mingw32-gcc
+    language: c
+    env:
+    - CXX=x86_64-w64-mingw32-g++
+    - CONF_OPTIONS="--host=x86_64-w64-mingw32 --enable-cplusplus --enable-static"
+    - MAKEFILE_TARGETS="all"
+  - addons:
+      apt:
+        packages:
+        - gcc-mingw-w64
+    compiler: x86_64-w64-mingw32-gcc
+    language: c
+    env:
+    - CONF_OPTIONS="--host=x86_64-w64-mingw32 --enable-gc-assertions --enable-gc-debug --enable-threads=pthreads"
+    - MAKEFILE_TARGETS="all"
+  - addons:
+      apt:
+        packages:
+        - gcc-mingw-w64
+    compiler: i686-w64-mingw32-gcc
+    language: c
+    env:
+    - CONF_OPTIONS="--host=i686-w64-mingw32"
+    - MAKEFILE_TARGETS="all"
+    - CFLAGS_EXTRA="-fno-omit-frame-pointer"
+  - dist: focal
+    env:
+    - MAKEFILE_TARGETS="distcheck"
+    - AUTOMAKE_VER=1.16.5
+    - LIBTOOL_VER=2.4.6
+    - NO_CLONE_LIBATOMIC_OPS=true
+
+before_install:
+- if [[ "$CPPCHECK_ENABLE" != "" ]]; then
+    CPPCHECK_VER=2.4.1;
+    git clone --depth=3 https://github.com/danmar/cppcheck.git
+            ~/cppcheck -b $CPPCHECK_VER;
+    make --directory ~/cppcheck -j8 CXXFLAGS="-O3 -march=native -D NDEBUG";
+  fi
+- if [[ "$AUTOMAKE_VER" != "" || "$LIBTOOL_VER" != ""
+        || "$M4_VER" != "" ]]; then
+    GNUTOOLS_ROOT=`pwd`/../gnu-tools;
+    export PATH=$GNUTOOLS_ROOT/bin:$PATH;
+    GNU_DOWNLOAD_SITE=https://ftp.gnu.org/gnu;
+  fi
+- if [[ "$M4_VER" != "" ]]; then
+    M4_XZ_URL=$GNU_DOWNLOAD_SITE/m4/m4-$M4_VER.tar.xz;
+    wget -O - $M4_XZ_URL | tar xf - --xz --directory ~;
+    (cd ~/m4-$M4_VER && ./configure --prefix=$GNUTOOLS_ROOT && make -j check && make install);
+  fi
+- if [[ "$LIBTOOL_VER" != "" ]]; then
+    LIBTOOL_XZ_URL=$GNU_DOWNLOAD_SITE/libtool/libtool-$LIBTOOL_VER.tar.xz;
+    wget -O - $LIBTOOL_XZ_URL | tar xf - --xz --directory ~;
+    (cd ~/libtool-$LIBTOOL_VER && ./configure --prefix=$GNUTOOLS_ROOT && make -j && make install);
+  fi
+- if [[ "$AUTOMAKE_VER" != "" ]]; then
+    AUTOMAKE_XZ_URL=$GNU_DOWNLOAD_SITE/automake/automake-$AUTOMAKE_VER.tar.xz;
+    wget -O - $AUTOMAKE_XZ_URL | tar xf - --xz --directory ~;
+    (cd ~/automake-$AUTOMAKE_VER && ./configure --prefix=$GNUTOOLS_ROOT && make -j && make install);
+  fi
+- if [[ "$MAKEFILE_TARGETS" == *"dist"* ]]; then
+    autoconf --version;
+    automake --version;
+    m4 --version;
+    libtool --version || true;
+  fi
+- if [[ "$CMAKE_OPTIONS" != "" ]]; then
+    cmake --version;
+  fi
+- if [[ "$CONF_CFLAGS" == "" ]]; then CONF_CFLAGS="-g -O2"; fi
+- if [[ "$MAKEFILE_NAME" == "" ]]; then MAKEFILE_NAME=Makefile; fi
+- if [[ "$MAKEFILE_TARGETS" == "" ]]; then MAKEFILE_TARGETS="check"; fi
+
+install:
+- if [[ "$NO_CLONE_LIBATOMIC_OPS" != true ]]; then
+    git clone --depth=50 https://github.com/ivmai/libatomic_ops.git;
+  fi
+- if [[ "$CMAKE_OPTIONS" == "" ]]; then
+    ./autogen.sh;
+  fi
+- if [[ "$GNUTOOLS_ROOT" != "" ]]; then mv $GNUTOOLS_ROOT $GNUTOOLS_ROOT-x; fi
+- if [[ "$REPORT_COVERAGE" == true ]]; then gem install coveralls-lcov; fi
+
+script:
+- if [[ "$CSA_CHECK" != true && "$CMAKE_OPTIONS" == ""
+        && "$CPPCHECK_ENABLE" == "" && "$MAKEFILE_NAME" != "Makefile.direct"
+        && "$COVERITY_SCAN_BRANCH" != 1 ]]; then
+    CFLAGS="$CONF_CFLAGS" ./configure $CONF_OPTIONS --enable-werror &&
+    cat include/config.h;
+  fi
+- if [[ "$CSA_CHECK" != true && "$CMAKE_OPTIONS" == ""
+        && "$CPPCHECK_ENABLE" == "" && "$COVERITY_SCAN_BRANCH" != 1 ]]; then
+    make -j$MAKE_NPROC -f $MAKEFILE_NAME $MAKEFILE_TARGETS
+         CFLAGS_EXTRA="$CFLAGS_EXTRA" LDFLAGS="$LDFLAGS";
+  fi
+- if [[ "$CMAKE_OPTIONS" != "" ]]; then
+    cmake $CMAKE_OPTIONS -Dbuild_tests=ON -Denable_werror=ON -Werror=dev .
+    && cmake --build . $CMAKE_BUILD_OPTIONS;
+  fi
+- if [[ "$CMAKE_OPTIONS" != "" ]]; then
+    ctest -j4 -V;
+  fi
+- if [[ "$CC_FOR_CHECK" != "" ]]; then
+    make -f $MAKEFILE_NAME $MAKEFILE_TARGETS_CHECK CC=$CC_FOR_CHECK
+            CFLAGS_EXTRA="$CFLAGS_EXTRA";
+  fi
+- if [ -f cordtest.log ]; then cat cordtest.log; fi
+- if [ -f disclaim_bench.log ]; then cat disclaim_bench.log; fi
+- if [ -f disclaimtest.log ]; then cat disclaimtest.log; fi
+- if [ -f gctest.log ]; then cat gctest.log; fi
+- if [ -f threadkeytest.log ]; then cat threadkeytest.log; fi
+- if [ -f threadleaktest.log ]; then cat threadleaktest.log; fi
+- if [ -f weakmaptest.log ]; then cat weakmaptest.log; fi
+- if [[ "$CSA_CHECK" == true ]]; then
+    set -o pipefail; ${CC} --analyze -Xanalyzer -analyzer-output=text -Werror
+        -I include -I libatomic_ops/src $CFLAGS_EXTRA
+        *.c *.cc cord/*.c cord/tests/cordtest.c cord/tests/de.c extra/gc.c
+        extra/msvc_dbg.c extra/pcr_interface.c extra/real_malloc.c
+        tests/*.c tests/*.cc tools/*.c 2>&1 | tee clang-analyzer-output.log;
+    if [ -s clang-analyzer-output.log ]; then exit 1; fi;
+  fi
+- if [[ "$CPPCHECK_ENABLE" != "" ]]; then
+    if [[ "$CPPCHECK_OUT_FILTER" == "" ]]; then CPPCHECK_OUT_FILTER="c "; fi;
+    set -o pipefail; ~/cppcheck/cppcheck --error-exitcode=2
+        -U GC_API -D CPPCHECK -I include $CPPCHECK_ENABLE |
+        grep --line-buffered "$CPPCHECK_OUT_FILTER";
+  fi
+- if [[ "$TESTS_CUSTOM_RUN" == true ]]; then
+    ASAN_OPTIONS="detect_leaks=1" UBSAN_OPTIONS="halt_on_error=1"
+        make check-without-test-driver;
+  fi
+
+after_success:
+- if [[ "$REPORT_COVERAGE" == true ]]; then
+    lcov --capture --base-directory . --directory . --output-file coverage.info;
+    lcov --remove coverage.info '/usr/*' 'cord/tests/*' 'libatomic_ops/*' 'tests/*' --output-file coverage.info;
+    lcov --list coverage.info;
+    coveralls-lcov --repo-token ${COVERALLS_TOKEN} coverage.info;
+    bash <(curl -s https://codecov.io/bash);
+  fi
+
+deploy:
+  provider: releases
+  edge: true
+  file: gc-*.tar.gz
+  file_glob: true
+  on:
+    condition: $MAKEFILE_TARGETS = distcheck
+    repo: ivmai/bdwgc
+    tags: true

+ 12 - 0
blitz.mod/bdwgc/AUTHORS

@@ -61,6 +61,7 @@ Andy Wingo <[email protected]>
 Anselm Baird-Smith <[email protected]>
 Anthony Green <[email protected]>
 Antoine de Maricourt
+Anuraag Agrawal <[email protected]>
 Ari Huttunen <[email protected]>
 Arrigo Triulzi <[email protected]>
 Ashley Bone <[email protected]>
@@ -137,10 +138,12 @@ David Stes <[email protected]>
 David Terei <[email protected]>
 David Van Horn <[email protected]>
 Davide Angelocola <[email protected]>
+Davide Beatrici <[email protected]>
 Demyan Kimitsa <[email protected]>
 Dick Porter <[email protected]>
 Dietmar Planitzer <[email protected]>
 Dima Pasechnik <[email protected]>
+Dimitris Apostolou <[email protected]>
 Dimitris Vyzovitis <[email protected]>
 Dimitry Andric <[email protected]>
 Djamel Magri <[email protected]>
@@ -168,6 +171,7 @@ George Koehler <[email protected]>
 George Talbot <[email protected]>
 Gerard A Allan
 Glauco Masotti <[email protected]>
+Greg Steuck <[email protected]>
 Grzegorz Jakacki <[email protected]>
 Gustavo Giraldez <[email protected]>
 Gustavo Rodriguez-Rivera <[email protected]>
@@ -187,6 +191,7 @@ Iain Sandoe <[email protected]>
 Ian Piumarta <[email protected]>
 Ian Searle <[email protected]>
 Igor Khavkine <[email protected]>
+Ilya Kurdyukov <[email protected]>
 Ivan Demakov <[email protected]>
 Ivan Maidanski <[email protected]>
 Ivan R <[email protected]>
@@ -257,6 +262,7 @@ Klemens Zwischenbrugger <[email protected]>
 Knut Tvedten <[email protected]>
 Krister Walfridsson <[email protected]>
 Kristian Kristensen <[email protected]>
+Kristian Larsson <[email protected]>
 Kumar Srikantan
 Kurt Miller <[email protected]>
 Lars Farm <[email protected]>
@@ -265,6 +271,7 @@ Leonardo Taccari <[email protected]>
 Linas Vepstas <[email protected]>
 Loren J. Rittle <[email protected]>
 Louis Zhuang <[email protected]>
+Lucas Holt <[email protected]>
 Lucas Meijer <[email protected]>
 Ludovic Courtes <[email protected]>
 Maarten Thibaut <[email protected]>
@@ -294,6 +301,7 @@ Matthias Drochner <[email protected]>
 Matthieu Herrb <[email protected]>
 Maurizio Vairani <[email protected]>
 Max Mouratov <[email protected]>
+Maximilian Downey Twiss <[email protected]>
 Maya Rashish <[email protected]>
 Melissa O'Neill <[email protected]>
 Michael Arnoldus <[email protected]>
@@ -370,6 +378,7 @@ Richard Zidlicky <[email protected]>
 Rob Haack <[email protected]>
 Robert Brazile <[email protected]>
 Rodrigo Kumpera <[email protected]>
+Roger Pack <[email protected]>
 Roger Sayle <[email protected]>
 Roland McGrath <[email protected]>
 Roman Hodek <[email protected]>
@@ -379,6 +388,7 @@ Rutger Ovidius <[email protected]>
 Ryan Gonzalez <[email protected]>
 Ryan Murray <[email protected]>
 Salvador Eduardo Tropea <[email protected]>
+Sam James <[email protected]>
 Samuel Martin <[email protected]>
 Samuel Thibault <[email protected]>
 Scott Ananian <[email protected]>
@@ -388,6 +398,7 @@ Shawn Wagner <[email protected]>
 Shea Levy <[email protected]>
 Shiro Kawai <[email protected]>
 Simon Gornall <[email protected]>
+Simon Kainz <[email protected]>
 Simon Posnjak <[email protected]>
 Slava Sysoltsev <[email protected]>
 Sorawee Porncharoenwase <[email protected]>
@@ -438,6 +449,7 @@ Walter Underwood <[email protected]>
 Wilson Ho <[email protected]>
 Wink Saville <[email protected]>
 Wookey <[email protected]>
+wzx <[email protected]>
 Xi Wang <[email protected]>
 Xiaokun Zhu <[email protected]>
 Yann Dirson <[email protected]>

+ 222 - 97
blitz.mod/bdwgc/CMakeLists.txt

@@ -3,13 +3,13 @@
 # Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
 # Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
 # Copyright (c) 2000-2010 by Hewlett-Packard Company.  All rights reserved.
-# Copyright (c) 2010-2021 Ivan Maidanski
+# Copyright (c) 2010-2022 Ivan Maidanski
 ##
 # THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
 # OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 ##
 # Permission is hereby granted to use or copy this program
-# for any purpose,  provided the above notices are retained on all copies.
+# for any purpose, provided the above notices are retained on all copies.
 # Permission to modify the code and to distribute modified code is granted,
 # provided the above notices are retained, and a notice that the code was
 # modified is included with the above copyright notice.
@@ -30,8 +30,8 @@ set(PACKAGE_VERSION 8.3.0)
 
 # Info (current:revision:age) for the Libtool versioning system.
 # These values should match those in cord/cord.am and Makefile.am.
-set(LIBCORD_VER_INFO    5:0:4)
-set(LIBGC_VER_INFO      6:0:5)
+set(LIBCORD_VER_INFO    6:0:5)
+set(LIBGC_VER_INFO      6:1:5)
 set(LIBGCCPP_VER_INFO   6:0:5)
 
 option(enable_cplusplus "C++ support" OFF)
@@ -41,6 +41,11 @@ else()
   project(gc C)
 endif()
 
+if (POLICY CMP0057)
+  # Required for CheckLinkerFlag, at least.
+  cmake_policy(SET CMP0057 NEW)
+endif()
+
 include(CheckCCompilerFlag)
 include(CheckCSourceCompiles)
 include(CheckFunctionExists)
@@ -50,6 +55,10 @@ include(CMakePackageConfigHelpers)
 include(CTest)
 include(GNUInstallDirs)
 
+if (NOT (${CMAKE_VERSION} VERSION_LESS "3.18.0"))
+  include(CheckLinkerFlag)
+endif()
+
 # Customize the build by passing "-D<option_name>=ON|OFF" in the command line.
 option(BUILD_SHARED_LIBS "Build shared libraries" ON)
 option(build_cord "Build cord library" ON)
@@ -77,9 +86,22 @@ option(enable_register_main_static_data "Perform the initial guess of data root
 option(enable_checksums "Report erroneously cleared dirty bits" OFF)
 option(enable_werror "Pass -Werror to the C compiler (treat warnings as errors)" OFF)
 option(enable_single_obj_compilation "Compile all libgc source files into single .o" OFF)
+option(disable_single_obj_compilation "Compile each libgc source file independently" OFF)
 option(enable_handle_fork "Attempt to ensure a usable collector after fork()" ON)
 option(disable_handle_fork "Prohibit installation of pthread_atfork() handlers" OFF)
+option(enable_emscripten_asyncify "Use Emscripten asyncify feature" OFF)
 option(install_headers "Install header and pkg-config metadata files" ON)
+option(with_libatomic_ops "Use an external libatomic_ops" OFF)
+option(without_libatomic_ops "Use atomic_ops.h in libatomic_ops/src" OFF)
+
+# Override the default build type to RelWithDebInfo (this instructs cmake to
+# pass -O2 -g -DNDEBUG options to the compiler by default).
+if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+  set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE
+      STRING "Choose the type of build." FORCE)
+  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
+               STRINGS "Debug" "Release" "RelWithDebInfo" "MinSizeRel")
+endif()
 
 # Convert VER_INFO values to [SO]VERSION ones.
 if (BUILD_SHARED_LIBS)
@@ -88,22 +110,22 @@ if (BUILD_SHARED_LIBS)
   string(REGEX REPLACE ".+:(.+):.+"  "\\1" cord_rev ${LIBCORD_VER_INFO})
   string(REGEX REPLACE ".+:.+:(.+)$" "\\1" cord_age ${LIBCORD_VER_INFO})
   math(EXPR CORD_SOVERSION "${cord_cur} - ${cord_age}")
-  set(CORD_VERSION "${CORD_SOVERSION}.${cord_age}.${cord_rev}")
-  message(STATUS "CORD_VERSION = ${CORD_VERSION}")
+  set(CORD_VERSION_PROP "${CORD_SOVERSION}.${cord_age}.${cord_rev}")
+  message(STATUS "CORD_VERSION_PROP = ${CORD_VERSION_PROP}")
   # gc:
   string(REGEX REPLACE "(.+):.+:.+"  "\\1" gc_cur ${LIBGC_VER_INFO})
   string(REGEX REPLACE ".+:(.+):.+"  "\\1" gc_rev ${LIBGC_VER_INFO})
   string(REGEX REPLACE ".+:.+:(.+)$" "\\1" gc_age ${LIBGC_VER_INFO})
   math(EXPR GC_SOVERSION "${gc_cur} - ${gc_age}")
-  set(GC_VERSION "${GC_SOVERSION}.${gc_age}.${gc_rev}")
-  message(STATUS "GC_VERSION = ${GC_VERSION}")
+  set(GC_VERSION_PROP "${GC_SOVERSION}.${gc_age}.${gc_rev}")
+  message(STATUS "GC_VERSION_PROP = ${GC_VERSION_PROP}")
   # gccpp and gctba:
   string(REGEX REPLACE "(.+):.+:.+"  "\\1" gccpp_cur ${LIBGCCPP_VER_INFO})
   string(REGEX REPLACE ".+:(.+):.+"  "\\1" gccpp_rev ${LIBGCCPP_VER_INFO})
   string(REGEX REPLACE ".+:.+:(.+)$" "\\1" gccpp_age ${LIBGCCPP_VER_INFO})
   math(EXPR GCCPP_SOVERSION "${gccpp_cur} - ${gccpp_age}")
-  set(GCCPP_VERSION "${GCCPP_SOVERSION}.${gccpp_age}.${gccpp_rev}")
-  message(STATUS "GCCPP_VERSION = ${GCCPP_VERSION}")
+  set(GCCPP_VERSION_PROP "${GCCPP_SOVERSION}.${gccpp_age}.${gccpp_rev}")
+  message(STATUS "GCCPP_VERSION_PROP = ${GCCPP_VERSION_PROP}")
 endif(BUILD_SHARED_LIBS)
 
 add_definitions("-DALL_INTERIOR_POINTERS -DNO_EXECUTE_PERMISSION")
@@ -118,11 +140,10 @@ endif()
 # Output all warnings.
 if (BORLAND)
   # All warnings except for particular ones.
-  add_compile_options(/w /w-pro /w-aus /w-par /w-ccc /w-inl /w-rch)
+  add_compile_options(/w /w-aus /w-ccc /w-inl /w-pro /w-rch)
 elseif (MSVC)
-  # All warnings but ignoring "unreferenced formal parameter" and
-  # "conditional expression is constant" ones.
-  add_compile_options(/W4 /wd4100 /wd4127)
+  # All warnings but ignoring "conditional expression is constant" one.
+  add_compile_options(/W4 /wd4127)
   # Disable crt security warnings, since unfortunately they warn about all
   # sorts of safe uses of strncpy.
   add_definitions("-D_CRT_SECURE_NO_DEPRECATE")
@@ -139,7 +160,11 @@ set(SRC alloc.c reclaim.c allchblk.c misc.c mach_dep.c os_dep.c
         mark_rts.c headers.c mark.c obj_map.c blacklst.c finalize.c
         new_hblk.c dbg_mlc.c malloc.c dyn_load.c typd_mlc.c ptr_chck.c
         mallocx.c)
+set(NODIST_SRC)
+set(ATOMIC_OPS_LIBS)
+set(ATOMIC_OPS_LIBS_CMAKE)
 set(THREADDLLIBS_LIST)
+set(NEED_LIB_RT)
 
 set(_HOST ${CMAKE_SYSTEM_PROCESSOR}-unknown-${CMAKE_SYSTEM})
 string(TOLOWER ${_HOST} HOST)
@@ -148,8 +173,38 @@ message(STATUS "TARGET = ${HOST}")
 if (enable_threads)
   find_package(Threads REQUIRED)
   message(STATUS "Thread library: ${CMAKE_THREAD_LIBS_INIT}")
-  include_directories(libatomic_ops/src)
   include_directories(${Threads_INCLUDE_DIR})
+  if (with_libatomic_ops)
+    if (without_libatomic_ops)
+      message(FATAL_ERROR
+        "with_libatomic_ops and without_libatomic_ops are mutually exclusive")
+    endif()
+    set(ATOMIC_OPS_LIBS "-latomic_ops")
+    find_package(Atomic_ops CONFIG)
+    if (Atomic_ops_FOUND)
+      get_target_property(AO_INCLUDE_DIRS Atomic_ops::atomic_ops
+                          INTERFACE_INCLUDE_DIRECTORIES)
+      include_directories(${AO_INCLUDE_DIRS})
+      message(STATUS "AO_INCLUDE_DIRS = ${AO_INCLUDE_DIRS}")
+      set(ATOMIC_OPS_LIBS_CMAKE Atomic_ops::atomic_ops)
+    else()
+      set(ATOMIC_OPS_LIBS_CMAKE ${ATOMIC_OPS_LIBS})
+    endif()
+  elseif (without_libatomic_ops)
+    include_directories(libatomic_ops/src)
+    # In the tests we use the source files directly from libatomic_ops subtree.
+    set(NODIST_SRC libatomic_ops/src/atomic_ops.c)
+    if (CMAKE_C_COMPILER_ID STREQUAL "SunPro")
+      # SunCC compiler on SunOS (Solaris).
+      set(NODIST_SRC ${NODIST_SRC} libatomic_ops/src/atomic_ops_sysdeps.S)
+    endif()
+  elseif (BORLAND OR MSVC OR WATCOM)
+    include_directories(libatomic_ops/src)
+    # Note: alternatively, use CFLAGS_EXTRA to pass -I<...>/libatomic_ops/src.
+  else()
+    # Assume the compiler supports GCC atomic intrinsics.
+    add_definitions("-DGC_BUILTIN_ATOMIC")
+  endif()
   set(THREADDLLIBS_LIST ${CMAKE_THREAD_LIBS_INIT})
   if (${CMAKE_DL_LIBS} MATCHES ^[^-].*)
     # Some cmake versions have a broken non-empty CMAKE_DL_LIBS omitting "-l".
@@ -160,21 +215,21 @@ if (enable_threads)
   endif()
 endif(enable_threads)
 
-set(ATOMIC_OPS_LIBS "") # TODO: Assume libatomic_ops library is not needed.
-
 # Thread support detection.
 if (CMAKE_USE_PTHREADS_INIT)
-  set(SRC ${SRC} gc_dlopen.c)
+  set(SRC ${SRC} gc_dlopen.c pthread_start.c pthread_support.c)
   if (CYGWIN OR MSYS)
     set(SRC ${SRC} win32_threads.c)
   else()
-    set(SRC ${SRC} pthread_start.c pthread_stop_world.c pthread_support.c)
+    if (APPLE)
+      set(SRC ${SRC} darwin_stop_world.c)
+    else()
+      set(SRC ${SRC} pthread_stop_world.c)
+    endif()
   endif()
   if (HOST MATCHES .*-.*-hpux10.*)
     message(FATAL_ERROR "HP/UX 10 POSIX threads are not supported.")
   endif()
-  # Assume the compiler supports GCC atomic intrinsics.
-  add_definitions("-DGC_BUILTIN_ATOMIC")
   # Common defines for POSIX platforms.
   add_definitions("-DGC_THREADS -D_REENTRANT")
   if (enable_parallel_mark)
@@ -188,16 +243,19 @@ if (CMAKE_USE_PTHREADS_INIT)
   if (HOST MATCHES .*-.*-hpux11.*)
     message("Only HP/UX 11 POSIX threads are supported.")
     add_definitions("-D_POSIX_C_SOURCE=199506L")
+    set(NEED_LIB_RT ON)
   elseif (HOST MATCHES .*-.*-netbsd.*)
     message("Only on NetBSD 2.0 or later.")
     add_definitions("-D_PTHREADS")
+    set(NEED_LIB_RT ON)
+  elseif (CMAKE_C_COMPILER_ID STREQUAL "SunPro")
+    set(NEED_LIB_RT ON)
   endif()
   if (MSYS)
     # Does not provide process fork functionality.
   elseif (APPLE)
     # The incremental mode conflicts with fork handling (for now).
     # Thus, HANDLE_FORK is not defined.
-    set(SRC ${SRC} darwin_stop_world.c)
   elseif (enable_handle_fork AND NOT disable_handle_fork)
     add_definitions("-DHANDLE_FORK")
   endif()
@@ -215,11 +273,29 @@ elseif (CMAKE_USE_WIN32_THREADS_INIT)
     set(SRC ${SRC} thread_local_alloc.c)
   endif()
   add_definitions("-DEMPTY_GETENV_RESULTS")
-  set(SRC ${SRC} win32_threads.c)
+  set(SRC ${SRC} pthread_start.c) # in case client defines GC_WIN32_PTHREADS
+  set(SRC ${SRC} pthread_support.c win32_threads.c)
 elseif (CMAKE_HP_PTHREADS_INIT OR CMAKE_USE_SPROC_INIT)
   message(FATAL_ERROR "Unsupported thread package")
 endif()
 
+# Check whether -lrt linker option is needed to use clock_gettime.
+if (NOT NEED_LIB_RT)
+  check_function_exists(clock_gettime HAVE_CLOCK_GETTIME_DIRECTLY)
+  if (NOT HAVE_CLOCK_GETTIME_DIRECTLY)
+    # Use of clock_gettime() probably requires linking with "rt" library.
+    set(NEED_LIB_RT ON)
+  endif()
+endif()
+
+# Locate and use "rt" library if needed (and the library is available).
+if (NEED_LIB_RT)
+  find_library(LIBRT rt)
+  if (LIBRT)
+    set(THREADDLLIBS_LIST ${THREADDLLIBS_LIST} ${LIBRT})
+  endif()
+endif(NEED_LIB_RT)
+
 if (disable_handle_fork)
   add_definitions("-DNO_HANDLE_FORK")
 endif()
@@ -329,12 +405,12 @@ if (enable_werror)
   endif()
 endif(enable_werror)
 
-if (enable_single_obj_compilation OR BUILD_SHARED_LIBS)
+if (enable_single_obj_compilation OR (BUILD_SHARED_LIBS AND NOT disable_single_obj_compilation))
   set(SRC extra/gc.c) # override SRC
-  if (CMAKE_USE_PTHREADS_INIT)
+  if (CMAKE_USE_PTHREADS_INIT AND NOT (APPLE OR CYGWIN OR MSYS))
     add_definitions("-DGC_PTHREAD_START_STANDALONE")
     set(SRC ${SRC} pthread_start.c)
-  endif(CMAKE_USE_PTHREADS_INIT)
+  endif()
 elseif (BORLAND)
   # Suppress "GC_push_contents_hdr() is declared but never used" warning.
   add_compile_options(/w-use)
@@ -345,12 +421,16 @@ if (MSVC)
   set(SRC ${SRC} extra/msvc_dbg.c)
 endif()
 
+# Instruct check_c_source_compiles to skip linking.
+# Alternatively, we could set CMAKE_REQUIRED_LIBRARIES properly.
+SET(CMAKE_REQUIRED_FLAGS "-c")
+
 # Instruct check_c_source_compiles and similar CMake checks not to ignore
 # compiler warnings (like "implicit declaration of function").
 if (NOT BORLAND AND NOT MSVC AND NOT WATCOM)
   check_c_compiler_flag(-Werror HAVE_FLAG_WERROR)
   if (HAVE_FLAG_WERROR)
-    SET(CMAKE_REQUIRED_FLAGS "-Werror")
+    SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror")
   endif(HAVE_FLAG_WERROR)
 endif()
 
@@ -364,7 +444,13 @@ if (BUILD_SHARED_LIBS)
   else()
     add_definitions("-DGC_NO_VISIBILITY")
   endif()
-  check_c_compiler_flag(-Wl,--no-undefined HAVE_FLAG_WL_NO_UNDEFINED)
+  if (${CMAKE_VERSION} VERSION_LESS "3.18.0")
+    set(WL_NO_UNDEFINED_OPT "-Wl,--no-undefined")
+    check_c_compiler_flag(${WL_NO_UNDEFINED_OPT} HAVE_FLAG_WL_NO_UNDEFINED)
+  else()
+    set(WL_NO_UNDEFINED_OPT "LINKER:--no-undefined")
+    check_linker_flag(C "${WL_NO_UNDEFINED_OPT}" HAVE_FLAG_WL_NO_UNDEFINED)
+  endif()
 else()
   add_definitions("-DGC_NOT_DLL")
   if (WIN32)
@@ -382,7 +468,8 @@ endif()
 
 # Extra user-defined flags to pass both to C and C++ compilers.
 if (DEFINED CFLAGS_EXTRA)
-  add_compile_options(${CFLAGS_EXTRA})
+  separate_arguments(CFLAGS_EXTRA_LIST UNIX_COMMAND "${CFLAGS_EXTRA}")
+  add_compile_options(${CFLAGS_EXTRA_LIST})
 endif()
 
 # Check whether execinfo.h header file is present.
@@ -408,9 +495,16 @@ if (NOT HAVE_SIGSETJMP)
   add_definitions("-DGC_NO_SIGSETJMP")
 endif()
 
+# Build with GC_wcsdup() support if possible.
+check_symbol_exists(wcslen wchar.h HAVE_WCSLEN)
+if (HAVE_WCSLEN)
+  add_definitions("-DGC_REQUIRE_WCSDUP")
+endif()
+
 # pthread_setname_np, if available, may have 1, 2 or 3 arguments.
 if (CMAKE_USE_PTHREADS_INIT)
   check_c_source_compiles("
+#define _GNU_SOURCE 1\n
 #include <pthread.h>\n
 int main(void) { (void)pthread_setname_np(\"thread-name\"); return 0; }"
     HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID)
@@ -419,6 +513,7 @@ int main(void) { (void)pthread_setname_np(\"thread-name\"); return 0; }"
     add_definitions("-DHAVE_PTHREAD_SETNAME_NP_WITHOUT_TID")
   else()
     check_c_source_compiles("
+#define _GNU_SOURCE 1\n
 #include <pthread.h>\n
 int main(void) {\n
   (void)pthread_setname_np(pthread_self(), \"thread-name-%u\", 0); return 0; }"
@@ -428,9 +523,7 @@ int main(void) {\n
       add_definitions("-DHAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG")
     else()
       check_c_source_compiles("
-#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) || defined(__CYGWIN__)\n
 #define _GNU_SOURCE 1\n
-#endif\n
 #include <pthread.h>\n
 int main(void) {\n
   (void)pthread_setname_np(pthread_self(), \"thread-name\"); return 0; }"
@@ -454,10 +547,25 @@ if (HAVE_DLADDR)
   add_definitions("-DHAVE_DLADDR")
 endif()
 
-add_library(gc ${SRC})
-if (enable_threads)
-  target_link_libraries(gc PRIVATE ${THREADDLLIBS_LIST} ${ATOMIC_OPS_LIBS})
+# Check for emscripten; use asyncify feature if requested.
+check_c_source_compiles("
+#ifndef __EMSCRIPTEN__\n
+# error This is not Emscripten\n
+#endif\n
+int main(void) { return 0; }"
+  EMSCRIPTEN)
+if (EMSCRIPTEN AND enable_emscripten_asyncify)
+  # Use this option if your program is targeting -sASYNCIFY.  The latter is
+  # required to scan the stack, ASYNCIFY_STACK_SIZE is probably needed for
+  # gctest only.
+  add_definitions("-DEMSCRIPTEN_ASYNCIFY")
+  set(CMAKE_EXE_LINKER_FLAGS
+        "${CMAKE_EXE_LINKER_FLAGS} -sASYNCIFY -sASYNCIFY_STACK_SIZE=128000")
 endif()
+
+add_library(gc ${SRC})
+target_link_libraries(gc
+                PRIVATE ${ATOMIC_OPS_LIBS_CMAKE} ${THREADDLLIBS_LIST})
 target_include_directories(gc INTERFACE
         "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
         "$<INSTALL_INTERFACE:include>")
@@ -494,7 +602,7 @@ if (build_cord)
         "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
         "$<INSTALL_INTERFACE:include>")
   if (BUILD_SHARED_LIBS)
-    set_property(TARGET cord PROPERTY VERSION ${CORD_VERSION})
+    set_property(TARGET cord PROPERTY VERSION ${CORD_VERSION_PROP})
     set_property(TARGET cord PROPERTY SOVERSION ${CORD_SOVERSION})
   endif()
   install(TARGETS cord EXPORT BDWgcTargets
@@ -506,21 +614,33 @@ endif(build_cord)
 
 if (BUILD_SHARED_LIBS AND HAVE_FLAG_WL_NO_UNDEFINED)
   # Declare that the libraries do not refer to external symbols.
-  # TODO: use add_link_options() when cmake_minimum_required > 3.13
-  target_link_libraries(gc PRIVATE -Wl,--no-undefined)
-  if (enable_cplusplus)
-    target_link_libraries(gccpp PRIVATE -Wl,--no-undefined)
-    if (enable_throw_bad_alloc_library)
-      target_link_libraries(gctba PRIVATE -Wl,--no-undefined)
-    endif(enable_throw_bad_alloc_library)
-  endif(enable_cplusplus)
-  if (build_cord)
-    target_link_libraries(cord PRIVATE -Wl,--no-undefined)
-  endif(build_cord)
+  if (${CMAKE_VERSION} VERSION_LESS "3.13.0")
+    target_link_libraries(gc PRIVATE ${WL_NO_UNDEFINED_OPT})
+    if (enable_cplusplus)
+      target_link_libraries(gccpp PRIVATE ${WL_NO_UNDEFINED_OPT})
+      if (enable_throw_bad_alloc_library)
+        target_link_libraries(gctba PRIVATE ${WL_NO_UNDEFINED_OPT})
+      endif(enable_throw_bad_alloc_library)
+    endif(enable_cplusplus)
+    if (build_cord)
+      target_link_libraries(cord PRIVATE ${WL_NO_UNDEFINED_OPT})
+    endif(build_cord)
+  else()
+    target_link_options(gc PRIVATE ${WL_NO_UNDEFINED_OPT})
+    if (enable_cplusplus)
+      target_link_options(gccpp PRIVATE ${WL_NO_UNDEFINED_OPT})
+      if (enable_throw_bad_alloc_library)
+        target_link_options(gctba PRIVATE ${WL_NO_UNDEFINED_OPT})
+      endif(enable_throw_bad_alloc_library)
+    endif(enable_cplusplus)
+    if (build_cord)
+      target_link_options(cord PRIVATE ${WL_NO_UNDEFINED_OPT})
+    endif(build_cord)
+  endif()
 endif()
 
 if (BUILD_SHARED_LIBS)
-  set_property(TARGET gc PROPERTY VERSION ${GC_VERSION})
+  set_property(TARGET gc PROPERTY VERSION ${GC_VERSION_PROP})
   set_property(TARGET gc PROPERTY SOVERSION ${GC_SOVERSION})
 endif()
 install(TARGETS gc EXPORT BDWgcTargets
@@ -531,7 +651,7 @@ install(TARGETS gc EXPORT BDWgcTargets
 
 if (enable_cplusplus)
   if (BUILD_SHARED_LIBS)
-    set_property(TARGET gccpp PROPERTY VERSION ${GCCPP_VERSION})
+    set_property(TARGET gccpp PROPERTY VERSION ${GCCPP_VERSION_PROP})
     set_property(TARGET gccpp PROPERTY SOVERSION ${GCCPP_SOVERSION})
   endif()
   install(TARGETS gccpp EXPORT BDWgcTargets
@@ -541,7 +661,7 @@ if (enable_cplusplus)
           INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
   if (enable_throw_bad_alloc_library)
     if (BUILD_SHARED_LIBS)
-      set_property(TARGET gctba PROPERTY VERSION ${GCCPP_VERSION})
+      set_property(TARGET gctba PROPERTY VERSION ${GCCPP_VERSION_PROP})
       set_property(TARGET gctba PROPERTY SOVERSION ${GCCPP_SOVERSION})
     endif()
     install(TARGETS gctba EXPORT BDWgcTargets
@@ -604,13 +724,13 @@ endif(install_headers)
 
 if (build_tests)
   if (build_cord)
-    add_executable(cordtest cord/tests/cordtest.c)
+    add_executable(cordtest cord/tests/cordtest.c ${NODIST_SRC})
     target_link_libraries(cordtest PRIVATE cord gc)
     add_test(NAME cordtest COMMAND cordtest)
 
     if (WIN32 AND NOT CYGWIN)
       add_executable(de cord/tests/de.c cord/tests/de_win.c
-                     cord/tests/de_win.rc)
+                     cord/tests/de_win.rc ${NODIST_SRC})
       set_target_properties(de PROPERTIES WIN32_EXECUTABLE TRUE)
       target_link_libraries(de PRIVATE cord gc gdi32)
     endif()
@@ -618,16 +738,20 @@ if (build_tests)
 
   # Compile some tests as C++ to test extern "C" in header files.
   if (enable_cplusplus)
-    set_source_files_properties(tests/leak_test.c tests/test.c
-                                PROPERTIES LANGUAGE CXX)
+    set_source_files_properties(tests/leak.c PROPERTIES LANGUAGE CXX)
+    if (NOT MSVC)
+      # WinMain-based test hangs at startup if compiled by VC as C++ code.
+      set_source_files_properties(tests/gctest.c PROPERTIES LANGUAGE CXX)
+    endif()
     # To avoid "treating 'c' input as 'c++' when in C++ mode" Clang warning.
     if (NOT (BORLAND OR MSVC OR WATCOM))
       add_compile_options(-x c++)
     endif()
   endif(enable_cplusplus)
 
-  add_executable(gctest WIN32 tests/test.c)
-  target_link_libraries(gctest PRIVATE gc ${THREADDLLIBS_LIST})
+  add_executable(gctest WIN32 tests/gctest.c ${NODIST_SRC})
+  target_link_libraries(gctest
+                PRIVATE gc ${ATOMIC_OPS_LIBS_CMAKE} ${THREADDLLIBS_LIST})
   add_test(NAME gctest COMMAND gctest)
   if (WATCOM)
     # Suppress "conditional expression in if statement is always true/false"
@@ -636,89 +760,90 @@ if (build_tests)
                            /wcd=13 /wcd=201 /wcd=367 /wcd=368 /wcd=726)
   endif()
 
-  add_executable(hugetest tests/huge_test.c)
+  add_executable(hugetest tests/huge.c ${NODIST_SRC})
   target_link_libraries(hugetest PRIVATE gc)
   add_test(NAME hugetest COMMAND hugetest)
 
-  add_executable(leaktest tests/leak_test.c)
+  add_executable(leaktest tests/leak.c ${NODIST_SRC})
   target_link_libraries(leaktest PRIVATE gc)
   add_test(NAME leaktest COMMAND leaktest)
 
-  add_executable(middletest tests/middle.c)
+  add_executable(middletest tests/middle.c ${NODIST_SRC})
   target_link_libraries(middletest PRIVATE gc)
   add_test(NAME middletest COMMAND middletest)
 
-  add_executable(realloc_test tests/realloc_test.c)
-  target_link_libraries(realloc_test PRIVATE gc)
-  add_test(NAME realloc_test COMMAND realloc_test)
+  add_executable(realloctest tests/realloc.c ${NODIST_SRC})
+  target_link_libraries(realloctest PRIVATE gc)
+  add_test(NAME realloctest COMMAND realloctest)
 
-  add_executable(smashtest tests/smash_test.c)
+  add_executable(smashtest tests/smash.c ${NODIST_SRC})
   target_link_libraries(smashtest PRIVATE gc)
   add_test(NAME smashtest COMMAND smashtest)
 
   if (NOT (BUILD_SHARED_LIBS AND WIN32))
-    add_library(staticrootslib_test tests/staticrootslib.c)
-    target_link_libraries(staticrootslib_test PRIVATE gc)
-    add_library(staticrootslib2_test tests/staticrootslib.c)
-    target_compile_options(staticrootslib2_test PRIVATE "-DSTATICROOTSLIB2")
-    target_link_libraries(staticrootslib2_test PRIVATE gc)
-    add_executable(staticrootstest tests/staticrootstest.c)
+    add_library(staticroots_lib_test tests/staticroots_lib.c)
+    target_link_libraries(staticroots_lib_test PRIVATE gc)
+    add_library(staticroots_lib2_test tests/staticroots_lib.c)
+    target_compile_options(staticroots_lib2_test PRIVATE "-DSTATICROOTSLIB2")
+    target_link_libraries(staticroots_lib2_test PRIVATE gc)
+    add_executable(staticrootstest tests/staticroots.c ${NODIST_SRC})
     target_compile_options(staticrootstest PRIVATE "-DSTATICROOTSLIB2")
     target_link_libraries(staticrootstest PRIVATE
-                          gc staticrootslib_test staticrootslib2_test)
+                          gc staticroots_lib_test staticroots_lib2_test)
     add_test(NAME staticrootstest COMMAND staticrootstest)
   endif()
 
   if (enable_gc_debug)
-    add_executable(tracetest tests/trace_test.c)
+    add_executable(tracetest tests/trace.c ${NODIST_SRC})
     target_link_libraries(tracetest PRIVATE gc)
     add_test(NAME tracetest COMMAND tracetest)
   endif()
 
   if (enable_threads)
-    add_executable(test_atomic_ops tests/test_atomic_ops.c)
-    target_link_libraries(test_atomic_ops PRIVATE ${THREADDLLIBS_LIST})
-    add_test(NAME test_atomic_ops COMMAND test_atomic_ops)
+    add_executable(atomicopstest tests/atomicops.c ${NODIST_SRC})
+    target_link_libraries(atomicopstest
+                PRIVATE ${ATOMIC_OPS_LIBS_CMAKE} ${THREADDLLIBS_LIST})
+    add_test(NAME atomicopstest COMMAND atomicopstest)
+
+    add_executable(initfromthreadtest tests/initfromthread.c ${NODIST_SRC})
+    target_link_libraries(initfromthreadtest PRIVATE gc ${THREADDLLIBS_LIST})
+    add_test(NAME initfromthreadtest COMMAND initfromthreadtest)
+
+    add_executable(subthreadcreatetest tests/subthreadcreate.c ${NODIST_SRC})
+    target_link_libraries(subthreadcreatetest
+                PRIVATE gc ${ATOMIC_OPS_LIBS_CMAKE} ${THREADDLLIBS_LIST})
+    add_test(NAME subthreadcreatetest COMMAND subthreadcreatetest)
 
-    add_executable(threadleaktest tests/thread_leak_test.c)
+    add_executable(threadleaktest tests/threadleak.c ${NODIST_SRC})
     target_link_libraries(threadleaktest PRIVATE gc ${THREADDLLIBS_LIST})
     add_test(NAME threadleaktest COMMAND threadleaktest)
 
     if (NOT WIN32)
-      add_executable(threadkey_test tests/threadkey_test.c)
-      target_link_libraries(threadkey_test PRIVATE gc ${THREADDLLIBS_LIST})
-      add_test(NAME threadkey_test COMMAND threadkey_test)
+      add_executable(threadkeytest tests/threadkey.c ${NODIST_SRC})
+      target_link_libraries(threadkeytest PRIVATE gc ${THREADDLLIBS_LIST})
+      add_test(NAME threadkeytest COMMAND threadkeytest)
     endif()
-
-    add_executable(subthreadcreate_test tests/subthread_create.c)
-    target_link_libraries(subthreadcreate_test PRIVATE gc ${THREADDLLIBS_LIST})
-    add_test(NAME subthreadcreate_test COMMAND subthreadcreate_test)
-
-    add_executable(initsecondarythread_test tests/initsecondarythread.c)
-    target_link_libraries(initsecondarythread_test
-                          PRIVATE gc ${THREADDLLIBS_LIST})
-    add_test(NAME initsecondarythread_test COMMAND initsecondarythread_test)
   endif(enable_threads)
 
   if (enable_cplusplus)
-    add_executable(test_cpp WIN32 tests/test_cpp.cc)
-    target_link_libraries(test_cpp PRIVATE gc gccpp)
-    add_test(NAME test_cpp COMMAND test_cpp)
+    add_executable(cpptest WIN32 tests/cpp.cc ${NODIST_SRC})
+    target_link_libraries(cpptest PRIVATE gc gccpp)
+    add_test(NAME cpptest COMMAND cpptest)
   endif()
 
   if (enable_disclaim)
-    add_executable(disclaim_bench tests/disclaim_bench.c)
+    add_executable(disclaim_bench tests/disclaim_bench.c ${NODIST_SRC})
     target_link_libraries(disclaim_bench PRIVATE gc)
     add_test(NAME disclaim_bench COMMAND disclaim_bench)
 
-    add_executable(disclaim_test tests/disclaim_test.c)
-    target_link_libraries(disclaim_test PRIVATE gc ${THREADDLLIBS_LIST})
-    add_test(NAME disclaim_test COMMAND disclaim_test)
+    add_executable(disclaimtest tests/disclaim.c ${NODIST_SRC})
+    target_link_libraries(disclaimtest PRIVATE gc ${THREADDLLIBS_LIST})
+    add_test(NAME disclaimtest COMMAND disclaimtest)
 
-    add_executable(disclaim_weakmap_test tests/disclaim_weakmap_test.c)
-    target_link_libraries(disclaim_weakmap_test
-                          PRIVATE gc ${THREADDLLIBS_LIST})
-    add_test(NAME disclaim_weakmap_test COMMAND disclaim_weakmap_test)
+    add_executable(weakmaptest tests/weakmap.c ${NODIST_SRC})
+    target_link_libraries(weakmaptest
+                PRIVATE gc ${ATOMIC_OPS_LIBS_CMAKE} ${THREADDLLIBS_LIST})
+    add_test(NAME weakmaptest COMMAND weakmaptest)
   endif()
 endif(build_tests)
 

+ 618 - 48
blitz.mod/bdwgc/ChangeLog

@@ -1,4 +1,393 @@
 
+== [8.3.0] (development) ==
+
+* Add 'lib' prefix to build artifact names in Makefile.direct
+* Add I_HOLD_LOCK assertion to scratch_alloc/recycle and their callers
+* Add assertion to GC_maybe_gc that GC is not in progress
+* Add assertion to ensure GC_unmapped_bytes cannot underflow
+* Add assertions about GC_mark_state to alloc.c and mark.c
+* Add check-deps goal to Makefiles to build the tests but not execute them
+* Add minimal testing of GC_allow_register_threads
+* Add missing cast in GC_is_init_called (refactoring)
+* Add missing undef GC_NO_THREAD_REDIRECTS in threaded tests
+* Adjust comments in block_unmap_inner
+* Adjust comments referring glibc version (documentation)
+* Adjust indentation in C preprocessor directives (reformatting)
+* Adjust naming of Win32/64 and x86/64 words in comments and documentation
+* Adjust printing on amount of unmapped memory after GC
+* Allow custom AO_SRC_DIR, CURSES, EXEEXT, HOSTCC/CFLAGS for Makefile.direct
+* Allow disable USE_PROC_FOR_LIBRARIES even if malloc is redirected on Linux
+* Allow mprotect-based incremental GC on AIX and for all Linux targets
+* Allow passing custom CFLAGS[_EXTRA] to Makefile.direct
+* Allow testing of retry-signals functionality
+* Allow to build with forced WRAP_MARK_SOME
+* Allow to compile tests with custom NTHREADS set to zero
+* Allow to skip heap expansion in GC_init
+* Allow to unmap memory block right in GC cycle where block is freed
+* Allow to use same signal for thread suspend and restart (default on E2K)
+* Always set only one bit past end in GC_set_hdr_marks
+* Assert SET_HDR does not write to GC_all_nils
+* Assert in GC_typed_mark_proc that GC lock is held by some collecting thread
+* Assert that bm_table is already initialized when GC_double_descr used
+* Assert that disappearing links are accessible during registration and GC
+* Assert that size of element of a typed object is non-zero (refactoring)
+* Avoid code duplication in GC_make_array_descriptor (refactoring)
+* Avoid code duplication regarding GC_push_roots in GC_mark_some_inner
+* Avoid duplication of magic numbers in disclaim.c, weakmap.c (refactoring)
+* Avoid unmap of memory allocated during GC init regardless of threshold
+* Better document GC_generate_random_heap/valid_address API functions
+* Better document GC_no_dls
+* Build extra/gc.c in digimars.mak
+* Build with GC_wcsdup support if wcslen exists
+* Call GC_init_parallel only from GC_init (refactoring)
+* Change GC_Thread_Rep in pthread_support.h to match that of win32_threads.c
+* Change default GC_time_limit value from 50 to 15 ms
+* Change default value of max_prior_attempts to 3
+* Change minimum heap growth to one block if requested explicitly
+* Change p local variable to current_p in push_all/conditional_eager
+* Change type of GC_collecting variable to match atomic operations over it
+* Check pointer tag in all mark procedures (E2K)
+* Collapse arch macro defines where possible (refactoring)
+* Consistent naming of GC_thread local variables (refactoring)
+* Declare GC_noop1 as public function unconditionally
+* Declare GC_register_stackbottom symbol as internal on IA64 (refactoring)
+* Define ALIGNMENT macro based on CPP_WORDSZ value by default (refactoring)
+* Define GC_GLIBC_PREREQ internal macro (refactoring)
+* Define GC_get_parallel and GC_set_markers_count in single-threaded GC
+* Define GC_save_regs_ret_val variable only if used on IA64 (refactoring)
+* Define GC_thread type in a single place both for pthreads and Win32
+* Define and use SIGNAL_BASED_STOP_WORLD macro internally (refactoring)
+* Define internal macro NO_SEH_AVAILABLE where SEH is absent (refactoring)
+* Define macros in gcconfig.h to use sigaction for SIGSEGV and SIGBUS
+* Define marker_[b]sp only if needed (refactoring)
+* Define op and nwords local variables consistently across typd_mlc.c
+* Define public GC_[p]valloc() and redirect to them in leak_detector.h
+* Disable H/W tag checking in mark procedures by default (E2K)
+* Disable memory unmapping explicitly in gcconfig.h for Emscripten
+* Discard sections with pseudo-paths except heap in register_map_entries
+* Do not compile pthread_start.c on Cygwin even if build shared libs (CMake)
+* Do not compile pthread_stop_world.c on Darwin (CMake)
+* Do not define GC_pthread_start/exit for Orbis and Sony PSP (refactoring)
+* Do not define GETPAGESIZE on Win32 (refactoring)
+* Do not define THREAD_SANITIZER if GC is built w/o threads support
+* Do not free entry in GC_delete_gc_thread to match that on Win32
+* Do not include sched.h from pthread_start.c (refactoring)
+* Do not invoke GC_approx_sp() repeatedly in GC_stopped_mark (refactoring)
+* Do not put atomic_ops[_sysdeps].o to libgc.a in Makefile.direct
+* Do not reference internal files in comments of public header files
+* Do not set SIGBUS handler to catch write faults on Linux
+* Do not treat warnings as errors by default in digimars.mak
+* Do not wrap mark_some to catch faults if libraries registration is off
+* Document GC_ENABLE_SUSPEND_THREAD better in configure
+* Document GC_with_callee_saves_pushed better
+* Document argument of GC_is_marked in gc_mark.h
+* Document that GC_is_X API functions may return only zero or one
+* Eliminate 'boolean result used in bitwise op' cppcheck FP in GC_thr_init
+* Eliminate 'checking if 1U<<12 is less than zero' cppcheck FP warning
+* Eliminate 'n obtained from untrusted source' code defect FP in test_cpp
+* Eliminate 'parameter can be declared as const pointer' cppcheck warnings
+* Eliminate 'scope of p variable could be reduced' cppcheck warning in de.c
+* Eliminate 'skipping config since static_assert is unknown' cppcheck FP
+* Eliminate 'struct treenode member is never used' cppcheck warning
+* Enable prefetch loop in GC_mark_from on E2K
+* Enable without_libatomic_ops for targets requiring atomic_ops.c (CMake)
+* Ensure GC is initialized when GC_push_all_stacks() is called (refactoring)
+* Ensure GC lock is held in GC_reset_finalizer_nested (refactoring)
+* Ensure GC lock is held in add_leaked/smashed, check_heap_proc (refactoring)
+* Ensure GC_n_set_marks() does not count extra bits in hb_marks
+* Ensure GC_our_memory is updated while holding GC lock (refactoring)
+* Ensure a collection occurs between adjacent heap expansions
+* Ensure every test prints a message on success
+* Export GC_apply_to_all_blocks() and GC_is_black_listed() as public API
+* Fail threadkeytest on pthread_create error in main loop
+* Fix digimars.mak to build 'all' by default
+* Force pthread_mutex_lock usage for GC lock if ThreadSanitizer
+* Get libpthread.so '.text' mapping only for glibc prior to v2.34 (Linux)
+* Group NEED_FIND_LIMIT definitions in gcconfig.h (refactoring)
+* Group functions related to GC_calloc_explicitly_typed (refactoring)
+* Include gc/gc[_cpp].h directly except for cord and tests (refactoring)
+* Include gc_inline.h from gc_priv.h (refactoring)
+* Include stdio.h and stdlib.h only from gc_priv.h (refactoring)
+* Increase number of iterations in leak and middle tests
+* Initialize GC_retry_signals to true in GC_stop_init (refactoring)
+* Make abort message unique in write_fault_handler
+* Make all functions static in msvc_dbg.c except for backtrace[_symbols]
+* Mention CMake-based build in README.md and README.QUICK
+* Move GC_NO_THREADS_DISCOVERY definition to gcconfig.h (refactoring)
+* Move HAVE_CLOCK_GETTIME definition from gc_priv.h to gcconfig.h
+* Move fields common between Concatenation and Function to Generic structure
+* Move non-cord [pkg]include_HEADERS assignments to include.am (refactoring)
+* Move non-license info from LICENSE file to README and vice versa
+* Move pthread_atfork() call to a separate function (refactoring)
+* Move public header files to include/gc in source tree
+* Name all tests consistently (refactoring)
+* New API function (GC_get_hblk_size) to get HBLKSIZE value
+* New CMake option to link with external libatomic_ops (system library)
+* New GC_count_set_marks_in_hblk and GC_iterate_free_hblks API functions
+* Output finalization information by GC_dump
+* Pass ATOMIC_OPS_LIBS to tests using AO primitives directly (Automake)
+* Prevent requesting blocks past max_heapsize in GC_collect_or_expand
+* Prevent use of redirected posix_memalign in GC_haiku_get_mem
+* Print in-use heap statistic on heap growth
+* Print iteration number on thread creation or join failure in tests
+* Print objs_in_block as zero for large objects in GC_print_block_list
+* Print thread number on marker thread creation failure
+* Print value of links in GC_dump_finalization_links
+* Put gc_badalc/cpp.cpp instead of .cc ones in CMake script (MSVC/BCC/WCC)
+* Really ignore bad GC_INITIAL/MAXIMUM_HEAP_SIZE values
+* Redirect aligned_alloc() and reallocarray() in leak_detector.h
+* Reduce number of iterations in disclaim and cpp tests
+* Reduce scope of local variables used for assertion checking in add_to_fl
+* Refactoring of GC_n_set_marks and GC_print_block_descr
+* Refine WARN message in GC_proc_read_dirty regarding buffer size
+* Refine column names output by GC_print_block_list
+* Refine comments in code regarding DllMain-based threads registration
+* Relax required dependencies for atomicopstest (CMake)
+* Remove -o option where not needed in Makefile.direct (refactoring)
+* Remove GC_copyright symbol
+* Remove GC_mark_threads variable (refactoring)
+* Remove GC_min/max() and simplify heap bounds update in expand_hp_inner
+* Remove GC_world_is_stopped variable (refactoring)
+* Remove IF_IA64 macro in pthread_stop_world (refactoring)
+* Remove STACK_GROWS_DOWN explicit definitions in gcconfig.h (refactoring)
+* Remove Symbian makefile
+* Remove USED_HEAP_SIZE macro (refactoring)
+* Remove ancient OS2_MAKEFILE, PCR-Makefile, SMakefile.amiga
+* Remove comment from gc_cpp.h about bugs in ancient compilers
+* Remove doc.am, and move gc.man to base folder (refactoring)
+* Remove duplicate 'called once' check in GC_init_lib_bounds (refactoring)
+* Remove duplication of random numbers generator formula (refactoring)
+* Remove extra parentheses in return statement (refactoring)
+* Remove main_pthread_id variable (refactoring)
+* Remove msvc_dbg.h file (refactoring)
+* Remove obsolete AC_PROG_LIBTOOL in configure.ac (refactoring)
+* Remove private pthread_stop_world.h and darwin_stop_world.h (refactoring)
+* Remove redundant 'private' prefix in include directives in include/private
+* Remove redundant GC_ATTR_UNUSED for GC_mark_and_push
+* Remove redundant HOST_TIZEN macro check for SEARCH_FOR_DATA_START
+* Remove specific DATASTART definition for ancient OpenBSD/m68k
+* Remove thread_blocked field in GC_thread (refactoring)
+* Remove trailing dot in WARN messages
+* Remove unreachable code in GC_lookup_pthread (refactoring)
+* Remove volatile qualifier for GC_threads (pthreads)
+* Rename GC_[inner_]start_routine to match that for Win32 (refactoring)
+* Rename MAP_LEN internal macro to OBJ_MAP_LEN (refactoring)
+* Rename README.QUICK to LICENSE and install it by default
+* Rename README.rs6000 to README.aix
+* Rename stack[_size] in GC_Thread_Rep and GC_register_altstack (refactoring)
+* Rename thread_args and GC_main_thread in win32_threads.c (refactoring)
+* Reorder macro definitions for rare architectures in gcconfig.h
+* Replace C-style casts in C++ headers and cpptest (refactoring)
+* Replace GC_MARK_FO macro with inline functions (refactoring)
+* Replace comments about GC is held or not with relevant assertions
+* Replace init_netbsd_elf with init_linux_data_start on NetBSD (refactoring)
+* Replace obsolete AC_TRY_COMPILE/LINK/RUN in configure.ac (refactoring)
+* Replace target names with '$@' in Makefile.direct (refactoring)
+* Return free memory to OS explicitly before getting new memory from OS
+* Roundup size passed to GC_expand_hp
+* Simplify code to define USE_x_SPECIFIC macros in thread_local_alloc.h
+* Simplify expression to clear extra bits in add_ext_descriptor (refactoring)
+* Simplify gcconfig code to define IRIX5 and ULTRIX on mips (refactoring)
+* Specify that error conditions are unlikely to be true in threads code
+* Specify that internal allocations failure is unlikely (refactoring)
+* Specify that out-of-memory is unlikely in typed alloc and make descriptor
+* State explicitly that license is MIT-style
+* Support 32-bit mode on E2K
+* Support CFLAGS_EXTRA in rare build scripts (NT/WCC_MAKEFILE, digimars.mak)
+* Support ThreadSanitizer (GCC)
+* Support client stop function properly in maybe_gc and collect_a_little
+* Support disable_single_obj_compilation option in cmake script
+* Support malloc redirection on E2K
+* Test garbage collection from a deep recursion in gctest
+* Test manual self-suspend in gctest
+* Test realloc() in leaktest
+* Test world stop while other thread in deep recursion in gctest (pthreads)
+* Treat GC_arrays as a part of internal memory when printing its size
+* Treat warnings as errors in C++ code if configure --enable-werror
+* Try find libatomic_ops installed by cmake if with_libatomic_ops (CMake)
+* Unify GC_Thread_Rep and thread id type in win32_threads.c (refactoring)
+* Unify GC_[mark_]lock_holder variable definition (refactoring)
+* Update next_random_no state using AO primitive
+* Use AO primitive in GC_noop1 instead of no_sanitize attribute
+* Use AO primitives in GC_RAND_NEXT instead of no_sanitize attribute
+* Use EXPECT() in checks of MAIN_THREAD bit (refactoring)
+* Use GC_printf in cpptest consistently (refactoring)
+* Use cast to void instead of the attribute to indicate unused arguments
+* Use consistent variables naming in typd_mlc.c (refactoring)
+* Use inline keyword in GC_INLINE (bcc)
+* Use modHBLKSZ where possible (refactoring)
+* Use register_my_thread_inner to add initial thread in pthread_support.c
+* Use single-argument suspend_handler for E2K, HP_PA, IA64, M68K
+* Warn if heap has grown while GC was disabled
+* Workaround 'TEXT is unknown macro' cppcheck FP warning
+* Workaround 'data access w/o lock' code defect FP in GC_incr_bytes_freed
+* Workaround 'returning pointer to local variable base' cppcheck FP in misc
+* Workaround 'total_time<0 is always false' cppcheck FP warning
+
+
+== [8.2.4] (not released yet) ==
+
+* Abort with appropriate message if first call of mmap fails with EPERM
+* Avoid potential race between realloc and GC_block_was_dirty
+* Eliminate 'GC_unmap_end declared but unused' bcc warning in disclaim_bench
+* Eliminate 'cast signed to bigger unsigned' CSA warning in WARN calls
+* Fix 'call to undeclared pthread_setname_np' errors in configure and cmake
+* Fix 'overflow in conversion from word' g++ warning in GC_init
+* Fix 'unknown option --no-undefined' linker error in cmake script (OS X)
+* Fix IRIX5 defined wrongly on FreeBSD/mips, WinCE/mips, Tandem S-Series
+* Fix data race in GC_heapsize_at_forced_unmap variable
+* Fix disabling of automatic dynamic libraries registration
+* Fix double initialization of main thread local free lists on Win32
+* Fix loop condition over dll_thread_table in GC_lookup_pthread (Win32)
+* Fix missing GC_CALLBACK for GC_waitForSingleObjectInfinite
+* Fix missing libalphagc.so dependency in Makefile.direct
+* Fix missing lock while updating GC_in_thread_creation in GC_exit_check
+* Fix missing recovery from faults in GC_mark_some on Win64 if MinGW
+* Fix missing result check of pthread_attr_getdetachstate in pthread_create
+* Fix mistyped function name in documentation of REDIRECT_REALLOC
+* Fix negative heap size values reported in WARN
+* Fix typos in comments of dll_thread_table and GC_Thread_Rep.dummy
+* Fix use of unset errno after pthread_create/sigmask calls
+* Remove false warning of missing libpthread.so on Linux
+* Remove redundant GC_ATTR_UNUSED for GC_mark_and_push
+* Replace WARN in GC_mark_some wrapper back to GC_COND_LOG_PRINTF
+
+
+== [8.2.2] 2022-08-26 ==
+
+* Abort if no progress with thread suspend/resume signals resending
+* Add CMake option to force libatomic_ops headers usage
+* Add _PROP suffix to CORD/GC[CPP]_VERSION variables in CMake script
+* Allow not to bypass pthread_cancel hardening in pthread_start
+* Allow to start marker threads in child of single-threaded client
+* Avoid potential race in GC_init_real_syms after GC_allow_register_threads
+* Avoid potential signal loss before sigsuspend in suspend_handler if TSan
+* Define SUNOS5SIGS macro for kFreeBSD
+* Distribute gc_gcj.h and some other headers in single-obj-compilation
+* Do not assert that GC is initialized at DLL_THREAD_DETACH (Win32)
+* Do not call SET_HDR() to remove forwarding counts if none exists in hblk
+* Do not call mprotect/mmap to GC_unmap/remap (Linux)
+* Do not count unmapped regions if GC_unmap is madvise-based (Linux)
+* Do not define NEED_FIND_LIMIT in case of OpenBSD user threads
+* Do not fail tests if pthread_create returns resource unavailable error
+* Do not name GCC intrinsics as C11 ones
+* Do not probe to find main data root start if dl_iterate_phdr exists
+* Do not send signal to thread which is suspended manually
+* Do not use usleep between signals resend if ThreadSanitizer
+* Eliminate '-pedantic is not option that controls warnings' GCC-6.3 message
+* Eliminate '/GS can not protect parameters' MS VC warning in msvc_dbg
+* Eliminate 'R_AARCH64_ABS64 used with TLS symbol' linker warning (clang)
+* Eliminate 'buffer overflow detected' FP error in realloc_test
+* Eliminate 'extension used' clang warning in sparc_mach_dep.S (configure)
+* Eliminate 'function/data pointer conversion in expression' MSVC warning
+* Eliminate 'implicit decl of _setjmp' gcc warning if -std=c11 on Cygwin
+* Eliminate 'layout of aggregates has changed in GCC 5' warning in test_cpp
+* Eliminate 'new_l may be used uninitialized' gcc warning in os_dep (Cygwin)
+* Eliminate 'old_gc_no is initialized but not referenced' MS VC false warning
+* Eliminate 'possible loss of data' compiler warning in GC_envfile_getenv
+* Eliminate 'potentially uninitialized local variable tc' warning (MSVC)
+* Eliminate 'skipping config since MAX_HEAP_SECTS is unknown' cppcheck FP
+* Eliminate 'unused but set variable' gcc warnings in cpptest
+* Eliminate 'value exceeds maximum size' warnings in debug_malloc, huge_test
+* Eliminate 'writing into region of size 0' gcc FP warning in realloc
+* Eliminate ASan stack-buffer-underflow FP in GC_mark_and_push_stack (E2K)
+* Eliminate code defect about incorrect size of allocated object (leaktest)
+* Eliminate data race reported by TSan in GC_have_errors
+* Eliminate division-by-zero FP warning in GC_ASSERT in reclaim_block
+* Eliminate stringop-overflow gcc-12 warning in CORD__next
+* Ensure typed objects descriptor is never located in the first word
+* Fix 'GC_greatest_stack_base_below is defined but not used' warning (IA64)
+* Fix 'GC_text_mapping not used' GCC warning if redirect malloc w/o threads
+* Fix 'ISO C forbids conversion of function pointer to object' warning
+* Fix 'undeclared getpagesize' compiler warning on AIX and OSF1
+* Fix 'undefined reference to __data_start' linker error on Linux/aarch64
+* Fix 'unresolved __imp__wsprintfA' linker error in msvc_dbg.c (MSVC)
+* Fix 'unresolved symbol GetModuleHandle' error in win32_threads.c (UWP)
+* Fix (workaround) stack overflow in gctest on Alpine Linux/s390x
+* Fix GC_ATTR_NO_SANITIZE_THREAD definition for GCC
+* Fix GC_allocate_ml incorrect cleanup in GC_deinit if pthreads (MinGW)
+* Fix GC_dirty() argument in GC_malloc_explicitly_typed_ignore_off_page
+* Fix GC_make_descriptor for zero length argument
+* Fix GC_suspend_thread if called before thread destructor
+* Fix GC_unmapped_bytes update in GC_unmap for Sony PS/3
+* Fix SIGSEGV caused by dropped stack access from child process in gctest
+* Fix SUNOS5SIGS documentation to match macro definition in gcconfig.h
+* Fix abort in Win32 DllMain if PARALLEL_MARK
+* Fix abort when GC_repeat_read returns zero
+* Fix assertion about built-in AO_test_and_set_acquire on sparc64 (gcc-12)
+* Fix assertion violation in GC_allow_register_threads on Windows
+* Fix assertion violation of GC_thread_key alignment if pthread-based TLS
+* Fix comment in GC_init regarding GC_init_parallel call
+* Fix context saving when GC_suspend_thread(self)
+* Fix data race in fail_proc1 of gctest
+* Fix hang in GC_free if GC_PREFER_MPROTECT_VDB (Mingw64)
+* Fix hang in select() called from suspend signal handler if TSan
+* Fix hang on sem_wait in GC_suspend_thread if thread was resumed recently
+* Fix hb_obj_kind type in documentation (ASCII diagram) describing hblkhdr
+* Fix incremental mode enabling in gctest if TEST_MANUAL_VDB
+* Fix linking of tests in case of finalization is off
+* Fix lock assertion violation in GC_find_limit if always multi-threaded
+* Fix memory return to OS in GC_unmap
+* Fix missing lock when GC_generate_random_valid_address is called
+* Fix missing write() declaration if CONSOLE_LOG (Watcom)
+* Fix nodist_libgc_la_SOURCES value in Makefile.am for Solaris/sparc
+* Fix oldProc initialization in gc_cleanup and eliminate related warnings
+* Fix parallel_initialized assertion violation in initsecondarythread (Win32)
+* Fix potential race if start_mark_threads called from threads in child
+* Fix propagation of out-of-memory occurred in GC_make_sequence_descriptor
+* Fix pthread_setname_np and dladdr detection by CMake
+* Fix race between calloc_explicitly_typed and push_complex_descriptor
+* Fix typos in comments and debugging.md
+* Fix undefined __stack_base__ on UWP/arm64 (llvm-mingw)
+* Force GC_with_callee_saves_pushed in suspend_handler if NO_SA_SIGACTION
+* Link with rt library to get clock_gettime where necessary
+* Make finalizer_closure pointer read/write atomic in malloc and callback
+* Move platform-specific sleep call to GC_usleep (refactoring)
+* Pass -lrt linker option in CMake script on HP/UX, NetBSD
+* Prevent (fix) parallel custom mark procs run in single-threaded clients
+* Prevent changing of GC_markers_m1 value while collection in progress
+* Refer to Makefile.direct instead of deleted Makefile file in README
+* Relax assertion of hb_n_marks in reclaim_block if more than two markers
+* Remove IF_IA64 macro in pthread_stop_world (refactoring)
+* Remove checking of RS6000 completely
+* Remove duplicate check of MSWIN_XBOX1 in os_dep.c
+* Remove duplicate include gc_tiny_fl.h in gc_priv.h
+* Remove non-working check of M68K in gctest
+* Remove useless TSan W/A about read of mark_lock_holder for Windows
+* Replace RAISE_SIGNAL macro with a static function (refactoring)
+* Replace SSH cloning with HTTPS one in README
+* Retry pthread_kill if EAGAIN (Linux)
+* Revert "Check real-symbols are already initialized in pthread_join/detach"
+* Revert "Remove nested always-false ifdef for HPUX and FREEBSD"
+* Revert addition of msvc_dbg.h in include.am
+* Set default build type to RelWithDebInfo (CMake)
+* Start configure help messages with a lower case letter
+* Support 'z' format modifier by CORD_vsprintf
+* Support Elbrus 2000 (Linux/e2k)
+* Support GCC MCF thread model (mcfgthreads) in configure (MinGW)
+* Support GC_remove_roots on Win32
+* Support OpenBSD/riscv64
+* Support build using Makefile.direct on Linux/sparc
+* Support space-separated flags in CFLAGS_EXTRA passed to CMake
+* Update README.win32 about default build configuration (configure, cmake)
+* Update documentation of GC_RATE and MAX_PRIOR_ATTEMPTS
+* Use SIGRTMIN+6 as suspend signal if sigrt-signals on OpenBSD
+* Use SIGUSR1/2 on FreeBSD/arm64
+* Use compiler TLS on NetBSD only if at least gcc-4.4 or clang-3.9
+* Workaround 'info is not assigned' cppcheck FP if assertions on (OS X)
+* Workaround SIG_SUSPEND delivery to thread inside mutex_lock fail if TSan
+* Workaround TSan FP about race between generic_malloc and array_mark_proc
+* Workaround TSan FP in acquire_mark_lock called from fork_prepare_proc
+* Workaround TSan FP warning in finalized_malloc, push_unconditionally
+* Workaround TSan FP warning in fork_prepare_proc
+* Workaround TSan FP warning in push_marked1/2/4, ptr_store_and_dirty
+* Workaround Thread Sanitizer (TSan) FP warning in is_valid_displacement
+* Workaround call stack size exceeded in gctest (Wasm)
+* Workaround crash in FreeBSD rand() by avoiding its concurrent usage
+* Workaround gctest hang if test compiled as C++ code by MSVC (CMake)
+* Workaround msvc_dbg.c build failure on arm[64] (MSVC)
+
+
 == [8.2.0] 2021-09-29 ==
 
 * Add API for accessing incremental GC time limit with nanosecond precision
@@ -210,13 +599,103 @@
 * Use clock_gettime() instead of clock() on Cygwin and Linux
 * Use compiler TLS on FreeBSD and NetBSD
 * Use mprotect-based VDB on PowerPC and S390 (Linux)
-* Use soft dirty bits on Linux (i386, powerpc, s390, x86_64)
+* Use soft dirty bits on Linux (x86, powerpc, s390, x64)
 * Workaround 'condition result<=0 is always false' cppcheck FP in get_maps
 * Workaround 'push_regs configured incorrectly' error (GCC-11)
 * Workaround 'same value in both branches of ternary operator' cppcheck FP
 * Workaround various cppcheck false positives
 
 
+== [8.0.10] (not released yet) ==
+
+* Abort with appropriate message if first call of mmap fails with EPERM
+* Avoid potential race between realloc and GC_block_was_dirty
+* Fix 'overflow in conversion from word' g++ warning in GC_init
+* Fix typo in comment of GC_Thread_Rep.dummy
+* Fix use of unset errno after pthread_sigmask calls
+* Remove redundant GC_ATTR_UNUSED for GC_mark_and_push
+
+Also, includes 7.6.18 changes
+
+
+== [8.0.8] 2022-08-26 ==
+
+* Avoid potential race in GC_init_real_syms after GC_allow_register_threads
+* Define SUNOS5SIGS macro for kFreeBSD
+* Distribute gc_disclaim.h in single-obj-compilation
+* Do not assert that GC is initialized at DLL_THREAD_DETACH (Win32)
+* Do not name GCC intrinsics as C11 ones
+* Do not send signal to thread which is suspended manually
+* Eliminate 'buffer overflow detected' FP error in realloc_test
+* Eliminate 'extension used' clang warning in sparc_mach_dep.S (configure)
+* Eliminate 'function/data pointer conversion in expression' MSVC warning
+* Eliminate 'implicit decl of _setjmp' gcc warning if -std=c11 on Cygwin
+* Eliminate 'new_l may be used uninitialized' gcc warning in os_dep (Cygwin)
+* Eliminate 'old_gc_no is initialized but not referenced' MS VC false warning
+* Eliminate 'possible loss of data' compiler warning in GC_envfile_getenv
+* Eliminate 'value exceeds maximum size' warnings in debug_malloc, huge_test
+* Eliminate 'writing into region of size 0' gcc FP warning in realloc
+* Eliminate division-by-zero FP warning in GC_ASSERT in reclaim_block
+* Eliminate stringop-overflow gcc-12 warning in CORD__next
+* Ensure typed objects descriptor is never located in the first word
+* Fix 'GC_greatest_stack_base_below is defined but not used' warning (IA64)
+* Fix 'GC_text_mapping not used' GCC warning if redirect malloc w/o threads
+* Fix 'ISO C forbids conversion of function pointer to object' warning
+* Fix 'undeclared getpagesize' compiler warning on AIX and OSF1
+* Fix 'undefined reference to __data_start' linker error on Linux/aarch64
+* Fix GC_allocate_ml incorrect cleanup in GC_deinit if pthreads (MinGW)
+* Fix GC_dirty() argument in GC_malloc_explicitly_typed_ignore_off_page
+* Fix GC_make_descriptor for zero length argument
+* Fix GC_suspend_thread if called before thread destructor
+* Fix GC_unmapped_bytes update in GC_unmap for Sony PS/3
+* Fix SIGSEGV caused by dropped stack access from child process in gctest
+* Fix SUNOS5SIGS documentation to match macro definition in gcconfig.h
+* Fix abort in Win32 DllMain if PARALLEL_MARK
+* Fix assertion about built-in AO_test_and_set_acquire on sparc64 (gcc-12)
+* Fix assertion violation in GC_allow_register_threads on Windows
+* Fix assertion violation of GC_thread_key alignment if pthread-based TLS
+* Fix context saving when GC_suspend_thread(self)
+* Fix data race in fail_proc1 of gctest
+* Fix get_maps failure when GC_repeat_read returns zero
+* Fix hang in GC_free if GC_PREFER_MPROTECT_VDB (Mingw64)
+* Fix hang in select() called from suspend signal handler if TSan
+* Fix hang on sem_wait in GC_suspend_thread if thread was resumed recently
+* Fix hb_obj_kind type in documentation (ASCII diagram) describing hblkhdr
+* Fix incremental mode enabling in gctest if TEST_MANUAL_VDB
+* Fix lock assertion violation in GC_find_limit if always multi-threaded
+* Fix missing lock when GC_generate_random_valid_address is called
+* Fix nodist_libgc_la_SOURCES value in Makefile.am for Solaris/sparc
+* Fix oldProc initialization in gc_cleanup and eliminate related warnings
+* Fix parallel_initialized assertion violation in initsecondarythread (Win32)
+* Fix potential race if start_mark_threads called from threads in child
+* Fix propagation of out-of-memory occurred in GC_make_sequence_descriptor
+* Fix race between calloc_explicitly_typed and push_complex_descriptor
+* Fix stack overflow in gctest on Alpine Linux/s390x
+* Fix typo in debugging.html
+* Fix typos in comments of .c files and gc.h
+* Fix undefined __stack_base__ on UWP/arm64 (llvm-mingw)
+* Make finalizer_closure pointer read/write atomic in malloc and callback
+* Prevent (fix) parallel custom mark procs run in single-threaded clients
+* Prevent changing of GC_markers_m1 value while collection in progress
+* Refer to Makefile.direct instead of deleted Makefile file in README
+* Relax assertion of hb_n_marks in reclaim_block if more than two markers
+* Remove checking of RS6000 completely
+* Remove duplicate check of MSWIN_XBOX1 in os_dep.c
+* Remove non-working check of M68K in gctest
+* Remove useless TSan W/A about read of mark_lock_holder for Windows
+* Replace SSH cloning with HTTPS one in README
+* Revert "Remove nested always-false ifdef for HPUX and FREEBSD"
+* Revert addition of msvc_dbg.h in include.am
+* Support 'z' format modifier by CORD_vsprintf
+* Update documentation of GC_RATE and MAX_PRIOR_ATTEMPTS
+* Use SIGRTMIN+6 as suspend signal if sigrt-signals on OpenBSD
+* Workaround TSan FP about race between generic_malloc and array_mark_proc
+* Workaround TSan FP warning in finalized_malloc, push_unconditionally
+* Workaround TSan FP warning in push_marked1/2/4, ptr_store_and_dirty
+* Workaround Thread Sanitizer (TSan) FP warning in is_valid_displacement
+* Workaround crash in FreeBSD rand() by avoiding its concurrent usage (tests)
+
+
 == [8.0.6] 2021-09-28 ==
 
 * Add loop to handle abort error like in suspend logic on Darwin
@@ -633,6 +1112,33 @@
 * Workaround Thread Sanitizer (TSan) false positive warnings
 
 
+== [7.6.18] (not released yet) ==
+
+* Fix IRIX5 defined wrongly on FreeBSD/mips
+* Fix data race in GC_heapsize_at_forced_unmap variable
+
+Also, includes 7.4.24 changes
+
+
+== [7.6.16] 2022-08-26 ==
+
+* Do not send signal to thread which is suspended manually
+* Eliminate 'old_gc_no is initialized but not referenced' MS VC false warning
+* Fix 'GC_greatest_stack_base_below is defined but not used' warning (IA64)
+* Fix context saving when GC_suspend_thread(self)
+* Fix data race in fail_proc1 of gctest
+* Fix GC_suspend_thread if called before thread destructor
+* Fix hang on sem_wait in GC_suspend_thread if thread was resumed recently
+* Fix lock assertion violation in GC_find_limit if always multi-threaded
+* Fix potential race if start_mark_threads called from threads in child
+* Make finalizer_closure pointer read/write atomic in malloc and callback
+* Prevent changing of GC_markers_m1 value while collection in progress
+* Replace SSH cloning with HTTPS one in README
+* Workaround Thread Sanitizer (TSan) FP warning in is_valid_displacement
+
+Also, includes 7.4.22 changes
+
+
 == [7.6.14] 2021-09-28 ==
 
 * Add loop to handle abort error like in suspend logic on Darwin
@@ -845,7 +1351,7 @@
 * Fix typo in comment in specific.h
 * Fix unbounded heap growth in case of intensive disappearing links usage
 * Remove API symbols renaming in WCC_MAKEFILE
-* Support Haiku/amd64 and Haiku/x86 hosts
+* Support Haiku/x64 and Haiku/x86 hosts
 * Support threads for DragonFly in configure
 * Workaround 'address of auto-variable returned' cppcheck error
 * Workaround gctest hang on kFreeBSD (if thread-local allocations are on)
@@ -1161,7 +1667,7 @@ Also, includes 7.4.6 changes
 * Show WoW64 warning message if running 32-bit on Win64 (enabled by macro)
 * Standalone profiling callback for threads suspend/resume
 * Support (add machine description for) TILE-Gx and TILEPro targets
-* Support build for Android 64-bit (arm64, mips64, x86_64)
+* Support build for Android 64-bit (arm64, mips64, x64)
 * Support FreeBSD/aarch64, FreeBSD/mips
 * Support iOS7 64-bit (AArch64) and iOS8+ 32/64-bit (Darwin)
 * Support MinGW build in scripts
@@ -1174,6 +1680,32 @@ Also, includes 7.4.6 changes
 Also, includes 7.4.4 changes
 
 
+== [7.4.24] (not released yet) ==
+
+* Eliminate 'cast signed to bigger unsigned' CSA warning in WARN calls
+* Fix missing lock while updating GC_in_thread_creation in GC_exit_check
+
+Also, includes 7.2q changes.
+
+
+== [7.4.22] 2022-08-26 ==
+
+* Eliminate 'new_l may be used uninitialized' gcc warning in os_dep (Cygwin)
+* Eliminate 'possible loss of data' compiler warning in GC_envfile_getenv
+* Fix 'undeclared getpagesize' compiler warning on AIX and OSF1
+* Fix GC_dirty() argument in GC_malloc_explicitly_typed_ignore_off_page
+* Fix SIGSEGV caused by dropped stack access from child process in gctest
+* Fix abort in Win32 DllMain if PARALLEL_MARK
+* Fix assertion violation of GC_thread_key alignment if pthread-based TLS
+* Fix comment in GC_init regarding GC_init_parallel call
+* Fix stack overflow in gctest on Alpine Linux/s390x
+* Revert "Remove nested always-false ifdef for HPUX and FREEBSD"
+* Use SIGRTMIN+6 as suspend signal if sigrt-signals on OpenBSD
+* Workaround crash in FreeBSD rand() by avoiding its concurrent usage
+
+Also, includes 7.2p changes.
+
+
 == [7.4.20] 2021-09-28 ==
 
 * Do not hold GC_fault_handler_lock when in Sleep (Windows)
@@ -1372,7 +1904,7 @@ Also, includes 7.2h changes
 == [7.4.4] 2016-05-25 ==
 
 * Allow GC_FAST_MALLOC_GRANS() multiple use in a function
-* Also enable the TSX workaround for i386 (Linux)
+* Also enable the TSX workaround for Linux/x86
 * Avoid unstructured procfs on Solaris
 * Change cord/de main() declaration style from K-R to ANSI C
 * Change no-argument functions declaration style to ANSI C (cord)
@@ -1700,6 +2232,44 @@ Also, includes 7.2e, 7.2d, 7.2c, 7.2b changes
 Also, includes 7.2 changes
 
 
+== [7.2q] (not released yet) ==
+
+* Fix IRIX5 defined wrongly on Tandem S-Series and WinCE/mips
+* Fix disabling of automatic dynamic libraries registration
+* Fix double initialization of main thread local free lists on Win32
+* Fix loop condition over dll_thread_table in GC_lookup_pthread (Win32)
+* Fix missing GC_CALLBACK for GC_waitForSingleObjectInfinite
+* Fix missing libalphagc.so dependency in Makefile.direct
+* Fix missing result check of pthread_attr_getdetachstate in pthread_create
+* Fix mistyped function name in documentation of REDIRECT_REALLOC
+* Fix typo in comment belonging to dll_thread_table
+* Fix use of unset errno after pthread_create call
+
+
+== [7.2p] 2022-08-25 ==
+
+* Avoid potential race in GC_init_real_syms after GC_allow_register_threads
+* Define SUNOS5SIGS macro for kFreeBSD
+* Do not assert that GC is initialized at DLL_THREAD_DETACH (Win32)
+* Ensure typed objects descriptor is never located in the first word
+* Fix GC_make_descriptor for zero length argument
+* Fix SUNOS5SIGS documentation to match macro definition in gcconfig.h
+* Fix assertion violation in GC_allow_register_threads on Windows
+* Fix get_maps failure when GC_repeat_read returns zero
+* Fix hb_obj_kind type in documentation (ASCII diagram) describing hblkhdr
+* Fix missing lock when GC_generate_random_valid_address is called
+* Fix nodist_libgc_la_SOURCES value in Makefile.am for Solaris/sparc
+* Fix oldProc initialization in gc_cleanup and eliminate related warnings
+* Fix parallel_initialized assertion violation in initsecondarythread (Win32)
+* Fix propagation of out-of-memory occurred in GC_make_sequence_descriptor
+* Fix race between calloc_explicitly_typed and push_complex_descriptor
+* Fix typos in comments of .c files, gc.h and a typo in debugging.html
+* Refer to Makefile.direct instead of deleted Makefile file in README
+* Remove checking of RS6000 completely
+* Remove non-working check of M68K in gctest
+* Revert addition of msvc_dbg.h in include.am
+
+
 == [7.2o] 2021-09-28 ==
 
 * Add loop to handle abort error like in suspend logic on Darwin
@@ -1947,7 +2517,7 @@ Also, includes 7.2 changes
 * Fix GC_scratch_last_end_ptr update on GC_scratch_alloc failure
 * Fix GET_MEM argument rounding in GC_scratch_alloc and similar
 * Fix PARALLEL_MARK for Windows 7+
-* Fix build (broken by fenv.h inclusion) on Linux/x86_64 under uClibc
+* Fix build (broken by fenv.h inclusion) on Linux/x64 under uClibc
 * Fix crash when using GC_malloc_many() as first allocation call
 * Fix mark stack excessive growth during parallel mark
 * Fix or remove broken URLs in documentation
@@ -2029,7 +2599,7 @@ Also, includes 7.2 changes
 * Abort in GC_thr_init on pthread_atfork failure (POSIX threads)
 * Add GC_WIN32_PTHREADS target in configure
 * Add GC_is_disabled new function to GC API
-* Add info that getcontext() resets FPE mask no longer on Linux/x86_64
+* Add info that getcontext() resets FPE mask no longer on Linux/x64
 * Add public GC_set_handle_fork to control forked child handling support
 * Add realloc_test.c test
 * Add support for Hexagon target
@@ -3224,7 +3794,7 @@ include fenv.h if defined (unless NO_GETCONTEXT or HAVE_PUSH_REGS).
 * mach_dep.c (GC_with_callee_saves_pushed): Restore FPU exception
 mask corrupted by getcontext if GETCONTEXT_FPU_EXCMASK_BUG.
 * include/private/gcconfig.h (GETCONTEXT_FPU_EXCMASK_BUG): Define
-for Linux/amd64 (since its GLibc getcontext currently has the bug).
+for Linux/x64 (since its GLibc getcontext currently has the bug).
 
 * allchblk.c (GC_use_entire_heap): Change type to int (as declared
 in gc.h); set the default value depending on new GC_USE_ENTIRE_HEAP
@@ -3620,7 +4190,7 @@ register pushing.
 * darwin_stop_world.c (GC_push_all_stacks): Set outCount to
 GC_MACH_THREAD_STATE_COUNT (instead of THREAD_STATE_MAX).
 * darwin_stop_world.c (GC_push_all_stacks): Remove FIXME and WARN
-for i386.
+for x86.
 
 * doc/README.macros (DARWIN_DONT_PARSE_STACK): Fix a typo.
 * darwin_stop_world.c (GC_use_mach_handler_thread): Change type
@@ -3631,7 +4201,7 @@ Simplify the expressions involving GC_use_mach_handler_thread.
 Initialize GC_use_mach_handler_thread to TRUE (instead of 1).
 
 * include/gc_pthread_redirects.h (GC_pthread_sigmask, GC_dlopen,
-pthread_sigmask, dlopen): Don't define for Win32 pthreads (and
+pthread_sigmask, dlopen): Don't define for pthreads-win32 (and
 don't include signal.h and dlfcn.h).
 
 * dyn_load.c (GC_register_dynlib_callback): Add FIXME.
@@ -3798,7 +4368,7 @@ is not yet).
 * win32_threads.c (GC_mark_thread_local_free_lists, GC_check_tls):
 Likewise.
 
-* NT_MAKEFILE: Remove the comment about DLL and Win32S.
+* NT_MAKEFILE: Remove the comment about DLL and win32s.
 * NT_STATIC_THREADS_MAKEFILE: Likewise.
 * NT_X64_STATIC_THREADS_MAKEFILE: Likewise.
 * NT_MAKEFILE: Add ".SUFFIXES" directive (to handle gc_cpp.cc
@@ -3993,7 +4563,7 @@ GC_enable_incremental() if MAKE_BACKGRAPH is defined, but
 do invoke it even if parallel marking is enabled.
 
 * tests/test.c (reverse_test): Comment out a check for MSWIN32
-(when determining BIG value) assuming outdated win32S.
+(when determining BIG value) assuming outdated win32s.
 * tests/test.c (reverse_test): Rename to reverse_test_inner;
 change the declaration (to be of GC_fn_type); call itself thru
 GC_call_with_gc_active() if the argument is zero.
@@ -4516,8 +5086,8 @@ with the ANSI C one.
 define it for OpenBSD.
 * include/gc_pthread_redirects.h (GC_pthread_sigmask,
 pthread_sigmask): Don't declare and redefine for OpenBSD.
-* include/private/gcconfig.h: Handle OpenBSD (on arm, sh, i386,
-amd64, powerpc).
+* include/private/gcconfig.h: Handle OpenBSD (on arm, sh, x86,
+x64, powerpc).
 * mach_dep.c (NO_GETCONTEXT): Likewise.
 * include/private/pthread_stop_world.h (thread_stop_info): Don't
 define last_stop_count field if OpenBSD.
@@ -5510,7 +6080,7 @@ replacing GC_never_stop_func with GC_default_stop_func (if
 possible).
 * alloc.c (GC_gcollect): Use GC_default_stop_func.
 * alloc.c (GC_collect_or_expand): Use GC_default_stop_func
-(instead of GC_never_stop_func) unless it is trigged due to out of
+(instead of GC_never_stop_func) unless it is triggered due to out of
 memory; don't increment GC_fail_count and don't output warning
 (before trying to collect again) in case the collection has been
 interrupted (by GC_default_stop_func) and the heap expansion has
@@ -6899,9 +7469,9 @@ prevent left shift overflow.
 * os_dep.c: change the type of GC_mem_top_down global variable
 (containing a flag) to DWORD.
 * include/gc_config_macros.h: define GC_SOLARIS_THREADS if GC_THREADS
-is defined on SunOS x86_64.
+is defined on SunOS/x64.
 * misc.c (GC_init_size_map): Ifdef out GC_ASSERT as a workaround
-for VC++ 2008 amd64 (v15.00.21022.08 for x64) compiler bug
+for VC++ 2008 x64 (v15.00.21022.08 for x64) compiler bug
 (the compiler gets hung if invoked with -Ox -D
 ALL_INTERIOR_POINTERS -D GC_ASSERTIONS)
 * backgraph.c: cast GC_gc_no value to unsigned short when
@@ -6997,7 +7567,7 @@ redundant code.
 references to deleted variable "code".  Remove redundant
 FREEBSD definitions.
 * include/private/gcconfig.h (GWW_VDB): Define for X86_64 when
-defined for X86. (STATIC): Define as "static" with NO_DEBUGGING.
+defined for x86. (STATIC): Define as "static" with NO_DEBUGGING.
 
 * include/private/gc_priv.h: Update MAX_HEAP_SECTS.
 
@@ -7075,7 +7645,7 @@ My highlights based on reading the patch:
 
 * allchblk.c: Remove GC_freehblk_ptr decl.
 Make free_list_index_of() static.
-* include/gc.h: Use __int64 on win64, define GC_oom_func,
+* include/gc.h: Use __int64 on Win64, define GC_oom_func,
 GC_finalizer_notifier_proc, GC_finalizer_notifier_proc,
 add getter and setters: GC_get_gc_no, GC_get_parallel,
 GC_set_oom_fn, GC_set_finalize_on_demand,
@@ -7143,7 +7713,7 @@ GC_delete_gc_thread.
 * misc.c: Declare GC_thr_init().
 
 * allchblk.c (add_to_fl): disable assertions with USE_MUNMAP,
-and refine assertions to handle huge unmergable blocks.
+and refine assertions to handle huge unmergeable blocks.
 (GC_allochblk_nth): Add comment.
 
 * include/private/gcconfig.h: Add missing FREEBSD macro
@@ -7403,18 +7973,18 @@ include/private/gc_priv.h, tests/test_cpp.cc:
 Replace old style function declarations.  Clean up integral types.
 Remove register declarations.  The change in malloc.c and the
 "int descr" declaration in mark.c are the most likely to have
-been real bugs outside of win64.
-* msvc_dbg.c: Disable on win64.
-* win32_threads.c: Add AMD64 support.
-* include/gc.h: no backtrace on AMD64 for now.
+been real bugs outside of Win64.
+* msvc_dbg.c: Disable on Win64.
+* win32_threads.c: Add x64 support.
+* include/gc.h: no backtrace on x64 for now.
 
 * msvc_dbg.c(GetModuleBase): Replace strcat with strcat_s.
 
-* include/gc.h: (GC_word, GC_signed_word): Fix win64 definitions.
+* include/gc.h: (GC_word, GC_signed_word): Fix Win64 definitions.
 Don't include windows.h in an extern "C" context.
-* include/private/gcconfig.h: Fix win64/X86_64 configuration.
+* include/private/gcconfig.h: Fix Win64 configuration.
 * tests/test.c: Eliminate more old style function definitions.
-Cleanup pointer and integer casts for win64.
+Cleanup pointer and integer casts for Win64.
 * tests/test_cpp.cc: Don't include gc_priv.h.
 * NT_STATIC_THREADS_MAKEFILE: Restrict suffixes for VC++ 2005.
 * NT_X64_STATIC_THREADS_MAKEFILE: New.
@@ -7871,7 +8441,7 @@ extremely unlikely circumstances.  (Thanks to Jean-Baptiste Nivois for
 some careful code inspection.)
 * Added support for kFreeBSD + glibc (thanks to Petr Salinger).
 * Fix more MacOS threads memory leaks (thanks to Allan Hsu).
-* Added initial Solaris/X86-64 support (thanks to Rainer Orth).
+* Added initial Solaris/x64 support (thanks to Rainer Orth).
 
 
 == [6.7] 2006-03-03 ==
@@ -7893,7 +8463,7 @@ to Hanno Boeck).
 David Ayers).
 * Use ld instead of nonexistent ldz instruction in Darwin FindTopOfStack
 (thanks to Andreas Tobler).
-* Add support for Darwin/X86 (thanks to Geoff Norton and the Mono
+* Add support for Darwin/x86 (thanks to Geoff Norton and the Mono
 developers).
 * Merge in some recent gcc fixes.  Add ppc64 asm code.  (Thanks to
 Bryce McKinlay and other GCJ developers.)
@@ -8009,7 +8579,7 @@ is set (thanks to Alexander Petrossian).
 Without it, s390x breaks.  (Thanks to Ulrich Weigand.)
 * Applied several MacOSX patches to support older tool chains (thanks
 to Stefan Ring).
-* Bug fix for NetBSD/amd64 (thanks to Marc Recht).
+* Bug fix for NetBSD/x64 (thanks to Marc Recht).
 * Add NetBSD/sh3 support (thanks to Uchiyama Yasushi).
 * Fixed an uninitialized variable in cordprnt.c.
 * Eliminated some, but not all, gcc -Wall warnings.
@@ -8017,7 +8587,7 @@ to Stefan Ring).
 (thanks to Dan Grayson).
 * GC_extend_size_map shouldn't adjust for GC_all_interior_pointers if
 GC_DONT_ADD_BYTE_AT_END is set.
-* Changed some (long) casts to (word) in preparation for win64 (thanks
+* Changed some (long) casts to (word) in preparation for Win64 (thanks
 to Peter Colson).
 * Changed "int stack_size" declaration in pthread_support.c to use
 size_t.  (Only mattered with GC_ASSERTIONS enabled.)
@@ -8082,8 +8652,8 @@ to Andrew Begel).
 == [6.3alpha6] 2004-05-06 ==
 
 * Define USE_GENERIC_PUSH_REGS for NetBSD/M68K.
-* Fixed the X86_64 PREFETCH macros to correctly handle ia32e (which uses
-different prefetch instructions from AMD64).  (Thanks to H.J. Lu.)
+* Fixed the x64 PREFETCH macros to correctly handle ia32e (which uses
+different prefetch instructions on x64).  (Thanks to H.J. Lu.)
 * GC_config_macros.h did not correctly define GC_WIN32_THREADS from
 GC_THREADS.
 * Added simple_example.html.
@@ -8123,7 +8693,7 @@ It probably made more sense in the gcc context.
 * Explicitly ensure that NEED_FIND_LIMIT is defined for {Open,Net}BSD/ELF.
 * Replaced USE_HPUX_TLS macro by USE_COMPILER_TLS, since gcc often
 supports the same extension on various platforms.
-* Added some basic (completely untested) defines for win64, in support
+* Added some basic (completely untested) defines for Win64, in support
 of future work.
 * Declared GC_jmp_buf in os_dep.s as JMP_BUF instead of jmp_buf, fixing
 a memory overwrite bug on Solaris and perhaps other platforms.
@@ -8310,7 +8880,7 @@ fork() call.  Thus incremental collection in the child won't work
 correctly.  (Thanks to Ben Cottrell for pointing this out.)
 - --enable-redirect-malloc is mostly untested and known not to work
 on some platforms.
-- There seem to be outstanding issues on Solaris/X86, possibly with
+- There seem to be outstanding issues on Solaris/x86, possibly with
 finding the data segment starting address.
 - Very large root set sizes (> 16 MB or so) could cause the collector
 to abort with an unexpected mark stack overflow.  (Thanks to
@@ -8383,7 +8953,7 @@ and patch.)
 * Added hand-coded structured exception handling support to mark.c.
 This should enable support of dynamic libraries under win32 with
 gcc-compiled code.  (Thanks to Ranjit Mathew for the patch.)
-Turned on dynamic library scanning for win32/gcc.
+Turned on dynamic library scanning for gcc on Win32.
 * Removed some remnants of read wrapping (thanks to Kenneth Schalk).
 GC_USE_LD_WRAP was probably broken in recent versions.
 * The build could fail on some platforms since gcconfig.h could include
@@ -8533,7 +9103,7 @@ The latter is more reliable and easier on Linux with dl_iterate_phdr.
 * Added GC_MAXIMUM_HEAP_SIZE environment variable.
 * Fix configure.in for MIPS/LINUX (thanks to H.J. Lu).
 * Double page hash table size for -DLARGE_CONFIG.
-* Integrated Bo Thorsen's X86-64 support.
+* Integrated Bo Thorsen's x64 support.
 * STACKBOTTOM definition for LINUX/MIPS was partially changed back
 (thanks to H.J. Lu and Hiroshi Kawashima for resolving this).
 * Replaced all occurrences of LINUX_DATA_START in gcconfig.h with
@@ -8638,7 +9208,7 @@ Jeffrey Mark Siskind).
 with a system header (thanks to Philip Brown).
 * Cause win32_threads.c to handle an out of range stack pointer correctly,
 though currently with a warning.  (Thanks to Jonathan Clark for
-observing that win32 applications may temporarily use the stack
+observing that Windows applications may temporarily use the stack
 pointer for other purposes, and suggesting a fix.  Unfortunately, it's
 not clear that there is a complete solution to this problem.)
 
@@ -8717,7 +9287,7 @@ collectible (gc_allocator) or GC-traceable, but not collectible
 which borrows heavily from the SGI implementation, this part of
 which was written by Matt Austern.  Changed test_cpp.cc to very
 minimally test this.
-* On Linux/X86, retry mmap with a different start argument.  That should
+* On Linux/x86, retry mmap with a different start argument.  That should
 allow the collector to use more (closer to 3GB) of the address space.
 * Force 64 bit alignment with GCJ support (reflects Bryce McKinlay's
 patch to the gcc tree).
@@ -8739,7 +9309,7 @@ Tilman Vogel; also ported for iPAQ by Oliver Kurth).
 == [6.1alpha3] 2002-02-07 ==
 
 * Minor cleanup on the gcconfig.h section for SPARC.
-* Minor fix to support Intel compiler for I386/Linux (thanks to
+* Minor fix to support Intel compiler for Linux/x86 (thanks to
 Sven Hartrumpf).
 * Added SPARC V9 (64-bit) support (thanks to Jeff Sturm).
 * Restructured the way in which we determine whether or not to keep
@@ -8955,7 +9525,7 @@ many people are likely to care, but ...)
 yet supported.  (Incremental collection should work if you have the
 right kernel.  Threads may work with a sufficiently patched pthread
 library.)
-* Changed gcconfig.h to recognize __i386__ as an alternative to i386 in
+* Changed gcconfig.h to recognize __i386__ as an alternative to x86 in
 many places (thanks to Benjamin Lerman).
 * Made win32_threads.c more tolerant of detaching a thread that it didn't
 know about (thanks to Paul Nash).
@@ -9005,7 +9575,7 @@ for pointing this out).
 * Added GC_no_dls hook for applications that want to register their own
 roots.
 * Integrated Kjetil Matheussen's Amiga changes.
-* Added FREEBSD_STACKBOTTOM.  Changed the X86/FreeBSD port to use it
+* Added FREEBSD_STACKBOTTOM.  Changed the FreeBSD/x86 port to use it
 (thanks to Matthew Flatt).
 * Added pthread_detach interception for platforms supported by linux_threads.c
 and irix_threads.c.
@@ -9124,10 +9694,10 @@ were and never will be any clients.
 * Added some code to linux_threads.c to possibly support HPUX threads
 using the Linux code.  Unfortunately, it doesn't work yet, and is
 currently disabled.
-* Added support under Linux/X86 for saving the call chain, both in (debug)
+* Added support under Linux/x86 for saving the call chain, both in (debug)
 objects for client debugging, and in GC_arrays._last_stack for GC
 debugging.  This was previously supported only under Solaris.  It is
-not enabled by default under X86, since it requires that code be compiled
+not enabled by default under x86, since it requires that code be compiled
 to explicitly gave frame pointers on the call stack.  (With gcc this
 currently happens by default, but is often turned off explicitly.)
 To turn it on, define SAVE_CALL_CHAIN.
@@ -9621,7 +10191,7 @@ supported.  The collector now defines USE_MMAP by default on Solaris.
 * Fixed MSWIN32 detection test.
 * Added Fergus Henderson's patches to allow putting the collector into
 a DLL under GNU win32.
-* Added Ivan V. Demakov's port to Watcom C on X86.
+* Added Ivan V. Demakov's port to Watcom C on x86.
 * Added Ian Piumarta's Linux/PowerPC port.
 * Added PointerFreeGC to the placement options in gc_cpp.h (suggested by
 Brian Burton).  This is of course unsafe, and may be controversial.
@@ -9852,7 +10422,7 @@ gc_cleanup is miscompiled.
 * Added Mac fixes.
 * Fixed os_dep.c to work around what appears to be
 a new and different VirtualQuery bug under newer
-versions of win32S.
+versions of win32s.
 * GC_non_gc_bytes was not correctly maintained by
 GC_free.  Fixed (thanks to James Clark).
 * Added GC_set_max_heap_size.
@@ -10018,8 +10588,8 @@ a problem.
 * Fixed a gross bug in CORD_prev.
 * Fixed a bug in blacklst.c that could result in unbounded
 heap growth during startup on machines that do not clear
-memory obtained from the OS (e.g. win32S).
-* Ported de editor to win32/win32S.  (This is now the only
+memory obtained from the OS (e.g. win32s).
+* Ported de editor to Win32 and win32s.  (This is now the only
 version with a mouse-sensitive UI.  Thanks to Rob Haack for the
 implementation based on the generic Windows application template.)
 * Added GC_malloc_ignore_off_page to allocate large arrays
@@ -10055,7 +10625,7 @@ optimizer bug.
 only by reimplementing some fraction of Solaris threads,
 since Sun doesn't currently make the thread debugging
 interface available).
-* Added non-threads win32 and win32S support.
+* Added non-threads Win32 and win32s support.
 * (Grudgingly, with suitable muttering of obscenities) renamed
 files so that the collector distribution could live on a FAT
 file system.  Files that are guaranteed to be useless on

+ 2 - 2
blitz.mod/bdwgc/LICENSE

@@ -8,7 +8,7 @@ Copyright (c) 1999-2001 by Red Hat, Inc.  All rights reserved.
 Copyright (c) 1999-2011 Hewlett-Packard Development Company, L.P.
 Copyright (c) 2004-2005 Andrei Polushin
 Copyright (c) 2007 Free Software Foundation, Inc.
-Copyright (c) 2008-2021 Ivan Maidanski
+Copyright (c) 2008-2022 Ivan Maidanski
 Copyright (c) 2011 Ludovic Courtes
 Copyright (c) 2018 Petter A. Urkedal
 
@@ -17,7 +17,7 @@ THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
 OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 
 Permission is hereby granted to use or copy this program
-for any purpose,  provided the above notices are retained on all copies.
+for any purpose, provided the above notices are retained on all copies.
 Permission to modify the code and to distribute modified code is granted,
 provided the above notices are retained, and a notice that the code was
 modified is included with the above copyright notice.

+ 33 - 33
blitz.mod/bdwgc/Makefile.am

@@ -4,7 +4,7 @@
 # OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 #
 # Permission is hereby granted to use or copy this program
-# for any purpose,  provided the above notices are retained on all copies.
+# for any purpose, provided the above notices are retained on all copies.
 # Permission to modify the code and to distribute modified code is granted,
 # provided the above notices are retained, and a notice that the code was
 # modified is included with the above copyright notice.
@@ -14,7 +14,7 @@
 # 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 = 6:0:5
+LIBGC_VER_INFO = 6:1:5
 LIBGCCPP_VER_INFO = 6:0:5
 
 ## FIXME: `make distcheck' in this directory will not currently work.
@@ -70,22 +70,24 @@ libgc_la_SOURCES = \
 # C Library: Architecture Dependent
 # ---------------------------------
 
+if THREADS
+
+libgc_la_SOURCES += pthread_start.c pthread_support.c
+
+if THREAD_LOCAL_ALLOC
+libgc_la_SOURCES += thread_local_alloc.c
+endif
+
 if WIN32_THREADS
 libgc_la_SOURCES += win32_threads.c
 else
-if PTHREADS
-# Not Cygwin or MinGW.
-libgc_la_SOURCES += pthread_start.c pthread_support.c
 if DARWIN_THREADS
 libgc_la_SOURCES += darwin_stop_world.c
 else
 libgc_la_SOURCES += pthread_stop_world.c
 endif
 endif
-endif
 
-if THREAD_LOCAL_ALLOC
-libgc_la_SOURCES += thread_local_alloc.c
 endif
 
 if MAKE_BACK_GRAPH
@@ -109,14 +111,13 @@ endif
 
 if USE_INTERNAL_LIBATOMIC_OPS
 nodist_libgc_la_SOURCES = libatomic_ops/src/atomic_ops.c
-endif
-
 if NEED_ATOMIC_OPS_ASM
-nodist_libgc_la_SOURCES = libatomic_ops/src/atomic_ops_sysdeps.S
+nodist_libgc_la_SOURCES += libatomic_ops/src/atomic_ops_sysdeps.S
+endif
 endif
 
 # Include THREADDLLIBS here to ensure that the correct versions of
-# linuxthread semaphore functions get linked:
+# linuxthread semaphore (and clock_gettime) functions get linked:
 libgc_la_LIBADD = @addobjs@ $(THREADDLLIBS) $(UNWINDLIBS) $(ATOMIC_OPS_LIBS)
 libgc_la_DEPENDENCIES = @addobjs@
 libgc_la_LDFLAGS = $(extra_ldflags_libgc) -version-info $(LIBGC_VER_INFO) \
@@ -148,7 +149,7 @@ EXTRA_DIST += gc_badalc.cpp gc_cpp.cpp
 # Misc
 # ----
 
-AM_CXXFLAGS = @GC_CFLAGS@
+AM_CXXFLAGS = $(WERROR_CFLAGS) @GC_CFLAGS@
 AM_CFLAGS = $(WERROR_CFLAGS) @GC_CFLAGS@
 
 CFLAGS += $(CFLAGS_EXTRA)
@@ -183,9 +184,8 @@ CCASFLAGS += $(DEFS)
 #
 
 # other makefiles
-EXTRA_DIST += NT_MAKEFILE OS2_MAKEFILE PCR-Makefile digimars.mak \
-    Makefile.direct SMakefile.amiga WCC_MAKEFILE autogen.sh CMakeLists.txt \
-    Config.cmake.in build/s60v3/bld.inf build/s60v3/libgc.mmp
+EXTRA_DIST += Makefile.direct NT_MAKEFILE WCC_MAKEFILE digimars.mak \
+    autogen.sh CMakeLists.txt Config.cmake.in
 
 # files used by makefiles other than Makefile.am
 #
@@ -216,28 +216,28 @@ dist_doc_DATA = \
     AUTHORS \
     LICENSE \
     README.md \
-    doc/README.DGUX386 \
-    doc/README.Mac \
-    doc/README.OS2 \
-    doc/README.aix \
-    doc/README.amiga \
-    doc/README.arm.cross \
+    doc/platforms/README.aix \
+    doc/platforms/README.amiga \
+    doc/platforms/README.arm_cross \
+    doc/platforms/README.darwin \
+    doc/platforms/README.dgux386 \
+    doc/platforms/README.emscripten \
+    doc/platforms/README.ews4800 \
+    doc/platforms/README.hp \
+    doc/platforms/README.linux \
+    doc/platforms/README.mac \
+    doc/platforms/README.os2 \
+    doc/platforms/README.sgi \
+    doc/platforms/README.solaris2 \
+    doc/platforms/README.symbian \
+    doc/platforms/README.uts \
+    doc/platforms/README.win32 \
+    doc/platforms/README.win64 \
     doc/README.autoconf \
     doc/README.cmake \
     doc/README.cords \
-    doc/README.darwin \
-    doc/README.emscripten \
     doc/README.environment \
-    doc/README.ews4800 \
-    doc/README.hp \
-    doc/README.linux \
     doc/README.macros \
-    doc/README.sgi \
-    doc/README.solaris2 \
-    doc/README.symbian \
-    doc/README.uts \
-    doc/README.win32 \
-    doc/README.win64 \
     doc/debugging.md \
     doc/finalization.md \
     doc/gcdescr.md \

+ 133 - 129
blitz.mod/bdwgc/Makefile.direct

@@ -13,46 +13,57 @@
 # check-cpp-deps - same as check-cpp but do not run the test
 # cord/de - builds dumb editor based on cords.
 
-ABI_FLAG=
+ABI_FLAG?=
 # ABI_FLAG should be the cc flag that specifies the ABI.  On most
 # platforms this will be the empty string.  Possible values:
 # +DD64 for 64-bit executable on HP/UX.
 # -n32, -n64, -o32 for SGI/MIPS ABIs.
 
-AS_ABI_FLAG=$(ABI_FLAG)
+AS_ABI_FLAG?= $(ABI_FLAG)
 # ABI flag for assembler.  On HP/UX this is +A64 for 64 bit
 # executables.
 
-CC=cc $(ABI_FLAG)
+CC?= cc $(ABI_FLAG)
 # Compiler executable name.  For EMX, replace to "gcc".
 
-CXX=g++ $(ABI_FLAG)
+CXX?= g++ $(ABI_FLAG)
 # Needed only for "make c++", which builds the C++ interface.
 
-AS=as $(AS_ABI_FLAG)
+AS= as $(AS_ABI_FLAG)
 # The above doesn't work with gas, which doesn't run cpp.
 # Define AS as `gcc -c -x assembler-with-cpp' instead.
 # Under Irix 6, you have to specify the ABI (-o32, -n32, or -64)
 # if you use something other than the default ABI on your machine.
 
-LD=ld
+LD= ld
 
-# Redefining srcdir allows object code for the nonPCR version of the collector
+# Redefining srcdir allows object code of the collector
 # to be generated in different directories.
 srcdir= .
 VPATH= $(srcdir)
 
 # Path to atomic_ops source.
-AO_SRC_DIR=$(srcdir)/libatomic_ops
+AO_SRC_DIR?= $(srcdir)/libatomic_ops
+
+CFLAGS_EXTRA?=
 
-CFLAGS_EXTRA=
 # We need CFLAGS_FOR_PIC because we might be building a shared library.
-CFLAGS= -O -I$(srcdir)/include -I$(AO_SRC_DIR)/src \
+CFLAGS_FOR_PIC?=
+
+# The default libgc configuration, OK to customize it by client.
+CFLAGS_DEFAULT_MACROS?= \
   -DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE \
   -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION \
-  -DUSE_MMAP -DUSE_MUNMAP $(CFLAGS_FOR_PIC) $(CFLAGS_EXTRA)
+  -DUSE_MMAP -DUSE_MUNMAP
+
+# The client or host might provide the default optimizations flags (e.g. -O2).
+CFLAGS?= -O
+
+# Add the required options to CFLAGS like -I option.
+CFLAGS+= -I$(srcdir)/include -I$(AO_SRC_DIR)/src \
+  $(CFLAGS_DEFAULT_MACROS) $(CFLAGS_FOR_PIC) $(CFLAGS_EXTRA)
 
-# To build the collector with threads support, add to the above:
+# To build the collector with threads support, add to CFLAGS_EXTRA:
 # -DGC_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC
 #
 # To build the preload library that intercepts malloc, add:
@@ -61,12 +72,16 @@ CFLAGS= -O -I$(srcdir)/include -I$(AO_SRC_DIR)/src \
 # To build the collector with fork() support by default, add to the above:
 # -DHANDLE_FORK
 
+# To build the collector with GC_wcsdup support, provided libc has wcslen(),
+# add to the above:
+# -DGC_REQUIRE_WCSDUP
+
 # HOSTCC and HOSTCFLAGS are used to build executables that will be run as
 # part of the build process, i.e. on the build machine.  These will usually
 # be the same as CC and CFLAGS, except in a cross-compilation environment.
 # Note that HOSTCFLAGS should include any -D flags that affect thread support.
-HOSTCC=$(CC)
-HOSTCFLAGS=$(CFLAGS)
+HOSTCC= $(CC)
+HOSTCFLAGS= $(CFLAGS)
 
 # For dynamic library builds, it may be necessary to add flags to generate
 # PIC code, e.g. -fPIC on Linux.
@@ -77,19 +92,27 @@ HOSTCFLAGS=$(CFLAGS)
 # Look into doc/README.macros for the description of the "define arguments"
 # influencing the collector configuration.
 
-CXXFLAGS= $(CFLAGS)
+# Flags for the C++ files.
+# Note: non-GNU make might not recognize "?=" properly, so just duplicate
+# the flags of CFLAGS as a workaround.
+CXXFLAGS?=
+CXXFLAGS+= -I$(srcdir)/include -I$(AO_SRC_DIR)/src \
+  $(CFLAGS_DEFAULT_MACROS) $(CFLAGS_FOR_PIC) $(CFLAGS_EXTRA)
+
 AR= ar
 
 RANLIB= ranlib
 # For EMX, replace "ranlib" with "ar s".
 
-
+# All .o files of libgc.a except for dyn_load.o.
 OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o \
   headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o  \
   malloc.o checksums.o pthread_support.o pthread_stop_world.o \
   darwin_stop_world.o typd_mlc.o ptr_chck.o mallocx.o gcj_mlc.o specific.o \
   gc_dlopen.o backgraph.o win32_threads.o pthread_start.o \
-  thread_local_alloc.o fnlz_mlc.o atomic_ops.o atomic_ops_sysdeps.o
+  thread_local_alloc.o fnlz_mlc.o
+
+NODIST_OBJS= atomic_ops.o atomic_ops_sysdeps.o
 
 CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c \
   headers.c mark.c obj_map.c blacklst.c finalize.c \
@@ -117,8 +140,7 @@ SRCS= $(CSRCS) \
   include/private/specific.h include/gc/leak_detector.h \
   include/gc/gc_pthread_redirects.h include/private/gc_atomic_ops.h \
   include/gc/gc_config_macros.h include/private/pthread_support.h \
-  include/private/pthread_stop_world.h include/private/darwin_semaphore.h \
-  include/private/darwin_stop_world.h include/private/thread_local_alloc.h \
+  include/private/darwin_semaphore.h include/private/thread_local_alloc.h \
   ia64_save_regs_in_stack.s sparc_mach_dep.S \
   sparc_netbsd_mach_dep.s $(CORD_SRCS)
 
@@ -126,13 +148,13 @@ CORD_INCLUDE_FILES= $(srcdir)/include/gc.h $(srcdir)/include/gc/cord.h \
   $(srcdir)/include/gc/ec.h $(srcdir)/include/gc/cord_pos.h
 
 # Executable file name extension.  For EMX, specify ".exe".
-EXEEXT=
+EXEEXT?=
 
 UTILS= if_mach$(EXEEXT) if_not_there$(EXEEXT) threadlibs$(EXEEXT)
 
 # Libraries needed for curses applications.  Only needed for de.
 # It might also require -ltermlib on some targets.
-CURSES= -lcurses
+CURSES?= -lcurses
 
 # The following is irrelevant on most systems.  But a few
 # versions of make otherwise fork the shell specified in
@@ -141,20 +163,20 @@ SHELL= /bin/sh
 
 SPECIALCFLAGS= -I$(srcdir)/include -I$(AO_SRC_DIR)/src $(CFLAGS_FOR_PIC)
 # Alternative flags to the C compiler for mach_dep.c.
-# Mach_dep.c often doesn't like optimization, and it's
+# mach_dep.c often doesn't like optimization, and it's
 # not time-critical anyway.
 # Set SPECIALCFLAGS to -q nodirect_code on Encore.
 
 all: base_lib cords c++
 
 atomic_ops.o: $(AO_SRC_DIR)/src/atomic_ops.c
-	$(CC) $(CFLAGS) -c -o $@ $(AO_SRC_DIR)/src/atomic_ops.c
+	$(CC) $(CFLAGS) -c $(AO_SRC_DIR)/src/atomic_ops.c
 # For some reason, Solaris make does not handle "$<" properly.
 
 atomic_ops_sysdeps.o: $(AO_SRC_DIR)/src/atomic_ops_sysdeps.S
-	$(CC) $(CFLAGS) -c -o $@ $(AO_SRC_DIR)/src/atomic_ops_sysdeps.S
+	$(CC) $(CFLAGS) -c $(AO_SRC_DIR)/src/atomic_ops_sysdeps.S
 
-LEAKFLAGS= $(CFLAGS) -DFIND_LEAK
+LEAK_CFLAGS= $(CFLAGS) -DFIND_LEAK
 
 BSD-pkg-all: bsd-libgc.a bsd-libleak.a
 
@@ -165,8 +187,8 @@ bsd-libgc.a bsd-libgccpp.a bsd-libgctba.a:
 	mv libgctba.a bsd-libgctba.a
 
 bsd-libleak.a:
-	$(MAKE) -f Makefile.direct CFLAGS="$(LEAKFLAGS)" clean c++-nt
-	mv libgc.a bsd-libleak.a
+	$(MAKE) -f Makefile.direct CFLAGS="$(LEAK_CFLAGS)" clean c++-nt
+	mv libgc.a $@
 
 BSD-pkg-install: BSD-pkg-all
 	${CP} bsd-libgc.a libgc.a
@@ -178,13 +200,7 @@ BSD-pkg-install: BSD-pkg-all
 	${INSTALL_DATA} gc.h gc_cpp.h ${PREFIX}/include
 	${INSTALL_MAN} gc.man ${PREFIX}/man/man3/gc.3
 
-pcr: PCR-Makefile include/private/gc_private.h include/private/gc_hdrs.h \
-  include/private/gc_locks.h include/gc.h include/private/gcconfig.h \
-  mach_dep.o $(SRCS)
-	$(MAKE) -f PCR-Makefile depend
-	$(MAKE) -f PCR-Makefile
-
-$(OBJS) tests/test.o dyn_load.o dyn_load_sunos53.o: \
+$(OBJS) tests/gctest.o dyn_load.o dyn_load_sunos53.o: \
   $(srcdir)/include/private/gc_priv.h \
   $(srcdir)/include/private/gc_hdrs.h $(srcdir)/include/private/gc_locks.h \
   $(srcdir)/include/gc.h $(srcdir)/include/gc/gc_pthread_redirects.h \
@@ -200,10 +216,10 @@ specific.o pthread_support.o thread_local_alloc.o win32_threads.o: \
 
 dbg_mlc.o gcj_mlc.o: $(srcdir)/include/private/dbg_mlc.h
 
-tests/test.o: $(srcdir)/tests/test.c
+tests/gctest.o: $(srcdir)/tests/gctest.c
 	mkdir tests || cat /dev/null
-	$(CC) $(CFLAGS) -c $(srcdir)/tests/test.c
-	mv test.o tests/test.o
+	$(CC) $(CFLAGS) -c $(srcdir)/tests/gctest.c
+	mv gctest.o $@
 
 base_lib libgc.a: $(OBJS) dyn_load.o $(UTILS)
 	rm -f dont_ar_1
@@ -229,27 +245,27 @@ cords libcord.a: $(CORD_OBJS) $(UTILS)
 
 gc_badalc.o: $(srcdir)/gc_badalc.cc $(srcdir)/include/gc_cpp.h \
   $(srcdir)/include/gc.h
-	$(CXX) -c $(CXXFLAGS) $(srcdir)/gc_badalc.cc
+	$(CXX) $(CXXFLAGS) -c $(srcdir)/gc_badalc.cc
 
 gc_cpp.o: $(srcdir)/gc_cpp.cc $(srcdir)/include/gc_cpp.h $(srcdir)/include/gc.h
-	$(CXX) -c $(CXXFLAGS) $(srcdir)/gc_cpp.cc
+	$(CXX) $(CXXFLAGS) -c $(srcdir)/gc_cpp.cc
 
-test_cpp$(EXEEXT): $(srcdir)/tests/test_cpp.cc $(srcdir)/include/gc_cpp.h \
-  $(srcdir)/include/gc.h c++ base_lib $(UTILS)
-	rm -f test_cpp$(EXEEXT)
-	./if_mach HP_PA HPUX $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/tests/test_cpp.cc libgc.a libgccpp.a -ldld `./threadlibs`
-	./if_not_there test_cpp$(EXEEXT) || $(CXX) $(CXXFLAGS) -DGC_NOT_DLL -o test_cpp$(EXEEXT) $(srcdir)/tests/test_cpp.cc libgc.a libgccpp.a `./threadlibs`
+cpptest$(EXEEXT): $(srcdir)/tests/cpp.cc $(srcdir)/include/gc_cpp.h \
+  $(srcdir)/include/gc.h c++ base_lib $(NODIST_OBJS) $(UTILS)
+	rm -f $@
+	./if_mach HP_PA HPUX $(CXX) $(CXXFLAGS) -o $@ $(srcdir)/tests/cpp.cc $(NODIST_OBJS) libgc.a libgccpp.a -ldld `./threadlibs`
+	./if_not_there $@ || $(CXX) $(CXXFLAGS) -DGC_NOT_DLL -o $@ $(srcdir)/tests/cpp.cc $(NODIST_OBJS) libgc.a libgccpp.a `./threadlibs`
 
-check-cpp-deps: test_cpp$(EXEEXT)
+check-cpp-deps: cpptest$(EXEEXT)
 
 check-cpp: check-cpp-deps
-	./test_cpp
+	./cpptest
 
-c++-t: c++ test_cpp$(EXEEXT)
-	./test_cpp 1
+c++-t: c++ cpptest$(EXEEXT)
+	./cpptest 1
 
 c++-nt: c++
-	@echo "Use ./test_cpp 1 to test the leak library"
+	@echo "Use ./cpptest 1 to test the leak library"
 
 c++ libgccpp.a libgctba.a: gc_badalc.o gc_cpp.o $(UTILS)
 	rm -f dont_ar_4
@@ -266,147 +282,135 @@ c++ libgccpp.a libgctba.a: gc_badalc.o gc_cpp.o $(UTILS)
 	echo > c++
 
 dyn_load_sunos53.o: dyn_load.c
-	$(CC) $(CFLAGS) -DSUNOS53_SHARED_LIB -c $(srcdir)/dyn_load.c -o $@
+	$(CC) $(CFLAGS) -DSUNOS53_SHARED_LIB -c -o $@ $(srcdir)/dyn_load.c
 
 # SunOS5 shared library version of the collector
-sunos5gc.so: $(OBJS) dyn_load_sunos53.o
-	$(CC) -G -o sunos5gc.so $(OBJS) dyn_load_sunos53.o -ldl
-	ln sunos5gc.so libgc.so
+sunos5gc.so: $(OBJS) $(NODIST_OBJS) dyn_load_sunos53.o
+	$(CC) -G -o $@ $(OBJS) $(NODIST_OBJS) dyn_load_sunos53.o -ldl
+	ln $@ libgc.so
 
 # Alpha/OSF shared library version of the collector
-libalphagc.so: $(OBJS)
-	$(LD) -shared -o libalphagc.so $(OBJS) dyn_load.o -lc
-	ln libalphagc.so libgc.so
+libalphagc.so: $(OBJS) $(NODIST_OBJS) dyn_load.o
+	$(LD) -shared -o $@ $(OBJS) $(NODIST_OBJS) dyn_load.o -lc
+	ln $@ libgc.so
 
 # IRIX shared library version of the collector
-libirixgc.so: $(OBJS) dyn_load.o
-	$(LD) -shared $(ABI_FLAG) -o libirixgc.so $(OBJS) dyn_load.o -lc
-	ln libirixgc.so libgc.so
+libirixgc.so: $(OBJS) $(NODIST_OBJS) dyn_load.o
+	$(LD) -shared $(ABI_FLAG) -o $@ $(OBJS) $(NODIST_OBJS) dyn_load.o -lc
+	ln $@ libgc.so
 
 # Linux shared library version of the collector
-liblinuxgc.so: $(OBJS) dyn_load.o
-	gcc -shared -o liblinuxgc.so $(OBJS) dyn_load.o
-	ln liblinuxgc.so libgc.so
+liblinuxgc.so: $(OBJS) $(NODIST_OBJS) dyn_load.o
+	gcc -shared -o $@ $(OBJS) $(NODIST_OBJS) dyn_load.o
+	ln $@ libgc.so
 
 # Build gctest with dynamic library
 dyn_test:
-	$(CC) $(CFLAGS) -o gctest$(EXEEXT) tests/test.c libgc.so `./threadlibs`
+	$(CC) $(CFLAGS) -o gctest$(EXEEXT) tests/gctest.c libgc.so `./threadlibs`
 	./gctest
 
-# Alternative Linux rule.  This is preferable, but is likely to break the
-# Makefile for some non-linux platforms.
-# LIBOBJS= $(patsubst %.o, %.lo, $(OBJS))
-#
-#.SUFFIXES: .lo $(SUFFIXES)
-#
-#.c.lo:
-# $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -c $< -o $@
-#
-# liblinuxgc.so: $(LIBOBJS) dyn_load.lo
-# 	gcc -shared -Wl,-soname=libgc.so.0 -o libgc.so.0 $(LIBOBJS) dyn_load.lo
-#	touch liblinuxgc.so
-
 mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/sparc_mach_dep.S \
   $(srcdir)/ia64_save_regs_in_stack.s \
   $(srcdir)/sparc_netbsd_mach_dep.s $(UTILS)
-	rm -f mach_dep.o
+	rm -f $@
+	./if_mach SPARC LINUX $(CC) -c -o mach_dep2.o $(srcdir)/sparc_mach_dep.S
 	./if_mach SPARC SOLARIS $(CC) -c -o mach_dep2.o $(srcdir)/sparc_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
+	./if_mach SPARC "" $(CC) $(SPECIALCFLAGS) -c -o mach_dep1.o $(srcdir)/mach_dep.c
+	./if_mach SPARC "" $(LD) -r -o $@ mach_dep1.o mach_dep2.o
 	./if_mach IA64 "" $(AS) -o ia64_save_regs_in_stack.o $(srcdir)/ia64_save_regs_in_stack.s
-	./if_mach IA64 "" $(CC) -c -o mach_dep1.o $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
-	./if_mach IA64 "" $(LD) -r -o mach_dep.o mach_dep1.o ia64_save_regs_in_stack.o
-	-./if_not_there mach_dep.o || $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
-	-./if_not_there mach_dep.o || `cygpath -w /bin/sh` $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
-	-./if_not_there mach_dep.o || /bin/sh $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
+	./if_mach IA64 "" $(CC) $(SPECIALCFLAGS) -c -o mach_dep1.o $(srcdir)/mach_dep.c
+	./if_mach IA64 "" $(LD) -r -o $@ mach_dep1.o ia64_save_regs_in_stack.o
+	-./if_not_there $@ || $(CC) $(SPECIALCFLAGS) -c $(srcdir)/mach_dep.c
+	-./if_not_there $@ || `cygpath -w /bin/sh` $(CC) $(SPECIALCFLAGS) -c $(srcdir)/mach_dep.c
+	-./if_not_there $@ || /bin/sh $(CC) $(SPECIALCFLAGS) -c $(srcdir)/mach_dep.c
 
 mark_rts.o: $(srcdir)/mark_rts.c $(UTILS)
-	rm -f mark_rts.o
-	-./if_mach ALPHA OSF1 $(CC) -c $(CFLAGS) -Wo,-notail $(srcdir)/mark_rts.c
-	-./if_not_there mark_rts.o || $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c
-	-./if_not_there mark_rts.o || `cygpath -w /bin/sh` $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c
-	-./if_not_there mark_rts.o || /bin/sh $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c
+	rm -f $@
+	-./if_mach ALPHA OSF1 $(CC) $(CFLAGS) -Wo,-notail -c $(srcdir)/mark_rts.c
+	-./if_not_there $@ || $(CC) $(CFLAGS) -c $(srcdir)/mark_rts.c
+	-./if_not_there $@ || `cygpath -w /bin/sh` $(CC) $(CFLAGS) -c $(srcdir)/mark_rts.c
+	-./if_not_there $@ || /bin/sh $(CC) $(CFLAGS) -c $(srcdir)/mark_rts.c
 #   Work-around for DEC optimizer tail recursion elimination bug.
 #   The ALPHA-specific line should be removed if gcc is used.
 
 alloc.o: include/gc/gc_version.h
 
 cord/cordbscs.o: $(srcdir)/cord/cordbscs.c $(CORD_INCLUDE_FILES)
-	$(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordbscs.c
+	$(CC) $(CFLAGS) -I$(srcdir) -c $(srcdir)/cord/cordbscs.c
 	mkdir cord || cat /dev/null
-	mv cordbscs.o cord/cordbscs.o
+	mv cordbscs.o $@
 #  not all compilers understand -o filename
 
 cord/cordxtra.o: $(srcdir)/cord/cordxtra.c $(CORD_INCLUDE_FILES)
-	$(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordxtra.c
+	$(CC) $(CFLAGS) -I$(srcdir) -c $(srcdir)/cord/cordxtra.c
 	mkdir cord || cat /dev/null
-	mv cordxtra.o cord/cordxtra.o
+	mv cordxtra.o $@
 
 cord/cordprnt.o: $(srcdir)/cord/cordprnt.c $(CORD_INCLUDE_FILES)
-	$(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordprnt.c
+	$(CC) $(CFLAGS) -I$(srcdir) -c $(srcdir)/cord/cordprnt.c
 	mkdir cord || cat /dev/null
-	mv cordprnt.o cord/cordprnt.o
+	mv cordprnt.o $@
 
-cordtest$(EXEEXT): $(srcdir)/cord/tests/cordtest.c cords base_lib $(UTILS)
-	rm -f cordtest$(EXEEXT)
-	./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cordtest $(srcdir)/cord/tests/cordtest.c libgc.a libcord.a -lucb
-	./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o cordtest $(srcdir)/cord/tests/cordtest.c libgc.a libcord.a -ldld `./threadlibs`
-	./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o cordtest $(srcdir)/cord/tests/cordtest.c libgc.a libcord.a `./threadlibs`
-	./if_not_there cordtest$(EXEEXT) || $(CC) $(CFLAGS) -o cordtest$(EXEEXT) $(srcdir)/cord/tests/cordtest.c libgc.a libcord.a `./threadlibs`
+cordtest$(EXEEXT): $(srcdir)/cord/tests/cordtest.c cords base_lib $(NODIST_OBJS) $(UTILS)
+	rm -f $@
+	./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o $@ $(srcdir)/cord/tests/cordtest.c $(NODIST_OBJS) libgc.a libcord.a -lucb
+	./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o $@ $(srcdir)/cord/tests/cordtest.c $(NODIST_OBJS) libgc.a libcord.a -ldld `./threadlibs`
+	./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o $@ $(srcdir)/cord/tests/cordtest.c $(NODIST_OBJS) libgc.a libcord.a `./threadlibs`
+	./if_not_there $@ || $(CC) $(CFLAGS) -o $@ $(srcdir)/cord/tests/cordtest.c $(NODIST_OBJS) libgc.a libcord.a `./threadlibs`
 
 cord/de: de$(EXEEXT)
 
 de$(EXEEXT): $(srcdir)/cord/tests/de.c $(srcdir)/cord/tests/de_win.c \
-  $(srcdir)/cord/tests/de_win.h cords base_lib $(UTILS)
-	rm -f de$(EXEEXT)
-	./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o de $(srcdir)/cord/tests/de.c libgc.a libcord.a -lcurses -ltermlib -lucb `./threadlibs`
-	./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o de $(srcdir)/cord/tests/de.c libgc.a libcord.a -lcurses -ltermlib -ldld `./threadlibs`
-	./if_mach POWERPC AIX $(CC) $(CFLAGS) -o de $(srcdir)/cord/tests/de.c libgc.a libcord.a -lcurses
-	./if_mach POWERPC DARWIN $(CC) $(CFLAGS) -o de $(srcdir)/cord/tests/de.c libgc.a libcord.a
-	./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o de $(srcdir)/cord/tests/de.c libgc.a libcord.a -lcurses
-	./if_not_there de$(EXEEXT) || $(CC) $(CFLAGS) -o de$(EXEEXT) $(srcdir)/cord/tests/de.c $(srcdir)/cord/tests/de_win.c libgc.a libcord.a $(CURSES) `./threadlibs`
+  $(srcdir)/cord/tests/de_win.h cords base_lib $(NODIST_OBJS) $(UTILS)
+	rm -f $@
+	./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o $@ $(srcdir)/cord/tests/de.c $(NODIST_OBJS) libgc.a libcord.a -lcurses -ltermlib -lucb `./threadlibs`
+	./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o $@ $(srcdir)/cord/tests/de.c $(NODIST_OBJS) libgc.a libcord.a -lcurses -ltermlib -ldld `./threadlibs`
+	./if_mach POWERPC AIX $(CC) $(CFLAGS) -o $@ $(srcdir)/cord/tests/de.c $(NODIST_OBJS) libgc.a libcord.a -lcurses
+	./if_mach POWERPC DARWIN $(CC) $(CFLAGS) -o $@ $(srcdir)/cord/tests/de.c $(NODIST_OBJS) libgc.a libcord.a
+	./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o $@ $(srcdir)/cord/tests/de.c $(NODIST_OBJS) libgc.a libcord.a -lcurses
+	./if_not_there $@ || $(CC) $(CFLAGS) -o $@ $(srcdir)/cord/tests/de.c $(srcdir)/cord/tests/de_win.c $(NODIST_OBJS) libgc.a libcord.a $(CURSES) `./threadlibs`
 
 if_mach$(EXEEXT): $(srcdir)/tools/if_mach.c \
   $(srcdir)/include/private/gcconfig.h
-	$(HOSTCC) $(HOSTCFLAGS) -o if_mach$(EXEEXT) $(srcdir)/tools/if_mach.c
+	$(HOSTCC) $(HOSTCFLAGS) -o $@ $(srcdir)/tools/if_mach.c
 
 threadlibs$(EXEEXT): $(srcdir)/tools/threadlibs.c \
   $(srcdir)/include/private/gcconfig.h
-	$(HOSTCC) $(HOSTCFLAGS) -o threadlibs$(EXEEXT) $(srcdir)/tools/threadlibs.c
+	$(HOSTCC) $(HOSTCFLAGS) -o $@ $(srcdir)/tools/threadlibs.c
 
 if_not_there$(EXEEXT): $(srcdir)/tools/if_not_there.c
-	$(HOSTCC) $(HOSTCFLAGS) -o if_not_there$(EXEEXT) $(srcdir)/tools/if_not_there.c
+	$(HOSTCC) $(HOSTCFLAGS) -o $@ $(srcdir)/tools/if_not_there.c
 
 clean:
-	rm -f *.a *.i *.o *.exe tests/*.o gctest gctest_dyn_link test_cpp \
+	rm -f *.a *.i *.o *.exe tests/*.o cpptest gctest gctest_dyn_link \
 	      setjmp_test mon.out gmon.out a.out core if_not_there if_mach \
 	      base_lib c++ $(CORD_OBJS) cordtest de cords dont_ar_* threadlibs
 	-rm -f *~
 
-gctest$(EXEEXT): tests/test.o base_lib $(UTILS)
-	rm -f gctest$(EXEEXT)
-	./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o gctest tests/test.o libgc.a -lucb
-	./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o gctest tests/test.o libgc.a -ldld `./threadlibs`
-	./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o gctest  tests/test.o libgc.a `./threadlibs`
-	./if_not_there gctest$(EXEEXT) || $(CC) $(CFLAGS) -o gctest$(EXEEXT) tests/test.o libgc.a `./threadlibs`
+gctest$(EXEEXT): tests/gctest.o base_lib $(NODIST_OBJS) $(UTILS)
+	rm -f $@
+	./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o $@ tests/gctest.o $(NODIST_OBJS) libgc.a -lucb
+	./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o $@ tests/gctest.o $(NODIST_OBJS) libgc.a -ldld `./threadlibs`
+	./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o $@ tests/gctest.o $(NODIST_OBJS) libgc.a `./threadlibs`
+	./if_not_there $@ || $(CC) $(CFLAGS) -o $@ tests/gctest.o $(NODIST_OBJS) libgc.a `./threadlibs`
 
 # If an optimized setjmp_test generates a segmentation fault,
 # odds are your compiler is broken.  gctest may still work.
 # Try compiling setjmp_t.c unoptimized.
 setjmp_test$(EXEEXT): $(srcdir)/tools/setjmp_t.c $(srcdir)/include/gc.h \
   $(UTILS)
-	$(CC) $(CFLAGS) -o setjmp_test$(EXEEXT) $(srcdir)/tools/setjmp_t.c
+	$(CC) $(CFLAGS) -o $@ $(srcdir)/tools/setjmp_t.c
 
 check-deps: cordtest$(EXEEXT) gctest$(EXEEXT) setjmp_test$(EXEEXT) \
-  test_cpp$(EXEEXT)
+  cpptest$(EXEEXT)
 
 check: check-deps
 	./setjmp_test
 	./gctest
 	./cordtest
-	./test_cpp
+	./cpptest
 
 # A synonym to "check" (for compatibility with older GC versions).
 test: check
@@ -415,22 +419,22 @@ test: check
 # Currently works only under SunOS5.  Requires GC_INIT call from statically
 # loaded client code.
 ABSDIR= `pwd`
-gctest_dyn_link: tests/test.o libgc.so
-	$(CC) -L$(ABSDIR) -R$(ABSDIR) -o gctest_dyn_link tests/test.o -lgc -ldl -lthread
+gctest_dyn_link: tests/gctest.o libgc.so
+	$(CC) -L$(ABSDIR) -R$(ABSDIR) -o $@ tests/gctest.o -lgc -ldl -lthread
 
-gctest_irix_dyn_link: tests/test.o libirixgc.so
-	$(CC) -L$(ABSDIR) -o gctest_irix_dyn_link tests/test.o -lirixgc
+gctest_irix_dyn_link: tests/gctest.o libirixgc.so
+	$(CC) -L$(ABSDIR) -o $@ tests/gctest.o -lirixgc
 
-SYM_PREFIX-libgc=GC
+SYM_PREFIX-libgc= GC
 
 reserved_namespace: $(SRCS)
-	for file in $(SRCS) tests/test.c tests/test_cpp.cc; do \
+	for file in $(SRCS) tests/gctest.c tests/cpp.cc; do \
 		sed s/GC_/_GC_/g < $$file > tmp; \
 		cp tmp $$file; \
 		done
 
 user_namespace: $(SRCS)
-	for file in $(SRCS) tests/test.c tests/test_cpp.cc; do \
+	for file in $(SRCS) tests/gctest.c tests/cpp.cc; do \
 		sed s/_GC_/GC_/g < $$file > tmp; \
 		cp tmp $$file; \
 		done

+ 17 - 16
blitz.mod/bdwgc/NT_MAKEFILE

@@ -1,4 +1,4 @@
-# Makefile for Windows NT.  Assumes Microsoft compiler.
+# Makefile for Windows (Win32/64).  Assumes Microsoft compiler.
 # Should be invoked as "nmake -f NT_MAKEFILE [<args>]"; the optional arguments
 # are: "cpu=AMD64" - to target x64, "cpu=i386" - to target x86,
 # "enable_static=1" - to build it as a static library, "nodebug=1" - to produce
@@ -78,7 +78,7 @@ CFLAGS_EXTRA=
 
 CFLAGS_SPECIFIC=$(CFLAGS_DEBUG) $(CFLAGS_GCDLL) $(CFLAGS_MT)
 
-CFLAGS_DEFAULT=-DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION -DUSE_MUNMAP
+CFLAGS_DEFAULT=-DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION -DGC_REQUIRE_WCSDUP -DUSE_MUNMAP
 
 CXXFLAGS_SPECIFIC=/EHsc
 
@@ -87,14 +87,15 @@ CXXFLAGS_SPECIFIC=/EHsc
 .SUFFIXES:
 .SUFFIXES: .obj .cpp .c
 
-# Atomic_ops installation directory.  For win32, the source directory
+# Atomic_ops installation directory.  For Win32, the source directory
 # should do, since we only need the headers.
 # We assume this was manually unpacked.
 AO_SRC_DIR=libatomic_ops/src
 AO_INCLUDE_DIR=$(AO_SRC_DIR)
 
 !IFDEF ENABLE_STATIC
-OBJS= misc.obj win32_threads.obj alloc.obj reclaim.obj allchblk.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj fnlz_mlc.obj malloc.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gcj_mlc.obj mallocx.obj extra\msvc_dbg.obj thread_local_alloc.obj
+# pthread_start.obj is needed just in case client defines GC_WIN32_PTHREADS.
+OBJS= misc.obj win32_threads.obj alloc.obj reclaim.obj allchblk.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj fnlz_mlc.obj malloc.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gcj_mlc.obj mallocx.obj extra\msvc_dbg.obj pthread_start.obj pthread_support.obj thread_local_alloc.obj
 !ELSE
 OBJS= extra\gc.obj extra\msvc_dbg.obj
 !ENDIF
@@ -103,22 +104,22 @@ COBJS= cord\cordbscs.obj cord\cordxtra.obj cord\cordprnt.obj
 
 all: gc.lib cord.lib gccpp.lib gctba.lib
 
-check-deps: gctest.exe test_cpp.exe cordtest.exe de.exe
+check-deps: gctest.exe cpptest.exe cordtest.exe de.exe
 
 check: check-deps
 	gctest.exe
 	cordtest.exe
-	test_cpp.exe
+	cpptest.exe
 
 .c.obj:
-	$(cc) $(cdebug) $(cflags) $(CFLAGS_SPECIFIC) $(CORDFLAG) -Iinclude -I$(AO_INCLUDE_DIR) $(CFLAGS_DEFAULT) -D_CRT_SECURE_NO_DEPRECATE $(CFLAGS_EXTRA) $*.c /Fo$*.obj /wd4100 /wd4127 /wd4701
+	$(cc) $(cdebug) $(cflags) $(CFLAGS_SPECIFIC) $(CORDFLAG) -Iinclude -I$(AO_INCLUDE_DIR) $(CFLAGS_DEFAULT) -D_CRT_SECURE_NO_DEPRECATE $(CFLAGS_EXTRA) $*.c /Fo$*.obj /wd4127 /wd4701
 # Disable crt security warnings, since unfortunately they warn about all sorts
 # of safe uses of strncpy.  It would be nice to leave the rest enabled.
 
 .cpp.obj:
 	$(cc) $(cdebug) $(cflags) $(CFLAGS_SPECIFIC) -Iinclude $(CFLAGS_DEFAULT) $(CXXFLAGS_SPECIFIC) -D_CRT_SECURE_NO_DEPRECATE $(CFLAGS_EXTRA) $*.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\gc_mark.h include\gc\gc_disclaim.h
+$(OBJS) tests\gctest.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\gc_mark.h include\gc\gc_disclaim.h
 
 !IFDEF ENABLE_STATIC
 
@@ -151,8 +152,8 @@ gctba.lib: gc_badalc.obj gc.lib
 
 !ENDIF
 
-gctest.exe: gc.lib tests\test.obj
-	$(link) /MACHINE:$(CPU) /INCREMENTAL:NO $(ldebug) $(lflags) user32.lib -out:$*.exe tests\test.obj gc.lib
+gctest.exe: gc.lib tests\gctest.obj
+	$(link) /MACHINE:$(CPU) /INCREMENTAL:NO $(ldebug) $(lflags) user32.lib -out:$*.exe tests\gctest.obj gc.lib
 #	mapsympe -n -o gctest.sym gctest.exe
 # This produces a GUI app that opens no window and writes to gctest.gc.log.
 
@@ -164,7 +165,7 @@ cord\tests\de.obj cord\tests\de_win.obj: include\gc\cord.h include\gc\cord_pos.h
 cord\tests\de_win.res: cord\tests\de_win.rc cord\tests\de_win.h cord\tests\de_cmds.h
 	$(rc) $(rcvars) -r -fo cord\tests\de_win.res cord\tests\de_win.rc
 
-# Cord/de is a real win32 GUI app.
+# Cord/de is a real Windows GUI app.
 de.exe: cord\tests\de.obj cord\tests\de_win.obj cord\tests\de_win.rbj gc.lib cord.lib
 	$(link) /MACHINE:$(CPU) /INCREMENTAL:NO $(ldebug) $(lflags) -out:de.exe cord\tests\de.obj cord\tests\de_win.obj cord\tests\de_win.rbj gc.lib cord.lib gdi32.lib user32.lib
 
@@ -175,14 +176,14 @@ gc_badalc.obj: gc_badalc.cc include\gc_cpp.h include\gc.h
 
 gc_cpp.obj: gc_cpp.cc include\gc_cpp.h include\gc.h
 
-test_cpp.cpp: tests\test_cpp.cc
-	copy tests\test_cpp.cc test_cpp.cpp
+test_cpp.cpp: tests\cpp.cc
+	copy tests\cpp.cc test_cpp.cpp
 
 # This generates the C++ test executable.  The executable expects
 # a single numeric argument, which is the number of iterations.
-# The output appears in test_cpp.gc.log file.
-test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib gccpp.lib
-	$(link) /MACHINE:$(CPU) /INCREMENTAL:NO $(ldebug) $(lflags) user32.lib -out:test_cpp.exe test_cpp.obj gc.lib gccpp.lib
+# The output appears in cpptest.gc.log file.
+cpptest.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib gccpp.lib
+	$(link) /MACHINE:$(CPU) /INCREMENTAL:NO $(ldebug) $(lflags) user32.lib -out:cpptest.exe test_cpp.obj gc.lib gccpp.lib
 
 $(AO_SRC_DIR):
 	tar xvfz $(AO_SRC_DIR).tar.gz

+ 0 - 64
blitz.mod/bdwgc/OS2_MAKEFILE

@@ -1,64 +0,0 @@
-# Makefile for OS/2.  Assumes IBM's compiler, static linking, and a single thread.
-# Adding dynamic linking support seems easy, but takes a little bit of work.
-# Adding thread support may be nontrivial, since we haven't yet figured out how to
-# look at another thread's registers.
-
-# Significantly revised by Mark Boulter (Jan 1994).
-
-OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj fnlz_mlc.obj malloc.obj typd_mlc.obj ptr_chck.obj mallocx.obj gcj_mlc.obj
-
-CORDOBJS= cord\cordbscs.obj cord\cordxtra.obj cord\cordprnt.obj
-
-# Extra user-defined flags to pass to the compiler.
-CFLAGS_EXTRA=
-
-CC= icc
-CFLAGS= /O /Q /DALL_INTERIOR_POINTERS /DENABLE_DISCLAIM /DGC_ATOMIC_UNCOLLECTABLE /DGC_GCJ_SUPPORT /DJAVA_FINALIZATION /DNO_EXECUTE_PERMISSION /DSMALL_CONFIG $(CFLAGS_EXTRA)
-# Use /Ti instead of /O for debugging
-# setjmp_test may yield overly optimistic results when compiled
-# without optimization.
-
-all: gc.lib cord.lib
-
-check-deps: gctest.exe cordtest.exe
-
-check: check-deps
-        gctest.exe
-        cordtest.exe
-
-$(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 it is there or erase will fail!)
-gc.lib: $(OBJS)
-        echo . > gc.lib
-        erase gc.lib
-        LIB gc.lib $(OBJS), gc.lst
-
-mach_dep.obj: mach_dep.c
-        $(CC) $(CFLAGS) /C mach_dep.c
-
-gctest.exe: test.obj gc.lib
-        $(CC) $(CFLAGS) /B"/STACK:524288" /Fegctest test.obj gc.lib
-
-cord\cordbscs.obj: cord\cordbscs.c include\gc\cord.h include\gc\cord_pos.h
-        $(CC) $(CFLAGS) /C /Focord\cordbscs cord\cordbscs.c
-
-cord\cordxtra.obj: cord\cordxtra.c include\gc\cord.h include\gc\cord_pos.h include\gc\ec.h
-        $(CC) $(CFLAGS) /C /Focord\cordxtra cord\cordxtra.c
-
-cord\cordprnt.obj: cord\cordprnt.c include\gc\cord.h include\gc\cord_pos.h include\gc\ec.h
-        $(CC) $(CFLAGS) /C /Focord\cordprnt cord\cordprnt.c
-
-cord.lib: $(CORDOBJS)
-        echo . > cord.lib
-        erase cord.lib
-        LIB cord.lib $(CORDOBJS), cord.lst
-
-cordtest.exe: cord\tests\cordtest.c include\gc\cord.h include\gc\cord_pos.h include\gc\ec.h gc.lib cord.lib
-        $(CC) $(CFLAGS) /B"/STACK:65536" /Fecordtest cord\tests\cordtest.c gc.lib cord.lib
-
-clean:
-        erase gc.lib cord.lib
-        erase gctest.exe cordtest.exe
-        erase $(OBJS) $(CORDOBJS)

+ 0 - 47
blitz.mod/bdwgc/PCR-Makefile

@@ -1,47 +0,0 @@
-#
-# Default target
-#
-
-default: gc.o
-
-include ../config/common.mk
-
-#
-# compilation flags, etc.
-#
-
-CPPFLAGS = $(INCLUDE) $(CONFIG_CPPFLAGS) \
-	-DPCR_NO_RENAME -DPCR_NO_HOSTDEP_ERR
-#CFLAGS	= -DPCR $(CONFIG_CFLAGS)
-CFLAGS	= -DPCR -DENABLE_DISCLAIM $(CONFIG_CFLAGS)
-SPECIALCFLAGS = 	# For code involving asm's
-
-ASPPFLAGS  = $(INCLUDE) $(CONFIG_ASPPFLAGS) \
-	-DPCR_NO_RENAME -DPCR_NO_HOSTDEP_ERR -DASM
-
-ASFLAGS	= $(CONFIG_ASFLAGS)
-
-LDRFLAGS = $(CONFIG_LDRFLAGS)
-
-LDFLAGS = $(CONFIG_LDFLAGS)
-
-#
-# BEGIN PACKAGE-SPECIFIC PART
-#
-
-# Fix to point to local pcr installation directory.
-PCRDIR= ..
-
-COBJ= alloc.o reclaim.o allchblk.o misc.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o extra/pcr_interface.o extra/real_malloc.o dyn_load.o dbg_mlc.o fnlz_mlc.o malloc.o checksums.o typd_mlc.o ptr_chck.o mallocx.o
-
-CSRC= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c blacklst.c finalize.c new_hblk.c extra/pcr_interface.c extra/real_malloc.c dyn_load.c dbg_mlc.c fnlz_mlc.c malloc.c checksums.c typd_mlc.c ptr_chck.c mallocx.c
-
-SHELL= /bin/sh
-
-default: gc.o
-
-gc.o: $(COBJ) mach_dep.o
-	$(LDR) $(CONFIG_LDRFLAGS) -o gc.o $(COBJ) mach_dep.o
-
-mach_dep.o: mach_dep.c
-	$(CC) -c $(SPECIALCFLAGS) mach_dep.c

+ 21 - 21
blitz.mod/bdwgc/README.md

@@ -1,13 +1,14 @@
 # Boehm-Demers-Weiser Garbage Collector
 
-[![Travis-CI build status](https://travis-ci.com/ivmai/bdwgc.svg?branch=master)](https://travis-ci.com/ivmai/bdwgc)
+[![Travis-CI build status](https://app.travis-ci.com/ivmai/bdwgc.svg?branch=master)](https://app.travis-ci.com/github/ivmai/bdwgc)
 [![AppVeyor CI build status](https://ci.appveyor.com/api/projects/status/github/ivmai/bdwgc?branch=master&svg=true)](https://ci.appveyor.com/project/ivmai/bdwgc)
 [![Codecov.io](https://codecov.io/github/ivmai/bdwgc/coverage.svg?branch=master)](https://codecov.io/github/ivmai/bdwgc?branch=master)
 [![Coveralls test coverage status](https://coveralls.io/repos/github/ivmai/bdwgc/badge.png?branch=master)](https://coveralls.io/github/ivmai/bdwgc)
 [![Coverity Scan build status](https://scan.coverity.com/projects/10813/badge.svg)](https://scan.coverity.com/projects/ivmai-bdwgc)
 [![LGTM Code Quality: Cpp](https://img.shields.io/lgtm/grade/cpp/g/ivmai/bdwgc.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/ivmai/bdwgc/context:cpp)
 [![LGTM Total Alerts](https://img.shields.io/lgtm/alerts/g/ivmai/bdwgc.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/ivmai/bdwgc/alerts)
-
+[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fivmai%2Fbdwgc.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fivmai%2Fbdwgc?ref=badge_shield)
+[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6332/badge)](https://bestpractices.coreinfrastructure.org/projects/6332)
 [![Hits-of-Code](https://hitsofcode.com/github/ivmai/bdwgc?branch=master)](https://hitsofcode.com/github/ivmai/bdwgc/view)
 [![Lines of code](https://img.shields.io/tokei/lines/github/ivmai/bdwgc)](https://shields.io/category/size)
 [![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/ivmai/bdwgc)](https://shields.io/category/size)
@@ -143,12 +144,12 @@ areas that are associated with dynamic libraries.  This is easy to remedy
 if you know how to find those data areas on your operating system (see
 `GC_add_roots`).  Code for doing this under SunOS, IRIX 5.X and 6.X, HP/UX,
 Alpha OSF/1, Linux, and Win32 is included and used by default.
-(See [README.win32](doc/README.win32) and [README.win64](doc/README.win64)
-for Windows details.)  On other systems, pointers from dynamic library data
-areas may not be considered by the collector.  If you're writing a program
-that depends on the collector scanning dynamic library data areas, it may
-be a good idea to include at least one call to `GC_is_visible` to ensure
-that those areas are visible to the collector.
+(See [README.win32](doc/platforms/README.win32) and
+[README.win64](doc/platforms/README.win64) for Windows details.)  On other
+systems, pointers from dynamic library data areas may not be considered by the
+collector.  If you're writing a program that depends on the collector scanning
+dynamic library data areas, it may be a good idea to include at least one call
+to `GC_is_visible` to ensure that those areas are visible to the collector.
 
 Note that the garbage collector does not need to be informed of shared
 read-only data.  However, if the shared library mechanism can introduce
@@ -182,7 +183,7 @@ will result in a few lines of descriptive output for each collection.
 (The given statistics exhibit a few peculiarities.
 Things don't appear to add up for a variety of reasons, most notably
 fragmentation losses.  These are probably much more significant for the
-contrived program `tests/test.c` than for your application.)
+contrived program `gctest` than for your application.)
 
 On most Unix-like platforms, the collector can be built either using a
 GNU autoconf-based build infrastructure (type `./configure; make` in the
@@ -193,9 +194,9 @@ Please note that the collector source repository does not contain configure
 and similar auto-generated files, thus the full procedure of autoconf-based
 build of `master` branch of the collector could look like:
 
-    git clone git://github.com/ivmai/bdwgc.git
+    git clone https://github.com/ivmai/bdwgc
     cd bdwgc
-    git clone git://github.com/ivmai/libatomic_ops.git
+    git clone https://github.com/ivmai/libatomic_ops
     ./autogen.sh
     ./configure
     make -j
@@ -209,7 +210,7 @@ this:
 
     mkdir out
     cd out
-    cmake ..
+    cmake -Dbuild_tests=ON ..
     cmake --build .
     ctest
 
@@ -218,12 +219,12 @@ See [README.cmake](doc/README.cmake) for details.
 Finally, on most targets, the collector could be built and tested directly
 with a single compiler invocation, like this:
 
-    gcc -I include -o gctest tests/test.c extra/gc.c && ./gctest
+    gcc -I include -o gctest tests/gctest.c extra/gc.c && ./gctest
 
 On Windows, CMake could be used to build the library as described above or
 by typing `nmake -f NT_MAKEFILE`, this assumes you have Microsoft command-line
-tools installed and suitably configured.  See [README.win32](doc/README.win32)
-for details.
+tools installed and suitably configured.  See
+[README.win32](doc/platforms/README.win32) for details.
 
 The library is built with threads support on (i.e. for thread-safe operation)
 by default, unless `--disable-threads` is passed to `./configure` (or
@@ -259,15 +260,14 @@ include subdirectory.  (Normally this is just gc.h.  `make cords` adds
 
 The collector currently is designed to run essentially unmodified on
 machines that use a flat 32-bit or 64-bit address space.
-That includes the vast majority of Workstations and X86 (X >= 3) PCs.
+That includes the vast majority of Workstations and x86 (i386 or later) PCs.
 
-In a few cases (Amiga, OS/2, PCR, Symbian, Win32) a separate makefile
-or equivalent is supplied.  Many of these have separate a host-specific
-doc/README.* file.
+In a few cases (e.g., OS/2, Win32) a separate makefile is supplied; these have
+a separate host-specific doc/platforms/README.* file.
 
 Dynamic libraries are completely supported only under SunOS/Solaris,
 (and even that support is not functional on the last Sun 3 release),
-Linux, FreeBSD, NetBSD, IRIX, HP/UX, Win32 (not Win32s) and OSF/1
+Linux, FreeBSD, NetBSD, IRIX, HP/UX, Win32 (not win32s) and OSF/1
 on DEC AXP machines plus perhaps a few others listed near the top
 of dyn_load.c.  On other machines we recommend that you do one of
 the following:
@@ -406,7 +406,7 @@ distribution.  If you intend to use this, type
 This creates libgccpp.a and libgctba.a files, or their shared library
 equivalents (libgccpp.so and libgctba.so).  You should link with either the
 first (gccpp) or the second one (gctba), but not both.  See gc_cpp.h and
-[gcinterface.md](doc/gcinterface.md) for the definition of the interface.
+[here](doc/gcinterface.md) for the definition of the interface.
 This interface tries to approximate the Ellis-Detlefs C++ garbage collection
 proposal without compiler changes.
 

+ 0 - 174
blitz.mod/bdwgc/SMakefile.amiga

@@ -1,174 +0,0 @@
-
-# Rewritten smakefile for amiga / sas/c. -Kjetil M.
-# Don't use the cord-package if you define parm=both or parm=reg.
-
-
-#----------------TOOLS--------------------------------
-CC=sc
-LINKER=slink
-LIBER=oml
-
-#----------------CPU OPTIONS--------------------------
-
-CPU=68060
-
-#----------------FPU OPTIONS--------------------------
-
-MATH=8
-MATHLIB=LIB:scm881.lib
-
-#----------------COMPILER OPTIONS---------------------
-
-IGNORE= IGNORE=85 IGNORE=154 IGNORE=161 IGNORE=100
-
-OPTIMIZE=optimize optimizetime optglobal optimizerdepth=100 optimizerpeephole optloop OPTSCHED optimizerinlocal optimizerrecurdepth=100
-# optimizerinline optimizercomplexity=100
-
-OPT= $(OPTIMIZE) CPU=$(CPU) math=$(MATH) NOSTACKCHECK VERBOSE \
-MAPHUNK NOVERSION NOICONS nodebug \
-parm=reg \
-DEFINE __USE_SYSBASE
-
-
-SOPT= $(OPT) $(IGNORE) \
-DEFINE AMIGA_SKIP_SEG \
-DEFINE GC_ATOMIC_UNCOLLECTABLE \
-DEFINE GC_AMIGA_FASTALLOC \
-DEFINE GC_AMIGA_RETRY \
-DEFINE GC_AMIGA_PRINTSTATS \
-DEFINE GC_AMIGA_GC
-
-
-#DEFINE ALL_INTERIOR_POINTERS \
-
-
-SCOPT= $(SOPT) define GC_AMIGA_MAKINGLIB
-
-CSCOPT= $(OPT) DEFINE AMIGA IGNORE=100 IGNORE=161
-
-#------------------LINKING----------------------------
-
-
-all: gc.lib cord.lib
-
-clean:
-	delete *.lib gctest setjmp_t *.o *.lnk cord/*.o cord/tests/*.o cordtest
-	smake
-
-check-deps: setjmp_t gctest cordtest
-
-check: check-deps
-	setjmp_t
-	gctest
-	cordtest
-
-gctest: gc.lib GCAmigaOS$(CPU).lib test.o
-	$(LINKER) LIB:c.o test.o TO gctest LIB gc.lib LIB:sc.lib $(MATHLIB)
-
-setjmp_t: setjmp_t.o gc.h
-	$(LINKER) LIB:c.o setjmp_t.o to setjmp_t lib LIB:sc.lib
-
-cordtest: cord/tests/cordtest.o cord.lib gc.lib
-	$(LINKER) LIB:c.o cord/tests/cordtest.o LIB $(MATHLIB) gc.lib cord.lib LIB:sc.lib TO cordtest
-
-
-#------------------LIBBING----------------------------
-
-OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dyn_load.o dbg_mlc.o malloc.o checksums.o typd_mlc.o ptr_chck.o mallocx.o fnlz_mlc.o
-
-gc.lib: $(OBJS)
-	$(LIBER) gc.lib r $(OBJS)
-
-
-COBJS = cord/cordbscs.o cord/cordprnt.o cord/cordxtra.o
-
-cord.lib: $(COBJS)
-	$(LIBER) cord.lib r $(COBJS)
-
-#------------------COMPILING--------------------------
-
-INC=  gc_private.h gc_hdrs.h gc.h gcconfig.h
-
-alloc.o : alloc.c $(INC)
-	$(CC) alloc.c $(SCOPT) ignore=7
-
-reclaim.o : reclaim.c $(INC)
-	$(CC) reclaim.c $(SCOPT)
-
-allchblk.o : allchblk.c $(INC)
-	$(CC) allchblk.c $(SCOPT)
-
-misc.o : misc.c $(INC)
-	$(CC) misc.c $(SCOPT)
-
-os_dep.o : os_dep.c $(INC) extra/AmigaOS.c
-	$(CC) os_dep.c $(SCOPT)
-
-mark_rts.o : mark_rts.c $(INC)
-	$(CC) mark_rts.c $(SCOPT)
-
-headers.o : headers.c $(INC)
-	$(CC) headers.c $(SCOPT)
-
-mark.o : mark.c $(INC)
-	$(CC) mark.c $(SCOPT)
-
-obj_map.o : obj_map.c $(INC)
-	$(CC) obj_map.c $(SCOPT)
-
-blacklst.o : blacklst.c $(INC)
-	$(CC) blacklst.c $(SCOPT)
-
-finalize.o : finalize.c $(INC)
-	$(CC) finalize.c $(SCOPT) noopt
-# Could sas/c still have problems with this one? gctest sometimes fails to finalize all.
-
-new_hblk.o : new_hblk.c $(INC)
-	$(CC) new_hblk.c $(SCOPT)
-
-dyn_load.o : dyn_load.c $(INC)
-	$(CC) dyn_load.c $(SCOPT)
-
-dbg_mlc.o : dbg_mlc.c $(INC)
-	$(CC) dbg_mlc.c $(SCOPT)
-
-fnlz_mlc.o : fnlz_mlc.c $(INC)
-	$(CC) fnlz_mlc.c $(SCOPT)
-
-malloc.o : malloc.c $(INC)
-	$(CC) malloc.c $(SCOPT)
-
-mallocx.o : mallocx.c $(INC)
-	$(CC) mallocx.c $(SCOPT)
-
-checksums.o : checksums.c $(INC)
-	$(CC) checksums.c $(SCOPT)
-
-typd_mlc.o: typd_mlc.c $(INC)
-	$(CC) typd_mlc.c $(SCOPT)
-
-mach_dep.o : mach_dep.c $(INC)
-	$(CC) mach_dep.c $(SCOPT)
-
-ptr_chck.o: ptr_chck.c $(INC)
-	$(CC) ptr_chck.c $(SCOPT)
-
-test.o : test.c $(INC)
-	$(CC) test.c $(SOPT)
-
-setjmp_t: tools/setjmp_t.c gc.h
-	$(CC) tools/setjmp_t.c $(SOPT)
-
-# cords:
-
-cord/cordbscs.o: cord/cordbscs.c
-	$(CC) cord/cordbscs.c $(CSCOPT)
-
-cord/cordprnt.o: cord/cordprnt.c
-	$(CC) cord/cordprnt.c $(CSCOPT)
-
-cord/cordxtra.o: cord/cordxtra.c
-	$(CC) cord/cordxtra.c $(CSCOPT)
-
-cord/tests/cordtest.o: cord/tests/cordtest.c
-	$(CC) cord/tests/cordtest.c $(CSCOPT)

+ 12 - 13
blitz.mod/bdwgc/WCC_MAKEFILE

@@ -1,4 +1,4 @@
-# Makefile for Watcom C/C++ 10.5, 10.6, 11.0 on NT, OS2 and DOS4GW.
+# Makefile for Watcom C/C++ 10.5, 10.6, 11.0 on NT, OS/2 and DOS4GW.
 # May work with Watcom 10.0.
 
 # Uncomment one of the lines below for cross compilation.
@@ -27,8 +27,7 @@ OPTIM=-oneatx -s
 # Extra user-defined flags to pass both to C and C++ compilers.
 CFLAGS_EXTRA=
 
-DEFS=-DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION #-DSMALL_CONFIG
-
+DEFS=-DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION -DGC_REQUIRE_WCSDUP #-DSMALL_CONFIG
 
 #####
 
@@ -83,11 +82,11 @@ COBJS= cordbscs.obj cordxtra.obj cordprnt.obj
 
 all: gc.lib gccpp.lib gctba.lib cord.lib
 
-check-deps: gctest.exe test_cpp.exe cordtest.exe .SYMBOLIC
+check-deps: gctest.exe cpptest.exe cordtest.exe .SYMBOLIC
 
 check: check-deps .SYMBOLIC
         *gctest.exe
-        *test_cpp.exe
+        *cpptest.exe
         *cordtest.exe
 
 !ifdef ENABLE_STATIC
@@ -201,7 +200,7 @@ gctba.dll: gc_badalc.obj gc.lib .AUTODEPEND
 
 !endif
 
-gctest.exe: test.obj gc.lib
+gctest.exe: gctest.obj gc.lib
         %create $*.lnk
 !ifdef DOS4GW
         @%append $*.lnk sys dos4g
@@ -213,7 +212,7 @@ gctest.exe: test.obj gc.lib
         @%append $*.lnk op case
         @%append $*.lnk op stack=256K
         @%append $*.lnk name $*
-        @%append $*.lnk file test.obj
+        @%append $*.lnk file gctest.obj
         @%append $*.lnk library gc.lib
         *wlink @$*.lnk
 
@@ -234,7 +233,7 @@ cordtest.exe: cordtest.obj gc.lib cord.lib
         @%append $*.lnk library cord.lib
         *wlink @$*.lnk
 
-test_cpp.exe: test_cpp.obj gc.lib gccpp.lib
+cpptest.exe: cpptest.obj gc.lib gccpp.lib
         %create $*.lnk
 !ifdef DOS4GW
         @%append $*.lnk sys dos4g
@@ -246,7 +245,7 @@ test_cpp.exe: test_cpp.obj gc.lib gccpp.lib
         @%append $*.lnk op case
         @%append $*.lnk op stack=256K
         @%append $*.lnk name $*
-        @%append $*.lnk file test_cpp.obj
+        @%append $*.lnk file cpptest.obj
         @%append $*.lnk library gc.lib
         @%append $*.lnk library gccpp.lib
         *wlink @$*.lnk
@@ -263,12 +262,12 @@ gc_badalc.obj: gc_badalc.cc .AUTODEPEND
 gc_cpp.obj: gc_cpp.cc .AUTODEPEND
         $(CXX) $(TEST_CXXFLAGS) $*.cc
 
-test.obj: tests\test.c .AUTODEPEND
-        $(CC) $(TEST_CFLAGS) /wcd=13 /wcd=201 /wcd=367 /wcd=368 tests\test.c
+gctest.obj: tests\gctest.c .AUTODEPEND
+        $(CC) $(TEST_CFLAGS) /wcd=13 /wcd=201 /wcd=367 /wcd=368 tests\gctest.c
 cordtest.obj: cord\tests\cordtest.c .AUTODEPEND
         $(CC) $(TEST_CFLAGS) $(CORDFLAG) cord\tests\cordtest.c
-test_cpp.obj: tests\test_cpp.cc .AUTODEPEND
-        $(CXX) $(TEST_CXXFLAGS) tests\test_cpp.cc
+cpptest.obj: tests\cpp.cc .AUTODEPEND
+        $(CXX) $(TEST_CXXFLAGS) -fo=cpptest.obj tests\cpp.cc
 
 .c.obj: .AUTODEPEND
         $(CC) $(CFLAGS) $*.c

+ 87 - 73
blitz.mod/bdwgc/allchblk.c

@@ -3,12 +3,13 @@
  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 1998-1999 by Silicon Graphics.  All rights reserved.
  * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
+ * Copyright (c) 2008-2022 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -16,8 +17,6 @@
 
 #include "private/gc_priv.h"
 
-#include <stdio.h>
-
 #ifdef GC_USE_ENTIRE_HEAP
   int GC_use_entire_heap = TRUE;
 #else
@@ -58,6 +57,20 @@
                                 /* block.  Remains externally visible   */
                                 /* as used by GNU GCJ currently.        */
 
+GC_API void GC_CALL GC_iterate_free_hblks(GC_walk_free_blk_fn fn,
+                                          GC_word client_data)
+{
+  int i;
+
+  for (i = 0; i <= N_HBLK_FLS; ++i) {
+    struct hblk *h;
+
+    for (h = GC_hblkfreelist[i]; h != NULL; h = HDR(h) -> hb_next) {
+      (*fn)(h, i, client_data);
+    }
+  }
+}
+
 #ifndef GC_GCJ_SUPPORT
   STATIC
 #endif
@@ -100,58 +113,58 @@ STATIC int GC_hblk_fl_from_blocks(word blocks_needed)
 # endif /* !USE_MUNMAP */
 
 #if !defined(NO_DEBUGGING) || defined(GC_ASSERTIONS)
+  static void GC_CALLBACK add_hb_sz(struct hblk *h, int i, GC_word client_data)
+  {
+      UNUSED_ARG(i);
+      *(word *)client_data += HDR(h) -> hb_sz;
+  }
+
   /* Should return the same value as GC_large_free_bytes.       */
   GC_INNER word GC_compute_large_free_bytes(void)
   {
       word total_free = 0;
-      unsigned i;
-
-      for (i = 0; i <= N_HBLK_FLS; ++i) {
-        struct hblk * h;
-        hdr * hhdr;
 
-        for (h = GC_hblkfreelist[i]; h != 0; h = hhdr->hb_next) {
-          hhdr = HDR(h);
-          total_free += hhdr->hb_sz;
-        }
-      }
+      GC_iterate_free_hblks(add_hb_sz, (word)&total_free);
       return total_free;
   }
 #endif /* !NO_DEBUGGING || GC_ASSERTIONS */
 
 # if !defined(NO_DEBUGGING)
-void GC_print_hblkfreelist(void)
-{
-    unsigned i;
-    word total;
+  static void GC_CALLBACK print_hblkfreelist_item(struct hblk *h, int i,
+                                                  GC_word prev_index_ptr)
+  {
+    hdr *hhdr = HDR(h);
 
-    for (i = 0; i <= N_HBLK_FLS; ++i) {
-      struct hblk * h = GC_hblkfreelist[i];
-
-      if (0 != h) GC_printf("Free list %u (total size %lu):\n",
-                            i, (unsigned long)GC_free_bytes[i]);
-      while (h /* != NULL */) { /* CPPCHECK */
-        hdr * hhdr = HDR(h);
-
-        GC_printf("\t%p size %lu %s black listed\n",
-                (void *)h, (unsigned long) hhdr -> hb_sz,
-                GC_is_black_listed(h, HBLKSIZE) != 0 ? "start" :
-                GC_is_black_listed(h, hhdr -> hb_sz) != 0 ? "partially" :
-                                                        "not");
-        h = hhdr -> hb_next;
-      }
+    if (i != *(int *)prev_index_ptr) {
+      GC_printf("Free list %d (total size %lu):\n",
+                i, (unsigned long)GC_free_bytes[i]);
+      *(int *)prev_index_ptr = i;
     }
+
+    GC_printf("\t%p size %lu %s black listed\n",
+              (void *)h, (unsigned long)(hhdr -> hb_sz),
+              GC_is_black_listed(h, HBLKSIZE) != NULL ? "start"
+                : GC_is_black_listed(h, hhdr -> hb_sz) != NULL ? "partially"
+                : "not");
+  }
+
+  void GC_print_hblkfreelist(void)
+  {
+    word total;
+    int prev_index = -1;
+
+    GC_iterate_free_hblks(print_hblkfreelist_item, (word)&prev_index);
     GC_printf("GC_large_free_bytes: %lu\n",
               (unsigned long)GC_large_free_bytes);
-
-    if ((total = GC_compute_large_free_bytes()) != GC_large_free_bytes)
-          GC_err_printf("GC_large_free_bytes INCONSISTENT!! Should be: %lu\n",
-                        (unsigned long)total);
-}
+    total = GC_compute_large_free_bytes();
+    if (total != GC_large_free_bytes)
+      GC_err_printf("GC_large_free_bytes INCONSISTENT!! Should be: %lu\n",
+                    (unsigned long)total);
+  }
 
 /* Return the free list index on which the block described by the header */
 /* appears, or -1 if it appears nowhere.                                 */
-static int free_list_index_of(hdr *wanted)
+static int free_list_index_of(const hdr *wanted)
 {
     int i;
 
@@ -228,6 +241,7 @@ static GC_bool setup_header(hdr * hhdr, struct hblk *block, size_t byte_sz,
 {
     word descr;
 
+    GC_ASSERT(I_HOLD_LOCK());
 #   ifdef MARK_BIT_PER_GRANULE
       if (byte_sz > MAXOBJBYTES)
         flags |= LARGE_BLOCK;
@@ -293,13 +307,13 @@ static GC_bool setup_header(hdr * hhdr, struct hblk *block, size_t byte_sz,
     GC_clear_hdr_marks(hhdr);
 
     hhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
-    return(TRUE);
+    return TRUE;
 }
 
 /* Remove hhdr from the free list (it is assumed to specified by index). */
 STATIC void GC_remove_from_fl_at(hdr *hhdr, int index)
 {
-    GC_ASSERT(((hhdr -> hb_sz) & (HBLKSIZE-1)) == 0);
+    GC_ASSERT(modHBLKSZ(hhdr -> hb_sz) == 0);
     if (hhdr -> hb_prev == 0) {
         GC_ASSERT(HDR(GC_hblkfreelist[index]) == hhdr);
         GC_hblkfreelist[index] = hhdr -> hb_next;
@@ -371,7 +385,9 @@ STATIC void GC_add_to_fl(struct hblk *h, hdr *hhdr)
 {
     int index = GC_hblk_fl_from_blocks(divHBLKSZ(hhdr -> hb_sz));
     struct hblk *second = GC_hblkfreelist[index];
+
 #   if defined(GC_ASSERTIONS) && !defined(USE_MUNMAP)
+    {
       struct hblk *next = (struct hblk *)((word)h + hhdr -> hb_sz);
       hdr * nexthdr = HDR(next);
       struct hblk *prev = GC_free_block_ending_at(h);
@@ -380,10 +396,11 @@ STATIC void GC_add_to_fl(struct hblk *h, hdr *hhdr)
       GC_ASSERT(nexthdr == 0 || !HBLK_IS_FREE(nexthdr)
                 || (GC_heapsize & SIGNB) != 0);
                 /* In the last case, blocks may be too large to merge. */
-      GC_ASSERT(prev == 0 || !HBLK_IS_FREE(prevhdr)
+      GC_ASSERT(NULL == prev || !HBLK_IS_FREE(prevhdr)
                 || (GC_heapsize & SIGNB) != 0);
+    }
 #   endif
-    GC_ASSERT(((hhdr -> hb_sz) & (HBLKSIZE-1)) == 0);
+    GC_ASSERT(modHBLKSZ(hhdr -> hb_sz) == 0);
     GC_hblkfreelist[index] = h;
     GC_free_bytes[index] += hhdr -> hb_sz;
     GC_ASSERT(GC_free_bytes[index] <= GC_large_free_bytes);
@@ -400,12 +417,6 @@ STATIC void GC_add_to_fl(struct hblk *h, hdr *hhdr)
 
 #ifdef USE_MUNMAP
 
-#   ifndef MUNMAP_THRESHOLD
-#     define MUNMAP_THRESHOLD 6
-#   endif
-
-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.      */
@@ -452,22 +463,22 @@ GC_INNER int GC_unmap_threshold = MUNMAP_THRESHOLD;
 
 /* 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)
+GC_INLINE void GC_adjust_num_unmapped(struct hblk *h, hdr *hhdr)
 {
 # ifdef COUNT_UNMAPPED_REGIONS
     GC_num_unmapped_regions += calc_num_unmapped_regions_delta(h, hhdr);
+# else
+    UNUSED_ARG(h);
+    UNUSED_ARG(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)
+/* Unmap blocks that haven't been recently touched.  This is the only   */
+/* way blocks are ever unmapped.                                        */
+GC_INNER void GC_unmap_old(unsigned threshold)
 {
     int i;
 
-    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. */
@@ -483,10 +494,10 @@ GC_INNER void GC_unmap_old(void)
         hhdr = HDR(h);
         if (!IS_MAPPED(hhdr)) continue;
 
-        /* Check that the interval is larger than the threshold (the    */
-        /* truncated counter value wrapping is handled correctly).      */
-        if ((unsigned short)(GC_gc_no - hhdr->hb_last_reclaimed) >
-                (unsigned short)GC_unmap_threshold) {
+        /* Check that the interval is not smaller than the threshold.   */
+        /* The truncated counter value wrapping is handled correctly.   */
+        if ((unsigned short)(GC_gc_no - hhdr->hb_last_reclaimed)
+            >= (unsigned short)threshold) {
 #         ifdef COUNT_UNMAPPED_REGIONS
             /* Continue with unmapping the block only if it will not    */
             /* create too many unmapped regions, or if unmapping        */
@@ -569,7 +580,7 @@ GC_INNER void GC_merge_unmapped(void)
             GC_add_to_fl(h, hhdr);
             /* Start over at beginning of list */
             h = GC_hblkfreelist[i];
-          } else /* not mergable with successor */ {
+          } else /* not mergeable with successor */ {
             h = hhdr -> hb_next;
           }
       } /* while (h != 0) ... */
@@ -590,19 +601,21 @@ GC_INNER void GC_merge_unmapped(void)
 STATIC struct hblk * GC_get_first_part(struct hblk *h, hdr *hhdr,
                                        size_t bytes, int index)
 {
-    word total_size = hhdr -> hb_sz;
+    word total_size;
     struct hblk * rest;
     hdr * rest_hdr;
 
-    GC_ASSERT((total_size & (HBLKSIZE-1)) == 0);
+    GC_ASSERT(I_HOLD_LOCK());
+    total_size = hhdr -> hb_sz;
+    GC_ASSERT(modHBLKSZ(total_size) == 0);
     GC_remove_from_fl_at(hhdr, index);
     if (total_size == bytes) return h;
     rest = (struct hblk *)((word)h + bytes);
     rest_hdr = GC_install_header(rest);
-    if (0 == rest_hdr) {
+    if (NULL == rest_hdr) {
         /* FIXME: This is likely to be very bad news ... */
         WARN("Header allocation failed: dropping block\n", 0);
-        return(0);
+        return NULL;
     }
     rest_hdr -> hb_sz = total_size - bytes;
     rest_hdr -> hb_flags = 0;
@@ -696,7 +709,7 @@ GC_allochblk(size_t sz, int kind, unsigned flags/* IGNORE_OFF_PAGE or 0 */)
 
     may_split = TRUE;
     if (GC_use_entire_heap || GC_dont_gc
-        || USED_HEAP_SIZE < GC_requested_heapsize
+        || GC_heapsize - GC_large_free_bytes < GC_requested_heapsize
         || GC_incremental || !GC_should_collect()) {
         /* Should use more of the heap, even if it requires splitting. */
         split_limit = N_HBLK_FLS;
@@ -748,6 +761,7 @@ GC_allochblk_nth(size_t sz, int kind, unsigned flags, int n, int may_split)
     signed_word size_needed = HBLKSIZE * OBJ_SZ_TO_BLOCKS_CHECKED(sz);
                                 /* number of bytes in requested objects */
 
+    GC_ASSERT(I_HOLD_LOCK());
     /* search for a big enough block in free list */
         for (hbp = GC_hblkfreelist[n];; hbp = hhdr -> hb_next) {
             signed_word size_avail; /* bytes available in this block */
@@ -826,10 +840,10 @@ GC_allochblk_nth(size_t sz, int kind, unsigned flags, int n, int may_split)
                 /* Punt, since anything else risks unreasonable heap growth. */
                 if (++GC_large_alloc_warn_suppressed
                     >= GC_large_alloc_warn_interval) {
-                  WARN("Repeated allocation of very large block "
-                       "(appr. size %" WARN_PRIdPTR "):\n"
+                  WARN("Repeated allocation of very large block"
+                       " (appr. size %" WARN_PRIuPTR " KiB):\n"
                        "\tMay lead to memory leak and poor performance\n",
-                       size_needed);
+                       (word)size_needed >> 10);
                   GC_large_alloc_warn_suppressed = 0;
                 }
                 size_avail = orig_avail;
@@ -894,16 +908,16 @@ GC_allochblk_nth(size_t sz, int kind, unsigned flags, int n, int may_split)
             }
         }
 
-    if (0 == hbp) return 0;
+    if (NULL == hbp) return NULL;
 
     /* Add it to map of valid blocks */
-        if (!GC_install_counts(hbp, (word)size_needed)) return(0);
+        if (!GC_install_counts(hbp, (word)size_needed)) return NULL;
         /* This leaks memory under very rare conditions. */
 
     /* Set up header */
         if (!setup_header(hhdr, hbp, sz, kind, flags)) {
             GC_remove_counts(hbp, (word)size_needed);
-            return(0); /* ditto */
+            return NULL; /* ditto */
         }
 #   ifndef GC_DISABLE_INCREMENTAL
         /* Notify virtual dirty bit implementation that we are about to */
@@ -911,7 +925,7 @@ GC_allochblk_nth(size_t sz, int kind, unsigned flags, int n, int may_split)
         /* if it is avoidable.  This also ensures that newly allocated  */
         /* blocks are treated as dirty.  Necessary since we don't       */
         /* protect free blocks.                                         */
-        GC_ASSERT((size_needed & (HBLKSIZE-1)) == 0);
+        GC_ASSERT(modHBLKSZ(size_needed) == 0);
         GC_remove_protection(hbp, divHBLKSZ(size_needed),
                              (hhdr -> hb_descr == 0) /* pointer-free */);
 #   endif
@@ -921,7 +935,7 @@ GC_allochblk_nth(size_t sz, int kind, unsigned flags, int n, int may_split)
 
     GC_large_free_bytes -= size_needed;
     GC_ASSERT(IS_MAPPED(hhdr));
-    return( hbp );
+    return hbp;
 }
 
 /*

+ 217 - 215
blitz.mod/bdwgc/alloc.c

@@ -3,13 +3,13 @@
  * Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.
  * Copyright (c) 1999-2011 Hewlett-Packard Development Company, L.P.
- * Copyright (c) 2008-2021 Ivan Maidanski
+ * Copyright (c) 2008-2022 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -18,7 +18,6 @@
 
 #include "private/gc_priv.h"
 
-#include <stdio.h>
 #if !defined(MACOS) && !defined(MSWINCE)
 # include <signal.h>
 # if !defined(GC_NO_TYPES) && !defined(SN_TARGET_PSP2) \
@@ -109,7 +108,7 @@ GC_API int GC_CALL GC_is_incremental_mode(void)
 #endif
 
 STATIC GC_bool GC_need_full_gc = FALSE;
-                           /* Need full GC do to heap growth.   */
+                           /* Need full GC due to heap growth.  */
 
 #ifdef THREAD_LOCAL_ALLOC
   GC_INNER GC_bool GC_world_stopped = FALSE;
@@ -171,7 +170,7 @@ GC_API unsigned GC_CALL GC_get_version(void)
 
 GC_INNER int GC_CALLBACK GC_never_stop_func(void)
 {
-  return(0);
+  return FALSE;
 }
 
 #if defined(GC_TIME_LIMIT) && !defined(CPPCHECK)
@@ -183,7 +182,7 @@ GC_INNER int GC_CALLBACK GC_never_stop_func(void)
                         /* The parallel marker cannot be interrupted for */
                         /* now, so the time limit is absent by default.  */
 #else
-  unsigned long GC_time_limit = 50;
+  unsigned long GC_time_limit = 15;
 #endif
 
 #ifndef NO_CLOCK
@@ -221,7 +220,7 @@ STATIC int GC_n_attempts = 0;   /* Number of attempts at finishing      */
                                 /* collection within GC_time_limit.     */
 
 STATIC GC_stop_func GC_default_stop_func = GC_never_stop_func;
-                                /* accessed holding the lock.           */
+                                /* Accessed holding the allocator lock. */
 
 GC_API void GC_CALL GC_set_stop_func(GC_stop_func stop_func)
 {
@@ -245,16 +244,18 @@ GC_API GC_stop_func GC_CALL GC_get_stop_func(void)
 #if defined(GC_DISABLE_INCREMENTAL) || defined(NO_CLOCK)
 # define GC_timeout_stop_func GC_default_stop_func
 #else
-  STATIC int GC_CALLBACK GC_timeout_stop_func (void)
+  STATIC int GC_CALLBACK GC_timeout_stop_func(void)
   {
     CLOCK_TYPE current_time;
     static unsigned count = 0;
     unsigned long time_diff, nsec_diff;
 
-    if ((*GC_default_stop_func)())
-      return(1);
+    if (GC_default_stop_func())
+      return TRUE;
+
+    if (GC_time_limit == GC_TIME_UNLIMITED || (count++ & 3) != 0)
+      return FALSE;
 
-    if ((count++ & 3) != 0) return(0);
     GET_TIME(current_time);
     time_diff = MS_TIME_DIFF(current_time,GC_start_time);
     nsec_diff = NS_FRAC_TIME_DIFF(current_time, GC_start_time);
@@ -266,9 +267,10 @@ GC_API GC_stop_func GC_CALL GC_get_stop_func(void)
       GC_COND_LOG_PRINTF("Abandoning stopped marking after %lu ms %lu ns"
                          " (attempt %d)\n",
                          time_diff, nsec_diff, GC_n_attempts);
-      return 1;
+      return TRUE;
     }
-    return(0);
+
+    return FALSE;
   }
 #endif /* !GC_DISABLE_INCREMENTAL */
 
@@ -370,10 +372,9 @@ STATIC word GC_adj_bytes_allocd(void)
         /* to collect too infrequently, since that would inhibit        */
         /* coalescing of free storage blocks.                           */
         /* This also makes us partially robust against client bugs.     */
-        return(GC_bytes_allocd >> 3);
-    } else {
-        return(result);
+        result = (signed_word)(GC_bytes_allocd >> 3);
     }
+    return (word)result;
 }
 
 
@@ -391,10 +392,6 @@ STATIC void GC_clear_a_few_frames(void)
     BZERO((word *)frames, CLEAR_NWORDS * sizeof(word));
 }
 
-/* Heap size at which we need a collection to avoid expanding past      */
-/* limits used by blacklisting.                                         */
-STATIC word GC_collect_at_heapsize = GC_WORD_MAX;
-
 GC_API void GC_CALL GC_start_incremental_collection(void)
 {
 # ifndef GC_DISABLE_INCREMENTAL
@@ -429,8 +426,10 @@ GC_INNER GC_bool GC_should_collect(void)
 # endif
     if (GC_disable_automatic_collection) return FALSE;
 
-    return(GC_adj_bytes_allocd() >= last_min_bytes_allocd
-           || GC_heapsize >= GC_collect_at_heapsize);
+    if (GC_last_heap_growth_gc_no == GC_gc_no)
+      return TRUE; /* avoid expanding past limits used by blacklisting  */
+
+    return GC_adj_bytes_allocd() >= last_min_bytes_allocd;
 }
 
 /* STATIC */ GC_start_callback_proc GC_start_call_back = 0;
@@ -468,63 +467,54 @@ STATIC GC_bool GC_is_full_gc = FALSE;
 STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func);
 STATIC void GC_finish_collection(void);
 
-/*
- * Initiate a garbage collection if appropriate.
- * Choose judiciously
- * between partial, full, and stop-world collections.
- */
+/* Initiate a garbage collection if appropriate.  Choose judiciously    */
+/* between partial, full, and stop-world collections.                   */
 STATIC void GC_maybe_gc(void)
 {
-    GC_ASSERT(I_HOLD_LOCK());
-    ASSERT_CANCEL_DISABLED();
-    if (GC_should_collect()) {
-        static int n_partial_gcs = 0;
-
-        if (!GC_incremental) {
-            /* TODO: If possible, GC_default_stop_func should be used here */
-            GC_try_to_collect_inner(GC_never_stop_func);
-            n_partial_gcs = 0;
-            return;
-        } else {
-#         ifdef PARALLEL_MARK
-            if (GC_parallel)
-              GC_wait_for_reclaim();
-#         endif
-          if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) {
-            GC_COND_LOG_PRINTF(
+  static int n_partial_gcs = 0;
+
+  GC_ASSERT(I_HOLD_LOCK());
+  ASSERT_CANCEL_DISABLED();
+  if (!GC_should_collect()) return;
+
+  if (!GC_incremental) {
+    GC_gcollect_inner();
+    return;
+  }
+
+  GC_ASSERT(!GC_collection_in_progress());
+# ifdef PARALLEL_MARK
+    if (GC_parallel)
+      GC_wait_for_reclaim();
+# endif
+  if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) {
+    GC_COND_LOG_PRINTF(
                 "***>Full mark for collection #%lu after %lu allocd bytes\n",
                 (unsigned long)GC_gc_no + 1, (unsigned long)GC_bytes_allocd);
-            GC_promote_black_lists();
-            (void)GC_reclaim_all((GC_stop_func)0, TRUE);
-            GC_notify_full_gc();
-            GC_clear_marks();
-            n_partial_gcs = 0;
-            GC_is_full_gc = TRUE;
-          } else {
-            n_partial_gcs++;
-          }
-        }
-        /* We try to mark with the world stopped.       */
-        /* If we run out of time, this turns into       */
-        /* incremental marking.                         */
-#       ifndef NO_CLOCK
-          if (GC_time_limit != GC_TIME_UNLIMITED) { GET_TIME(GC_start_time); }
-#       endif
-        /* TODO: If possible, GC_default_stop_func should be    */
-        /* used instead of GC_never_stop_func here.             */
-        if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED?
-                            GC_never_stop_func : GC_timeout_stop_func)) {
-#           ifdef SAVE_CALL_CHAIN
-                GC_save_callers(GC_last_stack);
-#           endif
-            GC_finish_collection();
-        } else {
-            if (!GC_is_full_gc) {
-                /* Count this as the first attempt */
-                GC_n_attempts++;
-            }
-        }
-    }
+    GC_promote_black_lists();
+    (void)GC_reclaim_all((GC_stop_func)0, TRUE);
+    GC_notify_full_gc();
+    GC_clear_marks();
+    n_partial_gcs = 0;
+    GC_is_full_gc = TRUE;
+  } else {
+    n_partial_gcs++;
+  }
+
+  /* Try to mark with the world stopped.  If we run out of      */
+  /* time, this turns into an incremental marking.              */
+# ifndef NO_CLOCK
+    if (GC_time_limit != GC_TIME_UNLIMITED) GET_TIME(GC_start_time);
+# endif
+  if (GC_stopped_mark(GC_timeout_stop_func)) {
+#   ifdef SAVE_CALL_CHAIN
+      GC_save_callers(GC_last_stack);
+#   endif
+    GC_finish_collection();
+  } else if (!GC_is_full_gc) {
+    /* Count this as the first attempt. */
+    GC_n_attempts++;
+  }
 }
 
 STATIC GC_on_collection_event_proc GC_on_collection_event = 0;
@@ -560,6 +550,7 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func)
 
     ASSERT_CANCEL_DISABLED();
     GC_ASSERT(I_HOLD_LOCK());
+    GC_ASSERT(GC_is_initialized);
     if (GC_dont_gc || (*stop_func)()) return FALSE;
     if (GC_on_collection_event)
       GC_on_collection_event(GC_EVENT_START);
@@ -570,7 +561,7 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func)
         while(GC_collection_in_progress()) {
             if ((*stop_func)()) {
               /* TODO: Notify GC_EVENT_ABANDON */
-              return(FALSE);
+              return FALSE;
             }
             ENTER_GC();
             GC_collect_a_little_inner(1);
@@ -601,7 +592,7 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func)
             && !GC_reclaim_all(stop_func, FALSE)) {
             /* Aborted.  So far everything is still consistent. */
             /* TODO: Notify GC_EVENT_ABANDON */
-            return(FALSE);
+            return FALSE;
         }
     GC_invalidate_mark_state();  /* Flush mark stack.   */
     GC_clear_marks();
@@ -619,7 +610,7 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func)
       } /* else we claim the world is already still consistent.  We'll  */
         /* finish incrementally.                                        */
       /* TODO: Notify GC_EVENT_ABANDON */
-      return(FALSE);
+      return FALSE;
     }
     GC_finish_collection();
 #   ifndef NO_CLOCK
@@ -646,31 +637,22 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func)
 #   endif
     if (GC_on_collection_event)
       GC_on_collection_event(GC_EVENT_END);
-    return(TRUE);
+    return TRUE;
 }
 
-/*
- * Perform n units of garbage collection work.  A unit is intended to touch
- * roughly GC_rate pages.  Every once in a while, we do more than that.
- * This needs to be a fairly large number with our current incremental
- * GC strategy, since otherwise we allocate too much during GC, and the
- * cleanup gets expensive.
- */
+/* The number of extra calls to GC_mark_some that we have made. */
+STATIC int GC_deficit = 0;
+
+/* The default value of GC_rate.        */
 #ifndef GC_RATE
 # define GC_RATE 10
 #endif
 
-#ifndef MAX_PRIOR_ATTEMPTS
-# define MAX_PRIOR_ATTEMPTS 1
-#endif
-        /* Maximum number of prior attempts at world stop marking       */
-        /* A value of 1 means that we finish the second time, no matter */
-        /* how long it takes.  Doesn't count the initial root scan      */
-        /* for a full GC.                                               */
-
-STATIC int GC_deficit = 0;/* The number of extra calls to GC_mark_some  */
-                          /* that we have made.                         */
-
+/* When GC_collect_a_little_inner() performs n units of GC work, a unit */
+/* is intended to touch roughly GC_rate pages.  (But, every once in     */
+/* a while, we do more than that.)  This needs to be a fairly large     */
+/* number with our current incremental GC strategy, since otherwise we  */
+/* allocate too much during GC, and the cleanup gets expensive.         */
 STATIC int GC_rate = GC_RATE;
 
 GC_API void GC_CALL GC_set_rate(int value)
@@ -684,6 +666,14 @@ GC_API int GC_CALL GC_get_rate(void)
     return GC_rate;
 }
 
+/* The default maximum number of prior attempts at world stop marking.  */
+#ifndef MAX_PRIOR_ATTEMPTS
+# define MAX_PRIOR_ATTEMPTS 3
+#endif
+
+/* The maximum number of prior attempts at world stop marking.          */
+/* A value of 1 means that we finish the second time, no matter how     */
+/* long it takes.  Does not count the initial root scan for a full GC.  */
 static int max_prior_attempts = MAX_PRIOR_ATTEMPTS;
 
 GC_API void GC_CALL GC_set_max_prior_attempts(int value)
@@ -702,6 +692,7 @@ GC_INNER void GC_collect_a_little_inner(int n)
     IF_CANCEL(int cancel_state;)
 
     GC_ASSERT(I_HOLD_LOCK());
+    GC_ASSERT(GC_is_initialized);
     if (GC_dont_gc) return;
 
     DISABLE_CANCEL(cancel_state);
@@ -722,7 +713,8 @@ GC_INNER void GC_collect_a_little_inner(int n)
 #       endif
 
         if (i < max_deficit) {
-            /* Need to finish a collection.     */
+            GC_ASSERT(!GC_collection_in_progress());
+            /* Need to follow up with a full collection.        */
 #           ifdef SAVE_CALL_CHAIN
                 GC_save_callers(GC_last_stack);
 #           endif
@@ -730,21 +722,16 @@ GC_INNER void GC_collect_a_little_inner(int n)
                 if (GC_parallel)
                     GC_wait_for_reclaim();
 #           endif
-            if (GC_n_attempts < max_prior_attempts
-                && GC_time_limit != GC_TIME_UNLIMITED) {
-#               ifndef NO_CLOCK
+#           ifndef NO_CLOCK
+                if (GC_time_limit != GC_TIME_UNLIMITED
+                        && GC_n_attempts < max_prior_attempts)
                     GET_TIME(GC_start_time);
-#               endif
-                if (GC_stopped_mark(GC_timeout_stop_func)) {
-                    GC_finish_collection();
-                } else {
-                    GC_n_attempts++;
-                }
-            } else {
-                /* TODO: If possible, GC_default_stop_func should be    */
-                /* used here.                                           */
-                (void)GC_stopped_mark(GC_never_stop_func);
+#           endif
+            if (GC_stopped_mark(GC_n_attempts < max_prior_attempts ?
+                                GC_timeout_stop_func : GC_never_stop_func)) {
                 GC_finish_collection();
+            } else {
+                GC_n_attempts++;
             }
         }
         if (GC_deficit > 0) {
@@ -766,6 +753,7 @@ GC_API int GC_CALL GC_collect_a_little(void)
     int result;
     DCL_LOCK_STATE;
 
+    if (!EXPECT(GC_is_initialized, TRUE)) GC_init();
     LOCK();
     ENTER_GC();
     GC_collect_a_little_inner(1);
@@ -773,7 +761,7 @@ GC_API int GC_CALL GC_collect_a_little(void)
     result = (int)GC_collection_in_progress();
     UNLOCK();
     if (!result && GC_debugging_started) GC_print_all_smashed();
-    return(result);
+    return result;
 }
 
 #ifndef NO_CLOCK
@@ -791,6 +779,11 @@ GC_API int GC_CALL GC_collect_a_little(void)
 #endif /* !NO_CLOCK */
 
 #ifdef USE_MUNMAP
+# ifndef MUNMAP_THRESHOLD
+#   define MUNMAP_THRESHOLD 7
+# endif
+  GC_INNER unsigned GC_unmap_threshold = MUNMAP_THRESHOLD;
+
 # define IF_USE_MUNMAP(x) x
 # define COMMA_IF_USE_MUNMAP(x) /* comma */, x
 #else
@@ -798,19 +791,19 @@ GC_API int GC_CALL GC_collect_a_little(void)
 # define COMMA_IF_USE_MUNMAP(x) /* empty */
 #endif
 
-/*
- * We stop the world and mark from all roots.
- * If stop_func() ever returns TRUE, we may fail and return FALSE.
- * Increment GC_gc_no if we succeed.
- */
+/* We stop the world and mark from all roots.  If stop_func() ever      */
+/* returns TRUE, we may fail and return FALSE.  Increment GC_gc_no if   */
+/* we succeed.                                                          */
 STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func)
 {
     int i;
+    ptr_t cold_gc_frame = GC_approx_sp();
 #   ifndef NO_CLOCK
       CLOCK_TYPE start_time = CLOCK_TYPE_INITIALIZER;
 #   endif
 
     GC_ASSERT(I_HOLD_LOCK());
+    GC_ASSERT(GC_is_initialized);
 #   if !defined(REDIRECT_MALLOC) && defined(USE_WINALLOC)
         GC_add_current_malloc_heap();
 #   endif
@@ -863,7 +856,7 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func)
             GC_parallel_mark_disabled = TRUE;
 #       endif
         for (i = 0; !(*stop_func)(); i++) {
-          if (GC_mark_some(GC_approx_sp())) {
+          if (GC_mark_some(cold_gc_frame)) {
 #           ifdef PARALLEL_MARK
               if (GC_parallel && GC_parallel_mark_disabled) {
                 GC_COND_LOG_PRINTF("Stopped marking done after %d iterations"
@@ -903,18 +896,6 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func)
         }
 
     GC_gc_no++;
-#   ifdef USE_MUNMAP
-      GC_ASSERT(GC_heapsize >= GC_unmapped_bytes);
-#   endif
-    GC_ASSERT(GC_our_mem_bytes >= GC_heapsize);
-    GC_DBGLOG_PRINTF("GC #%lu freed %ld bytes, heap %lu KiB ("
-                     IF_USE_MUNMAP("+ %lu KiB unmapped ")
-                     "+ %lu KiB internal)\n",
-                     (unsigned long)GC_gc_no, (long)GC_bytes_found,
-                     TO_KiB_UL(GC_heapsize - GC_unmapped_bytes) /*, */
-                     COMMA_IF_USE_MUNMAP(TO_KiB_UL(GC_unmapped_bytes)),
-                     TO_KiB_UL(GC_our_mem_bytes - GC_heapsize));
-
     /* Check all debugged objects for consistency */
     if (GC_debugging_started) {
       (*GC_check_heap)();
@@ -948,7 +929,8 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func)
         /* Compute new world-stop delay total time */
         total_time = world_stopped_total_time;
         divisor = world_stopped_total_divisor;
-        if ((int)total_time < 0 || divisor >= MAX_TOTAL_TIME_DIVISOR) {
+        if (total_time > (((unsigned)-1) >> 1)
+            || divisor >= MAX_TOTAL_TIME_DIVISOR) {
           /* Halve values if overflow occurs */
           total_time >>= 1;
           divisor >>= 1;
@@ -966,7 +948,7 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func)
                       total_time / divisor);
       }
 #   endif
-    return(TRUE);
+    return TRUE;
 }
 
 /* Set all mark bits for the free list whose first entry is q   */
@@ -1096,7 +1078,7 @@ GC_on_heap_resize_proc GC_on_heap_resize = 0;
 /* Used for logging only. */
 GC_INLINE int GC_compute_heap_usage_percent(void)
 {
-  word used = GC_composite_in_use + GC_atomic_in_use;
+  word used = GC_composite_in_use + GC_atomic_in_use + GC_bytes_allocd;
   word heap_sz = GC_heapsize - GC_unmapped_bytes;
 # if defined(CPPCHECK)
     word limit = (GC_WORD_MAX >> 1) / 50; /* to avoid a false positive */
@@ -1108,8 +1090,14 @@ GC_INLINE int GC_compute_heap_usage_percent(void)
                 (int)((used * 100) / heap_sz) : (int)(used / (heap_sz / 100));
 }
 
-/* Finish up a collection.  Assumes mark bits are consistent, lock is   */
-/* held, but the world is otherwise running.                            */
+#define GC_DBGLOG_PRINT_HEAP_IN_USE() \
+  GC_DBGLOG_PRINTF("In-use heap: %d%% (%lu KiB pointers + %lu KiB other)\n", \
+                   GC_compute_heap_usage_percent(), \
+                   TO_KiB_UL(GC_composite_in_use), \
+                   TO_KiB_UL(GC_atomic_in_use + GC_bytes_allocd))
+
+/* Finish up a collection.  Assumes mark bits are consistent, but the   */
+/* world is otherwise running.                                          */
 STATIC void GC_finish_collection(void)
 {
 #   ifndef NO_CLOCK
@@ -1203,25 +1191,32 @@ STATIC void GC_finish_collection(void)
 
     /* Reconstruct free lists to contain everything not marked */
     GC_start_reclaim(FALSE);
-    GC_DBGLOG_PRINTF("In-use heap: %d%% (%lu KiB pointers + %lu KiB other)\n",
-                     GC_compute_heap_usage_percent(),
-                     TO_KiB_UL(GC_composite_in_use),
-                     TO_KiB_UL(GC_atomic_in_use));
+
+#   ifdef USE_MUNMAP
+      if (GC_unmap_threshold > 0 /* unmapping enabled? */
+          && EXPECT(GC_gc_no != 1, TRUE)) /* do not unmap during GC init */
+        GC_unmap_old(GC_unmap_threshold);
+
+      GC_ASSERT(GC_heapsize >= GC_unmapped_bytes);
+#   endif
+    GC_ASSERT(GC_our_mem_bytes >= GC_heapsize);
+    GC_DBGLOG_PRINTF("GC #%lu freed %ld bytes, heap %lu KiB ("
+                     IF_USE_MUNMAP("+ %lu KiB unmapped ")
+                     "+ %lu KiB internal)\n",
+                     (unsigned long)GC_gc_no, (long)GC_bytes_found,
+                     TO_KiB_UL(GC_heapsize - GC_unmapped_bytes) /*, */
+                     COMMA_IF_USE_MUNMAP(TO_KiB_UL(GC_unmapped_bytes)),
+                     TO_KiB_UL(GC_our_mem_bytes - GC_heapsize
+                               + sizeof(GC_arrays)));
+    GC_DBGLOG_PRINT_HEAP_IN_USE();
     if (GC_is_full_gc) {
-        GC_used_heap_size_after_full = USED_HEAP_SIZE;
+        GC_used_heap_size_after_full = GC_heapsize - GC_large_free_bytes;
         GC_need_full_gc = FALSE;
     } else {
-        GC_need_full_gc = USED_HEAP_SIZE - GC_used_heap_size_after_full
-                            > min_bytes_allocd();
+        GC_need_full_gc = GC_heapsize - GC_used_heap_size_after_full
+                          > min_bytes_allocd() + GC_large_free_bytes;
     }
 
-    GC_VERBOSE_LOG_PRINTF("Immediately reclaimed %ld bytes, heapsize:"
-                          " %lu bytes" IF_USE_MUNMAP(" (%lu unmapped)") "\n",
-                          (long)GC_bytes_found,
-                          (unsigned long)GC_heapsize /*, */
-                          COMMA_IF_USE_MUNMAP((unsigned long)
-                                              GC_unmapped_bytes));
-
     /* Reset or increment counters for next cycle */
     GC_n_attempts = 0;
     GC_is_full_gc = FALSE;
@@ -1232,8 +1227,6 @@ STATIC void GC_finish_collection(void)
     GC_bytes_freed = 0;
     GC_finalizer_bytes_freed = 0;
 
-    IF_USE_MUNMAP(GC_unmap_old());
-
     if (GC_on_collection_event)
       GC_on_collection_event(GC_EVENT_RECLAIM_END);
 #   ifndef NO_CLOCK
@@ -1258,9 +1251,12 @@ STATIC void GC_finish_collection(void)
 #   endif
 }
 
+STATIC word GC_heapsize_at_forced_unmap = 0;
+                                /* accessed with the allocation lock held */
+
 /* If stop_func == 0 then GC_default_stop_func is used instead.         */
 STATIC GC_bool GC_try_to_collect_general(GC_stop_func stop_func,
-                                         GC_bool force_unmap GC_ATTR_UNUSED)
+                                         GC_bool force_unmap)
 {
     GC_bool result;
     IF_USE_MUNMAP(int old_unmap_threshold;)
@@ -1271,6 +1267,11 @@ STATIC GC_bool GC_try_to_collect_general(GC_stop_func stop_func,
     if (GC_debugging_started) GC_print_all_smashed();
     GC_INVOKE_FINALIZERS();
     LOCK();
+    if (force_unmap) {
+      /* Record current heap size to make heap growth more conservative */
+      /* afterwards (as if the heap is growing from zero size again).   */
+      GC_heapsize_at_forced_unmap = GC_heapsize;
+    }
     DISABLE_CANCEL(cancel_state);
 #   ifdef USE_MUNMAP
       old_unmap_threshold = GC_unmap_threshold;
@@ -1291,7 +1292,7 @@ STATIC GC_bool GC_try_to_collect_general(GC_stop_func stop_func,
         if (GC_debugging_started) GC_print_all_smashed();
         GC_INVOKE_FINALIZERS();
     }
-    return(result);
+    return result;
 }
 
 /* Externally callable routines to invoke full, stop-the-world collection. */
@@ -1307,16 +1308,12 @@ GC_API void GC_CALL GC_gcollect(void)
     /* 0 is passed as stop_func to get GC_default_stop_func value       */
     /* while holding the allocation lock (to prevent data races).       */
     (void)GC_try_to_collect_general(0, FALSE);
-    if (GC_have_errors) GC_print_all_errors();
+    if (get_have_errors())
+      GC_print_all_errors();
 }
 
-STATIC word GC_heapsize_at_forced_unmap = 0;
-
 GC_API void GC_CALL GC_gcollect_and_unmap(void)
 {
-    /* Record current heap size to make heap growth more conservative   */
-    /* afterwards (as if the heap is growing from zero size again).     */
-    GC_heapsize_at_forced_unmap = GC_heapsize;
     /* Collect and force memory unmapping to OS. */
     (void)GC_try_to_collect_general(GC_never_stop_func, TRUE);
 }
@@ -1325,6 +1322,7 @@ GC_API void GC_CALL GC_gcollect_and_unmap(void)
   /* Add HBLKSIZE aligned, GET_MEM-generated block to GC_our_memory. */
   GC_INNER void GC_add_to_our_memory(ptr_t p, size_t bytes)
   {
+    GC_ASSERT(I_HOLD_LOCK());
     GC_ASSERT(p != NULL);
     if (GC_n_memory >= MAX_HEAP_SECTS)
       ABORT("Too many GC-allocated memory sections: Increase MAX_HEAP_SECTS");
@@ -1336,7 +1334,7 @@ GC_API void GC_CALL GC_gcollect_and_unmap(void)
 #endif
 
 /* Use the chunk of memory starting at p of size bytes as part of the heap. */
-/* Assumes p is HBLKSIZE aligned, and bytes is a multiple of HBLKSIZE.      */
+/* Assumes p is HBLKSIZE aligned, bytes argument is a multiple of HBLKSIZE. */
 STATIC void GC_add_to_heap(struct hblk *p, size_t bytes)
 {
     hdr * phdr;
@@ -1347,6 +1345,7 @@ STATIC void GC_add_to_heap(struct hblk *p, size_t bytes)
       unsigned i;
 #   endif
 
+    GC_ASSERT(I_HOLD_LOCK());
     GC_ASSERT((word)p % HBLKSIZE == 0);
     GC_ASSERT(bytes % HBLKSIZE == 0);
     GC_ASSERT(bytes > 0);
@@ -1423,15 +1422,6 @@ STATIC void GC_add_to_heap(struct hblk *p, size_t bytes)
     GC_freehblk(p);
     GC_heapsize += bytes;
 
-    /* Normally the caller calculates a new GC_collect_at_heapsize,
-     * 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.
-     */
-    GC_collect_at_heapsize += bytes;
-    if (GC_collect_at_heapsize < GC_heapsize /* wrapped */)
-       GC_collect_at_heapsize = GC_WORD_MAX;
-
     if ((word)p <= (word)GC_least_plausible_heap_addr
         || GC_least_plausible_heap_addr == 0) {
         GC_least_plausible_heap_addr = (void *)((ptr_t)p - sizeof(word));
@@ -1485,16 +1475,6 @@ STATIC void GC_add_to_heap(struct hblk *p, size_t bytes)
 void * GC_least_plausible_heap_addr = (void *)GC_WORD_MAX;
 void * GC_greatest_plausible_heap_addr = 0;
 
-GC_INLINE word GC_max(word x, word y)
-{
-    return(x > y? x : y);
-}
-
-GC_INLINE word GC_min(word x, word y)
-{
-    return(x < y? x : y);
-}
-
 STATIC word GC_max_heapsize = 0;
 
 GC_API void GC_CALL GC_set_max_heap_size(GC_word n)
@@ -1510,6 +1490,7 @@ GC_INNER void GC_scratch_recycle_inner(void *ptr, size_t bytes)
   size_t displ = 0;
   size_t recycled_bytes;
 
+  GC_ASSERT(I_HOLD_LOCK());
   if (NULL == ptr) return;
 
   GC_ASSERT(bytes != 0);
@@ -1527,7 +1508,7 @@ GC_INNER void GC_scratch_recycle_inner(void *ptr, size_t bytes)
 
 /* This explicitly increases the size of the heap.  It is used          */
 /* internally, but may also be invoked from GC_expand_hp by the user.   */
-/* The argument is in units of HBLKSIZE (tiny values are rounded up).   */
+/* The argument is in units of HBLKSIZE (zero is treated as 1).         */
 /* Returns FALSE on failure.                                            */
 GC_INNER GC_bool GC_expand_hp_inner(word n)
 {
@@ -1538,23 +1519,24 @@ GC_INNER GC_bool GC_expand_hp_inner(word n)
 
     GC_ASSERT(I_HOLD_LOCK());
     GC_ASSERT(GC_page_size != 0);
-    if (n < MINHINCR) n = MINHINCR;
+    if (0 == n) n = 1;
     bytes = ROUNDUP_PAGESIZE((size_t)n * HBLKSIZE);
+    GC_DBGLOG_PRINT_HEAP_IN_USE();
     if (GC_max_heapsize != 0
         && (GC_max_heapsize < (word)bytes
             || GC_heapsize > GC_max_heapsize - (word)bytes)) {
         /* Exceeded self-imposed limit */
-        return(FALSE);
+        return FALSE;
     }
     space = GET_MEM(bytes);
     if (EXPECT(NULL == space, FALSE)) {
-        WARN("Failed to expand heap by %" WARN_PRIdPTR " bytes\n",
-             (word)bytes);
-        return(FALSE);
+        WARN("Failed to expand heap by %" WARN_PRIuPTR " KiB\n", bytes >> 10);
+        return FALSE;
     }
     GC_add_to_our_memory((ptr_t)space, bytes);
+    GC_last_heap_growth_gc_no = GC_gc_no;
     GC_INFOLOG_PRINTF("Grow heap to %lu KiB after %lu bytes allocated\n",
-                      TO_KiB_UL(GC_heapsize + (word)bytes),
+                      TO_KiB_UL(GC_heapsize + bytes),
                       (unsigned long)GC_bytes_allocd);
 
     /* Adjust heap limits generously for blacklisting to work better.   */
@@ -1566,48 +1548,47 @@ GC_INNER GC_bool GC_expand_hp_inner(word n)
             && (word)GC_last_heap_addr < (word)space)) {
         /* Assume the heap is growing up. */
         word new_limit = (word)space + (word)bytes + expansion_slop;
-        if (new_limit > (word)space) {
-          GC_greatest_plausible_heap_addr =
-            (void *)GC_max((word)GC_greatest_plausible_heap_addr,
-                           (word)new_limit);
-        }
+        if (new_limit > (word)space
+            && (word)GC_greatest_plausible_heap_addr < new_limit)
+          GC_greatest_plausible_heap_addr = (void *)new_limit;
     } else {
         /* Heap is growing down. */
         word new_limit = (word)space - expansion_slop;
-        if (new_limit < (word)space) {
-          GC_least_plausible_heap_addr =
-            (void *)GC_min((word)GC_least_plausible_heap_addr,
-                           (word)space - expansion_slop);
-        }
+        if (new_limit < (word)space
+            && (word)GC_least_plausible_heap_addr > new_limit)
+          GC_least_plausible_heap_addr = (void *)new_limit;
     }
     GC_last_heap_addr = (ptr_t)space;
 
     GC_add_to_heap(space, bytes);
-
-    /* Force GC before we are likely to allocate past expansion_slop.   */
-    GC_collect_at_heapsize =
-        GC_heapsize + expansion_slop - 2 * MAXHINCR * HBLKSIZE;
-    if (GC_collect_at_heapsize < GC_heapsize /* wrapped */)
-        GC_collect_at_heapsize = GC_WORD_MAX;
     if (GC_on_heap_resize)
         (*GC_on_heap_resize)(GC_heapsize);
 
-    return(TRUE);
+    return TRUE;
 }
 
 /* Really returns a bool, but it's externally visible, so that's clumsy. */
-/* Arguments is in bytes.  Includes GC_init() call.                      */
 GC_API int GC_CALL GC_expand_hp(size_t bytes)
 {
-    int result;
+    word n_blocks = OBJ_SZ_TO_BLOCKS_CHECKED(bytes);
+    word old_heapsize;
+    GC_bool result;
     DCL_LOCK_STATE;
 
     if (!EXPECT(GC_is_initialized, TRUE)) GC_init();
     LOCK();
-    result = (int)GC_expand_hp_inner(divHBLKSZ((word)bytes));
-    if (result) GC_requested_heapsize += bytes;
+    old_heapsize = GC_heapsize;
+    result = GC_expand_hp_inner(n_blocks);
+    if (result) {
+      GC_requested_heapsize += bytes;
+      if (GC_dont_gc) {
+        /* Do not call WARN if the heap growth is intentional.  */
+        GC_ASSERT(GC_heapsize >= old_heapsize);
+        GC_heapsize_on_gc_disable += GC_heapsize - old_heapsize;
+      }
+    }
     UNLOCK();
-    return(result);
+    return (int)result;
 }
 
 GC_INNER unsigned GC_fail_count = 0;
@@ -1650,6 +1631,7 @@ GC_INNER GC_bool GC_collect_or_expand(word needed_blocks,
     IF_CANCEL(int cancel_state;)
 
     GC_ASSERT(I_HOLD_LOCK());
+    GC_ASSERT(GC_is_initialized);
     DISABLE_CANCEL(cancel_state);
     if (!GC_incremental && !GC_dont_gc &&
         ((GC_dont_expand && GC_bytes_allocd > 0)
@@ -1670,7 +1652,7 @@ GC_INNER GC_bool GC_collect_or_expand(word needed_blocks,
         last_fo_entries = GC_fo_entries;
         last_bytes_finalized = GC_bytes_finalized;
         RESTORE_CANCEL(cancel_state);
-        return(TRUE);
+        return TRUE;
       }
     }
 
@@ -1696,8 +1678,24 @@ GC_INNER GC_bool GC_collect_or_expand(word needed_blocks,
       }
       if (blocks_to_get > divHBLKSZ(GC_WORD_MAX))
         blocks_to_get = divHBLKSZ(GC_WORD_MAX);
+    } else if (blocks_to_get < MINHINCR) {
+      blocks_to_get = MINHINCR;
+    }
+
+    if (GC_max_heapsize > GC_heapsize) {
+      word max_get_blocks = divHBLKSZ(GC_max_heapsize - GC_heapsize);
+      if (blocks_to_get > max_get_blocks)
+        blocks_to_get = max_get_blocks > needed_blocks
+                        ? max_get_blocks : needed_blocks;
     }
 
+#   ifdef USE_MUNMAP
+      if (GC_unmap_threshold > 1) {
+        /* Return as much memory to the OS as possible before   */
+        /* trying to get memory from it.                        */
+        GC_unmap_old(0);
+      }
+#   endif
     if (!GC_expand_hp_inner(blocks_to_get)
         && (blocks_to_get == needed_blocks
             || !GC_expand_hp_inner(needed_blocks))) {
@@ -1710,17 +1708,20 @@ GC_INNER GC_bool GC_collect_or_expand(word needed_blocks,
         GC_gcollect_inner();
       } else {
 #       if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC)
-          WARN("Out of Memory! Heap size: %" WARN_PRIdPTR " MiB."
+#         ifdef USE_MUNMAP
+            GC_ASSERT(GC_heapsize >= GC_unmapped_bytes);
+#         endif
+          WARN("Out of Memory! Heap size: %" WARN_PRIuPTR " MiB."
                " Returning NULL!\n", (GC_heapsize - GC_unmapped_bytes) >> 20);
 #       endif
         RESTORE_CANCEL(cancel_state);
-        return(FALSE);
+        return FALSE;
       }
     } else if (GC_fail_count) {
       GC_COND_LOG_PRINTF("Memory available again...\n");
     }
     RESTORE_CANCEL(cancel_state);
-    return(TRUE);
+    return TRUE;
 }
 
 /*
@@ -1735,9 +1736,10 @@ GC_INNER ptr_t GC_allocobj(size_t gran, int kind)
     GC_bool retry = FALSE;
 
     GC_ASSERT(I_HOLD_LOCK());
-    if (gran == 0) return(0);
+    GC_ASSERT(GC_is_initialized);
+    if (0 == gran) return NULL;
 
-    while (*flh == 0) {
+    while (NULL == *flh) {
       ENTER_GC();
 #     ifndef GC_DISABLE_INCREMENTAL
         if (GC_incremental && GC_time_limit != GC_TIME_UNLIMITED) {
@@ -1769,7 +1771,7 @@ GC_INNER ptr_t GC_allocobj(size_t gran, int kind)
           } else {
             if (!GC_collect_or_expand(1, FALSE, retry)) {
               EXIT_GC();
-              return(0);
+              return NULL;
             }
             retry = TRUE;
           }

+ 22 - 11
blitz.mod/bdwgc/backgraph.c

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -84,6 +84,7 @@ static back_edges *avail_back_edges = 0;
 
 static back_edges * new_back_edges(void)
 {
+  GC_ASSERT(I_HOLD_LOCK());
   if (0 == back_edge_space) {
     size_t bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(MAX_BACK_EDGE_STRUCTS
                                                    * sizeof(back_edges));
@@ -128,6 +129,7 @@ static size_t n_in_progress = 0;
 
 static void push_in_progress(ptr_t p)
 {
+  GC_ASSERT(I_HOLD_LOCK());
   if (n_in_progress >= in_progress_size) {
     ptr_t * new_in_progress_space;
 
@@ -164,7 +166,7 @@ static void push_in_progress(ptr_t p)
   in_progress_space[n_in_progress++] = p;
 }
 
-static GC_bool is_in_progress(ptr_t p)
+static GC_bool is_in_progress(const char *p)
 {
   size_t i;
   for (i = 0; i < n_in_progress; ++i) {
@@ -173,8 +175,11 @@ static GC_bool is_in_progress(ptr_t p)
   return FALSE;
 }
 
-GC_INLINE void pop_in_progress(ptr_t p GC_ATTR_UNUSED)
+GC_INLINE void pop_in_progress(ptr_t p)
 {
+# ifndef GC_ASSERTIONS
+    UNUSED_ARG(p);
+# endif
   --n_in_progress;
   GC_ASSERT(in_progress_space[n_in_progress] == p);
 }
@@ -281,7 +286,7 @@ static void add_edge(ptr_t p, ptr_t q)
 
 typedef void (*per_object_func)(ptr_t p, size_t n_bytes, word gc_descr);
 
-static void per_object_helper(struct hblk *h, word fn)
+static GC_CALLBACK void per_object_helper(struct hblk *h, GC_word fn)
 {
   hdr * hhdr = HDR(h);
   size_t sz = (size_t)hhdr->hb_sz;
@@ -300,9 +305,10 @@ GC_INLINE void GC_apply_to_each_object(per_object_func f)
   GC_apply_to_all_blocks(per_object_helper, (word)f);
 }
 
-static void reset_back_edge(ptr_t p, size_t n_bytes GC_ATTR_UNUSED,
-                            word gc_descr GC_ATTR_UNUSED)
+static void reset_back_edge(ptr_t p, size_t n_bytes, word gc_descr)
 {
+  UNUSED_ARG(n_bytes);
+  UNUSED_ARG(gc_descr);
   /* Skip any free list links, or dropped blocks */
   if (GC_HAS_DEBUG_INFO(p)) {
     ptr_t old_back_ptr = GET_OH_BG_PTR(p);
@@ -338,14 +344,17 @@ static void reset_back_edge(ptr_t p, size_t n_bytes GC_ATTR_UNUSED,
 
 static void add_back_edges(ptr_t p, size_t n_bytes, word gc_descr)
 {
-  word *currentp = (word *)(p + sizeof(oh));
+  ptr_t current_p = p + sizeof(oh);
 
   /* For now, fix up non-length descriptors conservatively.     */
     if((gc_descr & GC_DS_TAGS) != GC_DS_LENGTH) {
       gc_descr = n_bytes;
     }
-  while ((word)currentp < (word)(p + gc_descr)) {
-    word current = *currentp++;
+
+  for (; (word)current_p < (word)(p + gc_descr); current_p += sizeof(word)) {
+    word current;
+
+    LOAD_WORD_OR_CONTINUE(current, current_p);
     FIXUP_POINTER(current);
     if (current >= (word)GC_least_plausible_heap_addr &&
         current <= (word)GC_greatest_plausible_heap_addr) {
@@ -374,6 +383,7 @@ static word backwards_height(ptr_t p)
   ptr_t pred = GET_OH_BG_PTR(p);
   back_edges *be;
 
+  GC_ASSERT(I_HOLD_LOCK());
   if (NULL == pred)
     return 1;
   if (((word)pred & FLAG_MANY) == 0) {
@@ -447,9 +457,10 @@ STATIC ptr_t GC_deepest_obj = NULL;
 /* next GC.                                                             */
 /* Set GC_max_height to be the maximum height we encounter, and         */
 /* GC_deepest_obj to be the corresponding object.                       */
-static void update_max_height(ptr_t p, size_t n_bytes GC_ATTR_UNUSED,
-                              word gc_descr GC_ATTR_UNUSED)
+static void update_max_height(ptr_t p, size_t n_bytes, word gc_descr)
 {
+  UNUSED_ARG(n_bytes);
+  UNUSED_ARG(gc_descr);
   if (GC_is_marked(p) && GC_HAS_DEBUG_INFO(p)) {
     word p_height = 0;
     ptr_t p_deepest_obj = 0;

+ 24 - 19
blitz.mod/bdwgc/blacklst.c

@@ -6,7 +6,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -24,16 +24,10 @@
  * block, even though it does not start on the dangerous block.
  */
 
-/*
- * Externally callable routines are:
-
- * GC_add_to_black_list_normal
- * GC_add_to_black_list_stack
- * GC_promote_black_lists
- * GC_is_black_listed
- *
- * All require that the allocator lock is held.
- */
+/* Externally callable routines are:    */
+/* - GC_add_to_black_list_normal,       */
+/* - GC_add_to_black_list_stack,        */
+/* - GC_promote_black_lists.            */
 
 /* Pointers to individual tables.  We replace one table by another by   */
 /* switching these pointers.                                            */
@@ -91,6 +85,7 @@ GC_INNER void (*GC_print_heap_obj)(ptr_t p) = GC_default_print_heap_obj_proc;
 
 GC_INNER void GC_bl_init_no_interiors(void)
 {
+  GC_ASSERT(I_HOLD_LOCK());
   if (GC_incomplete_normal_bl == 0) {
     GC_old_normal_bl = (word *)GC_scratch_alloc(sizeof(page_hash_table));
     GC_incomplete_normal_bl = (word *)GC_scratch_alloc(
@@ -106,8 +101,9 @@ GC_INNER void GC_bl_init_no_interiors(void)
 
 GC_INNER void GC_bl_init(void)
 {
+    GC_ASSERT(I_HOLD_LOCK());
     if (!GC_all_interior_pointers) {
-      GC_bl_init_no_interiors();
+        GC_bl_init_no_interiors();
     }
     GC_ASSERT(NULL == GC_old_stack_bl && NULL == GC_incomplete_stack_bl);
     GC_old_stack_bl = (word *)GC_scratch_alloc(sizeof(page_hash_table));
@@ -139,6 +135,7 @@ GC_INNER void GC_promote_black_lists(void)
     word * very_old_normal_bl = GC_old_normal_bl;
     word * very_old_stack_bl = GC_old_stack_bl;
 
+    GC_ASSERT(I_HOLD_LOCK());
     GC_old_normal_bl = GC_incomplete_normal_bl;
     GC_old_stack_bl = GC_incomplete_stack_bl;
     if (!GC_all_interior_pointers) {
@@ -195,6 +192,9 @@ GC_INNER void GC_unpromote_black_lists(void)
   GC_INNER void GC_add_to_black_list_normal(word p)
 #endif
 {
+# ifndef PARALLEL_MARK
+    GC_ASSERT(I_HOLD_LOCK());
+# endif
   if (GC_modws_valid_offsets[p & (sizeof(word)-1)]) {
     word index = PHT_HASH((word)p);
 
@@ -219,6 +219,9 @@ GC_INNER void GC_unpromote_black_lists(void)
 {
   word index = PHT_HASH((word)p);
 
+# ifndef PARALLEL_MARK
+    GC_ASSERT(I_HOLD_LOCK());
+# endif
   if (HDR(p) == 0 || get_pht_entry_from_index(GC_old_stack_bl, index)) {
 #   ifdef PRINT_BLACK_LIST
       if (!get_pht_entry_from_index(GC_incomplete_stack_bl, index)) {
@@ -236,8 +239,10 @@ GC_INNER void GC_unpromote_black_lists(void)
  * that every smaller value of r after h is also black listed.)
  * If (h,len) is not black listed, return 0.
  * Knows about the structure of the black list hash tables.
+ * Assumes the allocation lock is held but no assertion about it by design.
  */
-struct hblk * GC_is_black_listed(struct hblk *h, word len)
+GC_API struct GC_hblk_s *GC_CALL GC_is_black_listed(struct GC_hblk_s *h,
+                                                    GC_word len)
 {
     word index = PHT_HASH((word)h);
     word i;
@@ -246,7 +251,7 @@ struct hblk * GC_is_black_listed(struct hblk *h, word len)
     if (!GC_all_interior_pointers
         && (get_pht_entry_from_index(GC_old_normal_bl, index)
             || get_pht_entry_from_index(GC_incomplete_normal_bl, index))) {
-      return (h+1);
+      return h + 1;
     }
 
     nblocks = divHBLKSZ(len);
@@ -258,14 +263,14 @@ struct hblk * GC_is_black_listed(struct hblk *h, word len)
         } else {
           if (get_pht_entry_from_index(GC_old_stack_bl, index)
               || get_pht_entry_from_index(GC_incomplete_stack_bl, index)) {
-            return(h+i+1);
+            return h + (i+1);
           }
           i++;
         }
         if (i >= nblocks) break;
-        index = PHT_HASH((word)(h+i));
+        index = PHT_HASH((word)(h + i));
     }
-    return(0);
+    return NULL;
 }
 
 /* Return the number of blacklisted blocks in a given range.    */
@@ -282,7 +287,7 @@ STATIC word GC_number_stack_black_listed(struct hblk *start,
 
         if (get_pht_entry_from_index(GC_old_stack_bl, index)) result++;
     }
-    return(result);
+    return result;
 }
 
 /* Return the total number of (stack) black-listed bytes. */
@@ -297,5 +302,5 @@ static word total_stack_black_listed(void)
 
         total += GC_number_stack_black_listed(start, endp1);
     }
-    return(total * HBLKSIZE);
+    return total * HBLKSIZE;
 }

+ 0 - 11
blitz.mod/bdwgc/build/s60v3/bld.inf

@@ -1,11 +0,0 @@
-/*
- Name : bld.inf
- Description : This file provides the information required for building the
- whole of a libgc.
-*/
-
-PRJ_PLATFORMS
-default armv5
-
-PRJ_MMPFILES
-libgc.mmp

+ 0 - 78
blitz.mod/bdwgc/build/s60v3/libgc.mmp

@@ -1,78 +0,0 @@
-TARGET     libgc.dll
-
-TARGETTYPE        dll
-UID       0x1000008d 0x200107C2 // check uid
-
-EXPORTUNFROZEN
-EPOCALLOWDLLDATA
-//ALWAYS_BUILD_AS_ARM
-//nocompresstarget
-//srcdbg
-//baseaddress   00500000
-//LINKEROPTION CW -map libgc.map
-//LINKEROPTION CW -filealign 0x10000
-
-CAPABILITY PowerMgmt ReadDeviceData ReadUserData WriteDeviceData WriteUserData SwEvent LocalServices NetworkServices UserEnvironment
-
-
-MACRO ALL_INTERIOR_POINTERS
-MACRO NO_EXECUTE_PERMISSION
-MACRO USE_MMAP
-MACRO GC_ATOMIC_UNCOLLECTABLE
-MACRO GC_DONT_REGISTER_MAIN_STATIC_DATA
-MACRO GC_DLL
-MACRO JAVA_FINALIZATION
-MACRO SYMBIAN
-MACRO ENABLE_DISCLAIM
-//MACRO GC_GCJ_SUPPORT
-
-USERINCLUDE      ..\..\include
-USERINCLUDE      ..\..\include\private
-
-SYSTEMINCLUDE   \epoc32\include
-SYSTEMINCLUDE   \epoc32\include\stdapis
-
-SOURCEPATH        ..\..\
-
-SOURCE          allchblk.c
-SOURCE          alloc.c
-SOURCE          blacklst.c
-SOURCE          dbg_mlc.c
-SOURCE          dyn_load.c
-SOURCE          finalize.c
-SOURCE          fnlz_mlc.c
-//SOURCE        gc_badalc.cpp
-//SOURCE        gc_cpp.cpp
-SOURCE          gcj_mlc.c
-SOURCE          headers.c
-SOURCE          mach_dep.c
-SOURCE          malloc.c
-SOURCE          mallocx.c
-SOURCE          mark.c
-SOURCE          mark_rts.c
-SOURCE          misc.c
-SOURCE          new_hblk.c
-SOURCE          obj_map.c
-SOURCE          os_dep.c
-SOURCE          extra/symbian.cpp
-SOURCE          ptr_chck.c
-SOURCE          reclaim.c
-SOURCE          typd_mlc.c
-
-/*
-#ifdef ENABLE_ABIV2_MODE
-  DEBUGGABLE_UDEBONLY
-#endif
-*/
-
-// Using main() as entry point
-STATICLIBRARY   libcrt0.lib
-
-// libc and euser are always needed when using main() entry point
-LIBRARY         libc.lib
-
-
-LIBRARY euser.lib
-LIBRARY efsrv.lib
-LIBRARY avkon.lib
-LIBRARY eikcore.lib

+ 5 - 4
blitz.mod/bdwgc/checksums.c

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -67,7 +67,7 @@ STATIC word GC_checksum(struct hblk *h)
     while ((word)p < (word)lim) {
         result += *p++;
     }
-    return(result | 0x80000000 /* doesn't look like pointer */);
+    return result | 0x80000000; /* does not look like pointer */
 }
 
 int GC_n_dirty_errors = 0;
@@ -114,10 +114,11 @@ STATIC void GC_update_check_page(struct hblk *h, int index)
 
 word GC_bytes_in_used_blocks = 0;
 
-STATIC void GC_add_block(struct hblk *h, word dummy GC_ATTR_UNUSED)
+STATIC void GC_CALLBACK GC_add_block(struct hblk *h, GC_word dummy)
 {
    hdr * hhdr = HDR(h);
 
+   UNUSED_ARG(dummy);
    GC_bytes_in_used_blocks += (hhdr->hb_sz + HBLKSIZE-1) & ~(HBLKSIZE-1);
 }
 
@@ -126,7 +127,7 @@ STATIC void GC_check_blocks(void)
     word bytes_in_free_blocks = GC_large_free_bytes;
 
     GC_bytes_in_used_blocks = 0;
-    GC_apply_to_all_blocks(GC_add_block, (word)0);
+    GC_apply_to_all_blocks(GC_add_block, 0);
     GC_COND_LOG_PRINTF("GC_bytes_in_used_blocks= %lu,"
                        " bytes_in_free_blocks= %lu, heapsize= %lu\n",
                        (unsigned long)GC_bytes_in_used_blocks,

+ 147 - 81
blitz.mod/bdwgc/configure.ac

@@ -1,12 +1,12 @@
 # Copyright (c) 1999-2001 by Red Hat, Inc. All rights reserved.
 # Copyright (c) 2005-2009 Hewlett-Packard Development Company, L.P.
-# Copyright (c) 2009-2021 Ivan Maidanski
+# Copyright (c) 2009-2022 Ivan Maidanski
 #
 # THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
 # OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 #
 # Permission is hereby granted to use or copy this program
-# for any purpose,  provided the above notices are retained on all copies.
+# for any purpose, provided the above notices are retained on all copies.
 # Permission to modify the code and to distribute modified code is granted,
 # provided the above notices are retained, and a notice that the code was
 # modified is included with the above copyright notice.
@@ -36,8 +36,8 @@ AC_PROG_INSTALL
 LT_INIT([disable-static])
 # Only the shared libraries are produced by default, use "--enable-static"
 # option to override it.
-dnl Note: If Autoconf reports that LIBTOOL (or AC_ENABLE_SHARED, or
-dnl AC_PROG_LIBTOOL) is undefined, Libtool installation should be checked.
+dnl Note: If Autoconf reports that LIBTOOL (or AC_ENABLE_SHARED) is
+dnl undefined, Libtool installation should be checked.
 
 # Special CFLAGS to use when building
 gc_cflags=""
@@ -86,17 +86,23 @@ esac
 
 AC_MSG_CHECKING([for emscripten])
 AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
-#ifdef __EMSCRIPTEN__
-#error "this is emscripten"
-#endif
-]])], [emscripten=no], [emscripten=yes])
-# Note -s ASYNCIFY is required to scan the stack, ASYNCIFY_STACK_SIZE is
-# probably needed for gctest only.
-AS_IF([test "x$emscripten" = "xyes"],
-      [gc_cflags="${gc_cflags} -s ASYNCIFY -s ASYNCIFY_STACK_SIZE=128000"])
+#   ifndef __EMSCRIPTEN__
+#     error This is not Emscripten
+#   endif
+  ]])], [emscripten=yes], [emscripten=no])
 AM_CONDITIONAL(EMSCRIPTEN, test x$emscripten = xyes)
 AC_MSG_RESULT([$emscripten])
 
+AC_ARG_ENABLE(emscripten-asyncify,
+    [AS_HELP_STRING([--enable-emscripten-asyncify],
+                    [use Emscripten asyncify feature])])
+# Use this option if your program is targeting -sASYNCIFY.  The latter is
+# required to scan the stack, ASYNCIFY_STACK_SIZE is probably needed for
+# gctest only.
+AS_IF([test "${emscripten}" = yes -a "${enable_emscripten_asyncify}" = yes],
+      [gc_cflags="${gc_cflags} -DEMSCRIPTEN_ASYNCIFY"
+       gc_cflags="${gc_cflags} -sASYNCIFY -sASYNCIFY_STACK_SIZE=128000"])
+
 GC_CFLAGS=${gc_cflags}
 AC_SUBST(GC_CFLAGS)
 
@@ -164,8 +170,7 @@ AH_TEMPLATE([USE_COMPILER_TLS],
             [Define to use of compiler-support for thread-local variables.])
 
 dnl Thread selection macros.
-AH_TEMPLATE([GC_THREADS],           [Define to support platform-specific
-                                     threads.])
+AH_TEMPLATE([GC_THREADS], [Define to support platform-specific threads.])
 AH_TEMPLATE([GC_WIN32_PTHREADS],
                 [Define to support pthreads-win32 or winpthreads.])
 
@@ -174,8 +179,6 @@ AH_TEMPLATE([_POSIX_C_SOURCE], [The POSIX feature macro.])
 AH_TEMPLATE([_PTHREADS], [Indicates the use of pthreads (NetBSD).])
 
 dnl Win32-specific API usage controls.
-AH_TEMPLATE([GC_UNDERSCORE_STDCALL],
-        [Explicitly prefix exported/imported WINAPI symbols with '_'.])
 AH_TEMPLATE([UNICODE],
         [Use Unicode (W) variant of Win32 API instead of ASCII (A) one.])
 
@@ -191,6 +194,8 @@ CFLAGS="$old_CFLAGS"
 
 THREADDLLIBS=
 need_atomic_ops_asm=false
+need_lib_rt=false
+compile_asm=false
 use_parallel_mark=no
 use_thread_local_alloc=no
 # Libraries needed to support dynamic loading and/or threads.
@@ -221,8 +226,9 @@ case "$THREADS" in
       *-*-hpux11*)
         AC_MSG_WARN("Only HP/UX 11 POSIX threads are supported.")
         AC_DEFINE(_POSIX_C_SOURCE,199506L)
-        THREADDLLIBS="-lpthread -lrt"
+        THREADDLLIBS="-lpthread"
         # HPUX needs REENTRANT for the _r calls.
+        need_lib_rt=true
         ;;
       *-*-openbsd*)
         AM_CFLAGS="$AM_CFLAGS -pthread"
@@ -241,10 +247,12 @@ case "$THREADS" in
       *-*-netbsd*)
         AC_MSG_WARN("Only on NetBSD 2.0 or later.")
         AC_DEFINE(_PTHREADS)
-        THREADDLLIBS="-lpthread -lrt"
+        THREADDLLIBS="-lpthread"
+        need_lib_rt=true
         ;;
       *-*-solaris*)
-        THREADDLLIBS="-lpthread -lrt"
+        THREADDLLIBS="-lpthread"
+        need_lib_rt=true
         ;;
       *-*-cygwin* | *-*-msys*)
         # Cygwin doesn't have a real libpthread, so Libtool can't link
@@ -265,7 +273,8 @@ case "$THREADS" in
         ;;
       *-*-osf*)
         AM_CFLAGS="$AM_CFLAGS -pthread"
-        THREADDLLIBS="-lpthread -lrt"
+        THREADDLLIBS="-lpthread"
+        need_lib_rt=true
         ;;
       *)
         AS_IF([test x$default_threadlibs != xtrue],
@@ -328,7 +337,22 @@ case "$THREADS" in
     AC_MSG_ERROR($THREADS is an unknown thread package)
     ;;
 esac
+
+# Check whether -lrt linker option is needed to use clock_gettime.
+if test "x$need_lib_rt" != xtrue; then
+  AC_MSG_CHECKING(for clock_gettime without additional libraries)
+  AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <time.h>],
+                    [struct timespec t; clock_gettime(CLOCK_REALTIME, &t)])],
+    [AC_MSG_RESULT(yes)],
+    [AC_MSG_RESULT(no)
+     AC_CHECK_LIB(rt, clock_gettime, [need_lib_rt=true])])
+fi
+
+if test "x$need_lib_rt" = xtrue; then
+  THREADDLLIBS="$THREADDLLIBS -lrt"
+fi
 AC_SUBST(THREADDLLIBS)
+
 AM_CONDITIONAL(THREADS, test x$THREADS != xnone)
 AM_CONDITIONAL(PTHREADS, test x$THREADS = xposix)
 AM_CONDITIONAL(DARWIN_THREADS, test x$darwin_threads = xtrue)
@@ -366,15 +390,15 @@ if test "$GCC" = yes; then
   AC_MSG_CHECKING([whether compiler supports -Wextra])
   old_CFLAGS="$CFLAGS"
   CFLAGS="-Wextra $CFLAGS"
-  AC_TRY_COMPILE([],[], [ac_cv_cc_wextra=yes], [ac_cv_cc_wextra=no])
+  AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],
+                    [ac_cv_cc_wextra=yes], [ac_cv_cc_wextra=no])
   CFLAGS="$old_CFLAGS"
   AC_MSG_RESULT($ac_cv_cc_wextra)
   AS_IF([test "$ac_cv_cc_wextra" = yes], [WEXTRA="-Wextra"], [WEXTRA="-W"])
   AC_MSG_CHECKING([whether compiler supports -Wpedantic])
   CFLAGS="-Wpedantic -Wno-long-long $CFLAGS"
-  AC_TRY_COMPILE([],[
-    extern int quiet;
-  ], [ac_cv_cc_pedantic=yes], [ac_cv_cc_pedantic=no])
+  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[extern int quiet;]])],
+                    [ac_cv_cc_pedantic=yes], [ac_cv_cc_pedantic=no])
   CFLAGS="$old_CFLAGS"
   AC_MSG_RESULT($ac_cv_cc_pedantic)
   WPEDANTIC=
@@ -385,15 +409,17 @@ if test "$GCC" = yes; then
 fi
 
 AC_MSG_CHECKING(for xlc)
-AC_TRY_COMPILE([],[
- #ifndef __xlC__
- # error
- #endif
-], [compiler_xlc=yes], [compiler_xlc=no])
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#   ifndef __xlC__
+#     error
+#   endif
+  ]])], [compiler_xlc=yes], [compiler_xlc=no])
 AC_MSG_RESULT($compiler_xlc)
 if test $compiler_xlc = yes -a "$powerpc_darwin" = true; then
-  # the darwin stack-frame-walking code is completely broken on xlc
-  AC_DEFINE([DARWIN_DONT_PARSE_STACK], 1, [See doc/README.macros.])
+  # The darwin stack-frame-walking code is completely broken on xlc.
+  AC_DEFINE([DARWIN_DONT_PARSE_STACK], 1,
+            [Define to discover thread stack bounds on Darwin without trying
+             to walk the frames on the stack.])
 fi
 
 # XLC neither requires nor tolerates the unnecessary assembler goop.
@@ -417,10 +443,11 @@ if test "$GCC" = yes; then
   if test "$ac_cv_fno_strict_aliasing" != skipped; then
     old_CFLAGS="$CFLAGS"
     CFLAGS="$CFLAGS -fno-strict-aliasing"
-    AC_TRY_COMPILE([],[], [ac_cv_fno_strict_aliasing=yes], [])
+    AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],
+                      [ac_cv_fno_strict_aliasing=yes])
     CFLAGS="$old_CFLAGS"
     AS_IF([test "$ac_cv_fno_strict_aliasing" = yes],
-          [CFLAGS="$CFLAGS -fno-strict-aliasing"], [])
+          [CFLAGS="$CFLAGS -fno-strict-aliasing"])
   fi
   AC_MSG_RESULT($ac_cv_fno_strict_aliasing)
 fi
@@ -549,8 +576,8 @@ if test "${enable_shared}" != no -a "${enable_static}" != yes; then
       AC_MSG_CHECKING([whether compiler supports -fvisibility])
       old_CFLAGS="$CFLAGS"
       CFLAGS="-Werror -fvisibility=hidden $CFLAGS"
-      AC_TRY_COMPILE([],[], [ac_cv_fvisibility_hidden=yes],
-                     [ac_cv_fvisibility_hidden=no])
+      AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])],
+                [ac_cv_fvisibility_hidden=yes], [ac_cv_fvisibility_hidden=no])
       CFLAGS="$old_CFLAGS"
       AS_IF([test "$ac_cv_fvisibility_hidden" = yes],
             [CFLAGS="-DGC_VISIBILITY_HIDDEN_SET -fvisibility=hidden $CFLAGS"],
@@ -564,7 +591,7 @@ else
       # Do not require the clients to link with "user32" system library.
       AC_DEFINE([DONT_USE_USER32_DLL], 1,
                 [Do not use user32.dll import library (Win32).])
-      # Use inline version of GC new and delete operators in test_cpp
+      # Use inline version of GC new and delete operators in cpptest
       # otherwise the system ones might be used instead because of arbitrary
       # ordering of object files when linking.
       CXXFLAGS="$CXXFLAGS -DGC_NOT_DLL"
@@ -590,17 +617,21 @@ case "$host" in
     ;;
  sparc-*-netbsd*)
     machdep="sparc_netbsd_mach_dep.lo"
+    compile_asm=true
     ;;
  sparc*-*-linux* | sparc*-*-openbsd* | sparc64-*-freebsd* | sparc64-*-netbsd*)
     machdep="sparc_mach_dep.lo"
+    compile_asm=true
     ;;
  sparc-sun-solaris2.3)
     machdep="sparc_mach_dep.lo"
+    compile_asm=true
     AC_DEFINE(SUNOS53_SHARED_LIB, 1,
               [Define to work around a Solaris 5.3 bug (see dyn_load.c).])
     ;;
  sparc*-sun-solaris2*)
     machdep="sparc_mach_dep.lo"
+    compile_asm=true
     ;;
  ia64-*-*)
     machdep="ia64_save_regs_in_stack.lo"
@@ -611,7 +642,18 @@ addobjs="$addobjs $machdep"
 AC_SUBST(addobjs)
 AC_SUBST(addlibs)
 
-AC_PROG_LIBTOOL
+# Suppress "extension used" clang warning (when compiling .S files).
+if test x$compile_asm = xtrue -a "$GCC" = yes; then
+  AC_MSG_CHECKING([whether compiler supports -Wno-language-extension-token])
+  old_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -Werror -Wno-language-extension-token"
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])],
+                    [ac_cv_lang_ext_token=yes], [ac_cv_lang_ext_token=no])
+  CFLAGS="$old_CFLAGS"
+  AS_IF([test "$ac_cv_lang_ext_token" = yes],
+        [CFLAGS="$CFLAGS -Wno-language-extension-token"])
+  AC_MSG_RESULT($ac_cv_lang_ext_token)
+fi
 
 dnl We use these options to decide which functions to include.
 AC_ARG_WITH(target-subdir,
@@ -684,7 +726,7 @@ if test x"$enable_gcj_support" != xno; then
         ;;
       *)
         AC_DEFINE([GC_ENABLE_SUSPEND_THREAD], 1,
-              [Define to turn on GC_suspend_thread support.])
+              [Define to turn on GC_suspend_thread support (Linux only).])
         ;;
     esac
 fi
@@ -705,7 +747,10 @@ dnl ---------
 
 AH_TEMPLATE([GC_HAVE_BUILTIN_BACKTRACE],
             [Define if backtrace information is supported.])
-AH_TEMPLATE([MAKE_BACK_GRAPH], [See doc/README.macros.])
+AH_TEMPLATE([MAKE_BACK_GRAPH],
+            [Define to build the collector with the support of the
+             functionality to print max length of chain through unreachable
+             objects ending in a reachable one.])
 AH_TEMPLATE([SAVE_CALL_COUNT],
             [The number of caller frames saved when allocating with the
              debugging API.])
@@ -722,7 +767,7 @@ AC_ARG_ENABLE(gc-debug,
               [Define to force debug headers on all objects.])
     AH_TEMPLATE([SHORT_DBG_HDRS],
                 [Shorten the headers to minimize object size at the expense
-                 of checking for writes past the end (see doc/README.macros).])
+                 of checking for writes past the end.])
 
     case $host in
       ia64-*-linux* )
@@ -754,9 +799,9 @@ AC_MSG_CHECKING([whether -Wno-frame-address works])
 use_wno_error_frame_address=no
 old_CFLAGS="$CFLAGS"
 CFLAGS="$CFLAGS -Werror -Wno-frame-address $CFLAGS_EXTRA"
-AC_TRY_COMPILE([], [{
-    if (!__builtin_return_address(1)) return 1;
-}], [ use_wno_error_frame_address=yes ])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
+    [if (!__builtin_return_address(1)) return 1;])],
+  [use_wno_error_frame_address=yes])
 CFLAGS="$old_CFLAGS"
 AC_MSG_RESULT($use_wno_error_frame_address)
 if test x"$use_wno_error_frame_address" = xyes; then
@@ -768,12 +813,13 @@ AC_MSG_CHECKING(for dladdr)
 have_dladdr=no
 old_CFLAGS="$CFLAGS"
 CFLAGS="$CFLAGS $CFLAGS_EXTRA"
-AC_TRY_COMPILE([
-#define _GNU_SOURCE 1
-#include <dlfcn.h>], [{
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+#   define _GNU_SOURCE 1
+#   include <dlfcn.h>
+  ], [
     Dl_info info;
     (void)dladdr("", &info);
-}], [ have_dladdr=yes ])
+  ])], [have_dladdr=yes])
 CFLAGS="$old_CFLAGS"
 AC_MSG_RESULT($have_dladdr)
 if test x"$have_dladdr" = xyes; then
@@ -784,37 +830,49 @@ fi
 AC_MSG_CHECKING(for sigsetjmp)
 old_CFLAGS="$CFLAGS"
 CFLAGS="$CFLAGS $CFLAGS_EXTRA"
-AC_TRY_LINK([#include <setjmp.h>],
-            [sigjmp_buf t; sigsetjmp(t, 0)],
+AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <setjmp.h>],
+                                [sigjmp_buf t; sigsetjmp(t, 0)])],
   [AC_MSG_RESULT(yes)],
   [AC_MSG_RESULT(no)
    AC_DEFINE([GC_NO_SIGSETJMP], [1], [Missing sigsetjmp function.])])
 CFLAGS="$old_CFLAGS"
 
+# Build with GC_wcsdup() support if possible.
+AC_MSG_CHECKING(for wcslen)
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS $CFLAGS_EXTRA"
+AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <wchar.h>],
+                                [wchar_t ws[] = {0}; (void)wcslen(&ws)])],
+  [AC_MSG_RESULT(yes)
+   AC_DEFINE([GC_REQUIRE_WCSDUP], [1],
+             [Define and export GC_wcsdup function.])],
+  [AC_MSG_RESULT(no)])
+CFLAGS="$old_CFLAGS"
+
 # pthread_setname_np, if available, may have 1, 2 or 3 arguments.
 AS_IF([test "$THREADS" = posix],
   [AC_MSG_CHECKING(for pthread_setname_np)
    old_CFLAGS="$CFLAGS"
    CFLAGS="$CFLAGS $CFLAGS_EXTRA -Werror"
-   AC_TRY_COMPILE([#include <pthread.h>],
-                  [pthread_setname_np("thread-name")],
+   AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+#         define _GNU_SOURCE 1
+#         include <pthread.h>
+        ], [pthread_setname_np("thread-name")])],
      [AC_MSG_RESULT([yes (w/o tid)])
       AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID], [1],
                 [Define to use 'pthread_setname_np(const char*)' function.])],
-     [AC_TRY_COMPILE([#include <pthread.h>],
-                     [pthread_setname_np(pthread_self(), "thread-name-%u", 0)],
+     [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+#         define _GNU_SOURCE 1
+#         include <pthread.h>
+        ], [pthread_setname_np(pthread_self(), "thread-name-%u", 0)])],
        [AC_MSG_RESULT([yes (with tid and arg)])
         AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG], [1],
          [Define to use 'pthread_setname_np(pthread_t, const char*, void *)'
           function.])],
-       [AC_TRY_COMPILE([
-#ifdef __CYGWIN__
-#define _GNU_SOURCE 1
-#elif defined(__linux__) || defined(__GLIBC__) || defined(__GNU__)
-#define _GNU_SOURCE 1
-#endif
-#include <pthread.h>],
-         [pthread_setname_np(pthread_self(), "thread-name")],
+       [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+#             define _GNU_SOURCE 1
+#             include <pthread.h>
+            ], [pthread_setname_np(pthread_self(), "thread-name")])],
          [AC_MSG_RESULT([yes (with tid)])
           AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_WITH_TID], [1],
                     [Define to use 'pthread_setname_np(pthread_t, const char*)'
@@ -844,7 +902,10 @@ AC_ARG_ENABLE(java-finalization,
     [AS_HELP_STRING([--disable-java-finalization],
                     [disable support for java finalization])])
 if test x"$enable_java_finalization" != xno; then
-    AC_DEFINE([JAVA_FINALIZATION], 1, [See doc/README.macros.])
+    AC_DEFINE([JAVA_FINALIZATION], 1,
+              [Define to make it somewhat safer by default to finalize objects
+               out of order by specifying a nonstandard finalization mark
+               procedure.])
 fi
 
 AC_ARG_ENABLE(atomic-uncollectable,
@@ -870,7 +931,10 @@ if test "${enable_redirect_malloc}" = yes; then
     else
         AC_DEFINE(REDIRECT_MALLOC, GC_malloc)
     fi
-    AC_DEFINE([GC_USE_DLOPEN_WRAP], 1, [See doc/README.macros.])
+    AC_DEFINE([GC_USE_DLOPEN_WRAP], 1,
+              [Define to cause the collector to redefine malloc and
+               intercepted pthread routines with their real names while using
+               dlsym to refer to the orignal routines.])
 fi
 
 AC_ARG_ENABLE(disclaim,
@@ -922,8 +986,8 @@ AC_ARG_ENABLE(mmap,
 
 AC_ARG_ENABLE(munmap,
     [AS_HELP_STRING([--enable-munmap=N],
-                    [return page to the OS if empty for N collections
-                     (default: 6)])],
+                    [return page to the OS if page is marked as
+                     empty during N collections (default: 7)])],
     MUNMAP_THRESHOLD=$enableval)
 if test x$enable_munmap != xno; then
     AC_DEFINE([USE_MMAP], 1,
@@ -932,13 +996,13 @@ if test x$enable_munmap != xno; then
                   [Define to use Win32 VirtualAlloc (instead of sbrk or
                    mmap) to expand the heap.])
     AC_DEFINE([USE_MUNMAP], 1,
-              [Define to return memory to OS with munmap calls
-               (see doc/README.macros).])
+              [Define to return memory to OS with munmap calls.])
     if test x$MUNMAP_THRESHOLD = x -o x$MUNMAP_THRESHOLD = xyes; then
-      MUNMAP_THRESHOLD=6
+      MUNMAP_THRESHOLD=7
     fi
     AC_DEFINE_UNQUOTED([MUNMAP_THRESHOLD], [${MUNMAP_THRESHOLD}],
-        [Number of GC cycles to wait before unmapping an unused block.])
+        [Number of sequential garbage collections during those a candidate
+         block for unmapping should be marked as free.])
 else
     if test "${gc_use_mmap}" = "yes"; then
       AC_DEFINE([USE_MMAP], 1,
@@ -1009,7 +1073,7 @@ AC_ARG_ENABLE(gcov,
 if test "$enable_gcov" = "yes"; then
   CFLAGS="-D NTHREADS=20 $CFLAGS --coverage"
   if test "${enable_shared}" = no; then
-    # FIXME: As of g++-4.8.4/x86_64, in case of shared library build, test_cpp
+    # FIXME: As of g++-4.8.4/x64, in case of shared library build, cpptest
     # linkage fails with "hidden symbol atexit is referenced by DSO" message.
     CXXFLAGS="$CXXFLAGS --coverage"
   fi
@@ -1032,7 +1096,7 @@ AM_CONDITIONAL(ENABLE_SHARED, test x$enable_shared = xyes)
 # found.
 AC_ARG_WITH([libatomic-ops],
     [AS_HELP_STRING([--with-libatomic-ops[=yes|no|check|none]],
-                    [Use an external libatomic_ops? (default: check;
+                    [use an external libatomic_ops? (default: check;
                      none: use compiler intrinsics or no thread support)])],
     [], [ AS_IF([test x"$THREADS" != xnone],
                 [with_libatomic_ops=check], [with_libatomic_ops=none]) ])
@@ -1042,8 +1106,8 @@ if test x"$with_libatomic_ops" = xcheck; then
   AC_MSG_CHECKING(for compiler intrinsics support)
   old_CFLAGS="$CFLAGS"
   CFLAGS="$CFLAGS $CFLAGS_EXTRA -DGC_BUILTIN_ATOMIC"
-  CFLAGS="$CFLAGS -I${srcdir}/include -I${srcdir}/tests"
-  AC_TRY_RUN([#include "test_atomic_ops.c"],
+  CFLAGS="$CFLAGS -I${srcdir}/include -I${srcdir}"
+  AC_RUN_IFELSE([AC_LANG_SOURCE([[#include "tests/atomicops.c"]])],
     [AC_MSG_RESULT(yes)
      with_libatomic_ops=none],
     [AC_MSG_RESULT(no)], [AC_MSG_RESULT(skipped because cross-compiling)])
@@ -1113,18 +1177,18 @@ AS_IF([test x$with_libatomic_ops != xnone -a x$need_atomic_ops_asm != xtrue],
     [ old_CFLAGS="$CFLAGS"
       CFLAGS="$CFLAGS $AO_TRYLINK_CFLAGS $CFLAGS_EXTRA"
       AC_MSG_CHECKING([for lock-free AO_or primitive])
-      AC_TRY_LINK([#include "atomic_ops.h"],
-                  [AO_t x=0;AO_or(&x,1)],
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([#include "atomic_ops.h"],
+                                      [AO_t x=0; AO_or(&x,1)])],
         [ AC_MSG_RESULT(yes)
           AC_DEFINE([HAVE_LOCKFREE_AO_OR], [1],
             [libatomic_ops AO_or primitive implementation is lock-free.]) ],
         [ AC_MSG_RESULT(no) ])
       AC_MSG_CHECKING([for lock-free AO load/store, test-and-set primitives])
-      AC_TRY_LINK([#include "atomic_ops.h"],
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([#include "atomic_ops.h"],
  [AO_t x=0;unsigned char c=0;AO_TS_t z=AO_TS_INITIALIZER;
   (void)AO_test_and_set_acquire(&z);AO_CLEAR(&z);AO_compiler_barrier();
   AO_store(&x,AO_load(&x)+1);AO_char_store(&c,AO_char_load(&c)+1);
-  AO_store_release(&x,AO_load_acquire(&x)+1)],
+  AO_store_release(&x,AO_load_acquire(&x)+1)])],
         [ AC_MSG_RESULT(yes) ],
         [ AC_MSG_RESULT(no)
           use_thread_local_alloc=no
@@ -1134,10 +1198,12 @@ AS_IF([test x$with_libatomic_ops != xnone -a x$need_atomic_ops_asm != xtrue],
       AS_IF([test x$use_parallel_mark != xno],
         [ AC_MSG_CHECKING(
                 [for lock-free compare-and-swap and fetch-and-add primitives])
-          AC_TRY_LINK(
- [#define AO_REQUIRE_CAS
-  #include "atomic_ops.h"],
- [AO_t x=0;(void)AO_fetch_and_add(&x,1);(void)AO_compare_and_swap(&x,1,2)],
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+            [
+#             define AO_REQUIRE_CAS
+#             include "atomic_ops.h"
+            ],
+ [AO_t x=0;(void)AO_fetch_and_add(&x,1);(void)AO_compare_and_swap(&x,1,2)])],
                     [ AC_MSG_RESULT(yes) ],
                     [ AC_MSG_RESULT(no)
                       use_parallel_mark=no ]) ])

+ 1 - 1
blitz.mod/bdwgc/cord/cord.am

@@ -3,7 +3,7 @@
 # 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).
-LIBCORD_VER_INFO = 5:0:4
+LIBCORD_VER_INFO = 6:0:5
 
 lib_LTLIBRARIES += libcord.la
 

+ 153 - 167
blitz.mod/bdwgc/cord/cordbscs.c

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -41,44 +41,34 @@ oom_fn CORD_oom_fn = (oom_fn) 0;
                           ABORT("Out of memory"); }
 # define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); }
 
-typedef unsigned long word;
-
     struct Concatenation {
-        char null;
-        char header;
-        char depth;     /* concatenation nesting depth. */
-        unsigned char left_len;
-                        /* Length of left child if it is sufficiently   */
-                        /* short; 0 otherwise.                          */
-#           define MAX_LEFT_LEN 255
-        word len;
         CORD left;      /* length(left) > 0     */
         CORD right;     /* length(right) > 0    */
     };
 
     struct Function {
-        char null;
-        char header;
-        char depth;     /* always 0     */
-        char left_len;  /* always 0     */
-        word len;
         CORD_fn fn;
         void * client_data;
     };
 
     struct Generic {
-        char null;
+        char nul;
         char header;
-        char depth;
-        char left_len;
-        word len;
+        char depth;     /* Concatenation nesting depth; 0 for function. */
+        unsigned char left_len;
+                        /* Length of left concatenated child if it is   */
+                        /* sufficiently short; 0 otherwise.             */
+        unsigned long len;
     };
 
-typedef union {
-    struct Concatenation concatenation;
+union ConcatOrFunc {
+    struct Concatenation concat;
     struct Function function;
-    struct Generic generic;
-    char string[1];
+};
+
+typedef struct {
+  struct Generic generic;
+  union ConcatOrFunc data;
 } CordRep;
 
 # define CONCAT_HDR 1
@@ -101,16 +91,18 @@ typedef union {
 #define DEPTH(s) (((CordRep *)s) -> generic.depth)
 #define GEN_LEN(s) (CORD_IS_STRING(s) ? strlen(s) : LEN(s))
 
-#define LEFT_LEN(c) ((c) -> left_len != 0? \
-                                (c) -> left_len \
-                                : (CORD_IS_STRING((c) -> left) ? \
-                                        (c) -> len - GEN_LEN((c) -> right) \
-                                        : LEN((c) -> left)))
+#define MAX_LEFT_LEN 255
+
+#define LEFT_LEN(s) (((CordRep *)s) -> generic.left_len != 0 ? \
+                ((CordRep *)s) -> generic.left_len \
+                : (CORD_IS_STRING(((CordRep *)s) -> data.concat.left) ? \
+                        ((CordRep *)s) -> generic.len - \
+                            GEN_LEN(((CordRep *)s) -> data.concat.right) \
+                        : LEN(((CordRep *)s) -> data.concat.left)))
 
 #define SHORT_LIMIT (sizeof(CordRep) - 1)
         /* Cords shorter than this are C strings */
 
-
 /* Dump the internal representation of x to stdout, with initial        */
 /* indentation level n.                                                 */
 void CORD_dump_inner(CORD x, unsigned n)
@@ -130,21 +122,22 @@ void CORD_dump_inner(CORD x, unsigned n)
         if (x[i] != '\0') fputs("...", stdout);
         putchar('\n');
     } else if (IS_CONCATENATION(x)) {
-        struct Concatenation * conc = &(((CordRep *)x) -> concatenation);
+        struct Concatenation * conc = &(((CordRep *)x) -> data.concat);
 
         printf("Concatenation: %p (len: %d, depth: %d)\n",
-               (void *)x, (int)(conc -> len), (int)(conc -> depth));
+               (void *)x, (int)LEN(x), (int)DEPTH(x));
         CORD_dump_inner(conc -> left, n+1);
         CORD_dump_inner(conc -> right, n+1);
     } else /* function */ {
-        struct Function * func = &(((CordRep *)x) -> function);
+        struct Function * f = &(((CordRep *)x) -> data.function);
+        size_t lim = (size_t)LEN(x);
 
         if (IS_SUBSTR(x)) printf("(Substring) ");
-        printf("Function: %p (len: %d): ", (void *)x, (int)(func -> len));
-        for (i = 0; i < 20 && i < func -> len; i++) {
-            putchar((*(func -> fn))(i, func -> client_data));
+        printf("Function: %p (len: %d): ", (void *)x, (int)lim);
+        for (i = 0; i < 20 && i < lim; i++) {
+            putchar((*(f -> fn))(i, f -> client_data));
         }
-        if (i < func -> len) fputs("...", stdout);
+        if (i < lim) fputs("...", stdout);
         putchar('\n');
     }
 }
@@ -162,15 +155,15 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny)
     size_t lenx;
     int depth;
 
-    if (x == CORD_EMPTY) return(y);
-    if (leny == 0) return(x);
+    if (x == CORD_EMPTY) return y;
+    if (leny == 0) return x;
     if (CORD_IS_STRING(x)) {
         lenx = strlen(x);
         result_len = lenx + leny;
         if (result_len <= SHORT_LIMIT) {
             char * result = (char *)GC_MALLOC_ATOMIC(result_len + 1);
 
-            if (result == 0) OUT_OF_MEMORY;
+            if (NULL == result) OUT_OF_MEMORY;
 #           ifdef LINT2
                 memcpy(result, x, lenx + 1);
 #           else
@@ -180,7 +173,7 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny)
 #           endif
             memcpy(result + lenx, y, leny);
             result[result_len] = '\0';
-            return((CORD) result);
+            return (CORD)result;
         } else {
             depth = 1;
         }
@@ -193,14 +186,14 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny)
 
         if (leny <= SHORT_LIMIT/2
             && IS_CONCATENATION(x)
-            && CORD_IS_STRING(right = ((CordRep *)x) -> concatenation.right)) {
+            && CORD_IS_STRING(right = ((CordRep *)x) -> data.concat.right)) {
             size_t right_len;
 
             /* Merge y into right part of x. */
-            if (!CORD_IS_STRING(left = ((CordRep *)x) -> concatenation.left)) {
+            if (!CORD_IS_STRING(left = ((CordRep *)x) -> data.concat.left)) {
                 right_len = lenx - LEN(left);
-            } else if (((CordRep *)x) -> concatenation.left_len != 0) {
-                right_len = lenx - ((CordRep *)x) -> concatenation.left_len;
+            } else if (((CordRep *)x) -> generic.left_len != 0) {
+                right_len = lenx - ((CordRep *)x) -> generic.left_len;
             } else {
                 right_len = strlen(right);
             }
@@ -229,36 +222,35 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny)
     }
     {
       /* The general case; lenx, result_len is known: */
-        struct Concatenation * result = GC_NEW(struct Concatenation);
+        CordRep *result = GC_NEW(CordRep);
 
         if (NULL == result) OUT_OF_MEMORY;
-        result->header = CONCAT_HDR;
-        result->depth = (char)depth;
+        result -> generic.header = CONCAT_HDR;
+        result -> generic.depth = (char)depth;
         if (lenx <= MAX_LEFT_LEN)
-            result->left_len = (unsigned char)lenx;
-        result->len = (word)result_len;
-        result->left = x;
-        GC_PTR_STORE_AND_DIRTY((void *)&result->right, y);
+            result -> generic.left_len = (unsigned char)lenx;
+        result -> generic.len = (unsigned long)result_len;
+        result -> data.concat.left = x;
+        GC_PTR_STORE_AND_DIRTY((void *)(&result -> data.concat.right), y);
         GC_reachable_here(x);
         if (depth >= MAX_DEPTH) {
-            return(CORD_balance((CORD)result));
+            return CORD_balance((CORD)result);
         } else {
-            return((CORD) result);
+            return (CORD)result;
         }
     }
 }
 
-
 CORD CORD_cat(CORD x, CORD y)
 {
     size_t result_len;
     int depth;
     size_t lenx;
 
-    if (x == CORD_EMPTY) return(y);
-    if (y == CORD_EMPTY) return(x);
+    if (x == CORD_EMPTY) return y;
+    if (y == CORD_EMPTY) return x;
     if (CORD_IS_STRING(y)) {
-        return(CORD_cat_char_star(x, y, strlen(y)));
+        return CORD_cat_char_star(x, y, strlen(y));
     } else if (CORD_IS_STRING(x)) {
         lenx = strlen(x);
         depth = DEPTH(y) + 1;
@@ -271,29 +263,28 @@ CORD CORD_cat(CORD x, CORD y)
     }
     result_len = lenx + LEN(y);
     {
-        struct Concatenation * result = GC_NEW(struct Concatenation);
+        CordRep *result = GC_NEW(CordRep);
 
         if (NULL == result) OUT_OF_MEMORY;
-        result->header = CONCAT_HDR;
-        result->depth = (char)depth;
+        result -> generic.header = CONCAT_HDR;
+        result -> generic.depth = (char)depth;
         if (lenx <= MAX_LEFT_LEN)
-            result->left_len = (unsigned char)lenx;
-        result->len = (word)result_len;
-        result->left = x;
-        GC_PTR_STORE_AND_DIRTY((void *)&result->right, y);
+            result -> generic.left_len = (unsigned char)lenx;
+        result -> generic.len = (unsigned long)result_len;
+        result -> data.concat.left = x;
+        GC_PTR_STORE_AND_DIRTY((void *)&(result -> data.concat.right), y);
         GC_reachable_here(x);
         if (depth >= MAX_DEPTH) {
-            return(CORD_balance((CORD)result));
+            return CORD_balance((CORD)result);
         } else {
-            return((CORD) result);
+            return (CORD)result;
         }
     }
 }
 
-
 static CordRep *CORD_from_fn_inner(CORD_fn fn, void * client_data, size_t len)
 {
-    if (len == 0) return(0);
+    if (0 == len) return NULL;
     if (len <= SHORT_LIMIT) {
         char * result;
         size_t i;
@@ -307,22 +298,23 @@ static CordRep *CORD_from_fn_inner(CORD_fn fn, void * client_data, size_t len)
         }
 
         result = (char *)GC_MALLOC_ATOMIC(len + 1);
-        if (result == 0) OUT_OF_MEMORY;
+        if (NULL == result) OUT_OF_MEMORY;
         memcpy(result, buf, len);
         result[len] = '\0';
         return (CordRep *)result;
     }
   gen_case:
     {
-        struct Function * result = GC_NEW(struct Function);
+        CordRep *result = GC_NEW(CordRep);
 
         if (NULL == result) OUT_OF_MEMORY;
-        result->header = FN_HDR;
+        result -> generic.header = FN_HDR;
         /* depth is already 0 */
-        result->len = (word)len;
-        result->fn = fn;
-        GC_PTR_STORE_AND_DIRTY(&result->client_data, client_data);
-        return (CordRep *)result;
+        result -> generic.len = (unsigned long)len;
+        result -> data.function.fn = fn;
+        GC_PTR_STORE_AND_DIRTY(&(result -> data.function.client_data),
+                               client_data);
+        return result;
     }
 }
 
@@ -333,11 +325,7 @@ CORD CORD_from_fn(CORD_fn fn, void * client_data, size_t len)
 
 size_t CORD_len(CORD x)
 {
-    if (x == 0) {
-        return(0);
-    } else {
-        return(GEN_LEN(x));
-    }
+    return x == 0 ? 0 : GEN_LEN(x);
 }
 
 struct substr_args {
@@ -349,15 +337,15 @@ char CORD_index_access_fn(size_t i, void * client_data)
 {
     struct substr_args *descr = (struct substr_args *)client_data;
 
-    return(((char *)(descr->sa_cord))[i + descr->sa_index]);
+    return ((char *)descr->sa_cord)[i + descr->sa_index];
 }
 
 char CORD_apply_access_fn(size_t i, void * client_data)
 {
     struct substr_args *descr = (struct substr_args *)client_data;
-    struct Function * fn_cord = &(descr->sa_cord->function);
+    struct Function * fn_cord = &(descr -> sa_cord -> data.function);
 
-    return((*(fn_cord->fn))(i + descr->sa_index, fn_cord->client_data));
+    return fn_cord -> fn(i + descr -> sa_index, fn_cord -> client_data);
 }
 
 /* A version of CORD_substr that simply returns a function node, thus   */
@@ -373,8 +361,8 @@ CORD CORD_substr_closure(CORD x, size_t i, size_t n, CORD_fn f)
     sa->sa_index = i;
     GC_PTR_STORE_AND_DIRTY(&sa->sa_cord, x);
     result = CORD_from_fn_inner(f, (void *)sa, n);
-    if ((CORD)result != CORD_EMPTY && 0 == result -> function.null)
-        result -> function.header = SUBSTR_HDR;
+    if ((CORD)result != CORD_EMPTY && 0 == result -> generic.nul)
+        result -> generic.header = SUBSTR_HDR;
     return (CORD)result;
 }
 
@@ -383,31 +371,31 @@ CORD CORD_substr_closure(CORD x, size_t i, size_t n, CORD_fn f)
         /* this are flat strings.  Othewise we use a functional         */
         /* representation, which is significantly slower to access.     */
 
-/* A version of CORD_substr that assumes i >= 0, n > 0, and i + n < length(x).*/
+/* A version of CORD_substr that assumes i >= 0, n > 0, i + n < length(x). */
 CORD CORD_substr_checked(CORD x, size_t i, size_t n)
 {
     if (CORD_IS_STRING(x)) {
         if (n > SUBSTR_LIMIT) {
-            return(CORD_substr_closure(x, i, n, CORD_index_access_fn));
+            return CORD_substr_closure(x, i, n, CORD_index_access_fn);
         } else {
             char * result = (char *)GC_MALLOC_ATOMIC(n + 1);
 
-            if (result == 0) OUT_OF_MEMORY;
+            if (NULL == result) OUT_OF_MEMORY;
             strncpy(result, x+i, n);
             result[n] = '\0';
-            return(result);
+            return result;
         }
     } else if (IS_CONCATENATION(x)) {
-        struct Concatenation * conc = &(((CordRep *)x) -> concatenation);
-        size_t left_len = LEFT_LEN(conc);
-        size_t right_len = conc -> len - left_len;
+        struct Concatenation * conc = &(((CordRep *)x) -> data.concat);
+        size_t left_len = LEFT_LEN(x);
+        size_t right_len = (size_t)LEN(x) - left_len;
 
         if (i >= left_len) {
-            if (n == right_len) return(conc -> right);
-            return(CORD_substr_checked(conc -> right, i - left_len, n));
+            if (n == right_len) return conc -> right;
+            return CORD_substr_checked(conc -> right, i - left_len, n);
         } else if (i+n <= left_len) {
-            if (n == left_len) return(conc -> left);
-            return(CORD_substr_checked(conc -> left, i, n));
+            if (n == left_len) return conc -> left;
+            return CORD_substr_checked(conc -> left, i, n);
         } else {
             /* Need at least one character from each side. */
             CORD left_part;
@@ -417,7 +405,8 @@ CORD CORD_substr_checked(CORD x, size_t i, size_t n)
             if (i == 0) {
                 left_part = conc -> left;
             } else {
-                left_part = CORD_substr_checked(conc -> left, i, left_part_len);
+                left_part = CORD_substr_checked(conc -> left, i,
+                                                left_part_len);
             }
             if (i + n == right_len + left_len) {
                  right_part = conc -> right;
@@ -425,25 +414,24 @@ CORD CORD_substr_checked(CORD x, size_t i, size_t n)
                  right_part = CORD_substr_checked(conc -> right, 0,
                                                   n - left_part_len);
             }
-            return(CORD_cat(left_part, right_part));
+            return CORD_cat(left_part, right_part);
         }
     } else /* function */ {
         if (n > SUBSTR_LIMIT) {
             if (IS_SUBSTR(x)) {
                 /* Avoid nesting substring nodes.       */
-                struct Function * f = &(((CordRep *)x) -> function);
+                struct Function * f = &(((CordRep *)x) -> data.function);
                 struct substr_args *descr =
                                 (struct substr_args *)(f -> client_data);
 
-                return(CORD_substr_closure((CORD)descr->sa_cord,
-                                           i + descr->sa_index,
-                                           n, f -> fn));
+                return CORD_substr_closure((CORD)descr->sa_cord,
+                                           i + descr->sa_index, n, f -> fn);
             } else {
-                return(CORD_substr_closure(x, i, n, CORD_apply_access_fn));
+                return CORD_substr_closure(x, i, n, CORD_apply_access_fn);
             }
         } else {
             char * result;
-            struct Function * f = &(((CordRep *)x) -> function);
+            struct Function * f = &(((CordRep *)x) -> data.function);
             char buf[SUBSTR_LIMIT+1];
             char * p = buf;
             size_t j;
@@ -453,15 +441,15 @@ CORD CORD_substr_checked(CORD x, size_t i, size_t n)
                 char c = (*(f -> fn))(j, f -> client_data);
 
                 if (c == '\0') {
-                    return(CORD_substr_closure(x, i, n, CORD_apply_access_fn));
+                    return CORD_substr_closure(x, i, n, CORD_apply_access_fn);
                 }
                 *p++ = c;
             }
             result = (char *)GC_MALLOC_ATOMIC(n + 1);
-            if (result == 0) OUT_OF_MEMORY;
+            if (NULL == result) OUT_OF_MEMORY;
             memcpy(result, buf, n);
             result[n] = '\0';
-            return(result);
+            return result;
         }
     }
 }
@@ -470,67 +458,67 @@ CORD CORD_substr(CORD x, size_t i, size_t n)
 {
     size_t len = CORD_len(x);
 
-    if (i >= len || n == 0) return(0);
+    if (i >= len || 0 == n) return 0;
     if (i + n > len) n = len - i;
-    return(CORD_substr_checked(x, i, n));
+    return CORD_substr_checked(x, i, n);
 }
 
 /* See cord.h for definition.  We assume i is in range. */
 int CORD_iter5(CORD x, size_t i, CORD_iter_fn f1,
                          CORD_batched_iter_fn f2, void * client_data)
 {
-    if (x == 0) return(0);
+    if (0 == x) return 0;
     if (CORD_IS_STRING(x)) {
         const char *p = x+i;
 
         if (*p == '\0') ABORT("2nd arg to CORD_iter5 too big");
         if (f2 != CORD_NO_FN) {
-            return((*f2)(p, client_data));
+            return f2(p, client_data);
         } else {
             while (*p) {
-                if ((*f1)(*p, client_data)) return(1);
+                if (f1(*p, client_data)) return 1;
                 p++;
             }
-            return(0);
+            return 0;
         }
     } else if (IS_CONCATENATION(x)) {
-        struct Concatenation * conc = &(((CordRep *)x) -> concatenation);
+        struct Concatenation * conc = &(((CordRep *)x) -> data.concat);
 
         if (i > 0) {
-            size_t left_len = LEFT_LEN(conc);
+            size_t left_len = LEFT_LEN(x);
 
             if (i >= left_len) {
-                return(CORD_iter5(conc -> right, i - left_len, f1, f2,
-                                  client_data));
+                return CORD_iter5(conc -> right, i - left_len, f1, f2,
+                                  client_data);
             }
         }
         if (CORD_iter5(conc -> left, i, f1, f2, client_data)) {
-            return(1);
+            return 1;
         }
-        return(CORD_iter5(conc -> right, 0, f1, f2, client_data));
+        return CORD_iter5(conc -> right, 0, f1, f2, client_data);
     } else /* function */ {
-        struct Function * f = &(((CordRep *)x) -> function);
+        struct Function * f = &(((CordRep *)x) -> data.function);
         size_t j;
-        size_t lim = f -> len;
+        size_t lim = (size_t)LEN(x);
 
         for (j = i; j < lim; j++) {
-            if ((*f1)((*(f -> fn))(j, f -> client_data), client_data)) {
-                return(1);
+            if (f1(f->fn(j, f->client_data), client_data)) {
+                return 1;
             }
         }
-        return(0);
+        return 0;
     }
 }
 
 #undef CORD_iter
 int CORD_iter(CORD x, CORD_iter_fn f1, void * client_data)
 {
-    return(CORD_iter5(x, 0, f1, CORD_NO_FN, client_data));
+    return CORD_iter5(x, 0, f1, CORD_NO_FN, client_data);
 }
 
 int CORD_riter4(CORD x, size_t i, CORD_iter_fn f1, void * client_data)
 {
-    if (x == 0) return(0);
+    if (0 == x) return 0;
     if (CORD_IS_STRING(x)) {
         const char *p = x + i;
 
@@ -538,42 +526,42 @@ int CORD_riter4(CORD x, size_t i, CORD_iter_fn f1, void * client_data)
             char c = *p;
 
             if (c == '\0') ABORT("2nd arg to CORD_riter4 too big");
-            if ((*f1)(c, client_data)) return(1);
+            if (f1(c, client_data)) return 1;
             if (p == x) break;
             p--;
         }
-        return(0);
     } else if (IS_CONCATENATION(x)) {
-        struct Concatenation * conc = &(((CordRep *)x) -> concatenation);
+        struct Concatenation * conc = &(((CordRep *)x) -> data.concat);
         CORD left_part = conc -> left;
-        size_t left_len = LEFT_LEN(conc);
+        size_t left_len = LEFT_LEN(x);
 
         if (i >= left_len) {
             if (CORD_riter4(conc -> right, i - left_len, f1, client_data)) {
-                return(1);
+                return 1;
             }
-            return(CORD_riter4(left_part, left_len - 1, f1, client_data));
+            return CORD_riter4(left_part, left_len - 1, f1, client_data);
         } else {
-            return(CORD_riter4(left_part, i, f1, client_data));
+            return CORD_riter4(left_part, i, f1, client_data);
         }
     } else /* function */ {
-        struct Function * f = &(((CordRep *)x) -> function);
+        struct Function * f = &(((CordRep *)x) -> data.function);
         size_t j;
 
         for (j = i; ; j--) {
-            if ((*f1)((*(f -> fn))(j, f -> client_data), client_data)) {
-                return(1);
+            if (f1(f -> fn(j, f -> client_data), client_data)) {
+                return 1;
             }
-            if (j == 0) return(0);
+            if (0 == j) break;
         }
     }
+    return 0;
 }
 
 int CORD_riter(CORD x, CORD_iter_fn f1, void * client_data)
 {
     size_t len = CORD_len(x);
-    if (len == 0) return(0);
-    return(CORD_riter4(x, len - 1, f1, client_data));
+    if (0 == len) return 0;
+    return CORD_riter4(x, len - 1, f1, client_data);
 }
 
 /*
@@ -627,7 +615,6 @@ void CORD_init_min_len(void)
     min_len_init = 1;
 }
 
-
 void CORD_init_forest(ForestElement * forest, size_t max_len)
 {
     int i;
@@ -693,7 +680,7 @@ CORD CORD_concat_forest(ForestElement * forest, size_t expected_len)
         }
         i++;
     }
-    return(sum);
+    return sum;
 }
 
 /* Insert the frontier of x into forest.  Balanced subtrees are */
@@ -708,8 +695,8 @@ void CORD_balance_insert(CORD x, size_t len, ForestElement * forest)
     } else if (IS_CONCATENATION(x)
                && ((depth = DEPTH(x)) >= MAX_DEPTH
                    || len < min_len[depth])) {
-        struct Concatenation * conc = &(((CordRep *)x) -> concatenation);
-        size_t left_len = LEFT_LEN(conc);
+        struct Concatenation * conc = &(((CordRep *)x) -> data.concat);
+        size_t left_len = LEFT_LEN(x);
 
         CORD_balance_insert(conc -> left, left_len, forest);
         CORD_balance_insert(conc -> right, len - left_len, forest);
@@ -718,19 +705,18 @@ void CORD_balance_insert(CORD x, size_t len, ForestElement * forest)
     }
 }
 
-
 CORD CORD_balance(CORD x)
 {
     Forest forest;
     size_t len;
 
-    if (x == 0) return(0);
-    if (CORD_IS_STRING(x)) return(x);
+    if (0 == x) return 0;
+    if (CORD_IS_STRING(x)) return x;
     if (!min_len_init) CORD_init_min_len();
     len = LEN(x);
     CORD_init_forest(forest, len);
     CORD_balance_insert(x, len, forest);
-    return(CORD_concat_forest(forest, len));
+    return CORD_concat_forest(forest, len);
 }
 
 
@@ -750,11 +736,11 @@ void CORD__extend_path(CORD_pos p)
      size_t top_len = GEN_LEN(top);
 
      /* Fill in the rest of the path. */
-       while(!CORD_IS_STRING(top) && IS_CONCATENATION(top)) {
-         struct Concatenation * conc = &(((CordRep *)top) -> concatenation);
+       while (!CORD_IS_STRING(top) && IS_CONCATENATION(top)) {
+         struct Concatenation * conc = &(((CordRep *)top) -> data.concat);
          size_t left_len;
 
-         left_len = LEFT_LEN(conc);
+         left_len = LEFT_LEN(top);
          current_pe++;
          if (pos >= top_pos + left_len) {
              current_pe -> pe_cord = top = conc -> right;
@@ -791,8 +777,8 @@ char CORD__pos_fetch(CORD_pos p)
     leaf = pe -> pe_cord;
     if (!IS_FUNCTION(leaf))
         ABORT("CORD_pos_fetch: bad leaf");
-    f = &((CordRep *)leaf)->function;
-    return ((*(f -> fn))(p[0].cur_pos - pe -> pe_start_pos, f -> client_data));
+    f = &((CordRep *)leaf) -> data.function;
+    return f -> fn(p[0].cur_pos - pe -> pe_start_pos, f -> client_data);
 }
 
 void CORD__next(CORD_pos p)
@@ -810,27 +796,27 @@ void CORD__next(CORD_pos p)
     p[0].cur_pos = cur_pos;
     if (!CORD_IS_STRING(leaf)) {
         /* Function leaf        */
-        struct Function * f = &(((CordRep *)leaf) -> function);
+        struct Function * f = &(((CordRep *)leaf) -> data.function);
         size_t start_pos = current_pe -> pe_start_pos;
-        size_t end_pos = start_pos + f -> len;
+        size_t end_pos = start_pos + (size_t)LEN(leaf);
 
         if (cur_pos < end_pos) {
           /* Fill cache and return. */
             size_t i;
-            size_t limit = cur_pos + FUNCTION_BUF_SZ;
+            size_t limit = FUNCTION_BUF_SZ;
             CORD_fn fn = f -> fn;
             void * client_data = f -> client_data;
 
-            if (limit > end_pos) {
-                limit = end_pos;
+            if (end_pos - cur_pos < FUNCTION_BUF_SZ) {
+                limit = end_pos - cur_pos;
             }
-            for (i = cur_pos; i < limit; i++) {
-                p[0].function_buf[i - cur_pos] =
-                        (*fn)(i - start_pos, client_data);
+            for (i = 0; i < limit; i++) {
+                p[0].function_buf[i] = (*fn)(i + cur_pos - start_pos,
+                                             client_data);
             }
             p[0].cur_start = cur_pos;
             p[0].cur_leaf = p[0].function_buf;
-            p[0].cur_end = limit;
+            p[0].cur_end = cur_pos + limit;
             return;
         }
     }
@@ -890,9 +876,9 @@ void CORD__prev(CORD_pos p)
 char CORD_pos_fetch(CORD_pos p)
 {
     if (p[0].cur_end != 0) {
-        return(p[0].cur_leaf[p[0].cur_pos - p[0].cur_start]);
+        return p[0].cur_leaf[p[0].cur_pos - p[0].cur_start];
     } else {
-        return(CORD__pos_fetch(p));
+        return CORD__pos_fetch(p);
     }
 }
 
@@ -916,17 +902,17 @@ void CORD_prev(CORD_pos p)
 
 size_t CORD_pos_to_index(CORD_pos p)
 {
-    return(p[0].cur_pos);
+    return p[0].cur_pos;
 }
 
 CORD CORD_pos_to_cord(CORD_pos p)
 {
-    return(p[0].path[0].pe_cord);
+    return p[0].path[0].pe_cord;
 }
 
 int CORD_pos_valid(CORD_pos p)
 {
-    return(p[0].path_len != CORD_POS_INVALID);
+    return p[0].path_len != CORD_POS_INVALID;
 }
 
 void CORD_set_pos(CORD_pos p, CORD x, size_t i)

+ 27 - 18
blitz.mod/bdwgc/cord/cordprnt.c

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -63,7 +63,7 @@ static int ec_len(CORD_ec x)
     return (int)(CORD_len(x[0].ec_cord) + (x[0].ec_bufptr - x[0].ec_buf));
 }
 
-/* Possible nonumeric precision values. */
+/* Possible non-numeric precision values.   */
 # define NONE -1
 # define VARIABLE -2
 /* Copy the conversion specification from CORD_pos into the buffer buf  */
@@ -74,7 +74,7 @@ static int ec_len(CORD_ec x)
 /* If width or prec is *, VARIABLE is assigned.                         */
 /* Set *left to 1 if left adjustment flag is present.                   */
 /* Set *long_arg to 1 if long flag ('l' or 'L') is present, or to       */
-/* -1 if 'h' is present.                                                */
+/* -1 if 'h' is present, or to 2 if 'z' is present.                     */
 static int extract_conv_spec(CORD_pos source, char *buf,
                              int * width, int *prec, int *left, int * long_arg)
 {
@@ -88,7 +88,7 @@ static int extract_conv_spec(CORD_pos source, char *buf,
     *width = NONE;
     buf[chars_so_far++] = '%';
     while(CORD_pos_valid(source)) {
-        if (chars_so_far >= CONV_SPEC_LEN) return(-1);
+        if (chars_so_far >= CONV_SPEC_LEN) return -1;
         current = CORD_pos_fetch(source);
         buf[chars_so_far++] = current;
         switch(current) {
@@ -129,6 +129,10 @@ static int extract_conv_spec(CORD_pos source, char *buf,
             *long_arg = 1;
             current_number = 0;
             break;
+          case 'z':
+            *long_arg = 2;
+            current_number = 0;
+            break;
           case 'h':
             *long_arg = -1;
             current_number = 0;
@@ -162,11 +166,11 @@ static int extract_conv_spec(CORD_pos source, char *buf,
           case 'r':
             goto done;
           default:
-            return(-1);
+            return -1;
         }
         CORD_next(source);
     }
-    return(-1);
+    return -1;
   done:
     if (saw_number) {
         if (saw_period) {
@@ -179,7 +183,7 @@ static int extract_conv_spec(CORD_pos source, char *buf,
         *prec = NONE;
     }
     buf[chars_so_far] = '\0';
-    return(result);
+    return result;
 }
 
 #if defined(__DJGPP__) || defined(__STRICT_ANSI__)
@@ -209,7 +213,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
         current = CORD_pos_fetch(pos);
         if (current == '%') {
             CORD_next(pos);
-            if (!CORD_pos_valid(pos)) return(-1);
+            if (!CORD_pos_valid(pos)) return -1;
             current = CORD_pos_fetch(pos);
             if (current == '%') {
                 CORD_ec_append(result, current);
@@ -223,7 +227,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
                 if (extract_conv_spec(pos, conv_spec,
                                       &width, &prec,
                                       &left_adj, &long_arg) < 0) {
-                    return(-1);
+                    return -1;
                 }
                 current = CORD_pos_fetch(pos);
                 switch(current) {
@@ -233,6 +237,9 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
                             int * pos_ptr;
                             pos_ptr = va_arg(args, int *);
                             *pos_ptr = ec_len(result);
+                        } else if (long_arg == 2) {
+                            size_t * pos_ptr = va_arg(args, size_t *);
+                            *pos_ptr = (size_t)(unsigned)ec_len(result);
                         } else if (long_arg > 0) {
                             long * pos_ptr;
                             pos_ptr = va_arg(args, long *);
@@ -250,7 +257,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
                         arg = va_arg(args, CORD);
                         len = CORD_len(arg);
                         if (prec != NONE && len > (unsigned)prec) {
-                          if (prec < 0) return(-1);
+                          if (prec < 0) return -1;
                           arg = CORD_substr(arg, 0, (unsigned)prec);
                           len = (unsigned)prec;
                         }
@@ -334,7 +341,9 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
                         case 'c':
                             if (long_arg <= 0) {
                               (void) va_arg(args, int);
-                            } else /* long_arg > 0 */ {
+                            } else if (long_arg == 2) {
+                              (void) va_arg(args, size_t);
+                            } else /* long_arg == 1 */ {
                               (void) va_arg(args, long);
                             }
                             break;
@@ -365,7 +374,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
                         /* old style vsprintf */
                         len = strlen(buf);
                     } else if (res < 0) {
-                        return(-1);
+                        return -1;
                     }
                     if (buf != result[0].ec_bufptr) {
                         char c;
@@ -385,7 +394,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
     }
     count = ec_len(result);
     *out = CORD_balance(CORD_ec_to_cord(result));
-    return(count);
+    return count;
 }
 
 int CORD_sprintf(CORD * out, CORD format, ...)
@@ -396,7 +405,7 @@ int CORD_sprintf(CORD * out, CORD format, ...)
     va_start(args, format);
     result = CORD_vsprintf(out, format, args);
     va_end(args);
-    return(result);
+    return result;
 }
 
 int CORD_fprintf(FILE * f, CORD format, ...)
@@ -409,7 +418,7 @@ int CORD_fprintf(FILE * f, CORD format, ...)
     result = CORD_vsprintf(&out, format, args);
     va_end(args);
     if (result > 0) CORD_put(out, f);
-    return(result);
+    return result;
 }
 
 int CORD_vfprintf(FILE * f, CORD format, va_list args)
@@ -419,7 +428,7 @@ int CORD_vfprintf(FILE * f, CORD format, va_list args)
 
     result = CORD_vsprintf(&out, format, args);
     if (result > 0) CORD_put(out, f);
-    return(result);
+    return result;
 }
 
 int CORD_printf(CORD format, ...)
@@ -432,7 +441,7 @@ int CORD_printf(CORD format, ...)
     result = CORD_vsprintf(&out, format, args);
     va_end(args);
     if (result > 0) CORD_put(out, stdout);
-    return(result);
+    return result;
 }
 
 int CORD_vprintf(CORD format, va_list args)
@@ -442,5 +451,5 @@ int CORD_vprintf(CORD format, va_list args)
 
     result = CORD_vsprintf(&out, format, args);
     if (result > 0) CORD_put(out, stdout);
-    return(result);
+    return result;
 }

+ 79 - 103
blitz.mod/bdwgc/cord/cordxtra.c

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -63,22 +63,16 @@ typedef void (* oom_fn)(void);
                          ABORT("Out of memory"); }
 # define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); }
 
-#if GC_GNUC_PREREQ(3, 4)
-# define CORD_ATTR_UNUSED __attribute__((__unused__))
-#else
-# define CORD_ATTR_UNUSED /* empty */
-#endif
-
 CORD CORD_cat_char(CORD x, char c)
 {
     char * string;
 
-    if (c == '\0') return(CORD_cat(x, CORD_nul(1)));
+    if ('\0' == c) return CORD_cat(x, CORD_nul(1));
     string = (char *)GC_MALLOC_ATOMIC(2);
-    if (string == 0) OUT_OF_MEMORY;
+    if (NULL == string) OUT_OF_MEMORY;
     string[0] = c;
     string[1] = '\0';
-    return(CORD_cat_char_star(x, string, 1));
+    return CORD_cat_char_star(x, string, 1);
 }
 
 CORD CORD_catn(int nargs, ...)
@@ -93,7 +87,7 @@ CORD CORD_catn(int nargs, ...)
         result = CORD_cat(result, next);
     }
     va_end(args);
-    return(result);
+    return result;
 }
 
 typedef struct {
@@ -109,11 +103,7 @@ int CORD_fill_proc(char c, void * client_data)
 
     (d -> buf)[count] = c;
     d -> count = ++count;
-    if (count >= d -> len) {
-        return(1);
-    } else {
-        return(0);
-    }
+    return count >= d -> len ? 1 : 0;
 }
 
 int CORD_batched_fill_proc(const char * s, void * client_data)
@@ -124,15 +114,15 @@ int CORD_batched_fill_proc(const char * s, void * client_data)
     char * buf = d -> buf;
     const char * t = s;
 
-    while((buf[count] = *t++) != '\0') {
+    while ((buf[count] = *t++) != '\0') {
         count++;
         if (count >= max) {
             d -> count = count;
-            return(1);
+            return 1;
         }
     }
     d -> count = count;
-    return(0);
+    return 0;
 }
 
 /* Fill buf with len characters starting at i.  */
@@ -154,30 +144,24 @@ int CORD_cmp(CORD x, CORD y)
     CORD_pos xpos;
     CORD_pos ypos;
 
-    if (y == CORD_EMPTY) return(x != CORD_EMPTY);
-    if (x == CORD_EMPTY) return(-1);
-    if (CORD_IS_STRING(y) && CORD_IS_STRING(x)) return(strcmp(x,y));
+    if (y == CORD_EMPTY) return x != CORD_EMPTY;
+    if (x == CORD_EMPTY) return -1;
+    if (CORD_IS_STRING(y) && CORD_IS_STRING(x)) return strcmp(x, y);
     CORD_set_pos(xpos, x, 0);
     CORD_set_pos(ypos, y, 0);
     for(;;) {
         size_t avail, yavail;
 
         if (!CORD_pos_valid(xpos)) {
-            if (CORD_pos_valid(ypos)) {
-                return(-1);
-            } else {
-                return(0);
-            }
-        }
-        if (!CORD_pos_valid(ypos)) {
-            return(1);
+            return CORD_pos_valid(ypos) ? -1 : 0;
         }
+        if (!CORD_pos_valid(ypos)) return 1;
         avail = CORD_pos_chars_left(xpos);
-        if (avail == 0
+        if (0 == avail
             || (yavail = CORD_pos_chars_left(ypos)) == 0) {
             char xcurrent = CORD_pos_fetch(xpos);
             char ycurrent = CORD_pos_fetch(ypos);
-            if (xcurrent != ycurrent) return(xcurrent - ycurrent);
+            if (xcurrent != ycurrent) return xcurrent - ycurrent;
             CORD_next(xpos);
             CORD_next(ypos);
         } else {
@@ -187,7 +171,7 @@ int CORD_cmp(CORD x, CORD y)
             if (avail > yavail) avail = yavail;
             result = strncmp(CORD_pos_cur_char_addr(xpos),
                          CORD_pos_cur_char_addr(ypos), avail);
-            if (result != 0) return(result);
+            if (result != 0) return result;
             CORD_pos_advance(xpos, avail);
             CORD_pos_advance(ypos, avail);
         }
@@ -206,21 +190,15 @@ int CORD_ncmp(CORD x, size_t x_start, CORD y, size_t y_start, size_t len)
         long avail, yavail;
 
         if (!CORD_pos_valid(xpos)) {
-            if (CORD_pos_valid(ypos)) {
-                return(-1);
-            } else {
-                return(0);
-            }
-        }
-        if (!CORD_pos_valid(ypos)) {
-            return(1);
+            return CORD_pos_valid(ypos) ? -1 : 0;
         }
+        if (!CORD_pos_valid(ypos)) return 1;
         if ((avail = CORD_pos_chars_left(xpos)) <= 0
             || (yavail = CORD_pos_chars_left(ypos)) <= 0) {
             char xcurrent = CORD_pos_fetch(xpos);
             char ycurrent = CORD_pos_fetch(ypos);
 
-            if (xcurrent != ycurrent) return(xcurrent - ycurrent);
+            if (xcurrent != ycurrent) return xcurrent - ycurrent;
             CORD_next(xpos);
             CORD_next(ypos);
             count++;
@@ -233,13 +211,13 @@ int CORD_ncmp(CORD x, size_t x_start, CORD y, size_t y_start, size_t len)
             if (count > len)
                 avail -= (long)(count - len);
             result = strncmp(CORD_pos_cur_char_addr(xpos),
-                         CORD_pos_cur_char_addr(ypos), (size_t)avail);
-            if (result != 0) return(result);
+                             CORD_pos_cur_char_addr(ypos), (size_t)avail);
+            if (result != 0) return result;
             CORD_pos_advance(xpos, (size_t)avail);
             CORD_pos_advance(ypos, (size_t)avail);
         }
     }
-    return(0);
+    return 0;
 }
 
 char * CORD_to_char_star(CORD x)
@@ -247,11 +225,11 @@ char * CORD_to_char_star(CORD x)
     size_t len = CORD_len(x);
     char * result = (char *)GC_MALLOC_ATOMIC(len + 1);
 
-    if (result == 0) OUT_OF_MEMORY;
+    if (NULL == result) OUT_OF_MEMORY;
     if (len > 0 && CORD_fill_buf(x, 0, len, result) != 1)
       ABORT("CORD_fill_buf malfunction");
     result[len] = '\0';
-    return(result);
+    return result;
 }
 
 CORD CORD_from_char_star(const char *s)
@@ -259,18 +237,18 @@ CORD CORD_from_char_star(const char *s)
     char * result;
     size_t len = strlen(s);
 
-    if (0 == len) return(CORD_EMPTY);
+    if (0 == len) return CORD_EMPTY;
     result = (char *)GC_MALLOC_ATOMIC(len + 1);
-    if (result == 0) OUT_OF_MEMORY;
+    if (NULL == result) OUT_OF_MEMORY;
     memcpy(result, s, len+1);
-    return(result);
+    return result;
 }
 
 const char * CORD_to_const_char_star(CORD x)
 {
-    if (x == 0) return("");
-    if (CORD_IS_STRING(x)) return((const char *)x);
-    return(CORD_to_char_star(x));
+    if (0 == x) return "";
+    if (CORD_IS_STRING(x)) return (const char *)x;
+    return CORD_to_char_star(x);
 }
 
 char CORD_fetch(CORD x, size_t i)
@@ -279,7 +257,7 @@ char CORD_fetch(CORD x, size_t i)
 
     CORD_set_pos(xpos, x, i);
     if (!CORD_pos_valid(xpos)) ABORT("bad index?");
-    return(CORD_pos_fetch(xpos));
+    return CORD_pos_fetch(xpos);
 }
 
 
@@ -287,24 +265,22 @@ int CORD_put_proc(char c, void * client_data)
 {
     FILE * f = (FILE *)client_data;
 
-    return(putc(c, f) == EOF);
+    return putc(c, f) == EOF;
 }
 
 int CORD_batched_put_proc(const char * s, void * client_data)
 {
     FILE * f = (FILE *)client_data;
 
-    return(fputs(s, f) == EOF);
+    return fputs(s, f) == EOF;
 }
 
 
 int CORD_put(CORD x, FILE * f)
 {
-    if (CORD_iter5(x, 0, CORD_put_proc, CORD_batched_put_proc, f)) {
-        return(EOF);
-    } else {
-        return(1);
-    }
+    if (CORD_iter5(x, 0, CORD_put_proc, CORD_batched_put_proc, f))
+        return EOF;
+    return 1;
 }
 
 typedef struct {
@@ -316,18 +292,18 @@ int CORD_chr_proc(char c, void * client_data)
 {
     chr_data * d = (chr_data *)client_data;
 
-    if (c == d -> target) return(1);
-    (d -> pos) ++;
-    return(0);
+    if (c == d -> target) return 1;
+    (d -> pos)++;
+    return 0;
 }
 
 int CORD_rchr_proc(char c, void * client_data)
 {
     chr_data * d = (chr_data *)client_data;
 
-    if (c == d -> target) return(1);
-    (d -> pos) --;
-    return(0);
+    if (c == d -> target) return 1;
+    (d -> pos)--;
+    return 0;
 }
 
 int CORD_batched_chr_proc(const char *s, void * client_data)
@@ -337,11 +313,10 @@ int CORD_batched_chr_proc(const char *s, void * client_data)
 
     if (NULL == occ) {
         d -> pos += strlen(s);
-        return(0);
-    } else {
-        d -> pos += occ - s;
-        return(1);
+        return 0;
     }
+    d -> pos += occ - s;
+    return 1;
 }
 
 size_t CORD_chr(CORD x, size_t i, int c)
@@ -351,9 +326,9 @@ size_t CORD_chr(CORD x, size_t i, int c)
     d.pos = i;
     d.target = (char)c;
     if (CORD_iter5(x, i, CORD_chr_proc, CORD_batched_chr_proc, &d)) {
-        return(d.pos);
+        return d.pos;
     } else {
-        return(CORD_NOT_FOUND);
+        return CORD_NOT_FOUND;
     }
 }
 
@@ -364,9 +339,9 @@ size_t CORD_rchr(CORD x, size_t i, int c)
     d.pos = i;
     d.target = (char)c;
     if (CORD_riter4(x, i, CORD_rchr_proc, &d)) {
-        return(d.pos);
+        return d.pos;
     } else {
-        return(CORD_NOT_FOUND);
+        return CORD_NOT_FOUND;
     }
 }
 
@@ -391,7 +366,7 @@ size_t CORD_str(CORD x, size_t start, CORD s)
     size_t i;
     size_t match_pos;
 
-    if (s == CORD_EMPTY) return(start);
+    if (s == CORD_EMPTY) return start;
     if (CORD_IS_STRING(s)) {
         s_start = s;
         slen = strlen(s);
@@ -399,7 +374,7 @@ size_t CORD_str(CORD x, size_t start, CORD s)
         s_start = CORD_to_char_star(CORD_substr(s, 0, sizeof(unsigned long)));
         slen = CORD_len(s);
     }
-    if (xlen < start || xlen - start < slen) return(CORD_NOT_FOUND);
+    if (xlen < start || xlen - start < slen) return CORD_NOT_FOUND;
     start_len = slen;
     if (start_len > sizeof(unsigned long)) start_len = sizeof(unsigned long);
     CORD_set_pos(xpos, x, start);
@@ -413,20 +388,17 @@ size_t CORD_str(CORD x, size_t start, CORD s)
         CORD_next(xpos);
     }
     for (match_pos = start; ; match_pos++) {
-        if ((x_buf & mask) == s_buf) {
-            if (slen == start_len ||
-                CORD_ncmp(x, match_pos + start_len,
-                      s, start_len, slen - start_len) == 0) {
-                return(match_pos);
-            }
-        }
-    if ( match_pos == xlen - slen ) {
-        return(CORD_NOT_FOUND);
-    }
+        if ((x_buf & mask) == s_buf
+            && (slen == start_len
+                || CORD_ncmp(x, match_pos + start_len,
+                             s, start_len, slen - start_len) == 0))
+          break;
+        if (match_pos == xlen - slen) return CORD_NOT_FOUND;
         x_buf <<= 8;
         x_buf |= (unsigned char)CORD_pos_fetch(xpos);
         CORD_next(xpos);
     }
+    return match_pos;
 }
 
 void CORD_ec_flush_buf(CORD_ec x)
@@ -449,8 +421,9 @@ void CORD_ec_append_cord(CORD_ec x, CORD s)
     x[0].ec_cord = CORD_cat(x[0].ec_cord, s);
 }
 
-char CORD_nul_func(size_t i CORD_ATTR_UNUSED, void * client_data)
+char CORD_nul_func(size_t i, void * client_data)
 {
+    (void)i;
     return (char)(GC_word)client_data;
 }
 
@@ -481,7 +454,7 @@ CORD CORD_from_file_eager(FILE * f)
         CORD_ec_append(ecord, (char)c);
     }
     (void) fclose(f);
-    return(CORD_balance(CORD_ec_to_cord(ecord)));
+    return CORD_balance(CORD_ec_to_cord(ecord));
 }
 
 /* The state maintained for a lazily read file consists primarily       */
@@ -567,25 +540,27 @@ char CORD_lf_func(size_t i, void * client_data)
         rd.state = state;
         rd.file_pos =  i;
         rd.new_cache = GC_NEW_ATOMIC(cache_line);
-        if (rd.new_cache == 0) OUT_OF_MEMORY;
+        if (NULL == rd.new_cache) OUT_OF_MEMORY;
         return (char)((GC_word)GC_call_with_alloc_lock(refill_cache, &rd));
     }
-    return(cl -> data[MOD_LINE_SZ(i)]);
+    return cl -> data[MOD_LINE_SZ(i)];
 }
 
-void CORD_lf_close_proc(void * obj, void * client_data CORD_ATTR_UNUSED)
-{
-    if (fclose(((lf_state *)obj) -> lf_file) != 0) {
+#ifndef GC_NO_FINALIZATION
+  void CORD_lf_close_proc(void * obj, void * client_data)
+  {
+    (void)client_data;
+    if (fclose(((lf_state *)obj) -> lf_file) != 0)
         ABORT("CORD_lf_close_proc: fclose failed");
-    }
-}
+  }
+#endif
 
 CORD CORD_from_file_lazy_inner(FILE * f, size_t len)
 {
     lf_state * state = GC_NEW(lf_state);
     int i;
 
-    if (state == 0) OUT_OF_MEMORY;
+    if (NULL == state) OUT_OF_MEMORY;
     if (len != 0) {
         /* Dummy read to force buffer allocation.       */
         /* This greatly increases the probability       */
@@ -604,8 +579,10 @@ CORD CORD_from_file_lazy_inner(FILE * f, size_t len)
         state -> lf_cache[i] = 0;
     }
     state -> lf_current = 0;
-    GC_REGISTER_FINALIZER(state, CORD_lf_close_proc, 0, 0, 0);
-    return(CORD_from_fn(CORD_lf_func, state, len));
+#   ifndef GC_NO_FINALIZATION
+      GC_REGISTER_FINALIZER(state, CORD_lf_close_proc, 0, 0, 0);
+#   endif
+    return CORD_from_fn(CORD_lf_func, state, len);
 }
 
 CORD CORD_from_file_lazy(FILE * f)
@@ -617,7 +594,7 @@ CORD CORD_from_file_lazy(FILE * f)
         || fseek(f, 0l, SEEK_SET) != 0) {
         ABORT("Bad f argument or I/O failure");
     }
-    return(CORD_from_file_lazy_inner(f, (size_t)len));
+    return CORD_from_file_lazy_inner(f, (size_t)len);
 }
 
 # define LAZY_THRESHOLD (128*1024 + 1)
@@ -632,8 +609,7 @@ CORD CORD_from_file(FILE * f)
         ABORT("Bad f argument or I/O failure");
     }
     if (len < LAZY_THRESHOLD) {
-        return(CORD_from_file_eager(f));
-    } else {
-        return(CORD_from_file_lazy_inner(f, (size_t)len));
+        return CORD_from_file_eager(f);
     }
+    return CORD_from_file_lazy_inner(f, (size_t)len);
 }

+ 33 - 9
blitz.mod/bdwgc/cord/tests/cordtest.c

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -49,18 +49,18 @@ int test_fn(char c, void * client_data)
             if (c != 'a') ABORT("bad char");
         }
         count++;
-        return(0);
+        return 0;
     } else {
         if (c != 'c') ABORT("bad char");
         count++;
-        return(1);
+        return 1;
     }
 }
 
 char id_cord_fn(size_t i, void * client_data)
 {
     if (client_data != 0) ABORT("id_cord_fn: bad client data");
-    return((char)i);
+    return (char)i;
 }
 
 void test_basics(void)
@@ -221,8 +221,10 @@ void test_extras(void)
     *(CORD volatile *)&w = CORD_EMPTY;
     *(CORD volatile *)&z = CORD_EMPTY;
     GC_gcollect();
-    GC_invoke_finalizers();
+#   ifndef GC_NO_FINALIZATION
+      GC_invoke_finalizers();
             /* Of course, this does not guarantee the files are closed. */
+#   endif
     if (remove(FNAME1) != 0) {
         /* On some systems, e.g. OS2, this may fail if f1 is still open. */
         /* But we cannot call fclose as it might lead to double close.   */
@@ -270,6 +272,8 @@ int wrap_vfprintf(FILE * f, CORD format, ...)
 # endif
 #endif
 
+/* no static */ /* no const */ char *zu_format = (char*)"%zu";
+
 void test_printf(void)
 {
     CORD result;
@@ -277,14 +281,15 @@ void test_printf(void)
     long l = -1;
     short s = (short)-1;
     CORD x;
+    int res;
 
     if (CORD_sprintf(&result, "%7.2f%ln", 3.14159F, &l) != 7)
         ABORT("CORD_sprintf failed 1");
-    if (CORD_cmp(result, "   3.14") != 0)ABORT("CORD_sprintf goofed 1");
+    if (CORD_cmp(result, "   3.14") != 0) ABORT("CORD_sprintf goofed 1");
     if (l != 7) ABORT("CORD_sprintf goofed 2");
     if (CORD_sprintf(&result, "%-7.2s%hn%c%s", "abcd", &s, 'x', "yz") != 10)
         ABORT("CORD_sprintf failed 2");
-    if (CORD_cmp(result, "ab     xyz") != 0)ABORT("CORD_sprintf goofed 3");
+    if (CORD_cmp(result, "ab     xyz") != 0) ABORT("CORD_sprintf goofed 3");
     if (s != 7) ABORT("CORD_sprintf goofed 4");
     x = "abcdefghij";
     x = CORD_cat(x,x);
@@ -299,7 +304,26 @@ void test_printf(void)
         (void)sprintf(result2, "->%-120.78s!\n", CORD_to_char_star(x));
 #   endif
     result2[sizeof(result2) - 1] = '\0';
-    if (CORD_cmp(result, result2) != 0)ABORT("CORD_sprintf goofed 5");
+    if (CORD_cmp(result, result2) != 0) ABORT("CORD_sprintf goofed 5");
+
+#   ifdef GC_SNPRINTF
+        /* Check whether "%zu" specifier is supported; pass the format  */
+        /* string via a variable to avoid a compiler warning if not.    */
+        res = GC_SNPRINTF(result2, sizeof(result2), zu_format, (size_t)0);
+#   else
+        res = sprintf(result2, zu_format, (size_t)0);
+#   endif
+    result2[sizeof(result2) - 1] = '\0';
+    if (res == 1) /* is "%z" supported by printf? */ {
+        if (CORD_sprintf(&result, "%zu %zd 0x%0zx",
+                         (size_t)123, (size_t)4567, (size_t)0x4abc) != 15)
+            ABORT("CORD_sprintf failed 5");
+        if (CORD_cmp(result, "123 4567 0x4abc") != 0)
+            ABORT("CORD_sprintf goofed 5");
+    } else {
+        (void)CORD_printf("printf lacks support of 'z' modifier\n");
+    }
+
     /* TODO: Better test CORD_[v][f]printf.     */
     (void)CORD_printf(CORD_EMPTY);
     (void)wrap_vfprintf(stdout, CORD_EMPTY);
@@ -321,5 +345,5 @@ int main(void)
     test_extras();
     test_printf();
     CORD_fprintf(stdout, "SUCCEEDED\n");
-    return(0);
+    return 0;
 }

+ 35 - 35
blitz.mod/bdwgc/cord/tests/de.c

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -40,38 +40,37 @@
 #if (defined(__BORLANDC__) || defined(__CYGWIN__) || defined(__MINGW32__) \
      || defined(__NT__) || defined(_WIN32)) && !defined(WIN32)
     /* If this is DOS or win16, we'll fail anyway.      */
-    /* Might as well assume win32.                      */
 #   define WIN32
 #endif
 
 #if defined(WIN32)
-#  ifndef WIN32_LEAN_AND_MEAN
-#    define WIN32_LEAN_AND_MEAN 1
-#  endif
-#  define NOSERVICE
-#  include <windows.h>
-#  include "de_win.h"
+# ifndef WIN32_LEAN_AND_MEAN
+#   define WIN32_LEAN_AND_MEAN 1
+# endif
+# define NOSERVICE
+# include <windows.h>
+# include "de_win.h"
 #elif defined(MACINTOSH)
-#       include <console.h>
+# include <console.h>
 /* curses emulation. */
-#       define initscr()
-#       define endwin()
-#       define nonl()
-#       define noecho() csetmode(C_NOECHO, stdout)
-#       define cbreak() csetmode(C_CBREAK, stdout)
-#       define refresh()
-#       define addch(c) putchar(c)
-#       define standout() cinverse(1, stdout)
-#       define standend() cinverse(0, stdout)
-#       define move(line,col) cgotoxy(col + 1, line + 1, stdout)
-#       define clrtoeol() ccleol(stdout)
-#       define de_error(s) { fprintf(stderr, s); getchar(); }
-#       define LINES 25
-#       define COLS 80
+# define initscr()
+# define endwin()
+# define nonl()
+# define noecho() csetmode(C_NOECHO, stdout)
+# define cbreak() csetmode(C_CBREAK, stdout)
+# define refresh()
+# define addch(c) putchar(c)
+# define standout() cinverse(1, stdout)
+# define standend() cinverse(0, stdout)
+# define move(line,col) cgotoxy(col + 1, line + 1, stdout)
+# define clrtoeol() ccleol(stdout)
+# define de_error(s) { fprintf(stderr, s); getchar(); }
+# define LINES 25
+# define COLS 80
 #else
-#  include <curses.h>
-#  include <unistd.h> /* for sleep() */
-#  define de_error(s) { fprintf(stderr, s); sleep(2); }
+# include <curses.h>
+# include <unistd.h> /* for sleep() */
+# define de_error(s) { fprintf(stderr, s); sleep(2); }
 #endif
 #include "de_cmds.h"
 
@@ -187,7 +186,7 @@ size_t line_pos(int i, int *c)
     if (map -> line < i - 2) /* rebuild */ invalidate_map(i);
     for (j = map -> line, cur = map -> pos; j < i;) {
         cur = CORD_chr(current, cur, '\n');
-        if (cur == current_len-1) return(CORD_NOT_FOUND);
+        if (cur == current_len-1) return CORD_NOT_FOUND;
         cur++;
         if (++j > current_map -> line) add_map(j, cur);
     }
@@ -200,7 +199,7 @@ size_t line_pos(int i, int *c)
         }
         cur += *c;
     }
-    return(cur);
+    return cur;
 }
 
 void add_hist(CORD s)
@@ -237,7 +236,6 @@ int screen_size = 0;
 /* terribly appropriate for tabs.                                                                       */
 void replace_line(int i, CORD s)
 {
-    CORD_pos p;
 #   if !defined(MACINTOSH)
         size_t len = CORD_len(s);
 #   endif
@@ -254,6 +252,8 @@ void replace_line(int i, CORD s)
         }
 #   endif
     if (CORD_cmp(screen[i], s) != 0) {
+        CORD_pos p;
+
         move(i, 0); clrtoeol(); move(i,0);
 
         CORD_FOR (p, s) {
@@ -284,7 +284,7 @@ CORD retrieve_line(CORD s, size_t pos, unsigned column)
     if (eol == CORD_NOT_FOUND) eol = CORD_len(candidate);
     len = (int)eol - (int)column;
     if (len < 0) len = 0;
-    return(CORD_substr(s, pos + column, len));
+    return CORD_substr(s, pos + column, len);
 }
 
 # ifdef WIN32
@@ -296,8 +296,8 @@ CORD retrieve_line(CORD s, size_t pos, unsigned column)
 
         invalidate_map(dis_line + LINES);       /* Prune search */
         pos = line_pos(dis_line + i, 0);
-        if (pos == CORD_NOT_FOUND) return(CORD_EMPTY);
-        return(retrieve_line(current, pos, dis_col));
+        if (pos == CORD_NOT_FOUND) return CORD_EMPTY;
+        return retrieve_line(current, pos, dis_col);
     }
 # endif
 
@@ -383,9 +383,9 @@ void fix_pos(void)
 }
 
 #if defined(WIN32)
-#  define beep() Beep(1000 /* Hz */, 300 /* ms */)
+# define beep() Beep(1000 /* Hz */, 300 /* ms */)
 #elif defined(MACINTOSH)
-#  define beep() SysBeep(1)
+# define beep() SysBeep(1)
 #else
 /*
  * beep() is part of some curses packages and not others.
@@ -394,7 +394,7 @@ void fix_pos(void)
   int beep(void)
   {
     putc('\007', stderr);
-    return(0);
+    return 0;
   }
 #endif /* !WIN32 && !MACINTOSH */
 

+ 1 - 1
blitz.mod/bdwgc/cord/tests/de_cmds.h

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.

+ 43 - 45
blitz.mod/bdwgc/cord/tests/de_win.c

@@ -5,18 +5,16 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
 
 /*
- * The MS Windows specific part of de.
+ * The Windows specific part of de.
  * This started as the generic Windows application template
  * but significant parts didn't survive to the final version.
- *
- * This was written by a nonexpert windows programmer.
  */
 #if defined(__BORLANDC__) || defined(__CYGWIN__) || defined(__MINGW32__) \
     || defined(__NT__) || defined(_WIN32) || defined(WIN32)
@@ -49,21 +47,21 @@ void de_error(const char *s)
 int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPSTR command_line, int nCmdShow)
 {
-   MSG         msg;
-   WNDCLASS    wndclass;
-   HACCEL      hAccel;
+    MSG         msg;
+    WNDCLASS    wndclass;
+    HACCEL      hAccel;
 
-   GC_set_find_leak(0);
-   GC_INIT();
-#  ifndef NO_INCREMENTAL
+    GC_set_find_leak(0);
+    GC_INIT();
+#   ifndef NO_INCREMENTAL
      GC_enable_incremental();
-#  endif
-#  if defined(CPPCHECK)
+#   endif
+#   if defined(CPPCHECK)
      GC_noop1((GC_word)&WinMain);
-#  endif
+#   endif
 
-   if (!hPrevInstance)
-   {
+    if (!hPrevInstance)
+    {
       wndclass.style          = CS_HREDRAW | CS_VREDRAW;
       wndclass.lpfnWndProc    = WndProc;
       wndclass.cbClsExtra     = 0;
@@ -77,30 +75,30 @@ int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
 
       if (RegisterClass (&wndclass) == 0) {
           de_error("RegisterClass error");
-          return(0);
+          return 0;
       }
-   }
+    }
 
-   /* Empirically, the command line does not include the command name ...
-   if (command_line != 0) {
+    /* Empirically, the command line does not include the command name ...
+    if (command_line != 0) {
        while (isspace(*command_line)) command_line++;
        while (*command_line != 0 && !isspace(*command_line)) command_line++;
        while (isspace(*command_line)) command_line++;
-   } */
+    } */
 
-   if (command_line == 0 || *command_line == 0) {
+    if (command_line == 0 || *command_line == 0) {
         de_error("File name argument required");
-        return( 0 );
-   } else {
+        return 0;
+    } else {
         char *p = command_line;
 
         while (*p != 0 && !isspace(*(unsigned char *)p))
             p++;
         arg_file_name = CORD_to_char_star(
                             CORD_substr(command_line, 0, p - command_line));
-   }
+    }
 
-   hwnd = CreateWindow (szAppName,
+    hwnd = CreateWindow(szAppName,
                         TEXT("Demonstration Editor"),
                         WS_OVERLAPPEDWINDOW | WS_CAPTION, /* Window style */
                         CW_USEDEFAULT, 0, /* default pos. */
@@ -108,24 +106,24 @@ int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                         NULL,   /* No parent */
                         NULL,   /* Window class menu */
                         hInstance, NULL);
-   if (hwnd == NULL) {
+    if (hwnd == NULL) {
         de_error("CreateWindow error");
-        return(0);
-   }
+        return 0;
+    }
 
-   ShowWindow (hwnd, nCmdShow);
+    ShowWindow (hwnd, nCmdShow);
 
-   hAccel = LoadAccelerators( hInstance, szAppName );
+    hAccel = LoadAccelerators( hInstance, szAppName );
 
-   while (GetMessage (&msg, NULL, 0, 0))
-   {
+    while (GetMessage (&msg, NULL, 0, 0))
+    {
       if( !TranslateAccelerator( hwnd, hAccel, &msg ) )
       {
          TranslateMessage (&msg);
          DispatchMessage (&msg);
       }
-   }
-   return (int)msg.wParam;
+    }
+    return (int)msg.wParam;
 }
 
 /* Return the argument with all control characters replaced by blanks.  */
@@ -143,7 +141,7 @@ char * plain_chars(char * text, size_t len)
        }
     }
     result[len] = '\0';
-    return(result);
+    return result;
 }
 
 /* Return the argument with all non-control-characters replaced by      */
@@ -162,7 +160,7 @@ char * control_chars(char * text, size_t len)
        }
     }
     result[len] = '\0';
-    return(result);
+    return result;
 }
 
 int char_width;
@@ -236,7 +234,7 @@ LRESULT CALLBACK WndProc (HWND hwnd_arg, UINT message,
            COLS = (client_area.right - client_area.left)/char_width;
            LINES = (client_area.bottom - client_area.top)/char_height;
            generic_init();
-           return(0);
+           return 0;
 
       case WM_CHAR:
            if (wParam == QUIT) {
@@ -244,20 +242,20 @@ LRESULT CALLBACK WndProc (HWND hwnd_arg, UINT message,
            } else {
                do_command((int)wParam);
            }
-           return(0);
+           return 0;
 
       case WM_SETFOCUS:
            CreateCaret(hwnd_arg, NULL, char_width, char_height);
            ShowCaret(hwnd_arg);
            caret_visible = 1;
            update_cursor();
-           return(0);
+           return 0;
 
       case WM_KILLFOCUS:
            HideCaret(hwnd_arg);
            DestroyCaret();
            caret_visible = 0;
-           return(0);
+           return 0;
 
       case WM_LBUTTONUP:
            {
@@ -266,7 +264,7 @@ LRESULT CALLBACK WndProc (HWND hwnd_arg, UINT message,
 
                set_position(xpos / (unsigned)char_width,
                             ypos / (unsigned)char_height);
-               return(0);
+               return 0;
            }
 
       case WM_COMMAND:
@@ -274,24 +272,24 @@ LRESULT CALLBACK WndProc (HWND hwnd_arg, UINT message,
            if (id & EDIT_CMD_FLAG) {
                if (id & REPEAT_FLAG) do_command(REPEAT);
                do_command(CHAR_CMD(id));
-               return( 0 );
+               return 0;
            } else {
              switch(id) {
                case IDM_FILEEXIT:
                   SendMessage(hwnd_arg, WM_CLOSE, 0, 0L);
-                  return( 0 );
+                  return 0;
 
                case IDM_HELPABOUT:
                   if( DialogBox( hInstance, TEXT("ABOUTBOX"),
                                  hwnd_arg, AboutBoxCallback ) )
                      InvalidateRect(hwnd_arg, NULL, TRUE);
-                  return( 0 );
+                  return 0;
                case IDM_HELPCONTENTS:
                   de_error(
                        "Cursor keys: ^B(left) ^F(right) ^P(up) ^N(down)\n"
                        "Undo: ^U    Write: ^W   Quit:^D  Repeat count: ^R[n]\n"
                        "Top: ^T   Locate (search, find): ^L text ^L\n");
-                  return( 0 );
+                  return 0;
              }
            }
            break;

+ 1 - 1
blitz.mod/bdwgc/cord/tests/de_win.h

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.

+ 1 - 1
blitz.mod/bdwgc/cord/tests/de_win.rc

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.

+ 65 - 62
blitz.mod/bdwgc/darwin_stop_world.c

@@ -4,12 +4,13 @@
  * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
  * Copyright (c) 2000-2010 by Hewlett-Packard Development Company.
  * All rights reserved.
+ * Copyright (c) 2008-2022 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -117,7 +118,7 @@ GC_INNER ptr_t GC_FindTopOfStack(unsigned long stack_start)
 /* GC_INIT() (or, at least, before going multi-threaded).  Deprecated.  */
 GC_API void GC_CALL GC_use_threads_discovery(void)
 {
-# if defined(GC_NO_THREADS_DISCOVERY) || defined(DARWIN_DONT_PARSE_STACK)
+# ifdef GC_NO_THREADS_DISCOVERY
     ABORT("Darwin task-threads-based stop and push unsupported");
 # else
 #   ifndef GC_ALWAYS_MULTITHREADED
@@ -126,7 +127,7 @@ GC_API void GC_CALL GC_use_threads_discovery(void)
 #   ifndef GC_DISCOVER_TASK_THREADS
       GC_query_task_threads = TRUE;
 #   endif
-    GC_init_parallel(); /* just to be consistent with Win32 one */
+    GC_init();
 # endif
 }
 
@@ -135,27 +136,28 @@ GC_API void GC_CALL GC_use_threads_discovery(void)
 #endif
 
 /* Evaluates the stack range for a given thread.  Returns the lower     */
-/* bound and sets *phi to the upper one.                                */
+/* bound and sets *phi to the upper one.  Sets *pfound_me to TRUE if    */
+/* this is current thread, otherwise the value is not changed.          */
 STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p,
-                                GC_bool thread_blocked, mach_port_t my_thread,
-                                ptr_t *paltstack_lo,
-                                ptr_t *paltstack_hi GC_ATTR_UNUSED)
+                                mach_port_t my_thread, ptr_t *paltstack_lo,
+                                ptr_t *paltstack_hi, GC_bool *pfound_me)
 {
+# ifdef DARWIN_DONT_PARSE_STACK
+    GC_stack_context_t crtn;
+# endif
   ptr_t lo;
+
   if (thread == my_thread) {
-    GC_ASSERT(!thread_blocked);
+    GC_ASSERT(NULL == p || (p -> flags & DO_BLOCKING) == 0);
     lo = GC_approx_sp();
 #   ifndef DARWIN_DONT_PARSE_STACK
       *phi = GC_FindTopOfStack(0);
 #   endif
-
-  } else if (thread_blocked) {
-#   if defined(CPPCHECK)
-      if (NULL == p) ABORT("Invalid GC_thread passed to GC_stack_range_for");
-#   endif
-    lo = p->stop_info.stack_ptr;
+    *pfound_me = TRUE;
+  } else if (p != NULL && (p -> flags & DO_BLOCKING) != 0) {
+    lo = p -> crtn -> stack_ptr;
 #   ifndef DARWIN_DONT_PARSE_STACK
-      *phi = p->topOfStack;
+      *phi = p -> crtn -> topOfStack;
 #   endif
 
   } else {
@@ -322,20 +324,24 @@ STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p,
 #   endif
   } /* thread != my_thread */
 
-# ifdef DARWIN_DONT_PARSE_STACK
+# ifndef DARWIN_DONT_PARSE_STACK
+    /* TODO: Determine p and handle altstack if !DARWIN_DONT_PARSE_STACK */
+    UNUSED_ARG(paltstack_hi);
+# else
     /* p is guaranteed to be non-NULL regardless of GC_query_task_threads. */
-    *phi = (p->flags & MAIN_THREAD) != 0 ? GC_stackbottom : p->stack_end;
-# endif
-
-  /* TODO: Determine p and handle altstack if !DARWIN_DONT_PARSE_STACK */
-# ifdef DARWIN_DONT_PARSE_STACK
-  if (p->altstack != NULL && (word)p->altstack <= (word)lo
-      && (word)lo <= (word)p->altstack + p->altstack_size) {
-    *paltstack_lo = lo;
-    *paltstack_hi = p->altstack + p->altstack_size;
-    lo = p->stack;
-    *phi = p->stack + p->stack_size;
-  } else
+#   ifdef CPPCHECK
+      if (NULL == p) ABORT("Bad GC_stack_range_for call");
+#   endif
+    crtn = p -> crtn;
+    *phi = EXPECT((p -> flags & MAIN_THREAD) == 0, TRUE) ? crtn -> stack_end
+            : GC_stackbottom;
+    if (crtn -> altstack != NULL && (word)(crtn -> altstack) <= (word)lo
+        && (word)lo <= (word)(crtn -> altstack) + crtn -> altstack_size) {
+      *paltstack_lo = lo;
+      *paltstack_hi = crtn -> altstack + crtn -> altstack_size;
+      lo = crtn -> normstack;
+      *phi = lo + crtn -> normstack_size;
+    } else
 # endif
   /* else */ {
     *paltstack_lo = NULL;
@@ -355,15 +361,16 @@ GC_INNER void GC_push_all_stacks(void)
   GC_bool found_me = FALSE;
   int nthreads = 0;
   word total_size = 0;
-  mach_msg_type_number_t listcount = (mach_msg_type_number_t)THREAD_TABLE_SZ;
-  if (!EXPECT(GC_thr_initialized, TRUE))
-    GC_thr_init();
+
+  GC_ASSERT(I_HOLD_LOCK());
+  GC_ASSERT(GC_thr_initialized);
 
 # ifndef DARWIN_DONT_PARSE_STACK
     if (GC_query_task_threads) {
       int i;
       kern_return_t kern_result;
-      thread_act_array_t act_list = 0;
+      thread_act_array_t act_list;
+      mach_msg_type_number_t listcount;
 
       /* Obtain the list of the threads from the kernel.  */
       kern_result = task_threads(my_task, &act_list, &listcount);
@@ -372,8 +379,8 @@ GC_INNER void GC_push_all_stacks(void)
 
       for (i = 0; i < (int)listcount; i++) {
         thread_act_t thread = act_list[i];
-        ptr_t lo = GC_stack_range_for(&hi, thread, NULL, FALSE, my_thread,
-                                      &altstack_lo, &altstack_hi);
+        ptr_t lo = GC_stack_range_for(&hi, thread, NULL, my_thread,
+                                      &altstack_lo, &altstack_hi, &found_me);
 
         if (lo) {
           GC_ASSERT((word)lo <= (word)hi);
@@ -382,8 +389,6 @@ GC_INNER void GC_push_all_stacks(void)
         }
         /* TODO: Handle altstack */
         nthreads++;
-        if (thread == my_thread)
-          found_me = TRUE;
         mach_port_deallocate(my_task, thread);
       } /* for (i=0; ...) */
 
@@ -394,29 +399,25 @@ GC_INNER void GC_push_all_stacks(void)
   /* else */ {
     int i;
 
-    for (i = 0; i < (int)listcount; i++) {
+    for (i = 0; i < THREAD_TABLE_SZ; i++) {
       GC_thread p;
 
-      for (p = GC_threads[i]; p != NULL; p = p->next)
-        if ((p->flags & FINISHED) == 0) {
-          thread_act_t thread = (thread_act_t)p->stop_info.mach_thread;
-          ptr_t lo = GC_stack_range_for(&hi, thread, p,
-                                        (GC_bool)p->thread_blocked,
-                                        my_thread, &altstack_lo,
-                                        &altstack_hi);
+      for (p = GC_threads[i]; p != NULL; p = p -> tm.next)
+        if (!KNOWN_FINISHED(p)) {
+          thread_act_t thread = (thread_act_t)(p -> mach_thread);
+          ptr_t lo = GC_stack_range_for(&hi, thread, p, my_thread,
+                                        &altstack_lo, &altstack_hi, &found_me);
 
           if (lo) {
             GC_ASSERT((word)lo <= (word)hi);
             total_size += hi - lo;
-            GC_push_all_stack_sections(lo, hi, p->traced_stack_sect);
+            GC_push_all_stack_sections(lo, hi, p -> crtn -> traced_stack_sect);
           }
           if (altstack_lo) {
             total_size += altstack_hi - altstack_lo;
             GC_push_all_stack(altstack_lo, altstack_hi);
           }
           nthreads++;
-          if (thread == my_thread)
-            found_me = TRUE;
         }
     } /* for (i=0; ...) */
   }
@@ -434,9 +435,9 @@ GC_INNER void GC_push_all_stacks(void)
     STATIC mach_port_t GC_mach_handler_thread = 0;
     STATIC GC_bool GC_use_mach_handler_thread = FALSE;
 
-    GC_INNER void GC_darwin_register_mach_handler_thread(mach_port_t thread)
+    GC_INNER void GC_darwin_register_self_mach_handler(void)
     {
-      GC_mach_handler_thread = thread;
+      GC_mach_handler_thread = mach_thread_self();
       GC_use_mach_handler_thread = TRUE;
     }
 # endif /* MPROTECT_VDB */
@@ -545,13 +546,14 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count,
 
 #endif /* !GC_NO_THREADS_DISCOVERY */
 
-/* Caller holds allocation lock.        */
 GC_INNER void GC_stop_world(void)
 {
   task_t my_task = current_task();
   mach_port_t my_thread = mach_thread_self();
   kern_return_t kern_result;
 
+  GC_ASSERT(I_HOLD_LOCK());
+  GC_ASSERT(GC_thr_initialized);
 # ifdef DEBUG_THREADS
     GC_log_printf("Stopping the world from thread %p\n",
                   (void *)(word)my_thread);
@@ -623,19 +625,19 @@ GC_INNER void GC_stop_world(void)
     for (i = 0; i < THREAD_TABLE_SZ; i++) {
       GC_thread p;
 
-      for (p = GC_threads[i]; p != NULL; p = p->next) {
-        if ((p->flags & FINISHED) == 0 && !p->thread_blocked &&
-             p->stop_info.mach_thread != my_thread) {
+      for (p = GC_threads[i]; p != NULL; p = p -> tm.next) {
+        if ((p -> flags & (FINISHED | DO_BLOCKING)) == 0
+            && p -> mach_thread != my_thread) {
           GC_acquire_dirty_lock();
           do {
-            kern_result = thread_suspend(p->stop_info.mach_thread);
+            kern_result = thread_suspend(p -> mach_thread);
           } while (kern_result == KERN_ABORTED);
           GC_release_dirty_lock();
           if (kern_result != KERN_SUCCESS)
             ABORT("thread_suspend failed");
           if (GC_on_thread_event)
             GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED,
-                               (void *)(word)p->stop_info.mach_thread);
+                               (void *)(word)(p -> mach_thread));
         }
       }
     }
@@ -664,7 +666,7 @@ GC_INLINE void GC_thread_resume(thread_act_t thread)
     struct thread_basic_info info;
     mach_msg_type_number_t outCount = THREAD_BASIC_INFO_COUNT;
 
-#   if defined(CPPCHECK) && defined(DEBUG_THREADS)
+#   ifdef CPPCHECK
       info.run_state = 0;
 #   endif
     kern_result = thread_info(thread, THREAD_BASIC_INFO,
@@ -685,11 +687,11 @@ GC_INLINE void GC_thread_resume(thread_act_t thread)
   }
 }
 
-/* Caller holds allocation lock, and has held it continuously since     */
-/* the world stopped.                                                   */
 GC_INNER void GC_start_world(void)
 {
   task_t my_task = current_task();
+
+  GC_ASSERT(I_HOLD_LOCK()); /* held continuously since the world stopped */
 # ifdef DEBUG_THREADS
     GC_log_printf("World starting\n");
 # endif
@@ -758,10 +760,11 @@ GC_INNER void GC_start_world(void)
 
     for (i = 0; i < THREAD_TABLE_SZ; i++) {
       GC_thread p;
-      for (p = GC_threads[i]; p != NULL; p = p->next) {
-        if ((p->flags & FINISHED) == 0 && !p->thread_blocked &&
-             p->stop_info.mach_thread != my_thread)
-          GC_thread_resume(p->stop_info.mach_thread);
+
+      for (p = GC_threads[i]; p != NULL; p = p -> tm.next) {
+        if ((p -> flags & (FINISHED | DO_BLOCKING)) == 0
+            && p -> mach_thread != my_thread)
+          GC_thread_resume(p -> mach_thread);
       }
     }
 

+ 80 - 60
blitz.mod/bdwgc/dbg_mlc.c

@@ -4,12 +4,13 @@
  * Copyright (c) 1997 by Silicon Graphics.  All rights reserved.
  * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
  * Copyright (c) 2007 Free Software Foundation, Inc.
+ * Copyright (c) 2008-2022 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -54,23 +55,19 @@
   }
 #endif /* !SHORT_DBG_HDRS */
 
+#ifdef KEEP_BACK_PTRS
+
 #ifdef LINT2
-  long GC_random(void)
+  static int GC_rand(void)
   {
-    static unsigned seed = 1; /* not thread-safe */
+    static GC_RAND_STATE_T seed;
 
-    /* Linear congruential pseudo-random numbers generator.     */
-    seed = (seed * 1103515245U + 12345) & GC_RAND_MAX; /* overflow is ok */
-    return (long)seed;
+    return GC_RAND_NEXT(&seed);
   }
-#endif
 
-#ifdef KEEP_BACK_PTRS
-
-#ifdef LINT2
-# define RANDOM() GC_random()
+# define RANDOM() (long)GC_rand()
 #else
-# include <stdlib.h>
+# undef GC_RAND_MAX
 # define GC_RAND_MAX RAND_MAX
 
 # if defined(__GLIBC__) || defined(SOLARIS) \
@@ -163,16 +160,17 @@
   GC_API void * GC_CALL GC_generate_random_heap_address(void)
   {
     size_t i;
-    word heap_offset = RANDOM();
+    word heap_offset = (word)RANDOM();
 
-    if (GC_heapsize > GC_RAND_MAX) {
+    if (GC_heapsize > (word)GC_RAND_MAX) {
         heap_offset *= GC_RAND_MAX;
-        heap_offset += RANDOM();
+        heap_offset += (word)RANDOM();
     }
     heap_offset %= GC_heapsize;
         /* This doesn't yield a uniform distribution, especially if     */
-        /* e.g. RAND_MAX = 1.5* GC_heapsize.  But for typical cases,    */
+        /* e.g. RAND_MAX is 1.5*GC_heapsize.  But for typical cases,    */
         /* it's not too bad.                                            */
+
     for (i = 0;; ++i) {
         size_t size;
 
@@ -210,6 +208,7 @@
     size_t offset;
     void *base;
 
+    GC_ASSERT(I_DONT_HOLD_LOCK());
     GC_print_heap_obj((ptr_t)GC_base(current));
 
     for (i = 0; ; ++i) {
@@ -247,24 +246,24 @@
     out:;
   }
 
-  /* Force a garbage collection and generate/print a backtrace  */
-  /* from a random heap address.                                */
-  GC_INNER void GC_generate_random_backtrace_no_gc(void)
-  {
-    void * current;
-    current = GC_generate_random_valid_address();
-    GC_printf("\n****Chosen address %p in object\n", current);
-    GC_print_backtrace(current);
-  }
-
   GC_API void GC_CALL GC_generate_random_backtrace(void)
   {
+    void *current;
+    DCL_LOCK_STATE;
+
+    GC_ASSERT(I_DONT_HOLD_LOCK());
     if (GC_try_to_collect(GC_never_stop_func) == 0) {
       GC_err_printf("Cannot generate a backtrace: "
                     "garbage collection is disabled!\n");
       return;
     }
-    GC_generate_random_backtrace_no_gc();
+
+    /* Generate/print a backtrace from a random heap address.   */
+    LOCK();
+    current = GC_generate_random_valid_address();
+    UNLOCK();
+    GC_printf("\n****Chosen address %p in object\n", current);
+    GC_print_backtrace(current);
   }
 
 #endif /* KEEP_BACK_PTRS */
@@ -272,7 +271,7 @@
 # define CROSSES_HBLK(p, sz) \
         (((word)((p) + sizeof(oh) + (sz) - 1) ^ (word)(p)) >= HBLKSIZE)
 
-GC_INNER void *GC_store_debug_info_inner(void *p, word sz GC_ATTR_UNUSED,
+GC_INNER void *GC_store_debug_info_inner(void *p, word sz,
                                          const char *string, int linenum)
 {
     word * result = (word *)((oh *)p + 1);
@@ -288,7 +287,9 @@ GC_INNER void *GC_store_debug_info_inner(void *p, word sz GC_ATTR_UNUSED,
 #   endif
     ((oh *)p) -> oh_string = string;
     ((oh *)p) -> oh_int = linenum;
-#   ifndef SHORT_DBG_HDRS
+#   ifdef SHORT_DBG_HDRS
+      UNUSED_ARG(sz);
+#   else
       ((oh *)p) -> oh_sz = sz;
       ((oh *)p) -> oh_sf = START_FLAG ^ (word)result;
       ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] =
@@ -328,10 +329,10 @@ static void *store_debug_info(void *p, size_t lb,
     ptr_t body = (ptr_t)(ohdr + 1);
     word gc_sz = GC_size((ptr_t)ohdr);
     if (ohdr -> oh_sz + DEBUG_BYTES > gc_sz) {
-        return((ptr_t)(&(ohdr -> oh_sz)));
+        return (ptr_t)(&(ohdr -> oh_sz));
     }
     if (ohdr -> oh_sf != (START_FLAG ^ (word)body)) {
-        return((ptr_t)(&(ohdr -> oh_sf)));
+        return (ptr_t)(&(ohdr -> oh_sf));
     }
     if (((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1] != (END_FLAG ^ (word)body)) {
         return (ptr_t)(&((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1]);
@@ -340,7 +341,7 @@ static void *store_debug_info(void *p, size_t lb,
         != (END_FLAG ^ (word)body)) {
         return (ptr_t)(&((word *)body)[SIMPLE_ROUNDED_UP_WORDS(ohdr->oh_sz)]);
     }
-    return(0);
+    return NULL;
   }
 #endif /* !SHORT_DBG_HDRS */
 
@@ -474,7 +475,7 @@ STATIC void GC_debug_print_heap_obj_proc(ptr_t p)
   STATIC void GC_print_all_smashed_proc (void);
 #else
   STATIC void GC_do_nothing(void) {}
-#endif
+#endif /* SHORT_DBG_HDRS */
 
 GC_INNER void GC_start_debugging_inner(void)
 {
@@ -539,7 +540,13 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc(size_t lb,
     /* Note that according to malloc() specification, if size is 0 then */
     /* malloc() returns either NULL, or a unique pointer value that can */
     /* later be successfully passed to free(). We always do the latter. */
-    result = GC_malloc(SIZET_SAT_ADD(lb, DEBUG_BYTES));
+#   if defined(_FORTIFY_SOURCE) && !defined(__clang__)
+      /* Workaround to avoid "exceeds maximum object size" gcc warning. */
+      result = GC_malloc(lb < GC_SIZE_MAX - DEBUG_BYTES ? lb + DEBUG_BYTES
+                                                        : GC_SIZE_MAX >> 1);
+#   else
+      result = GC_malloc(SIZET_SAT_ADD(lb, DEBUG_BYTES));
+#   endif
 #   ifdef GC_ADD_CALLER
       if (s == NULL) {
         GC_caller_func_offset(ra, &s, &i);
@@ -589,13 +596,13 @@ STATIC void * GC_debug_generic_malloc(size_t lb, int knd, GC_EXTRA_PARAMS)
     if (NULL == result) {
         GC_err_printf("GC internal allocation (%lu bytes) returning NULL\n",
                        (unsigned long) lb);
-        return(0);
+        return NULL;
     }
     if (!GC_debugging_started) {
         GC_start_debugging_inner();
     }
     ADD_CALL_CHAIN(result, GC_RETURN_ADDR);
-    return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", 0));
+    return GC_store_debug_info_inner(result, (word)lb, "INTERNAL", 0);
   }
 
   GC_INNER void * GC_debug_generic_malloc_inner_ignore_off_page(size_t lb,
@@ -609,13 +616,13 @@ STATIC void * GC_debug_generic_malloc(size_t lb, int knd, GC_EXTRA_PARAMS)
     if (NULL == result) {
         GC_err_printf("GC internal allocation (%lu bytes) returning NULL\n",
                        (unsigned long) lb);
-        return(0);
+        return NULL;
     }
     if (!GC_debugging_started) {
         GC_start_debugging_inner();
     }
     ADD_CALL_CHAIN(result, GC_RETURN_ADDR);
-    return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", 0));
+    return GC_store_debug_info_inner(result, (word)lb, "INTERNAL", 0);
   }
 #endif /* DBG_HDRS_ALL */
 
@@ -625,8 +632,10 @@ STATIC void * GC_debug_generic_malloc(size_t lb, int knd, GC_EXTRA_PARAMS)
     return GC_debug_malloc(lb, OPT_RA s, i);
   }
 
-  GC_API void GC_CALL GC_debug_change_stubborn(
-                                const void * p GC_ATTR_UNUSED) {}
+  GC_API void GC_CALL GC_debug_change_stubborn(const void *p)
+  {
+    UNUSED_ARG(p);
+  }
 #endif /* !CPPCHECK */
 
 GC_API void GC_CALL GC_debug_end_stubborn_change(const void *p)
@@ -748,6 +757,10 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc_uncollectable(size_t lb,
 # endif
 #endif
 
+#ifdef LINT2
+# include "private/gc_alloc_ptrs.h"
+#endif
+
 GC_API void GC_CALL GC_debug_free(void * p)
 {
     ptr_t base;
@@ -777,7 +790,7 @@ GC_API void GC_CALL GC_debug_free(void * p)
         ptr_t clobbered = GC_check_annotated_obj((oh *)base);
         word sz = GC_size(base);
         if (clobbered != 0) {
-          GC_have_errors = TRUE;
+          GC_SET_HAVE_ERRORS(); /* no "release" barrier is needed */
           if (((oh *)base) -> oh_sz == sz) {
             GC_print_smashed_obj(
                   "GC_debug_free: found previously deallocated (?) object at",
@@ -790,7 +803,7 @@ GC_API void GC_CALL GC_debug_free(void * p)
         }
         /* Invalidate size (mark the object as deallocated) */
         ((oh *)base) -> oh_sz = sz;
-#     endif /* SHORT_DBG_HDRS */
+#     endif /* !SHORT_DBG_HDRS */
     }
     if (GC_find_leak
 #       ifndef SHORT_DBG_HDRS
@@ -817,7 +830,11 @@ GC_API void GC_CALL GC_debug_free(void * p)
         /* Update the counter even though the real deallocation */
         /* is deferred.                                         */
         LOCK();
-        GC_bytes_freed += sz;
+#       ifdef LINT2
+          GC_incr_bytes_freed((size_t)sz);
+#       else
+          GC_bytes_freed += sz;
+#       endif
         UNLOCK();
       }
     } /* !GC_find_leak */
@@ -866,7 +883,7 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS)
     if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
         GC_err_printf(
               "GC_debug_realloc called on pointer %p w/o debugging info\n", p);
-        return(GC_realloc(p, lb));
+        return GC_realloc(p, lb);
     }
     hhdr = HDR(base);
     switch (hhdr -> hb_obj_kind) {
@@ -879,11 +896,11 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS)
       case UNCOLLECTABLE:
         result = GC_debug_malloc_uncollectable(lb, OPT_RA s, i);
         break;
-#    ifdef GC_ATOMIC_UNCOLLECTABLE
-      case AUNCOLLECTABLE:
-        result = GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i);
-        break;
-#    endif
+#     ifdef GC_ATOMIC_UNCOLLECTABLE
+        case AUNCOLLECTABLE:
+          result = GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i);
+          break;
+#     endif
       default:
         result = NULL; /* initialized to prevent warning. */
         ABORT_RET("GC_debug_realloc: encountered bad kind");
@@ -900,7 +917,7 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS)
         BCOPY(p, result, old_sz < lb ? old_sz : lb);
       GC_debug_free(p);
     }
-    return(result);
+    return result;
 }
 
 GC_API GC_ATTR_MALLOC void * GC_CALL
@@ -936,13 +953,14 @@ STATIC unsigned GC_n_smashed = 0;
 
 STATIC void GC_add_smashed(ptr_t smashed)
 {
+    GC_ASSERT(I_HOLD_LOCK());
     GC_ASSERT(GC_is_marked(GC_base(smashed)));
     /* FIXME: Prevent adding an object while printing smashed list.     */
     GC_smashed[GC_n_smashed] = smashed;
     if (GC_n_smashed < MAX_SMASHED - 1) ++GC_n_smashed;
       /* In case of overflow, we keep the first MAX_SMASHED-1   */
       /* entries plus the last one.                             */
-    GC_have_errors = TRUE;
+    GC_SET_HAVE_ERRORS();
 }
 
 /* Print all objects on the list.  Clear the list.      */
@@ -968,13 +986,14 @@ STATIC void GC_print_all_smashed_proc(void)
 
 /* Check all marked objects in the given block for validity     */
 /* Avoid GC_apply_to_each_object for performance reasons.       */
-STATIC void GC_check_heap_block(struct hblk *hbp, word dummy GC_ATTR_UNUSED)
+STATIC void GC_CALLBACK GC_check_heap_block(struct hblk *hbp, GC_word dummy)
 {
     struct hblkhdr * hhdr = HDR(hbp);
     word sz = hhdr -> hb_sz;
     word bit_no;
     char *p, *plim;
 
+    UNUSED_ARG(dummy);
     p = hbp->hb_body;
     if (sz > MAXOBJBYTES) {
       plim = p;
@@ -992,10 +1011,11 @@ STATIC void GC_check_heap_block(struct hblk *hbp, word dummy GC_ATTR_UNUSED)
     }
 }
 
-/* This assumes that all accessible objects are marked, and that        */
-/* I hold the allocation lock.  Normally called by collector.           */
+/* This assumes that all accessible objects are marked.         */
+/* Normally called by collector.                                */
 STATIC void GC_check_heap_proc(void)
 {
+  GC_ASSERT(I_HOLD_LOCK());
   GC_STATIC_ASSERT((sizeof(oh) & (GRANULE_BYTES - 1)) == 0);
   /* FIXME: Should we check for twice that alignment?   */
   GC_apply_to_all_blocks(GC_check_heap_block, 0);
@@ -1049,7 +1069,7 @@ STATIC void * GC_make_closure(GC_finalization_proc fn, void * data)
       result -> cl_fn = fn;
       result -> cl_data = data;
     }
-    return((void *)result);
+    return (void *)result;
 }
 
 /* An auxiliary fns to make finalization work correctly with displaced  */
@@ -1093,7 +1113,7 @@ GC_API void GC_CALL GC_debug_register_finalizer(void * obj,
                                         void * *ocd)
 {
     GC_finalization_proc my_old_fn = OFN_UNSET;
-    void * my_old_cd;
+    void * my_old_cd = NULL; /* to avoid "might be uninitialized" warning */
     ptr_t base = (ptr_t)GC_base(obj);
     if (NULL == base) {
         /* We won't collect it, hence finalizer wouldn't be run. */
@@ -1109,7 +1129,7 @@ GC_API void GC_CALL GC_debug_register_finalizer(void * obj,
       GC_register_finalizer(base, 0, 0, &my_old_fn, &my_old_cd);
     } else {
       cd = GC_make_closure(fn, cd);
-      if (cd == 0) return; /* out of memory */
+      if (cd == 0) return; /* out of memory; *ofn and *ocd are unchanged */
       GC_register_finalizer(base, GC_debug_invoke_finalizer,
                             cd, &my_old_fn, &my_old_cd);
     }
@@ -1122,7 +1142,7 @@ GC_API void GC_CALL GC_debug_register_finalizer_no_order
                                      void * *ocd)
 {
     GC_finalization_proc my_old_fn = OFN_UNSET;
-    void * my_old_cd;
+    void * my_old_cd = NULL;
     ptr_t base = (ptr_t)GC_base(obj);
     if (NULL == base) {
         /* We won't collect it, hence finalizer wouldn't be run. */
@@ -1151,7 +1171,7 @@ GC_API void GC_CALL GC_debug_register_finalizer_unreachable
                                      void * *ocd)
 {
     GC_finalization_proc my_old_fn = OFN_UNSET;
-    void * my_old_cd;
+    void * my_old_cd = NULL;
     ptr_t base = (ptr_t)GC_base(obj);
     if (NULL == base) {
         /* We won't collect it, hence finalizer wouldn't be run. */
@@ -1180,7 +1200,7 @@ GC_API void GC_CALL GC_debug_register_finalizer_ignore_self
                                      void * *ocd)
 {
     GC_finalization_proc my_old_fn = OFN_UNSET;
-    void * my_old_cd;
+    void * my_old_cd = NULL;
     ptr_t base = (ptr_t)GC_base(obj);
     if (NULL == base) {
         /* We won't collect it, hence finalizer wouldn't be run. */

+ 24 - 66
blitz.mod/bdwgc/digimars.mak

@@ -2,49 +2,29 @@
 # compiler from www.digitalmars.com
 # Written by Walter Bright
 
-DEFINES=-D_WINDOWS -DGC_DLL -DGC_THREADS -DGC_DISCOVER_TASK_THREADS -DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION -DUSE_MUNMAP
-CFLAGS=-Iinclude -Ilibatomic_ops\src $(DEFINES) -wx -g
+CFLAGS_EXTRA=
+DEFINES=-D_WINDOWS -DGC_DLL -DGC_THREADS -DGC_DISCOVER_TASK_THREADS \
+    -DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE \
+    -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION \
+    -DGC_REQUIRE_WCSDUP -DUSE_MUNMAP
+CFLAGS=-Iinclude -Ilibatomic_ops\src $(DEFINES) -g $(CFLAGS_EXTRA)
 LFLAGS=/ma/implib/co
 CC=sc
 
-.c.obj:
-	$(CC) -c $(CFLAGS) $*
+# Must precede other goals.
+all: gc.dll gc.lib
+
+gc.obj: extra\gc.c
+	$(CC) -c $(CFLAGS) extra\gc.c -ogc.obj
 
 .cpp.obj:
 	$(CC) -c $(CFLAGS) -Aa $*
 
-OBJS=	\
-	allchblk.obj\
-	alloc.obj\
-	blacklst.obj\
-	checksums.obj\
-	dbg_mlc.obj\
-	fnlz_mlc.obj\
-	dyn_load.obj\
-	finalize.obj\
-	gc_badalc.obj\
-	gc_cpp.obj\
-	gcj_mlc.obj\
-	headers.obj\
-	mach_dep.obj\
-	malloc.obj\
-	mallocx.obj\
-	mark.obj\
-	mark_rts.obj\
-	misc.obj\
-	new_hblk.obj\
-	obj_map.obj\
-	os_dep.obj\
-	ptr_chck.obj\
-	reclaim.obj\
-	typd_mlc.obj\
-	win32_threads.obj
-
-targets: gc.dll gc.lib
+OBJS= gc.obj gc_badalc.obj gc_cpp.obj
 
-check: gctest.exe test_cpp.exe
+check: gctest.exe cpptest.exe
 	gctest.exe
-	test_cpp.exe
+	cpptest.exe
 
 gc.lib: gc.dll
 
@@ -60,43 +40,21 @@ gc.def: digimars.mak
 	echo GC_is_valid_displacement_print_proc >>gc.def
 
 clean:
-	del *.log gc.def gc.dll gc.lib gc.map gctest.map test_cpp.map
-	del tests\test.obj gctest.exe tests\test_cpp.obj test_cpp.exe
+	del *.log gc.def gc.dll gc.lib gc.map gctest.map cpptest.map
+	del tests\gctest.obj gctest.exe tests\cpptest.obj cpptest.exe
 	del $(OBJS)
 
-gctest.exe: gc.lib tests\test.obj
-	$(CC) -ogctest.exe tests\test.obj gc.lib
+gctest.exe: gc.lib tests\gctest.obj
+	$(CC) -ogctest.exe tests\gctest.obj gc.lib
 
-tests\test.obj: tests\test.c
-	$(CC) -c $(CFLAGS) tests\test.c -otests\test.obj
+tests\gctest.obj: tests\gctest.c
+	$(CC) -c $(CFLAGS) tests\gctest.c -otests\gctest.obj
 
-test_cpp.exe: gc.lib tests\test_cpp.obj
-	$(CC) -otest_cpp.exe tests\test_cpp.obj gc.lib
+cpptest.exe: gc.lib tests\cpptest.obj
+	$(CC) -ocpptest.exe tests\cpptest.obj gc.lib
 
-tests\test_cpp.obj: tests\test_cpp.cc
-	$(CC) -c $(CFLAGS) -cpp tests\test_cpp.cc -otests\test_cpp.obj
+tests\cpptest.obj: tests\cpp.cc
+	$(CC) -c $(CFLAGS) -cpp tests\cpp.cc -otests\cpptest.obj
 
-allchblk.obj: allchblk.c
-alloc.obj: alloc.c
-blacklst.obj: blacklst.c
-checksums.obj: checksums.c
-dbg_mlc.obj: dbg_mlc.c
-dyn_load.obj: dyn_load.c
-finalize.obj: finalize.c
-fnlz_mlc.obj: fnlz_mlc.c
 gc_badalc.obj: gc_badalc.cc gc_badalc.cpp
 gc_cpp.obj: gc_cpp.cc gc_cpp.cpp
-headers.obj: headers.c
-mach_dep.obj: mach_dep.c
-malloc.obj: malloc.c
-mallocx.obj: mallocx.c
-mark.obj: mark.c
-mark_rts.obj: mark_rts.c
-misc.obj: misc.c
-new_hblk.obj: new_hblk.c
-obj_map.obj: obj_map.c
-os_dep.obj: os_dep.c
-ptr_chck.obj: ptr_chck.c
-reclaim.obj: reclaim.c
-typd_mlc.obj: typd_mlc.c
-win32_threads.obj: win32_threads.c

+ 0 - 6
blitz.mod/bdwgc/doc/README.OS2

@@ -1,6 +0,0 @@
-The code assumes static linking, and a single thread.  The editor de has
-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 how to do partial linking or to build static
-libraries, clients currently need to link against a long list of executables.

+ 17 - 6
blitz.mod/bdwgc/doc/README.cmake

@@ -5,7 +5,7 @@ CMAKE
 Unix and Win32 binaries (both 32- and 64-bit) can be built using CMake.
 CMake is an open-source tool like automake - it generates makefiles.
 
-CMake v3.14.5 is able to generate:
+CMake (as of v3.14.5) is able to generate:
   Borland Makefiles
   MSYS Makefiles
   MinGW Makefiles
@@ -24,23 +24,34 @@ CMake v3.14.5 is able to generate:
 BUILD PROCESS
 -------------
 
+The steps are:
  . install cmake (cmake.org)
  . add directory containing cmake.exe to %PATH%
- . run cmake from the gc root directory, passing the target with -G:
+ . run cmake from the bdwgc root directory, passing the target with -G:
    e.g.,
       > cmake -G "Visual Studio 9 2008" .
-   use the gc.sln file generated by cmake to build gc
- . specify -Denable_cplusplus=ON option to build gccpp (GC C++ support)
+      > use the gc.sln file generated by cmake to build gc
+
+Notes:
+ . specify -Denable_cplusplus=ON option to build gccpp, gctba (GC C++ support)
  . specify -Dbuild_tests=ON option to the tests (and run them by "ctest -V")
  . you can also run cmake from a build directory to build outside of
-   the source tree. Just specify the path to the source tree:
+   the source tree; just specify the path to the source tree:
    e.g.,
       > mkdir out
       > cd out
-      > cmake -G "Visual Studio 9 2008" ..
+      > cmake -G "Visual Studio 9 2008" -Dbuild_tests=ON ..
       > cmake --build . --config Release
       > ctest --build-config Release -V
 
+Here's a sample for Linux (build, test and install, w/o C++ support):
+      > mkdir out
+      > cd out
+      > cmake -Dbuild_tests=ON ..
+      > cmake --build .
+      > ctest
+      > make install
+
 
 INPUT
 -----

+ 4 - 4
blitz.mod/bdwgc/doc/README.environment

@@ -147,10 +147,10 @@ GC_FREE_SPACE_DIVISOR - Set GC_free_space_divisor to the indicated value.
                       Setting it to larger values decreases space consumption
                       and increases GC frequency.
 
-GC_UNMAP_THRESHOLD - Set the desired memory blocks unmapping threshold (the
-                   number of sequential garbage collections for which
-                   a candidate block for unmapping should remain free).  The
-                   special value "0" completely disables unmapping.
+GC_UNMAP_THRESHOLD - Set the desired threshold of memory blocks unmapping
+                   (the number of sequential garbage collections during those
+                   a candidate block for unmapping should be marked as free).
+                   The special value "0" completely disables unmapping.
 
 GC_FORCE_UNMAP_ON_GCOLLECT - Turn "unmap as much as possible on explicit GC"
                 mode on (overrides the default value).  Has no effect on

+ 84 - 63
blitz.mod/bdwgc/doc/README.macros

@@ -24,11 +24,15 @@ either include/private/gcconfig.h or in Makefile.direct.  Here is an attempt
 at documenting these macros:  (Thanks to Walter Bright for suggesting
 this.)
 
+
+The following macros are tested by the public headers (gc.h and others).
+
 MACRO           EXPLANATION
 -----           -----------
 
-GC_DEBUG        Tested by gc.h.  Causes all-upper-case macros to
-                expand to calls to debug versions of collector routines.
+GC_DEBUG        Tested by gc.h (and by gc_cpp.cc).  Causes all-upper-case
+                macros to expand to calls to debug versions of collector
+                routines.
 
 GC_NAMESPACE    Tested by gc_cpp.h. Causes gc_cpp symbols to be defined
                 in "boehmgc" namespace.
@@ -37,13 +41,14 @@ GC_DEBUG_REPLACEMENT    Tested by gc.h. Causes GC_MALLOC/REALLOC() to be
                 defined as GC_debug_malloc/realloc_replacement().
 
 GC_NO_THREAD_REDIRECTS  Tested by gc.h.  Prevents redirection of thread
-                creation routines etc. to GC_ versions.  Requires the
+                creation routines and friends to GC_ versions.  Requires the
                 programmer to explicitly handle thread registration.
 
-GC_NO_THREAD_DECLS      Tested by gc.h.  MS Windows only.  Do not declare
-                Windows thread creation routines and do not include windows.h.
+GC_NO_THREAD_DECLS      Tested by gc.h (and by dyn_load.c, win32_threads.c).
+                Do not declare thread creation (and related) routines and do
+                not include windows.h from gc.h.
 
-GC_DONT_INCLUDE_WINDOWS_H   Tested by gc.h.  MS Windows only.  Do not include
+GC_DONT_INCLUDE_WINDOWS_H   Tested by gc.h.  Windows only.  Do not include
                 windows.h from gc.h (but Windows-specific thread creation
                 routines are declared).
 
@@ -52,12 +57,16 @@ GC_UNDERSCORE_STDCALL   Tested by gc.h.  Explicitly prefix exported/imported
                 used with MinGW (for x86) compiler (in conjunction with
                 GC_DLL) to follow MS conventions for __stdcall symbols naming.
 
-_ENABLE_ARRAYNEW
-                #define'd by the Digital Mars C++ compiler when
-                operator new[] and delete[] are separately
-                overloadable. Used in gc_cpp.h.
+_ENABLE_ARRAYNEW    Tested by gc_cpp.h.  Predefined by the Digital Mars C++
+                compiler when operator new[] and delete[] are separately
+                overloadable.
+
+GC_NO_OPERATOR_NEW_ARRAY    Tested by gc_cpp.h.  Declares that the C++
+                compiler does not support the new syntax "operator new[]" for
+                allocating and deleting arrays.  This is defined implicitly
+                in a few environments.
 
-GC_NO_INLINE_STD_NEW    Tested by gc_cpp.cc and gc_cpp.h.  MS Windows only.
+GC_NO_INLINE_STD_NEW    Tested by gc_cpp.h (and by gc_cpp.cc).  Windows only.
                 Define the system-wide new and delete operators in gccpp.dll
                 instead of providing an inline version of the operators.
 
@@ -67,36 +76,48 @@ _DLL            Tested by gc_config_macros.h. Defined by Visual C++ if runtime
                 __declspec(dllimport) needs to be added to declarations
                 to support the case in which the collector is in a DLL.
 
-GC_DLL          Defined by user if dynamic libraries are being built
-                or used.  Also set by gc.h if _DLL is defined (except for
-                mingw) while GC_NOT_DLL and __GNUC__ are both undefined.
-                This is the macro that is tested internally to determine
-                whether the GC is in its own dynamic library.  May need
-                to be set by clients before including gc.h.  Note that
-                inside the GC implementation it indicates that the
-                collector is in its own dynamic library, should export
-                its symbols, etc.  But in clients it indicates that the
-                GC resides in a different DLL, its entry points should
-                be referenced accordingly, and precautions may need to
-                be taken to properly deal with statically allocated
-                variables in the main program.  Used for MS Windows.
-                Also used by GCC v4+ (only when the dynamic shared library
-                is being built) to hide internally used symbols.
-
-GC_NOT_DLL      User-settable macro that overrides _DLL, e.g. if runtime
-                dynamic libraries are used, but the collector is in a static
-                library.  Tested by gc_config_macros.h.
-
-GC_MARKERS=<n>  Set the desired number of marker threads.  If not defined or
-                defined to zero, then the collector decides based on the
-                number of CPU cores.  Only if compiled with PARALLEL_MARK.
-
-
-These define arguments influence the collector configuration:
-
-GC_REQUIRE_WCSDUP       Force GC to export GC_wcsdup() (the Unicode version
-  of GC_strdup); could be useful in the leak-finding mode.  Clients should
-  define it before including gc.h if the function is needed.
+GC_DLL          Tested by cord.h, gc.h, gc_config_macros.h.  Defined by client
+                if dynamic libraries are being built or used.  Also set by
+                gc.h if _DLL is defined (except for mingw) when GC_NOT_DLL
+                and __GNUC__ are both undefined.  This is the macro that is
+                tested internally to determine whether the GC is in its own
+                dynamic library.  May need to be set by clients before
+                including gc.h.  Note that inside the GC implementation
+                it indicates that the collector is in its own dynamic library,
+                should export its symbols, etc.  But in clients, it indicates
+                that the GC resides in a different DLL, its entry points
+                should be referenced accordingly, and precautions may need to
+                be taken to properly deal with statically allocated variables
+                in the main program.  Used for Windows, and also by GCC v4+
+                (only when the dynamic shared library is being built) to hide
+                internally used symbols.
+
+GC_NOT_DLL      Tested by gc_config_macros.h and gc_cpp.h.  Client-settable
+                macro that overrides _DLL, e.g. if runtime dynamic libraries
+                are used, but the collector is in a static library.
+
+GC_NO_VALLOC    Tested by gc.h and leak_detector.h.  Do not provide GC_valloc
+                and GC_pvalloc functions, and do not redirect the
+                corresponding glibc functions in leak_detector.h.
+
+GC_REQUIRE_WCSDUP   Tested by gc.h and leak_detector.h (and by dbg_mlc.c and
+                mallocx.c).  Force GC to export GC_wcsdup() (the Unicode
+                version of GC_strdup); could be useful in the leak-finding
+                mode.  Clients should define it before including gc.h if the
+                function is needed.
+
+GC_MARKERS=<n>  Tested by gc.h.  Set the desired number of marker threads.
+                If not defined or defined to zero, then the collector decides
+                based on the number of CPU cores.  Only if compiled with
+                PARALLEL_MARK defined.
+
+
+The following macros (-D arguments passed to the compiler) are tested only
+in .c, .cpp files and private headers.  Some of them provide the default
+configuration values, others become hard-coded values for the library.
+
+MACRO           EXPLANATION
+-----           -----------
 
 FIND_LEAK       Causes GC_find_leak to be initially set.  This causes the
   collector to assume that all inaccessible objects should have been
@@ -114,11 +135,11 @@ GC_ABORT_ON_LEAK        Causes the application to be terminated once leaked or
 
 SUNOS5SIGS      Solaris-like signal handling.  This is probably misnamed,
   since it really doesn't guarantee much more than POSIX.  Currently set only
-  for Solaris2.X, HPUX, and DRSNX.  Should probably be set for some other
-  platforms.
+  for DRSNX, FreeBSD, HP/UX and Solaris.
 
 PCR     Set if the collector is being built as part of the Xerox Portable
-  Common Runtime.
+  Common Runtime.  The client might need to define PCR_NO_RENAME and
+  PCR_NO_HOSTDEP_ERR as well.
 
 GC_THREADS      Should set the appropriate one of the below macros,
   except GC_WIN32_PTHREADS, which must be set explicitly.  Tested by gc.h.
@@ -160,8 +181,8 @@ GC_DARWIN_THREADS       Enables support for Mac OS X pthreads.  Deprecated,
 GC_AIX_THREADS  Enables support for IBM AIX threads.  Deprecated, use
   GC_THREADS instead.
 
-GC_DGUX386_THREADS      Enables support for DB/UX on I386 threads.
-  See README.DGUX386.  (Probably has not been tested recently.)  Deprecated,
+GC_DGUX386_THREADS      Enables support for DB/UX x86 threads.
+  See README.dgux386.  (Probably has not been tested recently.)  Deprecated,
   use GC_THREADS instead.
 
 GC_WIN32_THREADS        Enables support for Win32 threads.  Deprecated,
@@ -218,12 +239,6 @@ NO_EXECUTE_PERMISSION   May cause some or all of the heap to not
   GC_set_pages_executable(1) at the process initialization time if the
   execute permission is required.
 
-GC_NO_OPERATOR_NEW_ARRAY        Declares that the C++ compiler does not
-  support the new syntax "operator new[]" for allocating and deleting arrays.
-  See gc_cpp.h for details.  No effect on the C part of the collector.
-  This is defined implicitly in a few environments.  Must also be defined
-  by clients that use gc_cpp.h.
-
 REDIRECT_MALLOC=<X>     Causes malloc to be defined as alias for X.
   Unless the following macros are defined, realloc is also redirected
   to GC_realloc, and free is redirected to GC_free.
@@ -231,7 +246,7 @@ REDIRECT_MALLOC=<X>     Causes malloc to be defined as alias for X.
   be either GC_malloc or GC_malloc_uncollectable, or
   GC_debug_malloc_replacement.  (The latter invokes GC_debug_malloc
   with dummy source location information, but still results in
-  properly remembered call stacks on Linux/X86 and Solaris/SPARC.
+  properly remembered call stacks on Linux/x86 and Solaris/SPARC.
   It requires that the following two macros also be used.)
   The former is occasionally useful for working around leaks in code
   you don't want to (or can't) look at.  It may not work for
@@ -241,7 +256,7 @@ REDIRECT_MALLOC=<X>     Causes malloc to be defined as alias for X.
   you should only use GC_debug_malloc_replacement as a malloc
   replacement.
 
-REDIRECT_REALLOC=<X>    Causes GC_realloc to be redirected to X.
+REDIRECT_REALLOC=<X>    Causes realloc to be redirected to X.
   The canonical use is REDIRECT_REALLOC=GC_debug_realloc_replacement,
   together with REDIRECT_MALLOC=GC_debug_malloc_replacement to
   generate leak reports with call stacks for both malloc and realloc.
@@ -296,7 +311,7 @@ MARK_BIT_PER_OBJ        Requests that a mark bit be allocated for each
   MARK_BIT_PER_GRANULE.
 
 HBLKSIZE=<ddd>  Explicitly sets the heap block size (where ddd is a power of
-  2 between 512 and 16384).  Each heap block is devoted to a single size and
+  2 between 512 and 65536).  Each heap block is devoted to a single size and
   kind of object.  For the incremental collector it makes sense to match
   the most likely page size.  Otherwise large values result in more
   fragmentation, but generally better performance for large heaps.
@@ -311,9 +326,10 @@ USE_MUNMAP      Causes memory to be returned to the OS under the right
 USE_WINALLOC (Cygwin only)   Use Win32 VirtualAlloc (instead of sbrk or mmap)
   to get new memory.  Useful if memory unmapping (USE_MUNMAP) is enabled.
 
-MUNMAP_THRESHOLD=<value>        Set the desired memory blocks unmapping
-  threshold (the number of sequential garbage collections for which
-  a candidate block for unmapping should remain free).
+MUNMAP_THRESHOLD=<value>        Set the default threshold of memory blocks
+  unmapping (the number of sequential garbage collections during those
+  a candidate block for unmapping should be marked as free).  The special
+  value "0" completely disables unmapping.
 
 GC_FORCE_UNMAP_ON_GCOLLECT      Set "unmap as much as possible on explicit GC"
   mode on by default.  The mode could be changed at run-time.  Has no effect
@@ -356,9 +372,9 @@ SHORT_DBG_HDRS  Assume that all objects have debug headers.  Shorten
 SAVE_CALL_COUNT=<n>     Set the number of call frames saved with objects
   allocated through the debugging interface.  Affects the amount of
   information generated in leak reports.  Only matters on platforms
-  on which we can quickly generate call stacks, currently Linux/X86,
+  on which we can quickly generate call stacks, currently Linux/x86,
   Linux/SPARC, Solaris/SPARC, and platforms that provide execinfo.h.
-  Default is zero.  On X86, client code should NOT be compiled with
+  Default is zero.  On x86, client code should NOT be compiled with
   -fomit-frame-pointer.
 
 SAVE_CALL_NARGS=<n>     Set the number of functions arguments to be saved
@@ -373,10 +389,10 @@ GC_GCJ_SUPPORT  Includes support for gcj (and possibly other systems
   that include a pointer to a type descriptor in each allocated object).
 
 USE_I686_PREFETCH       Causes the collector to issue Pentium III style
-  prefetch instructions.  No effect except on Linux/X86 platforms.
+  prefetch instructions.  No effect except on Linux/x86 platforms.
   Empirically the code appears to still run correctly on Pentium II
   processors, though with no performance benefit.  May not run on other
-  X86 processors probably.  In some cases this improves performance by 15%
+  x86 processors probably.  In some cases this improves performance by 15%
   or so.
 
 USE_3DNOW_PREFETCH      Causes the collector to issue AMD 3DNow style
@@ -417,7 +433,6 @@ GC_BUILTIN_ATOMIC       Use GCC atomic intrinsics instead of libatomic_ops
   primitives.
 
 GC_ALWAYS_MULTITHREADED     Force multi-threaded mode at GC initialization.
-  (Turns GC_allow_register_threads into a no-op routine.)
 
 GC_ENABLE_SUSPEND_THREAD (Linux only)   Turn on thread suspend/resume API
 support.
@@ -603,3 +618,9 @@ USE_GET_STACKBASE_FOR_MAIN (Linux only)  Use pthread_attr_getstack() instead
   of __libc_stack_end (or instead of any hard-coded value) for getting the
   primordial thread stack bottom (useful if the client modifies the program's
   address space).
+
+EMSCRIPTEN_ASYNCIFY (Emscripten only)   Use Asyncify feature.  Note this is
+  a relatively rarely used feature of Emscripten, most developers do not use
+  it, and it does not scale well to moderate-to-large code bases.  But the
+  feature is needed to pass gctest, at least.  Requires -sASYNCIFY linker
+  flag.

+ 0 - 11
blitz.mod/bdwgc/doc/README.symbian

@@ -1,11 +0,0 @@
-Instructions for Symbian:
-1. Build: use libgc.mmp
-2. Limitations
-2.1. No multi-threaded support yet
-2.2. Be careful with limitation that emulator introduces: Static roots are not
-dynamically accessible (there are Symbian APIs for this purpose but are just
-stubs, returning irrelevant values).
-Consequently, on emulator, you can only use dlls or exe, and retrieve static
-roots by calling global_init_static_root per dll (or exe).
-On target, only libs are supported, because static roots are retrieved by
-linker flags, by calling global_init_static_root in main exe.

+ 1 - 1
blitz.mod/bdwgc/doc/debugging.md

@@ -21,7 +21,7 @@ there was not other handler previously installed.
 
 We recommend debugging without incremental collection if possible. (This
 applies directly to UNIX systems. Debugging with incremental collection under
-win32 is worse. See README.win32.)
+Win32 is worse. See `README.win32` file.)
 
 If the application generates an unhandled SIGSEGV or equivalent, it may often
 be easiest to set the environment variable `GC_LOOP_ON_ABORT`. On many

+ 1 - 1
blitz.mod/bdwgc/doc/gcdescr.md

@@ -400,7 +400,7 @@ of allocation have taken place. After `GC_full_freq` minor collections a major
 collection is started.
 
 All collections initially run uninterrupted until a predetermined amount
-of time (50 ms by default) has expired. If this allows the collection
+of time (15 ms by default) has expired. If this allows the collection
 to complete entirely, we can avoid correcting for data structure modifications
 during the collection. If it does not complete, we return control to the
 mutator, and perform small amounts of additional GC work during those later

+ 4 - 4
blitz.mod/bdwgc/doc/gcinterface.md

@@ -187,12 +187,12 @@ Users may include `gc_cpp.h` and then cause members of classes to be allocated
 in garbage collectible memory by having those classes inherit from class `gc`.
 For details see `gc_cpp.h` file.
 
-Linking against `libgccpp` in addition to the `gc` library overrides `::new`
+Linking against `gccpp` in addition to the `gc` library overrides `::new`
 (and friends) to allocate traceable but uncollectible memory, making
 it safe to refer to collectible objects from the resulting memory.
 
 If the user includes `gc_cpp.h` but `::new` should not be overridden then
-`libgctba` (in addition to the `gc`) library should be linked with to provide
+`gctba` (in addition to the `gc`) library should be linked with to provide
 the definition of `GC_throw_bad_alloc` C++ function used by operator `new` of
 class `gc`. Alternatively, the client may define `GC_NEW_ABORTS_ON_OOM` macro
 before include of `gc_cpp.h` (this instructs `::new` to issue an abort instead
@@ -206,11 +206,11 @@ It is also possible to use the C interface from `gc.h` directly. On platforms
 which use `malloc` to implement `::new`, it should usually be possible to use
 a version of the collector that has been compiled as a `malloc` replacement.
 It is also possible to replace `::new` and other allocation functions
-suitably, as is done by `libgccpp`.
+suitably, as is done by `gccpp`.
 
 Note that user-implemented small-block allocation often works poorly with
 an underlying garbage-collected large block allocator, since the collector has
 to view all objects accessible from the user's free list as reachable. This
 is likely to cause problems if `GC_MALLOC` is used with something like the
 original HP version of STL. This approach works well with the SGI versions
-of the STL only if the `malloc_alloc` allocator is used.
+of the STL only if the STL "malloc_alloc" allocator is used.

+ 15 - 15
blitz.mod/bdwgc/doc/leak.md

@@ -35,12 +35,12 @@ To use the collector as a leak detector, do the following steps:
 
 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`, `free` (as well as `strdup`,
-`strndup`, `wcsdup`, `memalign`, `posix_memalign`) 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 the
-information about how objects were allocated. The error reports will include
-only object addresses.
+defining `malloc`, `calloc`, `realloc`, `free` (as well as `posix_memalign`,
+`reallocarray`, `strdup`, `strndup`, `wcsdup`, BSD `memalign`, GNU `valloc`,
+GNU `pvalloc`) to call the corresponding garbage collector function. But this,
+by itself, will not yield very informative diagnostics, since the collector
+does not keep track of the 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
@@ -57,7 +57,7 @@ The same is generally true of thread support. However, the correct leak
 reports should be generated with linuxthreads, at least.
 
 On a few platforms (currently Solaris/SPARC, Irix, and, with
-`-DSAVE_CALL_CHAIN`, Linux/X86), `GC_MALLOC` also causes some more information
+`-DSAVE_CALL_CHAIN`, Linux/x86), `GC_MALLOC` also causes some more information
 about its call stack to be saved in the object. Such information is reproduced
 in the error reports in very non-symbolic form, but it can be very useful with
 the aid of a debugger.
@@ -70,18 +70,18 @@ distribution.
 Assume the collector has been built with `-DFIND_LEAK` or
 `GC_set_find_leak(1)` exists as the first statement in `main`.
 
-The program to be tested for leaks could look like `tests/leak_test.c` file
+The program to be tested for leaks could look like `tests/leak.c` file
 of the distribution.
 
-On an Intel X86 Linux system this produces on the stderr stream:
+On a Linux/x86 system this produces on the stderr stream:
 
 
     Found 1 leaked objects:
-    0x806dff0 (tests/leak_test.c:19, sz=4, NORMAL)
+    0x806dff0 (tests/leak.c:19, sz=4, NORMAL)
 
 
 (On most unmentioned operating systems, the output is similar to this. If the
-collector had been built on Linux/X86 with `-DSAVE_CALL_CHAIN`, the output
+collector had been built on Linux/x86 with `-DSAVE_CALL_CHAIN`, the output
 would be closer to the Solaris example. For this to work, the program should
 not be compiled with `-fomit_frame_pointer`.)
 
@@ -89,7 +89,7 @@ On Irix it reports:
 
 
     Found 1 leaked objects:
-    0x10040fe0 (tests/leak_test.c:19, sz=4, NORMAL)
+    0x10040fe0 (tests/leak.c:19, sz=4, NORMAL)
             Caller at allocation:
                     ##PC##= 0x10004910
 
@@ -98,7 +98,7 @@ and on Solaris the error report is:
 
 
     Found 1 leaked objects:
-    0xef621fc8 (tests/leak_test.c:19, sz=4, NORMAL)
+    0xef621fc8 (tests/leak.c:19, sz=4, NORMAL)
             Call chain at allocation:
                     args: 4 (0x4), 200656 (0x30FD0)
                     ##PC##= 0x14ADC
@@ -118,12 +118,12 @@ In many cases, a debugger is needed to interpret the additional information.
 On systems supporting the `adb` debugger, the `tools/callprocs.sh` script can
 be used to replace program counter values with symbolic names. The collector
 tries to generate symbolic names for call stacks if it knows how to do so on
-the platform. This is true on Linux/X86, but not on most other platforms.
+the platform. This is true on Linux/x86, but not on most other platforms.
 
 ## Simplified leak detection under Linux
 
 It should be possible to run the collector in the leak detection mode on
-a program a.out under Linux/X86 as follows:
+a program a.out under Linux/x86 as follows:
 
   1. If possible, ensure that a.out is a single-threaded executable. On some
   platforms this does not work at all for the multi-threaded programs.

+ 36 - 19
blitz.mod/bdwgc/doc/overview.md

@@ -1,5 +1,5 @@
-[Interface Overview](gcinterface.md) | [Tutorial Slides](http://www.hboehm.info/gc/04tutorial.pdf) | [FAQ](http://www.hboehm.info/gc/faq.html) | [Example](simple_example.md) | [Download](https://github.com/ivmai/bdwgc/wiki/Download) | [License](http://www.hboehm.info/gc/license.txt)
----|---|---|---|---|---
+[Interface Overview](gcinterface.md) | [Tutorial Slides](http://www.hboehm.info/gc/04tutorial.pdf) | [FAQ](http://www.hboehm.info/gc/faq.html) | [Example](simple_example.md) | [Download](https://github.com/ivmai/bdwgc/wiki/Download)
+---|---|---|---|---
 
 # A garbage collector for C and C++
 
@@ -7,6 +7,7 @@
   * Some collector details
   * Further reading
   * Information provided on the BDWGC site
+  * Documentation files
   * More background information
   * Contacts and new release announcements
 
@@ -43,9 +44,7 @@ The development version (snapshot) is available in the master branch of
 [bdwgc git](https://github.com/ivmai/bdwgc) repository on GitHub.
 
 The arguments for and against conservative garbage collection in C and C++ are
-briefly discussed [here](http://www.hboehm.info/gc/issues.html). The
-beginnings of a frequently-asked-questions list are
-[here](http://www.hboehm.info/gc/faq.html).
+briefly discussed [here](http://www.hboehm.info/gc/issues.html).
 
 The garbage collector code is copyrighted by
 [Hans-J. Boehm](http://www.hboehm.info), Alan J. Demers,
@@ -54,8 +53,7 @@ The garbage collector code is copyrighted by
 [Hewlett-Packard Company](http://www.hp.com/),
 [Ivan Maidanski](https://github.com/ivmai), and partially by some others.
 It may be used and copied without payment of a fee under minimal restrictions.
-See the LICENSE file in the distribution or the
-[license](http://www.hboehm.info/gc/license.txt) for more details.
+See the LICENSE file in the distribution for more details.
 **IT IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED OR IMPLIED.
 ANY USE IS AT YOUR OWN RISK.**
 
@@ -75,6 +73,9 @@ platforms are more polished (better supported) than others.
 Irix pthreads, Linux threads, Windows threads, Solaris threads (pthreads
 only), HP/UX 11 pthreads, Tru64 pthreads, and MacOS X threads are supported.
 
+See also [here](porting.md) for the instructions on how to port the library to
+new platforms.
+
 ## Some Collector Details
 
 The collector uses a [mark-sweep](http://www.hboehm.info/gc/complexity.html)
@@ -91,8 +92,9 @@ For an overview of the implementation, see [here](gcdescr.md).
 
 The garbage collector distribution includes a C string (`cord.h`) package that
 provides for fast concatenation and substring operations on long strings.
-A simple curses- and win32-based editor that represents the entire file as
-a cord is included as a sample application.
+A simple curses- and Windows-based editor that represents the entire file as
+a cord is included as a sample application.  See [README.cords](README.cords)
+file for the details.
 
 Performance of the non-incremental collector is typically competitive with
 `malloc`/`free` implementations. Both space and time overhead are likely to be
@@ -111,9 +113,6 @@ for garbage collection.
 
 ## Further reading
 
-**The beginnings of a frequently asked questions list for this collector are
-[here](http://www.hboehm.info/gc/faq.html).**
-
 **The following provide information on garbage collection in general:**
 
 Paul Wilson's
@@ -224,14 +223,22 @@ Slides for Hans Boehm's
 
 [Current users](https://github.com/ivmai/bdwgc/wiki/Known-clients) list.
 
-[A simple illustration of how to build and use the collector](simple_example.md).
-
-[Description of alternate interfaces to the garbage collector](gcinterface.md).
-
 [Slides from an ISMM 2004 tutorial about the GC](http://www.hboehm.info/gc/04tutorial.pdf).
 
 [A FAQ (frequently asked questions) list](http://www.hboehm.info/gc/faq.html).
 
+[Directory](http://www.hboehm.info/gc/gc_source/) containing the distribution
+files of all garbage collector releases.  It duplicates
+[Download](https://github.com/ivmai/bdwgc/wiki/Download) page on GitHub.
+
+## Documentation files
+
+The following documents are not platform-specific in general.
+
+[A simple illustration of how to build and use the collector](simple_example.md).
+
+[Description of alternate interfaces to the garbage collector](gcinterface.md).
+
 [How to use the garbage collector as a leak detector](leak.md).
 
 [Some hints on debugging garbage collected applications](debugging.md).
@@ -242,9 +249,19 @@ Slides for Hans Boehm's
 
 [Scalability of the collector to multiprocessors](scale.md).
 
-[Directory](http://www.hboehm.info/gc/gc_source/) containing the distribution
-files of all garbage collector releases. It duplicates
-[Download](https://github.com/ivmai/bdwgc/wiki/Download) page on GitHub.
+[Instructions on building the library using autoconf/configure](README.autoconf).
+
+[Instructions on building the library using cmake](README.cmake).
+
+[List of environment variables that affect the collector operation at runtime](README.environment).
+
+[List of compile time macros that affect the library when built](README.macros).
+
+[Details on the finalization facility](finalization.md).
+
+[Instructions on how to port the library to new platforms](porting.md).
+
+[Description of the cord library built on top of GC](README.cords).
 
 ## More background information
 

+ 0 - 0
blitz.mod/bdwgc/doc/README.aix → blitz.mod/bdwgc/doc/platforms/README.aix


+ 13 - 7
blitz.mod/bdwgc/doc/README.amiga → blitz.mod/bdwgc/doc/platforms/README.amiga

@@ -3,7 +3,7 @@
 Compiles under SAS/C again. Should also still compile under other
 Amiga compilers without big changes. I haven't checked if it still
 works under gcc, because I don't have gcc for Amiga. But I have
-updated 'Makefile', and hope it compiles fine.
+updated Makefile.direct, and hope it compiles fine.
 
 
 WHATS NEW:
@@ -105,12 +105,18 @@ WHATS NEW:
 
 2. A few small compiler-specific additions to make it compile with SAS/C again.
 
-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 typing "smake -f SMakefile.amiga", both gc.lib and
-   cord.lib will be made.
+3. To build the collector with SAS/C, create SMakefile including the following
+   specific content:
 
+IGNORE= IGNORE=85 IGNORE=154 IGNORE=161 IGNORE=100
+OPTIMIZE=optimize optimizetime optglobal optimizerdepth=100 optimizerpeephole optloop OPTSCHED optimizerinlocal optimizerrecurdepth=100
+OPT= $(OPTIMIZE) NOSTACKCHECK MAPHUNK NOVERSION NOICONS nodebug parm=reg
+
+DEFINE __USE_SYSBASE DEFINE AMIGA_SKIP_SEG DEFINE GC_ATOMIC_UNCOLLECTABLE
+DEFINE GC_AMIGA_FASTALLOC GC_AMIGA_RETRY GC_AMIGA_PRINTSTATS GC_AMIGA_GC
+
+DEFINE GC_AMIGA_MAKINGLIB
+DEFINE AMIGA IGNORE=100 IGNORE=161
 
 
 STILL MISSING:
@@ -135,7 +141,7 @@ tested with hardware: MC68060
                            Martin Tauchmann's notes             (1-Apr-99)
 
 Works now, also with the GNU-C compiler V2.7.2.1. <ftp://ftp.unina.it/pub/amiga/geekgadgets/amiga/m68k/snapshots/971125/amiga-bin/>
-Modify the `Makefile`
+Modify the `Makefile.direct`
 CC=cc $(ABI_FLAG)
 to
 CC=gcc $(ABI_FLAG)

+ 0 - 0
blitz.mod/bdwgc/doc/README.arm.cross → blitz.mod/bdwgc/doc/platforms/README.arm_cross


+ 0 - 0
blitz.mod/bdwgc/doc/README.darwin → blitz.mod/bdwgc/doc/platforms/README.darwin


+ 0 - 0
blitz.mod/bdwgc/doc/README.DGUX386 → blitz.mod/bdwgc/doc/platforms/README.dgux386


+ 0 - 0
blitz.mod/bdwgc/doc/README.emscripten → blitz.mod/bdwgc/doc/platforms/README.emscripten


+ 0 - 0
blitz.mod/bdwgc/doc/README.ews4800 → blitz.mod/bdwgc/doc/platforms/README.ews4800


+ 0 - 0
blitz.mod/bdwgc/doc/README.hp → blitz.mod/bdwgc/doc/platforms/README.hp


+ 0 - 0
blitz.mod/bdwgc/doc/README.linux → blitz.mod/bdwgc/doc/platforms/README.linux


+ 9 - 28
blitz.mod/bdwgc/doc/README.Mac → blitz.mod/bdwgc/doc/platforms/README.mac

@@ -53,8 +53,8 @@ As for target settings the major obstacles may be:
 
 What you need to do:
 1) Build the GC as a library
-2) Test that the library works with 'test.c'.
-3) Test that the C++ interface 'gc_cpp.cc/h' works with 'test_cpp.cc'.
+2) Test that the library works with 'gctest.c'.
+3) Test that the C++ interface 'gc_cpp.h' works with 'tests/cpp.cc'.
 
 == 1. The Libraries ==
 
@@ -193,38 +193,19 @@ struct gc_private_assert_intsize_{ char x[ sizeof(int)>=4 ? 1 : 0 ]; };
 
 Files to build the GC libraries:
 --------------------------------
-    allchblk.c
-    alloc.c
-    blacklst.c
-    checksums.c
-    dbg_mlc.c
-    finalize.c
-    fnlz_mlc.c
-    headers.c
-    mach_dep.c
+    extra/gc.c
     extra/MacOS.c -- contains MacOS code
-    malloc.c
-    mallocx.c
-    mark.c
-    mark_rts.c
-    misc.c
-    new_hblk.c
-    obj_map.c
-    os_dep.c   -- contains MacOS code
-    ptr_chck.c
-    reclaim.c
-    typd_mlc.c
     gc_badalc.cc
     gc_cpp.cc
 
-== 2. Test that the library works with 'test.c' ==
+== 2. Test that the library works with 'gctest.c' ==
 
 The test app is just an ordinary ANSI-C console app. Make sure settings
 match the library you're testing.
 
 Files
 -----
-    test.c
+    gctest.c
     the GC library to test        -- link order before ANSI libs
     suitable Mac+ANSI libraries
 
@@ -238,23 +219,23 @@ prefix:
 #define ALL_INTERIOR_POINTERS   /* for GC_priv.h */
 ---- ( cut here ) ----
 
-== 3. Test that the C++ interface 'gc_cpp.cc/h' works with 'test_cpp.cc' ==
+== 3. Test that the C++ interface 'gc_cpp.h' works with 'tests/cpp.cc' ==
 
 The test app is just an ordinary ANSI-C console app. Make sure settings match
 the library you're testing.
 
 Files
 -----
-    test_cpp.cc
+    tests/cpp.cc
     the GC library to test        -- link order before ANSI libs
     suitable Mac+ANSI libraries
 
 prefix:
 ------
-same as for test.c
+same as for gctest.c
 
 For convenience I used one test-project with several targets so that all
-test apps are build at once. Two for each library to test: test.c and
+test apps are build at once. Two for each library to test: gctest.c and
 gc_app.cc. When I was satisfied that the libraries were OK. I put the
 libraries + gc.h + the c++ interface-file in a folder that I then put into
 the MSL hierarchy so that I don't have to alter access-paths in projects

+ 13 - 0
blitz.mod/bdwgc/doc/platforms/README.os2

@@ -0,0 +1,13 @@
+The code assumes static linking, and a single thread.  The editor de has
+not been ported; the cord test program has.  The supplied WCC_MAKEFILE should
+work for OS/2 but was not tested on.
+
+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.
+
+Notes:
+* adding dynamic linking support seems easy, but was not done;
+* adding thread support may be nontrivial, since we have not yet figured out
+  how to look at another thread's registers;
+* setjmp_test may yield overly optimistic results when compiled without
+  optimization.

+ 0 - 0
blitz.mod/bdwgc/doc/README.sgi → blitz.mod/bdwgc/doc/platforms/README.sgi


+ 1 - 1
blitz.mod/bdwgc/doc/README.solaris2 → blitz.mod/bdwgc/doc/platforms/README.solaris2

@@ -41,7 +41,7 @@ Unless USE_PROC_FOR_LIBRARIES is defined, dlopen disables collection
 temporarily.  In some unlikely cases, this can result in unpleasant heap
 growth.  But it seems better than the race/deadlock issues we had before.
 
-If threads are used on an X86 processor with malloc redirected to
+If threads are used on an x86 processor with malloc redirected to
 GC_malloc, it is necessary to call GC_INIT explicitly before forking the
 first thread.  (This avoids a deadlock arising from calling GC_thr_init
 with the allocation lock held.)

+ 65 - 0
blitz.mod/bdwgc/doc/platforms/README.symbian

@@ -0,0 +1,65 @@
+Instructions for Symbian:
+1. Build: use libgc.mmp (the sample for s60v3 is provided below)
+2. Limitations
+2.1. No multi-threaded support yet
+2.2. Be careful with limitation that emulator introduces: Static roots are not
+dynamically accessible (there are Symbian APIs for this purpose but are just
+stubs, returning irrelevant values).
+Consequently, on emulator, you can only use dlls or exe, and retrieve static
+roots by calling global_init_static_root per dll (or exe).
+On target, only libs are supported, because static roots are retrieved by
+linker flags, by calling global_init_static_root in main exe.
+
+
+bld.inf sample contents:
+
+PRJ_PLATFORMS
+default armv5
+
+PRJ_MMPFILES
+libgc.mmp
+
+
+libgc.mmp sample contents:
+
+TARGET libgc.dll
+
+TARGETTYPE dll
+UID 0x1000008d 0x200107C2 // check uid
+
+EXPORTUNFROZEN
+EPOCALLOWDLLDATA
+
+CAPABILITY PowerMgmt ReadDeviceData ReadUserData WriteDeviceData WriteUserData SwEvent LocalServices NetworkServices UserEnvironment
+
+MACRO ALL_INTERIOR_POINTERS
+MACRO NO_EXECUTE_PERMISSION
+MACRO USE_MMAP
+MACRO GC_ATOMIC_UNCOLLECTABLE
+MACRO GC_DONT_REGISTER_MAIN_STATIC_DATA
+MACRO GC_DLL
+MACRO JAVA_FINALIZATION
+MACRO SYMBIAN
+MACRO ENABLE_DISCLAIM
+
+USERINCLUDE .\include
+USERINCLUDE .\include\private
+
+SYSTEMINCLUDE \epoc32\include
+SYSTEMINCLUDE \epoc32\include\stdapis
+
+SOURCEPATH .
+
+SOURCE extra/gc.c
+SOURCE extra/symbian.cpp
+
+SOURCE extra/symbian/global_end.cpp
+SOURCE extra/symbian/global_start.cpp
+SOURCE extra/symbian/init_global_static_roots.cpp
+
+STATICLIBRARY libcrt0.lib
+LIBRARY libc.lib
+LIBRARY euser.lib
+LIBRARY efsrv.lib
+LIBRARY avkon.lib
+LIBRARY eikcore.lib

+ 0 - 0
blitz.mod/bdwgc/doc/README.uts → blitz.mod/bdwgc/doc/platforms/README.uts


+ 6 - 6
blitz.mod/bdwgc/doc/README.win32 → blitz.mod/bdwgc/doc/platforms/README.win32

@@ -1,6 +1,6 @@
 The collector has at various times been compiled under Windows 95 and later,
 NT, and XP, with the original Microsoft SDK, with Visual C++ 2.0, 4.0, and 6,
-with the GNU win32 tools, with Borland C++ Builder, with Watcom C, with EMX,
+with the GNU Win32 tools, with Borland C++ Builder, with Watcom C, with EMX,
 and with the Digital Mars compiler (DMC).
 
 For historical reasons,
@@ -15,7 +15,7 @@ message.
 
 A toy editor (de.exe) based on cords (heavyweight
 strings represented as trees) has been ported and is included.
-It runs fine under either win32 or win32S.  It serves as an example
+It runs fine under either Win32 or win32s.  It serves as an example
 of a true Windows application, except that it was written by a
 nonexpert Windows programmer.  (There are some peculiarities
 in the way files are displayed.  The <cr> is displayed explicitly
@@ -65,7 +65,7 @@ GNU Tools
 The collector should be buildable under Cygwin with the
 "./configure; make check" machinery.
 
-MinGW builds (including for x86_64) are available both directly (on a Windows
+MinGW builds (including for x64) are available both directly (on a Windows
 host) and via cross-compilation, e.g.
 "./configure --host=i686-pc-mingw32; make check"
 
@@ -104,9 +104,9 @@ Watcom compiler
 Ivan V. Demakov's README for the Watcom port:
 
 The collector has been tested with Watcom C 10.6, 11.0 and OpenWatcom 2.0.
-It runs under win32, win32s, and even under msdos with dos4gw
+It runs under Win32 and win32s, and even under DOS with dos4gw
 dos-extender. It should also run under OS/2, though this isn't
-tested. Under win32 the collector can be built either as dll
+tested. Under Win32 the collector can be built either as dll
 or as static library.
 
 Note that all compilations were done under Windows 95 or NT.
@@ -201,7 +201,7 @@ equivalent of _beginthread, and it should not be used.
 
 GC_INIT should be called from the main thread before other GC calls.
 
-We strongly advise against using the TerminateThread() win32 API call,
+We strongly advise against using the TerminateThread() Windows API call,
 especially with the garbage collector.  Any use is likely to provoke a
 crash in the GC, since it makes it impossible for the collector to
 correctly track threads.

+ 3 - 3
blitz.mod/bdwgc/doc/README.win64 → blitz.mod/bdwgc/doc/platforms/README.win64

@@ -1,5 +1,5 @@
-64-bit Windows on AMD64/Intel EM64T is supported.  A collector can be built
-with Microsoft Visual C++ 2005 or with mingw-w64 gcc.
+64-bit Windows on AMD64/Intel EM64T (x64) is supported.  A collector can be
+built with Microsoft Visual C++ 2005 or with mingw-w64 gcc.
 
 NT_MAKEFILE has been used in this environment.  Type
 "nmake -f NT_MAKEFILE cpu=AMD64 nodebug=1" in a Visual C++ command line
@@ -9,7 +9,7 @@ To verify that the collector is at least somewhat functional,
 type "nmake -f NT_MAKEFILE cpu=AMD64 check" to build and run the usual test
 programs.  This should create gctest.gc.log after a few seconds.
 
-Test_cpp.exe might not run correctly in case of dynamic GC linking.  (It seems
+cpptest.exe might not run correctly in case of dynamic GC linking.  (It seems
 that we're getting wrong instances of operator new/delete in some cases.)
 
 This process is completely analogous to NT_MAKEFILE usage

+ 1 - 1
blitz.mod/bdwgc/doc/porting.md

@@ -78,7 +78,7 @@ operating system:
   * `ALIGNMENT` - Defined to be the largest _N_ such that all pointer
   are guaranteed to be aligned on _N_-byte boundaries. Defining it to be _1_
   will always work, but perform poorly. For all modern 32-bit platforms, this
-  is 4. For all modern 64-bit platforms, this is 8. Whether or not X86
+  is 4. For all modern 64-bit platforms, this is 8. Whether or not x86
   qualifies as a modern architecture here is compiler- and OS-dependent.
   * `DATASTART` - The beginning of the main data segment. The collector will
   trace all memory between `DATASTART` and `DATAEND` for root pointers.

+ 4 - 3
blitz.mod/bdwgc/doc/scale.md

@@ -38,9 +38,10 @@ to Makefile.direct again.)
   collector itself, though not the allocation process. Currently the marking
   is performed by the thread that triggered the collection, together with
   _N_ - 1 dedicated threads, where _N_ is the number of processors (cores)
-  detected by the collector. The dedicated marker threads are created at
-  initialization time (and optionally recreated in child processes after
-  forking). Another effect of this flag is to switch to a more
+  detected by the collector. The dedicated marker threads are created when the
+  client calls `GC_start_mark_threads()` or when the client starts the first
+  non-main thread after the GC initialization (or after fork operation in
+  a child process). Another 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

+ 3 - 3
blitz.mod/bdwgc/doc/simple_example.md

@@ -31,8 +31,8 @@ a basic correctness test which usually takes well under a minute.
 ### Other platforms
 
 On non-Unix, non-Linux platforms, the collector is usually built by copying
-the appropriate makefile (see the platform-specific README in doc/README.xxx
-in the distribution) to the file "Makefile", and then typing `make` (or
+the appropriate makefile (see the platform-specific README in `doc/platforms`
+folder in the distribution) to the file `Makefile`, and then typing `make` (or
 `nmake` or ...). This builds the library in the source tree. You may want
 to move it and the files in the include directory to a more convenient place.
 
@@ -179,4 +179,4 @@ The executable can of course be run normally, e.g. by typing:
 
 The operation of the collector is affected by a number of environment
 variables. For example, setting `GC_PRINT_STATS` produces some GC statistics
-on stdout. See `README.environment` in the distribution for details.
+on stdout. See [README.environment](README.environment) file for the details.

+ 4 - 2
blitz.mod/bdwgc/doc/tree.md

@@ -122,7 +122,7 @@ contributed originally by Dave Barrett.
            |   +--------------+                      |   +-+-+-----+-+-+-+-+   |
            |   |  hash_link   |                      |   | | |     | | | | |   v
            |   +--------------+                      |   +-+-+-----+-+-+-+-+  ---
-           |                                         |   |<----MAP_LEN---->|
+           |                                         |   |<--OBJ_MAP_LEN-->|
            |                                         |   =HBLKSIZE/GRANULE_BYTES
      HDR(p)| GC_find_header(p)                       |    (1024 on Alpha)
            |                           \ from        |    (8/16 bits each)
@@ -136,7 +136,9 @@ contributed originally by Dave Barrett.
                 +----------------------+             |
                 | char * hb_map        |>------------+
                 +----------------------+
-                | ushort hb_obj_kind   |
+                |   uchar hb_obj_kind  |
+                +----------------------+
+                |    uchar hb_flags    |
                 +----------------------+
                 |   hb_last_reclaimed  |
        ---      +----------------------+

+ 53 - 42
blitz.mod/bdwgc/dyn_load.c

@@ -1,13 +1,13 @@
 /*
  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 1997 by Silicon Graphics.  All rights reserved.
- * Copyright (c) 2009-2021 Ivan Maidanski
+ * Copyright (c) 2009-2022 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -68,7 +68,6 @@ STATIC GC_has_static_roots_func GC_has_static_roots = 0;
 # error Additional SVR4 variants might not be too hard to add.
 #endif
 
-#include <stdio.h>
 #ifdef SOLARISDL
 #   include <sys/elf.h>
 #   include <dlfcn.h>
@@ -140,29 +139,29 @@ STATIC GC_has_static_roots_func GC_has_static_roots = 0;
 
 /* Newer versions of GNU/Linux define this macro.  We
  * define it similarly for any ELF systems that don't.  */
-#  ifndef ElfW
-#    if defined(FREEBSD)
-#      if __ELF_WORD_SIZE == 32
-#        define ElfW(type) Elf32_##type
-#      else
-#        define ElfW(type) Elf64_##type
-#      endif
-#    elif defined(NETBSD) || defined(OPENBSD)
-#      if ELFSIZE == 32
-#        define ElfW(type) Elf32_##type
-#      elif ELFSIZE == 64
-#        define ElfW(type) Elf64_##type
-#      else
-#        error Missing ELFSIZE define
-#      endif
-#    else
-#      if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
-#        define ElfW(type) Elf32_##type
-#      else
-#        define ElfW(type) Elf64_##type
-#      endif
-#    endif
-#  endif
+# ifndef ElfW
+#   if defined(FREEBSD)
+#     if __ELF_WORD_SIZE == 32
+#       define ElfW(type) Elf32_##type
+#     else
+#       define ElfW(type) Elf64_##type
+#     endif
+#   elif defined(NETBSD) || defined(OPENBSD)
+#     if ELFSIZE == 32
+#       define ElfW(type) Elf32_##type
+#     elif ELFSIZE == 64
+#       define ElfW(type) Elf64_##type
+#     else
+#       error Missing ELFSIZE define
+#     endif
+#   else
+#     if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
+#       define ElfW(type) Elf32_##type
+#     else
+#       define ElfW(type) Elf64_##type
+#     endif
+#   endif
+# endif
 
 #if defined(SOLARISDL) && !defined(USE_PROC_FOR_LIBRARIES)
 
@@ -193,7 +192,7 @@ STATIC GC_has_static_roots_func GC_has_static_roots = 0;
 
     if (0 == COVERT_DATAFLOW(dynStructureAddr)) {
         /* _DYNAMIC symbol not resolved. */
-        return(0);
+        return NULL;
     }
     if (cachedResult == 0) {
         int tag;
@@ -232,6 +231,7 @@ GC_INNER void GC_register_dynamic_libraries(void)
 {
   struct link_map *lm;
 
+  GC_ASSERT(I_HOLD_LOCK());
   for (lm = GC_FirstDLOpenedLinkMap(); lm != 0; lm = lm->l_next) {
         ElfW(Ehdr) * e;
         ElfW(Phdr) * p;
@@ -258,7 +258,7 @@ GC_INNER void GC_register_dynamic_libraries(void)
     }
 }
 
-# endif /* !USE_PROC ... */
+# endif /* !USE_PROC_FOR_LIBRARIES */
 # endif /* SOLARISDL */
 
 #if defined(SCO_ELF) || defined(DGUX) || defined(HURD) || defined(NACL) \
@@ -308,7 +308,7 @@ static void sort_heap_sects(struct HeapSect *base, size_t number_of_elements)
 
 STATIC void GC_register_map_entries(const char *maps)
 {
-    const char *prot;
+    const char *prot, *path;
     ptr_t start, end;
     unsigned int maj_dev;
     ptr_t least_ha, greatest_ha;
@@ -321,7 +321,7 @@ STATIC void GC_register_map_entries(const char *maps)
                   + GC_our_memory[GC_n_memory-1].hs_bytes;
 
     for (;;) {
-        maps = GC_parse_map_entry(maps, &start, &end, &prot, &maj_dev, 0);
+        maps = GC_parse_map_entry(maps, &start, &end, &prot, &maj_dev, &path);
         if (NULL == maps) break;
 
         if (prot[1] == 'w') {
@@ -333,6 +333,15 @@ STATIC void GC_register_map_entries(const char *maps)
                 /* Stack mapping; discard       */
                 continue;
             }
+#           if defined(E2K) && defined(__ptr64__)
+              /* TODO: avoid hard-coded addresses */
+              if ((word)start == 0xc2fffffff000UL
+                  && (word)end == 0xc30000000000UL && path[0] == '\n')
+                continue; /* discard some special mapping */
+#           endif
+            if (path[0] == '[' && strncmp(path+1, "heap]", 5) != 0)
+              continue; /* discard if a pseudo-path unless "[heap]" */
+
 #           ifdef THREADS
               /* This may fail, since a thread may already be           */
               /* unregistered, but its thread stack may still be there. */
@@ -415,9 +424,8 @@ GC_INNER GC_bool GC_register_main_static_data(void)
 /* for glibc 2.2.4+.  Unfortunately, it doesn't work for older  */
 /* versions.  Thanks to Jakub Jelinek for most of the code.     */
 
-#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
-    || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)) \
-    || defined(HOST_ANDROID) /* Are others OK here, too? */
+#if GC_GLIBC_PREREQ(2, 3) || defined(HOST_ANDROID)
+                        /* Are others OK here, too? */
 # ifndef HAVE_DL_ITERATE_PHDR
 #   define HAVE_DL_ITERATE_PHDR
 # endif
@@ -686,7 +694,7 @@ STATIC GC_bool GC_register_dynamic_libraries_dl_iterate_phdr(void)
 #     define PF_W       2
 #   endif
 # elif !defined(HOST_ANDROID)
-#  include <elf.h>
+#   include <elf.h>
 # endif
 
 # ifndef HOST_ANDROID
@@ -709,9 +717,9 @@ GC_FirstDLOpenedLinkMap(void)
 
     if (0 == COVERT_DATAFLOW(_DYNAMIC)) {
         /* _DYNAMIC symbol not resolved. */
-        return(0);
+        return NULL;
     }
-    if( cachedResult == 0 ) {
+    if (NULL == cachedResult) {
 #     if defined(NETBSD) && defined(RTLD_DI_LINKMAP)
 #       if defined(CPPCHECK)
 #         define GC_RTLD_DI_LINKMAP 2
@@ -753,6 +761,7 @@ GC_INNER void GC_register_dynamic_libraries(void)
 {
   struct link_map *lm;
 
+  GC_ASSERT(I_HOLD_LOCK());
 # ifdef HAVE_DL_ITERATE_PHDR
     if (GC_register_dynamic_libraries_dl_iterate_phdr()) {
         return;
@@ -811,9 +820,10 @@ GC_INNER void GC_register_dynamic_libraries(void)
 GC_INNER void GC_register_dynamic_libraries(void)
 {
     static int fd = -1;
-    char buf[30];
     static prmap_t * addr_map = 0;
     static int current_sz = 0;  /* Number of records currently in addr_map */
+
+    char buf[32];
     int needed_sz = 0;          /* Required size of addr_map            */
     int i;
     long flags;
@@ -826,6 +836,7 @@ GC_INNER void GC_register_dynamic_libraries(void)
 #     define MA_PHYS 0
 #   endif /* SOLARISDL */
 
+    GC_ASSERT(I_HOLD_LOCK());
     if (fd < 0) {
       (void)snprintf(buf, sizeof(buf), "/proc/%ld", (long)getpid());
       buf[sizeof(buf) - 1] = '\0';
@@ -920,12 +931,10 @@ GC_INNER void GC_register_dynamic_libraries(void)
         fd = -1;
 }
 
-# endif /* USE_PROC || IRIX5 */
+# endif /* USE_PROC_FOR_LIBRARIES || IRIX5 */
 
 # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
 
-# include <stdlib.h>
-
   /* We traverse the entire address space and register all segments     */
   /* that could possibly have been written to.                          */
   STATIC void GC_cond_add_roots(char *base, char * limit)
@@ -1005,6 +1014,7 @@ GC_INNER void GC_register_dynamic_libraries(void)
     char * base;
     char * limit, * new_limit;
 
+    GC_ASSERT(I_HOLD_LOCK());
 #   ifdef MSWIN32
       if (GC_no_win32_dlls) return;
 #   endif
@@ -1308,7 +1318,6 @@ STATIC const char *GC_dyld_name_for_hdr(const struct GC_MACH_HEADER *hdr)
     return NULL;
 }
 
-/* This should never be called by a thread holding the lock.    */
 STATIC void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr,
                               intptr_t slide)
 {
@@ -1319,6 +1328,7 @@ STATIC void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr,
   GC_has_static_roots_func callback = GC_has_static_roots;
   DCL_LOCK_STATE;
 
+  GC_ASSERT(I_DONT_HOLD_LOCK());
   if (GC_no_dls) return;
 # ifdef DARWIN_DEBUG
     name = GC_dyld_name_for_hdr(hdr);
@@ -1378,7 +1388,6 @@ STATIC void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr,
 # endif
 }
 
-/* This should never be called by a thread holding the lock.    */
 STATIC void GC_dyld_image_remove(const struct GC_MACH_HEADER *hdr,
                                  intptr_t slide)
 {
@@ -1389,6 +1398,7 @@ STATIC void GC_dyld_image_remove(const struct GC_MACH_HEADER *hdr,
     DCL_LOCK_STATE;
 # endif
 
+  GC_ASSERT(I_DONT_HOLD_LOCK());
   for (i = 0; i < sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]); i++) {
     sec = GC_GETSECTBYNAME(hdr, GC_dyld_sections[i].seg,
                            GC_dyld_sections[i].sect);
@@ -1452,6 +1462,7 @@ GC_INNER void GC_init_dyld(void)
 {
   static GC_bool initialized = FALSE;
 
+  GC_ASSERT(I_DONT_HOLD_LOCK());
   if (initialized) return;
 
 # ifdef DARWIN_DEBUG

+ 1 - 1
blitz.mod/bdwgc/extra/AmigaOS.c

@@ -72,7 +72,7 @@ ptr_t GC_get_main_stack_base(void)
      BPTR myseglist;
      ULONG *data;
 
-#    ifdef __GNUC__
+#     ifdef __GNUC__
         ULONG dataSegSize;
         GC_bool found_segment = FALSE;
         extern char __data_size[];

+ 1 - 2
blitz.mod/bdwgc/extra/gc.c

@@ -10,7 +10,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -46,7 +46,6 @@
 #include "../obj_map.c"
 #include "../ptr_chck.c"
 
-#include "gc/gc_inline.h"
 #include "../allchblk.c"
 #include "../alloc.c"
 #include "../dbg_mlc.c"

+ 5 - 5
blitz.mod/bdwgc/extra/msvc_dbg.c

@@ -1,9 +1,9 @@
 /*
   Copyright (c) 2004-2005 Andrei Polushin
 
-  Permission is hereby granted, free of charge,  to any person obtaining a copy
+  Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction,  including without limitation the rights
+  in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:
@@ -23,14 +23,14 @@
 #if !defined(_M_ARM) && !defined(_M_ARM64) \
     && !defined(_M_X64) && defined(_MSC_VER)
 
-/* TODO: arm[64], x86_64 currently miss some machine-dependent code below.  */
+/* TODO: arm[64], x64 currently miss some machine-dependent code below.     */
 /* See also GC_HAVE_BUILTIN_BACKTRACE in gc_config_macros.h.                */
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #define GC_BUILD
-#include "gc.h"
+#include "gc/gc.h"
 
 #ifndef WIN32_LEAN_AND_MEAN
 # define WIN32_LEAN_AND_MEAN 1
@@ -368,7 +368,7 @@ static size_t GetDescriptionFromStack(void* const frames[], size_t count,
   return buffer - begin;
 }
 
-/* Compatibility with <execinfo.h> */
+/* Compatibility with execinfo.h:       */
 
 int backtrace(void* addresses[], int count)
 {

+ 1 - 1
blitz.mod/bdwgc/extra/pcr_interface.c

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.

+ 2 - 2
blitz.mod/bdwgc/extra/real_malloc.c

@@ -6,7 +6,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -27,7 +27,7 @@
 
 void * real_malloc(size_t size)
 {
-    return(malloc(size));
+    return malloc(size);
 }
 
 # else

+ 96 - 56
blitz.mod/bdwgc/finalize.c

@@ -3,13 +3,13 @@
  * Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.
  * Copyright (c) 2007 Free Software Foundation, Inc.
- * Copyright (c) 2008-2020 Ivan Maidanski
+ * Copyright (c) 2008-2022 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -88,11 +88,10 @@ GC_API void GC_CALL GC_push_finalizer_structures(void)
 #endif
 
 /* Double the size of a hash table. *log_size_ptr is the log of its     */
-/* current size.  May be a no-op.                                       */
-/* *table is a pointer to an array of hash headers.  If we succeed, we  */
-/* update both *table and *log_size_ptr.  Lock is held.                 */
+/* current size.  May be a no-op.  *table is a pointer to an array of   */
+/* hash headers.  We update both *table and *log_size_ptr on success.   */
 STATIC void GC_grow_table(struct hash_chain_entry ***table,
-                          unsigned *log_size_ptr, word *entries_ptr)
+                          unsigned *log_size_ptr, const word *entries_ptr)
 {
     word i;
     struct hash_chain_entry *p;
@@ -112,7 +111,7 @@ STATIC void GC_grow_table(struct hash_chain_entry ***table,
       IF_CANCEL(int cancel_state;)
 
       DISABLE_CANCEL(cancel_state);
-      (void)GC_try_to_collect_inner(GC_never_stop_func);
+      GC_gcollect_inner();
       RESTORE_CANCEL(cancel_state);
       /* GC_finalize might decrease entries value.  */
       if (*entries_ptr < ((word)1 << log_old_size) - (*entries_ptr >> 2))
@@ -155,7 +154,7 @@ GC_API int GC_CALL GC_register_disappearing_link(void * * link)
     base = (ptr_t)GC_base(link);
     if (base == 0)
         ABORT("Bad arg to GC_register_disappearing_link");
-    return(GC_general_register_disappearing_link(link, base));
+    return GC_general_register_disappearing_link(link, base);
 }
 
 STATIC int GC_register_disappearing_link_inner(
@@ -167,7 +166,11 @@ STATIC int GC_register_disappearing_link_inner(
     struct disappearing_link * new_dl;
     DCL_LOCK_STATE;
 
+    GC_ASSERT(GC_is_initialized);
     if (EXPECT(GC_find_leak, FALSE)) return GC_UNIMPLEMENTED;
+#   ifdef GC_ASSERTIONS
+      GC_noop1((word)(*link)); /* check accessibility */
+#   endif
     LOCK();
     GC_ASSERT(obj != NULL && GC_base_C(obj) == obj);
     if (EXPECT(NULL == dl_hashtbl -> head, FALSE)
@@ -189,7 +192,7 @@ STATIC int GC_register_disappearing_link_inner(
     }
     new_dl = (struct disappearing_link *)
         GC_INTERNAL_MALLOC(sizeof(struct disappearing_link),NORMAL);
-    if (0 == new_dl) {
+    if (EXPECT(NULL == new_dl, FALSE)) {
       GC_oom_func oom_fn = GC_oom_fn;
       UNLOCK();
       new_dl = (struct disappearing_link *)
@@ -277,7 +280,7 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link)
     struct disappearing_link *curr_dl;
     DCL_LOCK_STATE;
 
-    if (((word)link & (ALIGNMENT-1)) != 0) return(0); /* Nothing to do. */
+    if (((word)link & (ALIGNMENT-1)) != 0) return 0; /* Nothing to do. */
 
     LOCK();
     curr_dl = GC_unregister_disappearing_link_inner(&GC_dl_hashtbl, link);
@@ -287,6 +290,27 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link)
     return 1;
 }
 
+/* Mark from one finalizable object using the specified mark proc.      */
+/* May not mark the object pointed to by real_ptr (i.e, it is the job   */
+/* of the caller, if appropriate).  Note that this is called with the   */
+/* mutator running.  This is safe only if the mutator (client) gets     */
+/* the allocation lock to reveal hidden pointers.                       */
+GC_INLINE void GC_mark_fo(ptr_t real_ptr, finalization_mark_proc mark_proc)
+{
+  GC_ASSERT(I_HOLD_LOCK());
+  mark_proc(real_ptr);
+  /* Process objects pushed by the mark procedure.      */
+  while (!GC_mark_stack_empty())
+    MARK_FROM_MARK_STACK();
+}
+
+/* Complete a collection in progress, if any.   */
+GC_INLINE void GC_complete_ongoing_collection(void) {
+  if (EXPECT(GC_collection_in_progress(), FALSE)) {
+    while (!GC_mark_some(NULL)) { /* empty */ }
+  }
+}
+
 /* Toggle-ref support.  */
 #ifndef GC_TOGGLE_REFS_NOT_NEEDED
   typedef union toggle_ref_u GCToggleRef;
@@ -336,23 +360,11 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link)
 
   STATIC void GC_normal_finalize_mark_proc(ptr_t);
 
-  static void push_and_mark_object(void *p)
-  {
-    GC_normal_finalize_mark_proc((ptr_t)p);
-    while (!GC_mark_stack_empty()) {
-      MARK_FROM_MARK_STACK();
-    }
-    GC_set_mark_bit(p);
-    if (GC_mark_state != MS_NONE) {
-      while (!GC_mark_some(0)) {
-        /* Empty. */
-      }
-    }
-  }
-
   STATIC void GC_mark_togglerefs(void)
   {
     size_t i;
+
+    GC_ASSERT(I_HOLD_LOCK());
     if (NULL == GC_toggleref_arr)
       return;
 
@@ -360,7 +372,10 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link)
     for (i = 0; i < GC_toggleref_array_size; ++i) {
       void *obj = GC_toggleref_arr[i].strong_ref;
       if (obj != NULL && ((word)obj & 1) == 0) {
-        push_and_mark_object(obj);
+        /* Push and mark the object.    */
+        GC_mark_fo((ptr_t)obj, GC_normal_finalize_mark_proc);
+        GC_set_mark_bit(obj);
+        GC_complete_ongoing_collection();
       }
     }
   }
@@ -495,7 +510,7 @@ GC_API GC_await_finalize_proc GC_CALL GC_get_await_finalize_proc(void)
     struct disappearing_link *curr_dl;
     DCL_LOCK_STATE;
 
-    if (((word)link & (ALIGNMENT-1)) != 0) return(0); /* Nothing to do. */
+    if (((word)link & (ALIGNMENT-1)) != 0) return 0; /* Nothing to do. */
 
     LOCK();
     curr_dl = GC_unregister_disappearing_link_inner(&GC_ll_hashtbl, link);
@@ -507,7 +522,6 @@ GC_API GC_await_finalize_proc GC_CALL GC_get_await_finalize_proc(void)
 #endif /* !GC_LONG_REFS_NOT_NEEDED */
 
 #ifndef GC_MOVE_DISAPPEARING_LINK_NOT_NEEDED
-  /* Moves a link.  Assume the lock is held.    */
   STATIC int GC_move_disappearing_link_inner(
                                 struct dl_hashtbl_s *dl_hashtbl,
                                 void **link, void **new_link)
@@ -517,6 +531,9 @@ GC_API GC_await_finalize_proc GC_CALL GC_get_await_finalize_proc(void)
     size_t curr_index, new_index;
     word curr_hidden_link, new_hidden_link;
 
+#   ifdef GC_ASSERTIONS
+      GC_noop1((word)(*new_link));
+#   endif
     GC_ASSERT(I_HOLD_LOCK());
     if (EXPECT(NULL == dl_hashtbl -> head, FALSE)) return GC_NOT_FOUND;
 
@@ -602,7 +619,7 @@ GC_API GC_await_finalize_proc GC_CALL GC_get_await_finalize_proc(void)
 /* 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). */
+  /* Otherwise some optimizer bug is tickled in VC for x86 (v19, at least). */
 #endif
 STATIC void GC_normal_finalize_mark_proc(ptr_t p)
 {
@@ -617,7 +634,7 @@ STATIC void GC_ignore_self_finalize_mark_proc(ptr_t p)
 {
     hdr * hhdr = HDR(p);
     word descr = hhdr -> hb_descr;
-    ptr_t q;
+    ptr_t current_p;
     ptr_t scan_limit;
     ptr_t target_limit = p + hhdr -> hb_sz - 1;
 
@@ -626,16 +643,21 @@ STATIC void GC_ignore_self_finalize_mark_proc(ptr_t p)
     } else {
        scan_limit = target_limit + 1 - sizeof(word);
     }
-    for (q = p; (word)q <= (word)scan_limit; q += ALIGNMENT) {
-        word r = *(word *)q;
+    for (current_p = p; (word)current_p <= (word)scan_limit;
+         current_p += ALIGNMENT) {
+        word q;
 
-        if (r < (word)p || r > (word)target_limit) {
-            GC_PUSH_ONE_HEAP(r, q, GC_mark_stack_top);
+        LOAD_WORD_OR_CONTINUE(q, current_p);
+        if (q < (word)p || q > (word)target_limit) {
+            GC_PUSH_ONE_HEAP(q, current_p, GC_mark_stack_top);
         }
     }
 }
 
-STATIC void GC_null_finalize_mark_proc(ptr_t p GC_ATTR_UNUSED) {}
+STATIC void GC_null_finalize_mark_proc(ptr_t p)
+{
+    UNUSED_ARG(p);
+}
 
 /* Possible finalization_marker procedures.  Note that mark stack       */
 /* overflow is handled by the caller, and is not a disaster.            */
@@ -666,8 +688,13 @@ STATIC void GC_register_finalizer_inner(void * obj,
     hdr *hhdr = NULL; /* initialized to prevent warning. */
     DCL_LOCK_STATE;
 
-    if (EXPECT(GC_find_leak, FALSE)) return;
+    GC_ASSERT(GC_is_initialized);
+    if (EXPECT(GC_find_leak, FALSE)) {
+      /* No-op.  *ocd and *ofn remain unchanged.    */
+      return;
+    }
     LOCK();
+    GC_ASSERT(obj != NULL && GC_base_C(obj) == obj);
     if (EXPECT(NULL == GC_fnlz_roots.fo_head, FALSE)
         || EXPECT(GC_fo_entries > ((word)1 << GC_log_fo_table_size), FALSE)) {
         GC_grow_table((struct hash_chain_entry ***)&GC_fnlz_roots.fo_head,
@@ -675,7 +702,6 @@ STATIC void GC_register_finalizer_inner(void * obj,
         GC_COND_LOG_PRINTF("Grew fo table to %u entries\n",
                            1U << GC_log_fo_table_size);
     }
-    /* in the THREADS case we hold allocation lock.             */
     for (;;) {
       struct finalizable_object *prev_fo = NULL;
       GC_oom_func oom_fn;
@@ -762,7 +788,7 @@ STATIC void GC_register_finalizer_inner(void * obj,
       new_fo = (struct finalizable_object *)
                 (*oom_fn)(sizeof(struct finalizable_object));
       if (0 == new_fo) {
-        /* No enough memory.  *ocd and *ofn remains unchanged.  */
+        /* No enough memory.  *ocd and *ofn remain unchanged.   */
         return;
       }
       /* It's not likely we'll make it here, but ... */
@@ -840,8 +866,8 @@ GC_API void GC_CALL GC_register_finalizer_unreachable(void * obj,
         ptr_t real_ptr = (ptr_t)GC_REVEAL_POINTER(curr_dl->dl_hidden_obj);
         ptr_t real_link = (ptr_t)GC_REVEAL_POINTER(curr_dl->dl_hidden_link);
 
-        GC_printf("Object: %p, link: %p\n",
-                  (void *)real_ptr, (void *)real_link);
+        GC_printf("Object: %p, link value: %p, link addr: %p\n",
+                  (void *)real_ptr, *(void **)real_link, (void *)real_link);
       }
     }
   }
@@ -853,13 +879,13 @@ GC_API void GC_CALL GC_register_finalizer_unreachable(void * obj,
     size_t fo_size = GC_fnlz_roots.fo_head == NULL ? 0 :
                                 (size_t)1 << GC_log_fo_table_size;
 
-    GC_printf("Disappearing (short) links:\n");
+    GC_printf("\n***Disappearing (short) links:\n");
     GC_dump_finalization_links(&GC_dl_hashtbl);
 #   ifndef GC_LONG_REFS_NOT_NEEDED
-      GC_printf("Disappearing long links:\n");
+      GC_printf("\n***Disappearing long links:\n");
       GC_dump_finalization_links(&GC_ll_hashtbl);
 #   endif
-    GC_printf("Finalizers:\n");
+    GC_printf("\n***Finalizers:\n");
     for (i = 0; i < fo_size; i++) {
       for (curr_fo = GC_fnlz_roots.fo_head[i];
            curr_fo != NULL; curr_fo = fo_next(curr_fo)) {
@@ -904,7 +930,7 @@ GC_API void GC_CALL GC_register_finalizer_unreachable(void * obj,
     *(char *)&GC_finalizer_nested = (char)(nesting_level + 1);
     return (unsigned char *)&GC_finalizer_nested;
   }
-#endif /* THREADS */
+#endif /* !THREADS */
 
 GC_INLINE void GC_make_disappearing_links_disappear(
                                         struct dl_hashtbl_s* dl_hashtbl,
@@ -923,6 +949,10 @@ GC_INLINE void GC_make_disappearing_links_disappear(
 
     for (curr_dl = dl_hashtbl->head[i]; curr_dl != NULL; curr_dl = next_dl) {
       next_dl = dl_next(curr_dl);
+#     if defined(GC_ASSERTIONS) && !defined(THREAD_SANITIZER)
+         /* Check accessibility of the location pointed by link. */
+        GC_noop1(*(word *)GC_REVEAL_POINTER(curr_dl->dl_hidden_link));
+#     endif
       if (is_remove_dangling) {
         ptr_t real_link = (ptr_t)GC_base(GC_REVEAL_POINTER(
                                                 curr_dl->dl_hidden_link));
@@ -956,9 +986,8 @@ GC_INLINE void GC_make_disappearing_links_disappear(
     GC_dirty(dl_hashtbl -> head); /* entire object */
 }
 
-/* Called with held lock (but the world is running).                    */
 /* Cause disappearing links to disappear and unreachable objects to be  */
-/* enqueued for finalization.                                           */
+/* enqueued for finalization.  Called with the world running.           */
 GC_INNER void GC_finalize(void)
 {
     struct finalizable_object * curr_fo, * prev_fo, * next_fo;
@@ -984,7 +1013,7 @@ GC_INNER void GC_finalize(void)
 
   /* Mark all objects reachable via chains of 1 or more pointers        */
   /* from finalizable objects.                                          */
-    GC_ASSERT(GC_mark_state == MS_NONE);
+    GC_ASSERT(!GC_collection_in_progress());
     for (i = 0; i < fo_size; i++) {
       for (curr_fo = GC_fnlz_roots.fo_head[i];
            curr_fo != NULL; curr_fo = fo_next(curr_fo)) {
@@ -992,7 +1021,7 @@ GC_INNER void GC_finalize(void)
         real_ptr = (ptr_t)GC_REVEAL_POINTER(curr_fo->fo_hidden_base);
         if (!GC_is_marked(real_ptr)) {
             GC_MARKED_FOR_FINALIZATION(real_ptr);
-            GC_MARK_FO(real_ptr, curr_fo -> fo_mark_proc);
+            GC_mark_fo(real_ptr, curr_fo -> fo_mark_proc);
             if (GC_is_marked(real_ptr)) {
                 WARN("Finalization cycle involving %p\n", real_ptr);
             }
@@ -1056,7 +1085,7 @@ GC_INNER void GC_finalize(void)
         real_ptr = (ptr_t)curr_fo -> fo_hidden_base;
         if (!GC_is_marked(real_ptr)) {
             if (curr_fo -> fo_mark_proc == GC_null_finalize_mark_proc) {
-                GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
+                GC_mark_fo(real_ptr, GC_normal_finalize_mark_proc);
             }
             if (curr_fo -> fo_mark_proc != GC_unreachable_finalize_mark_proc) {
                 GC_set_mark_bit(real_ptr);
@@ -1130,9 +1159,10 @@ GC_INNER void GC_finalize(void)
 #ifndef JAVA_FINALIZATION_NOT_NEEDED
 
   /* Enqueue all remaining finalizers to be run.        */
+  /* A collection in progress, if any, is completed     */
+  /* when the first finalizer is enqueued.              */
   STATIC void GC_enqueue_all_finalizers(void)
   {
-    struct finalizable_object * next_fo;
     size_t i;
     size_t fo_size = GC_fnlz_roots.fo_head == NULL ? 0 :
                                 (size_t)1 << GC_log_fo_table_size;
@@ -1144,11 +1174,12 @@ GC_INNER void GC_finalize(void)
 
       GC_fnlz_roots.fo_head[i] = NULL;
       while (curr_fo != NULL) {
+          struct finalizable_object * next_fo;
           ptr_t real_ptr = (ptr_t)GC_REVEAL_POINTER(curr_fo->fo_hidden_base);
 
-          GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
+          GC_mark_fo(real_ptr, GC_normal_finalize_mark_proc);
           GC_set_mark_bit(real_ptr);
-
+          GC_complete_ongoing_collection();
           next_fo = fo_next(curr_fo);
 
           /* Add to list of objects awaiting finalization.      */
@@ -1179,8 +1210,6 @@ GC_INNER void GC_finalize(void)
    * may have been finalized when these finalizers are run.
    * Finalizers run at this point must be prepared to deal with a
    * mostly broken world.
-   * This routine is externally callable, so is called without
-   * the allocation lock.
    */
   GC_API void GC_CALL GC_finalize_all(void)
   {
@@ -1215,13 +1244,13 @@ GC_API int GC_CALL GC_should_invoke_finalizers(void)
 }
 
 /* Invoke finalizers for all objects that are ready to be finalized.    */
-/* Should be called without allocation lock.                            */
 GC_API int GC_CALL GC_invoke_finalizers(void)
 {
     int count = 0;
     word bytes_freed_before = 0; /* initialized to prevent warning. */
     DCL_LOCK_STATE;
 
+    GC_ASSERT(I_DONT_HOLD_LOCK());
     while (GC_should_invoke_finalizers()) {
         struct finalizable_object * curr_fo;
 
@@ -1298,8 +1327,11 @@ GC_INNER void GC_notify_or_invoke_finalizers(void)
               /* which may cause occasional mysterious results.         */
               /* We need to release the GC lock, since GC_print_callers */
               /* acquires it.  It probably shouldn't.                   */
+              void *current = GC_generate_random_valid_address();
+
               UNLOCK();
-              GC_generate_random_backtrace_no_gc();
+              GC_printf("\n****Chosen address %p in object\n", current);
+              GC_print_backtrace(current);
               LOCK();
           }
           last_back_trace_gc_no = GC_gc_no;
@@ -1317,7 +1349,15 @@ GC_INNER void GC_notify_or_invoke_finalizers(void)
     }
 
     if (!GC_finalize_on_demand) {
-      unsigned char *pnested = GC_check_finalizer_nested();
+      unsigned char *pnested;
+
+#     ifdef THREADS
+        if (EXPECT(GC_in_thread_creation, FALSE)) {
+          UNLOCK();
+          return;
+        }
+#     endif
+      pnested = GC_check_finalizer_nested();
       UNLOCK();
       /* Skip GC_invoke_finalizers() if nested */
       if (pnested != NULL) {

+ 14 - 8
blitz.mod/bdwgc/fnlz_mlc.c

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -17,7 +17,6 @@
 #ifdef ENABLE_DISCLAIM
 
 #include "gc/gc_disclaim.h"
-#include "gc/gc_inline.h" /* for GC_malloc_kind */
 #include "private/dbg_mlc.h" /* for oh type */
 
 #if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
@@ -29,7 +28,11 @@
 
 STATIC int GC_CALLBACK GC_finalized_disclaim(void *obj)
 {
-    word fc_word = *(word *)obj;
+#   ifdef AO_HAVE_load
+        word fc_word = (word)AO_load((volatile AO_t *)obj);
+#   else
+        word fc_word = *(word *)obj;
+#   endif
 
     if ((fc_word & FINALIZER_CLOSURE_FLAG) != 0) {
        /* The disclaim function may be passed fragments from the        */
@@ -94,19 +97,22 @@ GC_API void GC_CALL GC_register_disclaim_proc(int kind, GC_disclaim_proc proc,
 GC_API GC_ATTR_MALLOC void * GC_CALL GC_finalized_malloc(size_t lb,
                                 const struct GC_finalizer_closure *fclos)
 {
-    word *op;
+    void *op;
 
     GC_ASSERT(GC_finalized_kind != 0);
     GC_ASSERT(NONNULL_ARG_NOT_NULL(fclos));
     GC_ASSERT(((word)fclos & FINALIZER_CLOSURE_FLAG) == 0);
-    op = (word *)GC_malloc_kind(SIZET_SAT_ADD(lb, sizeof(word)),
-                                GC_finalized_kind);
+    op = GC_malloc_kind(SIZET_SAT_ADD(lb, sizeof(word)), GC_finalized_kind);
     if (EXPECT(NULL == op, FALSE))
         return NULL;
-    *op = (word)fclos | FINALIZER_CLOSURE_FLAG;
+#   ifdef AO_HAVE_store
+        AO_store((volatile AO_t *)op, (AO_t)fclos | FINALIZER_CLOSURE_FLAG);
+#   else
+        *(word *)op = (word)fclos | FINALIZER_CLOSURE_FLAG;
+#   endif
     GC_dirty(op);
     REACHABLE_AFTER_DIRTY(fclos);
-    return op + 1;
+    return (word *)op + 1;
 }
 
 #endif /* ENABLE_DISCLAIM */

+ 2 - 2
blitz.mod/bdwgc/gc_badalc.cc

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -24,7 +24,7 @@
 #endif
 
 #define GC_DONT_INCL_WINDOWS_H
-#include "gc.h"
+#include "gc/gc.h"
 
 #include <new> // for bad_alloc, precedes include of gc_cpp.h
 

+ 3 - 3
blitz.mod/bdwgc/gc_cpp.cc

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -31,11 +31,11 @@ built-in "new" and "delete".
 #endif
 
 #define GC_DONT_INCL_WINDOWS_H
-#include "gc.h"
+#include "gc/gc.h"
 
 #include <new> // for bad_alloc, precedes include of gc_cpp.h
 
-#include "gc_cpp.h" // for GC_OPERATOR_NEW_ARRAY
+#include "gc/gc_cpp.h" // for GC_OPERATOR_NEW_ARRAY
 
 #if !(defined(_MSC_VER) || defined(__DMC__)) || defined(GC_NO_INLINE_STD_NEW)
 

+ 2 - 2
blitz.mod/bdwgc/gc_dlopen.c

@@ -7,7 +7,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -82,7 +82,7 @@ GC_API void * WRAP_DLFUNC(dlopen)(const char *path, int mode)
 # ifndef USE_PROC_FOR_LIBRARIES
     GC_enable(); /* undoes disable_gc_for_dlopen */
 # endif
-  return(result);
+  return result;
 }
 
 #ifdef GC_USE_LD_WRAP

+ 14 - 11
blitz.mod/bdwgc/gcj_mlc.c

@@ -1,12 +1,13 @@
 /*
  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
+ * Copyright (c) 2008-2022 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -45,16 +46,17 @@ int GC_gcj_debug_kind = 0;
                         /* The kind of objects that is always marked    */
                         /* with a mark proc call.                       */
 
-STATIC struct GC_ms_entry * GC_gcj_fake_mark_proc(word * addr GC_ATTR_UNUSED,
+STATIC struct GC_ms_entry * GC_gcj_fake_mark_proc(word * addr,
                         struct GC_ms_entry *mark_stack_ptr,
-                        struct GC_ms_entry * mark_stack_limit GC_ATTR_UNUSED,
-                        word env GC_ATTR_UNUSED)
+                        struct GC_ms_entry * mark_stack_limit, word env)
 {
+    UNUSED_ARG(addr);
+    UNUSED_ARG(mark_stack_limit);
+    UNUSED_ARG(env);
     ABORT_RET("No client gcj mark proc is specified");
     return mark_stack_ptr;
 }
 
-/* Caller does not hold allocation lock. */
 GC_API void GC_CALL GC_init_gcj_malloc(int mp_index,
                                        void * /* really GC_mark_proc */mp)
 {
@@ -130,6 +132,7 @@ static void maybe_finalize(void)
    static word last_finalized_no = 0;
    DCL_LOCK_STATE;
 
+   GC_ASSERT(I_HOLD_LOCK());
    if (GC_gc_no == last_finalized_no ||
        !EXPECT(GC_is_initialized, TRUE)) return;
    UNLOCK();
@@ -165,7 +168,7 @@ static void maybe_finalize(void)
             if (0 == op) {
                 GC_oom_func oom_fn = GC_oom_fn;
                 UNLOCK();
-                return((*oom_fn)(lb));
+                return (*oom_fn)(lb);
             }
         } else {
             GC_gcjobjfreelist[lg] = (ptr_t)obj_link(op);
@@ -179,7 +182,7 @@ static void maybe_finalize(void)
         if (0 == op) {
             GC_oom_func oom_fn = GC_oom_fn;
             UNLOCK();
-            return((*oom_fn)(lb));
+            return (*oom_fn)(lb);
         }
     }
     *(void **)op = ptr_to_struct_containing_descr;
@@ -203,12 +206,12 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_gcj_malloc(size_t lb,
     maybe_finalize();
     result = GC_generic_malloc_inner(SIZET_SAT_ADD(lb, DEBUG_BYTES),
                                      GC_gcj_debug_kind);
-    if (result == 0) {
+    if (NULL == result) {
         GC_oom_func oom_fn = GC_oom_fn;
         UNLOCK();
         GC_err_printf("GC_debug_gcj_malloc(%lu, %p) returning NULL (%s:%d)\n",
                 (unsigned long)lb, ptr_to_struct_containing_descr, s, i);
-        return((*oom_fn)(lb));
+        return (*oom_fn)(lb);
     }
     *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
     if (!GC_debugging_started) {
@@ -242,7 +245,7 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_gcj_malloc_ignore_off_page(size_t lb,
             if (0 == op) {
                 GC_oom_func oom_fn = GC_oom_fn;
                 UNLOCK();
-                return((*oom_fn)(lb));
+                return (*oom_fn)(lb);
             }
         } else {
             GC_gcjobjfreelist[lg] = (ptr_t)obj_link(op);
@@ -255,7 +258,7 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_gcj_malloc_ignore_off_page(size_t lb,
         if (0 == op) {
             GC_oom_func oom_fn = GC_oom_fn;
             UNLOCK();
-            return((*oom_fn)(lb));
+            return (*oom_fn)(lb);
         }
     }
     *(void **)op = ptr_to_struct_containing_descr;

+ 41 - 30
blitz.mod/bdwgc/headers.c

@@ -2,12 +2,13 @@
  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
+ * Copyright (c) 2008-2022 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -30,9 +31,9 @@ GC_INNER hdr * GC_find_header(ptr_t h)
 #   ifdef HASH_TL
         hdr * result;
         GET_HDR(h, result);
-        return(result);
+        return result;
 #   else
-        return(HDR_INNER(h));
+        return HDR_INNER(h);
 #   endif
 }
 
@@ -107,6 +108,7 @@ GC_INNER ptr_t GC_scratch_alloc(size_t bytes)
     ptr_t result = GC_scratch_free_ptr;
     size_t bytes_to_get;
 
+    GC_ASSERT(I_HOLD_LOCK());
     bytes = ROUNDUP_GRANULE_SIZE(bytes);
     for (;;) {
         GC_ASSERT((word)GC_scratch_end_ptr >= (word)result);
@@ -138,7 +140,7 @@ GC_INNER ptr_t GC_scratch_alloc(size_t bytes)
         result = (ptr_t)GET_MEM(bytes_to_get);
         if (EXPECT(NULL == result, FALSE)) {
             WARN("Out of memory - trying to allocate requested amount"
-                 " (%" WARN_PRIdPTR " bytes)...\n", (word)bytes);
+                 " (%" WARN_PRIuPTR " bytes)...\n", bytes);
             bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(bytes);
             result = (ptr_t)GET_MEM(bytes_to_get);
             if (result != NULL) {
@@ -166,13 +168,14 @@ static hdr * alloc_hdr(void)
 {
     hdr * result;
 
+    GC_ASSERT(I_HOLD_LOCK());
     if (NULL == GC_hdr_free_list) {
         result = (hdr *)GC_scratch_alloc(sizeof(hdr));
     } else {
         result = GC_hdr_free_list;
         GC_hdr_free_list = (hdr *) result -> hb_next;
     }
-    return(result);
+    return result;
 }
 
 GC_INLINE void free_hdr(hdr * hhdr)
@@ -191,6 +194,7 @@ GC_INNER void GC_init_headers(void)
 {
     unsigned i;
 
+    GC_ASSERT(I_HOLD_LOCK());
     GC_ASSERT(NULL == GC_all_nils);
     GC_all_nils = (bottom_index *)GC_scratch_alloc(sizeof(bottom_index));
     if (GC_all_nils == NULL) {
@@ -218,10 +222,9 @@ static GC_bool get_index(word addr)
 #   ifdef HASH_TL
       i = TL_HASH(hi);
 
-      pi = p = GC_top_index[i];
-      while(p != GC_all_nils) {
-          if (p -> key == hi) return(TRUE);
-          p = p -> hash_link;
+      pi = GC_top_index[i];
+      for (p = pi; p != GC_all_nils; p = p -> hash_link) {
+          if (p -> key == hi) return TRUE;
       }
 #   else
       if (GC_top_index[hi] != GC_all_nils)
@@ -254,7 +257,7 @@ static GC_bool get_index(word addr)
       *prev = r;
 
       GC_top_index[i] = r;
-    return(TRUE);
+    return TRUE;
 }
 
 /* Install a header for block h.        */
@@ -264,15 +267,17 @@ GC_INNER struct hblkhdr * GC_install_header(struct hblk *h)
 {
     hdr * result;
 
-    if (!get_index((word) h)) return(0);
+    GC_ASSERT(I_HOLD_LOCK());
+    if (EXPECT(!get_index((word)h), FALSE)) return NULL;
+
     result = alloc_hdr();
-    if (result) {
+    if (EXPECT(result != NULL, TRUE)) {
       SET_HDR(h, result);
 #     ifdef USE_MUNMAP
         result -> hb_last_reclaimed = (unsigned short)GC_gc_no;
 #     endif
     }
-    return(result);
+    return result;
 }
 
 /* Set up forwarding counts for block h of size sz */
@@ -310,16 +315,22 @@ GC_INNER void GC_remove_counts(struct hblk *h, size_t sz/* bytes */)
 {
     struct hblk * hbp;
 
+    if (sz <= HBLKSIZE) return;
+    if (HDR(h+1) == 0) {
+#     ifdef GC_ASSERTIONS
+        for (hbp = h+2; (word)hbp < (word)h + sz; hbp++)
+          GC_ASSERT(HDR(hbp) == 0);
+#     endif
+      return;
+    }
+
     for (hbp = h+1; (word)hbp < (word)h + sz; hbp += 1) {
         SET_HDR(hbp, 0);
     }
 }
 
-/* Apply fn to all allocated blocks.  It is the caller responsibility   */
-/* to avoid data race during the function execution (e.g. by holding    */
-/* the allocation lock).                                                */
-void GC_apply_to_all_blocks(void (*fn)(struct hblk *h, word client_data),
-                            word client_data)
+GC_API void GC_CALL GC_apply_to_all_blocks(GC_walk_hblk_fn fn,
+                                           GC_word client_data)
 {
     signed_word j;
     bottom_index * index_p;
@@ -366,9 +377,8 @@ GC_INNER struct hblk * GC_next_block(struct hblk *h, GC_bool allow_free)
                 j++;
             } else {
                 if (allow_free || !HBLK_IS_FREE(hhdr)) {
-                    return ((struct hblk *)
-                              (((bi -> key << LOG_BOTTOM_SZ) + j)
-                               << LOG_HBLKSIZE));
+                    return (struct hblk *)(((bi -> key << LOG_BOTTOM_SZ)
+                                            + j) << LOG_HBLKSIZE);
                 } else {
                     j += divHBLKSZ(hhdr -> hb_sz);
                 }
@@ -377,7 +387,7 @@ GC_INNER struct hblk * GC_next_block(struct hblk *h, GC_bool allow_free)
         j = 0;
         bi = bi -> asc_link;
     }
-    return(0);
+    return NULL;
 }
 
 GC_INNER struct hblk * GC_prev_block(struct hblk *h)
@@ -389,25 +399,26 @@ GC_INNER struct hblk * GC_prev_block(struct hblk *h)
     GET_BI(h, bi);
     if (bi == GC_all_nils) {
         word hi = (word)h >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE);
+
         bi = GC_all_bottom_indices_end;
-        while (bi != 0 && bi -> key > hi) bi = bi -> desc_link;
+        while (bi != NULL && bi -> key > hi)
+            bi = bi -> desc_link;
         j = BOTTOM_SZ - 1;
     }
-    while(bi != 0) {
+    for (; bi != NULL; bi = bi -> desc_link) {
         while (j >= 0) {
             hdr * hhdr = bi -> index[j];
-            if (0 == hhdr) {
+
+            if (NULL == hhdr) {
                 --j;
             } else if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
                 j -= (signed_word)hhdr;
             } else {
-                return((struct hblk *)
-                          (((bi -> key << LOG_BOTTOM_SZ) + j)
-                               << LOG_HBLKSIZE));
+                return (struct hblk *)(((bi -> key << LOG_BOTTOM_SZ) + j)
+                                       << LOG_HBLKSIZE);
             }
         }
         j = BOTTOM_SZ - 1;
-        bi = bi -> desc_link;
     }
-    return(0);
+    return NULL;
 }

+ 36 - 36
blitz.mod/bdwgc/include/gc/cord.h

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -26,7 +26,7 @@
  * - A text editor that converts the input file to a cord, and then
  *   performs editing operations by producing a new cord representing
  *   the file after each character change (and keeping the old ones in an
- *   edit history)
+ *   edit history).
  *
  * For optimal performance, cords should be built by
  * concatenating short sections.
@@ -44,14 +44,15 @@
  * CORD_cat(cord1,cord2) - concatenation of two cords;
  * CORD_substr(cord, start, len) - substring (or subcord);
  * CORD_pos i;  CORD_FOR(i, cord) {  ... CORD_pos_fetch(i) ... } -
- *    examine each character in a cord.  CORD_pos_fetch(i) is the char.
- * CORD_fetch(int i) - Retrieve i'th character (slowly).
- * CORD_cmp(cord1, cord2) - compare two cords.
- * CORD_from_file(FILE * f) - turn a read-only file into a cord.
- * CORD_to_char_star(cord) - convert to C string.
- *   (Non-NULL C constant strings are cords.)
- * CORD_printf (etc.) - cord version of printf. Use %r for cords.
+ *  examine each character in a cord (CORD_pos_fetch(i) is the char);
+ * CORD_fetch(int i) - Retrieve i'th character (slowly);
+ * CORD_cmp(cord1, cord2) - compare two cords;
+ * CORD_from_file(FILE * f) - turn a read-only file into a cord;
+ * CORD_to_char_star(cord) - convert to C string
+ *  (non-NULL C constant strings are cords);
+ * CORD_printf (etc.) - cord version of printf (use %r for cords).
  */
+
 #ifndef CORD_H
 #define CORD_H
 
@@ -97,7 +98,7 @@
 
 typedef const char * CORD;
 
-/* An empty cord is always represented as nil   */
+/* An empty cord is always represented as nil.  */
 #define CORD_EMPTY 0
 
 /* Is a nonempty cord represented as a C string? */
@@ -114,10 +115,10 @@ CORD_API CORD CORD_cat(CORD x, CORD y);
 /* not be altered by the caller.                                        */
 CORD_API CORD CORD_cat_char_star(CORD x, const char * y, size_t leny);
 
-/* Compute the length of a cord */
+/* Compute the length of a cord. */
 CORD_API size_t CORD_len(CORD x);
 
-/* Cords may be represented by functions defining the ith character */
+/* Cords may be represented by functions defining the ith character.    */
 typedef char (* CORD_fn)(size_t i, void * client_data);
 
 /* Turn a functional description into a cord.   */
@@ -152,8 +153,8 @@ typedef int (* CORD_batched_iter_fn)(const char * s, void * client_data);
 #define CORD_NO_FN ((CORD_batched_iter_fn)0)
 
 /* Apply f1 to each character in the cord, in ascending order,          */
-/* starting at position i. If                                           */
-/* f2 is not CORD_NO_FN, then multiple calls to f1 may be replaced by   */
+/* starting at position i.  If f2 is not CORD_NO_FN, then               */
+/* multiple calls to f1 may be replaced by                              */
 /* a single call to f2.  The parameter f2 is provided only to allow     */
 /* some optimization by the client.  This terminates when the right     */
 /* end of this string is reached, or when f1 or f2 return != 0.  In the */
@@ -162,15 +163,15 @@ typedef int (* CORD_batched_iter_fn)(const char * s, void * client_data);
 CORD_API int CORD_iter5(CORD x, size_t i, CORD_iter_fn f1,
                         CORD_batched_iter_fn f2, void * client_data);
 
-/* A simpler version that starts at 0, and without f2:  */
+/* A simpler version that starts at 0, and without f2.  */
 CORD_API int CORD_iter(CORD x, CORD_iter_fn f1, void * client_data);
 #define CORD_iter(x, f1, cd) CORD_iter5(x, 0, f1, CORD_NO_FN, cd)
 
-/* Similar to CORD_iter5, but end-to-beginning. No provisions for       */
+/* Similar to CORD_iter5, but end-to-beginning.  No provisions for      */
 /* CORD_batched_iter_fn.                                                */
 CORD_API int CORD_riter4(CORD x, size_t i, CORD_iter_fn f1, void * client_data);
 
-/* A simpler version that starts at the end:    */
+/* A simpler version that starts at the end.    */
 CORD_API int CORD_riter(CORD x, CORD_iter_fn f1, void * client_data);
 
 #ifdef __cplusplus
@@ -184,9 +185,9 @@ CORD_API int CORD_riter(CORD x, CORD_iter_fn f1, void * client_data);
 /* positions are big (order of a few 100 bytes), so allocate them with  */
 /* caution.                                                             */
 /* Things in cord_pos.h should be treated as opaque, except as          */
-/* described below.  Also note that                                     */
-/* CORD_pos_fetch, CORD_next and CORD_prev have both macro and function */
-/* definitions.  The former may evaluate their argument more than once. */
+/* described below.  Also, note that CORD_pos_fetch, CORD_next and      */
+/* CORD_prev have both macro and function definitions.  The former      */
+/* may evaluate their argument more than once.                          */
 #include "cord_pos.h"
 
 #ifdef __cplusplus
@@ -237,7 +238,7 @@ extern void (* CORD_oom_fn)(void);
 CORD_API void CORD_dump(CORD x);
 
 /* The following could easily be implemented by the client.  They are   */
-/* provided in cordxtra.c for convenience.                              */
+/* provided by the cord library for convenience.                        */
 
 /* Concatenate a character to the end of a cord.        */
 CORD_API CORD CORD_cat_char(CORD x, char c);
@@ -245,10 +246,10 @@ CORD_API CORD CORD_cat_char(CORD x, char c);
 /* Concatenate n cords. */
 CORD_API CORD CORD_catn(int n, /* CORD */ ...);
 
-/* Return the character in CORD_substr(x, i, 1)         */
+/* Return the character in CORD_substr(x, i, 1).        */
 CORD_API char CORD_fetch(CORD x, size_t i);
 
-/* Return < 0, 0, or > 0, depending on whether x < y, x = y, x > y      */
+/* Return < 0, 0, or > 0, depending on whether x < y, x = y, x > y.     */
 CORD_API int CORD_cmp(CORD x, CORD y);
 
 /* A generalization that takes both starting positions for the          */
@@ -276,13 +277,13 @@ CORD_API CORD CORD_chars(char c, size_t i);
 /* We must have exclusive access to the descriptor f, i.e. we may       */
 /* read it at any time, and expect the file pointer to be               */
 /* where we left it.  Normally this should be invoked as                */
-/* CORD_from_file(fopen(...))                                           */
+/* CORD_from_file(fopen(...)).                                          */
 /* CORD_from_file arranges to close the file descriptor when it is no   */
 /* longer needed (e.g. when the result becomes inaccessible).           */
 /* The file f must be such that ftell reflects the actual character     */
 /* position in the file, i.e. the number of characters that can be      */
-/* or were read with fread.  On UNIX systems this is always true.  On   */
-/* MS Windows systems, f must be opened in binary mode.                 */
+/* or were read with fread.  On UNIX systems this is always true.       */
+/* On Windows systems, f must be opened in binary mode.                 */
 CORD_API CORD CORD_from_file(FILE * f);
 
 /* Equivalent to the above, except that the entire file will be read    */
@@ -290,8 +291,8 @@ CORD_API CORD CORD_from_file(FILE * f);
 /* The binary mode restriction from above does not apply.               */
 CORD_API CORD CORD_from_file_eager(FILE * f);
 
-/* Equivalent to the above, except that the file will be read on demand.*/
-/* The binary mode restriction applies.                                 */
+/* Equivalent to the above, except that the file will be read on        */
+/* demand.  The binary mode restriction applies.                        */
 CORD_API CORD CORD_from_file_lazy(FILE * f);
 
 /* Turn a cord into a C string. The result shares no structure with     */
@@ -306,8 +307,8 @@ CORD_API CORD CORD_from_char_star(const char *s);
 /* the argument and is thus not modifiable.                             */
 CORD_API const char * CORD_to_const_char_star(CORD x);
 
-/* Write a cord to a file, starting at the current position.  No        */
-/* trailing NULs are newlines are added.                                */
+/* Write a cord to a file, starting at the current position.            */
+/* No trailing NULs are newlines are added.                             */
 /* Returns EOF if a write error occurs, 1 otherwise.                    */
 CORD_API int CORD_put(CORD x, FILE * f);
 
@@ -316,11 +317,11 @@ CORD_API int CORD_put(CORD x, FILE * f);
 
 /* A vague analog of strchr.  Returns the position (an integer, not     */
 /* a pointer) of the first occurrence of (char) c inside x at position  */
-/* i or later. The value i must be < CORD_len(x).                       */
+/* i or later.  The value i must be < CORD_len(x).                      */
 CORD_API size_t CORD_chr(CORD x, size_t i, int c);
 
 /* A vague analog of strrchr.  Returns index of the last occurrence     */
-/* of (char) c inside x at position i or earlier. The value i           */
+/* of (char) c inside x at position i or earlier.  The value i          */
 /* must be < CORD_len(x).                                               */
 CORD_API size_t CORD_rchr(CORD x, size_t i, int c);
 
@@ -328,8 +329,7 @@ CORD_API size_t CORD_rchr(CORD x, size_t i, int c);
   } /* extern "C" */
 #endif
 
-/* The following are also not primitive, but are implemented in         */
-/* cordprnt.c.  They provide functionality similar to the ANSI C        */
+/* The following ones provide functionality similar to the ANSI C       */
 /* functions with corresponding names, but with the following           */
 /* additions and changes:                                               */
 /* 1. A %r conversion specification specifies a CORD argument.  Field   */
@@ -337,8 +337,8 @@ CORD_API size_t CORD_rchr(CORD x, size_t i, int c);
 /*    (Note that %c, %C, and %S were already taken.)                    */
 /* 2. The format string is represented as a CORD.                       */
 /* 3. CORD_sprintf and CORD_vsprintf assign the result through the 1st  */
-/*    argument. Unlike their ANSI C versions, there is no need to guess */
-/*    the correct buffer size.                                          */
+/*    argument.  Unlike their ANSI C versions, there is no need to      */
+/*    guess the correct buffer size.                                    */
 /* 4. Most of the conversions are implement through the native          */
 /*    vsprintf.  Hence they are usually no faster, and                  */
 /*    idiosyncrasies of the native printf are preserved.  However,      */

+ 7 - 7
blitz.mod/bdwgc/include/gc/cord_pos.h

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -47,8 +47,8 @@ typedef struct CORD_Pos {
                                 /* Always points to a valid string      */
                                 /* containing the current character     */
                                 /* unless cur_end is 0.                 */
-    size_t cur_start;   /* Start position of cur_leaf   */
-    size_t cur_end;     /* Ending position of cur_leaf  */
+    size_t cur_start;   /* Start position of cur_leaf.  */
+    size_t cur_end;     /* Ending position of cur_leaf; */
                         /* 0 if cur_leaf is invalid.    */
     struct CORD_pe path[MAX_DEPTH + 1];
         /* path[path_len] is the leaf corresponding to cur_pos  */
@@ -110,16 +110,16 @@ CORD_API void CORD__prev(CORD_pos);
 #define CORD_pos_valid(p) ((p)[0].path_len != CORD_POS_INVALID)
 
 /* Some grubby stuff for performance-critical friends:  */
-#define CORD_pos_chars_left(p) ((long)((p)[0].cur_end) - (long)((p)[0].cur_pos))
+#define CORD_pos_chars_left(p) ((long)((p)[0].cur_end)-(long)((p)[0].cur_pos))
         /* Number of characters in cache.  <= 0 ==> none        */
 
 #define CORD_pos_advance(p,n) ((p)[0].cur_pos += (n) - 1, CORD_next(p))
-        /* Advance position by n characters     */
-        /* 0 < n < CORD_pos_chars_left(p)       */
+        /* Advance position by n characters;    */
+        /* 0 < n < CORD_pos_chars_left(p).      */
 
 #define CORD_pos_cur_char_addr(p) \
         (p)[0].cur_leaf + ((p)[0].cur_pos - (p)[0].cur_start)
-        /* address of current character in cache.       */
+        /* Address of the current character in cache.   */
 
 #ifdef __cplusplus
   } /* extern "C" */

+ 4 - 6
blitz.mod/bdwgc/include/gc/ec.h

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -14,9 +14,9 @@
 #ifndef EC_H
 #define EC_H
 
-# ifndef CORD_H
-#  include "cord.h"
-# endif
+#ifndef CORD_H
+# include "cord.h"
+#endif
 
 #ifdef __cplusplus
   extern "C" {
@@ -61,8 +61,6 @@ typedef struct CORD_ec_struct {
 /* ec_buf[0 ... (ec_bufptr-ec_buf-1)]                           */
 
 /* Flush the buffer part of the extended cord into ec_cord.     */
-/* Note that this is almost the only real function, and it is   */
-/* implemented in 6 lines in cordxtra.c                         */
 void CORD_ec_flush_buf(CORD_ec x);
 
 /* Convert an extensible cord to a cord. */

+ 101 - 80
blitz.mod/bdwgc/include/gc/gc.h

@@ -5,13 +5,13 @@
  * Copyright (c) 1999 by Hewlett-Packard Company.  All rights reserved.
  * Copyright (c) 2007 Free Software Foundation, Inc.
  * Copyright (c) 2000-2011 by Hewlett-Packard Development Company.
- * Copyright (c) 2009-2020 Ivan Maidanski
+ * Copyright (c) 2009-2022 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -87,32 +87,29 @@ GC_API GC_word GC_CALL GC_get_gc_no(void);
                         /* avoid data races on multiprocessors.         */
 
 #ifdef GC_THREADS
+  /* GC is parallelized for performance on multiprocessors.  Set to     */
+  /* a non-zero value when client calls GC_start_mark_threads()         */
+  /* directly or starts the first non-main thread, provided the         */
+  /* collector is built with PARALLEL_MARK defined, and either          */
+  /* GC_MARKERS (or GC_NPROCS) environment variable is set to a value   */
+  /* bigger than 1, or multiple cores (processors) are available, or    */
+  /* the client calls GC_set_markers_count() before GC initialization.  */
+  /* After setting, GC_parallel value is equal to the number of marker  */
+  /* threads minus one (i.e. the number of existing parallel marker     */
+  /* threads excluding the initiating one).                             */
   GC_API GC_ATTR_DEPRECATED int GC_parallel;
-                        /* GC is parallelized for performance on        */
-                        /* 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, or the client    */
-                        /* calls GC_set_markers_count() before the GC   */
-                        /* initialization.  The getter does             */
-                        /* not use or need synchronization (i.e.        */
-                        /* acquiring the GC lock).  GC_parallel value   */
-                        /* is equal to the number of marker threads     */
-                        /* minus one (i.e. number of existing parallel  */
-                        /* marker threads excluding the initiating one).*/
-  GC_API int GC_CALL GC_get_parallel(void);
-
-  /* Set the number of marker threads (including the initiating one)    */
-  /* to the desired value at start-up.  Zero value means the collector  */
-  /* is to decide.  Has no effect if called after GC initialization.    */
-  /* If the correct non-zero value is passed, then GC_parallel should   */
-  /* be set to the value minus one.  The function does not use any      */
-  /* synchronization.                                                   */
-  GC_API void GC_CALL GC_set_markers_count(unsigned);
 #endif
 
+/* Return value of GC_parallel.  Does not acquire the GC lock.          */
+GC_API int GC_CALL GC_get_parallel(void);
+
+/* Set the number of marker threads (including the initiating one)      */
+/* to the desired value at start-up.  Zero value means the collector    */
+/* is to decide.  If the correct non-zero value is passed, then later   */
+/* GC_parallel will be set to the value minus one.  Has no effect if    */
+/* called after GC initialization.  Does not itself cause creation of   */
+/* the marker threads.  Does not use any synchronization.               */
+GC_API void GC_CALL GC_set_markers_count(unsigned);
 
 /* Public R/W variables */
 /* The supplied setter and getter functions are preferred for new code. */
@@ -306,14 +303,17 @@ GC_API void GC_CALL GC_set_non_gc_bytes(GC_word);
 GC_API GC_word GC_CALL GC_get_non_gc_bytes(void);
 
 GC_API GC_ATTR_DEPRECATED int GC_no_dls;
-                        /* Don't register dynamic library data segments. */
-                        /* Wizards only.  Should be used only if the     */
-                        /* application explicitly registers all roots.   */
-                        /* (In some environments like Microsoft Windows  */
-                        /* and Apple's Darwin, this may also prevent     */
-                        /* registration of the main data segment as part */
-                        /* of the root set.)                             */
-                        /* The setter and getter are unsynchronized.     */
+                        /* Do not register dynamic library data         */
+                        /* segments automatically.  Also, if set by the */
+                        /* collector itself (during GC), this means     */
+                        /* that such a registration is not supported.   */
+                        /* Wizards only.  Should be set only if the     */
+                        /* application explicitly registers all roots.  */
+                        /* (In some environments like Microsoft Windows */
+                        /* and Apple's Darwin, this may also prevent    */
+                        /* registration of the main data segment as a   */
+                        /* part of the root set.)                       */
+                        /* The setter and getter are unsynchronized.    */
 GC_API void GC_CALL GC_set_no_dls(int);
 GC_API int GC_CALL GC_get_no_dls(void);
 
@@ -512,7 +512,7 @@ GC_API void GC_CALL GC_set_handle_fork(int);
 /* before fork(); GC_atfork_parent should be invoked just after fork in */
 /* the branch that corresponds to parent process (i.e., fork result is  */
 /* non-zero); GC_atfork_child is to be called immediately in the child  */
-/* branch (i.e., fork result is 0). Note that GC_atfork_child() call    */
+/* branch (i.e., fork result is 0).  Note that GC_atfork_child() call   */
 /* should, of course, precede GC_start_mark_threads call (if any).      */
 GC_API void GC_CALL GC_atfork_prepare(void);
 GC_API void GC_CALL GC_atfork_parent(void);
@@ -522,8 +522,8 @@ GC_API void GC_CALL GC_atfork_child(void);
 /* from the main program instead.                                       */
 GC_API void GC_CALL GC_init(void);
 
-/* Returns non-zero (TRUE) if and only if the collector is initialized  */
-/* (or, at least, the initialization is in progress).                   */
+/* Return 1 (true) if the collector is initialized (or, at least, the   */
+/* initialization is in progress), 0 otherwise.                         */
 GC_API int GC_CALL GC_is_init_called(void);
 
 /* Perform the collector shutdown.  (E.g. dispose critical sections on  */
@@ -551,11 +551,19 @@ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
         GC_malloc_uncollectable(size_t /* size_in_bytes */);
 GC_API GC_ATTR_DEPRECATED void * GC_CALL GC_malloc_stubborn(size_t);
 
-/* GC_memalign() is not well tested.                                    */
+/* The routines that guarantee the requested alignment of the allocated */
+/* memory object.  Note that GC_base() and GC_size() might return the   */
+/* value which is not the expected one (due to the alignment).          */
 GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(2) void * GC_CALL
         GC_memalign(size_t /* align */, size_t /* lb */);
 GC_API int GC_CALL GC_posix_memalign(void ** /* memptr */, size_t /* align */,
                         size_t /* lb */) GC_ATTR_NONNULL(1);
+#ifndef GC_NO_VALLOC
+  GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_valloc(size_t /* lb */);
+  GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_pvalloc(size_t /* lb */);
+#endif /* !GC_NO_VALLOC */
 
 /* Explicitly deallocate an object.  Dangerous if used incorrectly.     */
 /* Requires a pointer to the base of an object.                         */
@@ -593,10 +601,10 @@ GC_API void GC_CALL GC_end_stubborn_change(const void *) GC_ATTR_NONNULL(1);
 /* GC_free.                                                             */
 GC_API void * GC_CALL GC_base(void * /* displaced_pointer */);
 
-/* Return non-zero (TRUE) if and only if the argument points to         */
-/* somewhere in GC heap.  Primary use is as a fast alternative to       */
-/* GC_base to check whether the pointed object is allocated by GC       */
-/* or not.  It is assumed that the collector is already initialized.    */
+/* Return 1 (true) if the argument points to somewhere in the GC heap,  */
+/* 0 otherwise.  Primary use is as a fast alternative to GC_base() to   */
+/* check whether the given object is allocated by the collector or not. */
+/* It is assumed that the collector is already initialized.             */
 GC_API int GC_CALL GC_is_heap_ptr(const void *);
 
 /* Given a pointer to the base of an object, return its size in bytes.  */
@@ -628,8 +636,8 @@ GC_API void * GC_CALL GC_realloc(void * /* old_object */,
                                  size_t /* new_size_in_bytes */)
                         /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2);
 
-/* Explicitly increase the heap size.   */
-/* Returns 0 on failure, 1 on success.  */
+/* Increase the heap size explicitly.  Includes a GC_init() call.       */
+/* Returns 0 on failure, 1 on success.                                  */
 GC_API int GC_CALL GC_expand_hp(size_t /* number_of_bytes */);
 
 /* Limit the heap size to n bytes.  Useful when you're debugging,       */
@@ -655,13 +663,13 @@ GC_API void GC_CALL GC_clear_exclusion_table(void);
 GC_API void GC_CALL GC_clear_roots(void);
 
 /* Add a root segment.  Wizards only.                                   */
+/* May merge adjacent or overlapping segments if appropriate.           */
 /* Both segment start and end are not needed to be pointer-aligned.     */
 /* low_address must not be greater than high_address_plus_1.            */
 GC_API void GC_CALL GC_add_roots(void * /* low_address */,
                                  void * /* high_address_plus_1 */);
 
-/* Remove a root segment.  Wizards only.                                */
-/* May be unimplemented on some platforms.                              */
+/* Remove root segments located fully in the region.  Wizards only.     */
 GC_API void GC_CALL GC_remove_roots(void * /* low_address */,
                                     void * /* high_address_plus_1 */);
 
@@ -711,8 +719,8 @@ GC_API int GC_CALL GC_try_to_collect(GC_stop_func /* stop_func */)
                                                         GC_ATTR_NONNULL(1);
 
 /* Set and get the default stop_func.  The default stop_func is used by */
-/* GC_gcollect() and by implicitly trigged collections (except for the  */
-/* case when handling out of memory).  Must not be 0.                   */
+/* GC_gcollect() and by implicitly triggered collections (except for    */
+/* the case when handling out of memory).  Must not be 0.               */
 /* Both the setter and getter acquire the GC lock to avoid data races.  */
 GC_API void GC_CALL GC_set_stop_func(GC_stop_func /* stop_func */)
                                                         GC_ATTR_NONNULL(1);
@@ -851,8 +859,9 @@ GC_API size_t GC_CALL GC_get_memory_use(void);
 /* ineffective.                                                         */
 GC_API void GC_CALL GC_disable(void);
 
-/* Return non-zero (TRUE) if and only if garbage collection is disabled */
-/* (i.e., GC_dont_gc value is non-zero).  Does not acquire the lock.    */
+/* Return 1 (true) if the garbage collection is disabled (i.e., the     */
+/* value of GC_dont_gc is non-zero), 0 otherwise.  Does not acquire     */
+/* the lock.                                                            */
 GC_API int GC_CALL GC_is_disabled(void);
 
 /* Try to re-enable garbage collection.  GC_disable() and GC_enable()   */
@@ -881,10 +890,10 @@ GC_API int GC_CALL GC_get_manual_vdb_allowed(void);
 /* allocation.  Must be called before any such GC_gcj_malloc() calls.   */
 /* For best performance, should be called as early as possible.         */
 /* On some platforms, calling it later may have adverse effects.        */
-/* Safe to call before GC_INIT().  Includes a  GC_init() call.          */
+/* Safe to call before GC_INIT().  Includes a GC_init() call.           */
 GC_API void GC_CALL GC_enable_incremental(void);
 
-/* Return non-zero (TRUE) if and only if the incremental mode is on.    */
+/* Return 1 (true) if the incremental mode is on, 0 otherwise.          */
 /* Does not acquire the lock.                                           */
 GC_API int GC_CALL GC_is_incremental_mode(void);
 
@@ -928,7 +937,7 @@ GC_API int GC_CALL GC_collect_a_little(void);
 /* integer that happens to be an address inside the array.  (Actually,  */
 /* it reduces the chance of the allocator not finding space for such    */
 /* an array, since it will try hard to avoid introducing such a false   */
-/* reference.)  On a SunOS 4.X or MS Windows system this is recommended */
+/* reference.)  On a SunOS 4.X or Windows system this is recommended    */
 /* for arrays likely to be larger than 100 KB or so.  For other systems,*/
 /* or if the collector is not configured to recognize all interior      */
 /* pointers, the threshold is normally much higher.                     */
@@ -1384,18 +1393,24 @@ GC_API int GC_CALL GC_invoke_finalizers(void);
 /* The function is sometimes called keep_alive in other         */
 /* settings.                                                    */
 #if defined(__GNUC__) && !defined(__INTEL_COMPILER)
-# define GC_reachable_here(ptr) \
-                __asm__ __volatile__(" " : : "X"(ptr) : "memory")
-#else
-  GC_API void GC_CALL GC_noop1(GC_word);
-# ifdef LINT2
-#   define GC_reachable_here(ptr) GC_noop1(~(GC_word)(ptr)^(~(GC_word)0))
-                /* The expression matches the one of COVERT_DATAFLOW(). */
+# if defined(__e2k__)
+#   define GC_reachable_here(ptr) \
+                __asm__ __volatile__ (" " : : "r"(ptr) : "memory")
 # else
-#   define GC_reachable_here(ptr) GC_noop1((GC_word)(ptr))
+#   define GC_reachable_here(ptr) \
+                __asm__ __volatile__ (" " : : "X"(ptr) : "memory")
 # endif
+#elif defined(LINT2)
+# define GC_reachable_here(ptr) GC_noop1(~(GC_word)(ptr)^(~(GC_word)0))
+                /* The expression matches the one of COVERT_DATAFLOW(). */
+#else
+# define GC_reachable_here(ptr) GC_noop1((GC_word)(ptr))
 #endif
 
+/* Make the argument appear live to compiler.  Should be robust against */
+/* the whole program analysis.                                          */
+GC_API void GC_CALL GC_noop1(GC_word);
+
 /* GC_set_warn_proc can be used to redirect or filter warning messages. */
 /* p may not be a NULL pointer.  msg is printf format string (arg must  */
 /* match the format).  Both the setter and the getter acquire the GC    */
@@ -1481,7 +1496,8 @@ GC_API void * GC_CALL GC_call_with_alloc_lock(GC_fn_type /* fn */,
 /* On most platforms this contains just a single address.               */
 struct GC_stack_base {
   void * mem_base;      /* the bottom of the general-purpose stack */
-# if defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
+# if defined(__e2k__) \
+     || defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
     void * reg_base;    /* the bottom of the register stack */
 # endif
 };
@@ -1504,12 +1520,19 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */,
 #define GC_NOT_FOUND 4          /* Requested link not found (returned   */
                                 /* by GC_move_disappearing_link).       */
 
+/* Start the parallel marker threads, if available.  Useful, e.g.,      */
+/* after POSIX fork in a child process (provided not followed by exec)  */
+/* or in single-threaded clients (provided it is OK for the client to   */
+/* perform marking in parallel).  Acquires the GC lock to avoid a race. */
+GC_API void GC_CALL GC_start_mark_threads(void);
+
 #if defined(GC_DARWIN_THREADS) || defined(GC_WIN32_THREADS)
   /* Use implicit thread registration and processing (via Win32 DllMain */
   /* or Darwin task_threads).  Deprecated.  Must be called before       */
   /* GC_INIT() and other GC routines.  Should be avoided if             */
-  /* GC_pthread_create, GC_beginthreadex (or GC_CreateThread) could be  */
-  /* called instead.  Disables parallelized GC on Win32.                */
+  /* GC_pthread_create, GC_beginthreadex (or GC_CreateThread), or       */
+  /* GC_register_my_thread could be called instead.                     */
+  /* Includes a GC_init() call.  Disables parallelized GC on Win32.     */
   GC_API void GC_CALL GC_use_threads_discovery(void);
 #endif
 
@@ -1520,6 +1543,7 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */,
 
   /* Suggest the GC to use the specific signal to resume threads.       */
   /* Has no effect after GC_init and on non-POSIX systems.              */
+  /* The same signal might be used for threads suspension and restart.  */
   GC_API void GC_CALL GC_set_thr_restart_signal(int);
 
   /* Return the signal number (constant after initialization) used by   */
@@ -1531,10 +1555,6 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */,
   /* systems.  Return -1 otherwise.                                     */
   GC_API int GC_CALL GC_get_thr_restart_signal(void);
 
-  /* Restart marker threads after POSIX fork in child.  Meaningless in  */
-  /* other situations.  Should not be called if fork followed by exec.  */
-  GC_API void GC_CALL GC_start_mark_threads(void);
-
   /* Explicitly enable GC_register_my_thread() invocation.              */
   /* Done implicitly if a GC thread-creation function is called (or     */
   /* implicit thread registration is activated, or the collector is     */
@@ -1542,6 +1562,7 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */,
   /* must be called from the main (or any previously registered) thread */
   /* between the collector initialization and the first explicit        */
   /* registering of a thread (it should be called as late as possible). */
+  /* Includes a GC_start_mark_threads() call.                           */
   GC_API void GC_CALL GC_allow_register_threads(void);
 
   /* Register the current thread, with the indicated stack bottom, as   */
@@ -1568,16 +1589,17 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */,
   GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *)
                                                         GC_ATTR_NONNULL(1);
 
-  /* Return non-zero (TRUE) if and only if the calling thread is        */
-  /* registered with the garbage collector.                             */
+  /* Return 1 (true) if the calling (current) thread is registered with */
+  /* the garbage collector, 0 otherwise.  Acquires the allocator lock.  */
   GC_API int GC_CALL GC_thread_is_registered(void);
 
   /* Notify the collector about the stack and the alt-stack of the      */
-  /* current thread.  stack_start/size is used to determine the stack   */
-  /* boundaries when a thread is suspended while it is on an alt-stack. */
-  GC_API void GC_CALL GC_register_altstack(void * /* stack_start */,
-                                           GC_word /* stack_size */,
-                                           void * /* altstack_base */,
+  /* current thread.  normstack and normstack_size are used to          */
+  /* determine the "normal" stack boundaries when a thread is suspended */
+  /* while it is on an alt-stack.                                       */
+  GC_API void GC_CALL GC_register_altstack(void * /* normstack */,
+                                           GC_word /* normstack_size */,
+                                           void * /* altstack */,
                                            GC_word /* altstack_size */);
 
   /* Unregister the current thread.  Only an explicitly registered      */
@@ -1591,7 +1613,7 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */,
   /* thread, it must do this before calling GC_unregister_my_thread,    */
   /* most probably by saving it in a global data structure.  Must not   */
   /* be called inside a GC callback function (except for                */
-  /* GC_call_with_stack_base() one).                                    */
+  /* GC_call_with_stack_base() one).  Always returns GC_SUCCESS.        */
   GC_API int GC_CALL GC_unregister_my_thread(void);
 
   /* Stop/start the world explicitly.  Not recommended for general use. */
@@ -1934,9 +1956,8 @@ GC_API void GC_CALL GC_register_has_static_roots_callback(
 # endif /* !GC_NO_THREAD_DECLS */
 
 # ifdef GC_WINMAIN_REDIRECT
-    /* win32_threads.c implements the real WinMain(), which will start  */
-    /* a new thread to call GC_WinMain() after initializing the garbage */
-    /* collector.                                                       */
+    /* The collector provides the real WinMain(), which starts a new    */
+    /* thread to call GC_WinMain() after initializing the GC.           */
 #   define WinMain GC_WinMain
 # endif
 
@@ -2013,7 +2034,7 @@ GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void);
 #endif
 
 #ifdef GC_DONT_EXPAND
-  /* Set GC_dont_expand to TRUE at start-up */
+  /* Set GC_dont_expand to true at start-up.    */
 # define GC_INIT_CONF_DONT_EXPAND GC_set_dont_expand(1)
 #else
 # define GC_INIT_CONF_DONT_EXPAND /* empty */
@@ -2136,7 +2157,7 @@ GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void);
                     GC_INIT_CONF_IGNORE_WARN; \
                     GC_INIT_CONF_INITIAL_HEAP_SIZE; }
 
-/* win32S may not free all resources on process exit.                   */
+/* win32s may not free all resources on process exit.                   */
 /* This explicitly deallocates the heap.  Defined only for Windows.     */
 GC_API void GC_CALL GC_win32_free_heap(void);
 

+ 3 - 3
blitz.mod/bdwgc/include/gc/gc_allocator.h

@@ -148,7 +148,7 @@ public:
     { GC_FREE(__p); }
 
   size_type max_size() const GC_NOEXCEPT
-    { return size_t(-1) / sizeof(GC_Tp); }
+    { return static_cast<size_t>(-1) / sizeof(GC_Tp); }
 
   void construct(pointer __p, const GC_Tp& __val) { new(__p) GC_Tp(__val); }
   void destroy(pointer __p) { __p->~GC_Tp(); }
@@ -225,7 +225,7 @@ public:
     { GC_FREE(__p); }
 
   size_type max_size() const GC_NOEXCEPT
-    { return size_t(-1) / sizeof(GC_Tp); }
+    { return static_cast<size_t>(-1) / sizeof(GC_Tp); }
 
   void construct(pointer __p, const GC_Tp& __val) { new(__p) GC_Tp(__val); }
   void destroy(pointer __p) { __p->~GC_Tp(); }
@@ -304,7 +304,7 @@ public:
     { GC_FREE(__p); }
 
   size_type max_size() const GC_NOEXCEPT
-    { return size_t(-1) / sizeof(GC_Tp); }
+    { return static_cast<size_t>(-1) / sizeof(GC_Tp); }
 
   void construct(pointer __p, const GC_Tp& __val) { new(__p) GC_Tp(__val); }
   void destroy(pointer __p) { __p->~GC_Tp(); }

+ 6 - 6
blitz.mod/bdwgc/include/gc/gc_backptr.h

@@ -9,7 +9,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -69,19 +69,19 @@ GC_API GC_ref_kind GC_CALL GC_get_back_ptr_info(void * /* dest */,
                                 void ** /* base_p */, size_t * /* offset_p */)
                                 GC_ATTR_NONNULL(1);
 
-/* Generate a random heap address.            */
-/* The resulting address is in the heap, but  */
-/* not necessarily inside a valid object.     */
+/* Generate a random heap address.  The resulting address is    */
+/* in the heap, but not necessarily inside a valid object.      */
+/* The caller should hold the allocation lock.                  */
 GC_API void * GC_CALL GC_generate_random_heap_address(void);
 
 /* Generate a random address inside a valid marked heap object. */
+/* The caller should hold the allocation lock.                  */
 GC_API void * GC_CALL GC_generate_random_valid_address(void);
 
 /* Force a garbage collection and generate a backtrace from a   */
 /* random heap address.                                         */
 /* This uses the GC logging mechanism (GC_printf) to produce    */
-/* output.  It can often be called from a debugger.  The        */
-/* source in dbg_mlc.c also serves as a sample client.          */
+/* output.  It can often be called from a debugger.             */
 GC_API void GC_CALL GC_generate_random_backtrace(void);
 
 /* Print a backtrace from a specific address.  Used by the      */

+ 2 - 2
blitz.mod/bdwgc/include/gc/gc_config_macros.h

@@ -10,7 +10,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -20,7 +20,7 @@
 /* We separate it only to make gc.h more suitable as documentation.       */
 #if defined(GC_H)
 
-/* Convenient internal macro to test version of GCC.    */
+/* Convenient internal macro to test version of gcc.    */
 #if defined(__GNUC__) && defined(__GNUC_MINOR__)
 # define GC_GNUC_PREREQ(major, minor) \
             ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((major) << 16) + (minor))

+ 37 - 38
blitz.mod/bdwgc/include/gc/gc_cpp.h

@@ -88,13 +88,10 @@ objects.  In practice, it finds almost all of them.
 
 Cautions:
 
-1. Be sure the collector has been augmented with "make c++" or
-"--enable-cplusplus".
+1. Be sure the collector is compiled with the C++ support
+(e.g. --enable-cplusplus option is passed to make).
 
-2.  If your compiler supports the new "operator new[]" syntax, then
-add -DGC_OPERATOR_NEW_ARRAY to the Makefile.
-
-If your compiler doesn't support "operator new[]", beware that an
+2. If the compiler does not support "operator new[]", beware that an
 array of type T, where T is derived from "gc", may or may not be
 allocated as a collectible object (it depends on the compiler).  Use
 the explicit GC placement to make the array collectible.  For example:
@@ -120,19 +117,7 @@ clean-up function:
 that preserves the correct exception semantics requires a language
 extension, e.g. the "gc" keyword.)
 
-4. Compiler bugs (now hopefully history):
-
-* Solaris 2's CC (SC3.0) doesn't implement t->~T() correctly, so the
-destructors of classes derived from gc_cleanup won't be invoked.
-You'll have to explicitly register a clean-up function with
-new-placement syntax.
-
-* Evidently cfront 3.0 does not allow destructors to be explicitly
-invoked using the ANSI-conforming syntax t->~T().  If you're using
-cfront 3.0, you'll have to comment out the class gc_cleanup, which
-uses explicit invocation.
-
-5. GC name conflicts:
+4. GC name conflicts:
 
 Many other systems seem to use the identifier "GC" as an abbreviation
 for "Graphics Context".  Thus, GC placement has been replaced
@@ -488,31 +473,40 @@ inline void gc::operator delete(void* obj) GC_NOEXCEPT
 
 inline gc_cleanup::~gc_cleanup()
 {
-  void* base = GC_base(this);
-  if (0 == base) return; // Non-heap object.
-  GC_register_finalizer_ignore_self(base, 0, 0, 0, 0);
+# ifndef GC_NO_FINALIZATION
+    void* base = GC_base(this);
+    if (0 == base) return; // Non-heap object.
+    GC_register_finalizer_ignore_self(base, 0, 0, 0, 0);
+# endif
 }
 
 inline void GC_CALLBACK gc_cleanup::cleanup(void* obj, void* displ)
 {
-  ((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();
+  reinterpret_cast<gc_cleanup*>(reinterpret_cast<char*>(obj)
+                        + reinterpret_cast<ptrdiff_t>(displ))->~gc_cleanup();
 }
 
 inline gc_cleanup::gc_cleanup()
 {
-  GC_finalization_proc oldProc;
-  void* oldData;
-  void* this_ptr = (void*)this;
-  void* base = GC_base(this_ptr);
-  if (base != 0) {
-    // Don't call the debug version, since this is a real base address.
-    GC_register_finalizer_ignore_self(base, (GC_finalization_proc) cleanup,
-                                      (void*)((char*)this_ptr - (char*)base),
-                                      &oldProc, &oldData);
-    if (oldProc != 0) {
-      GC_register_finalizer_ignore_self(base, oldProc, oldData, 0, 0);
+# ifndef GC_NO_FINALIZATION
+    GC_finalization_proc oldProc = 0;
+    void* oldData = 0; // to avoid "might be uninitialized" compiler warning
+    void* this_ptr = reinterpret_cast<void*>(this);
+    void* base = GC_base(this_ptr);
+    if (base != 0) {
+      // Don't call the debug version, since this is a real base address.
+      GC_register_finalizer_ignore_self(base,
+                reinterpret_cast<GC_finalization_proc>(cleanup),
+                reinterpret_cast<void*>(reinterpret_cast<char*>(this_ptr) -
+                                        reinterpret_cast<char*>(base)),
+                &oldProc, &oldData);
+      if (oldProc != 0) {
+        GC_register_finalizer_ignore_self(base, oldProc, oldData, 0, 0);
+      }
     }
-  }
+# elif defined(CPPCHECK)
+    (void)cleanup;
+# endif
 }
 
 #ifdef GC_NAMESPACE
@@ -527,9 +521,14 @@ inline void* operator new(size_t size, GC_NS_QUALIFY(GCPlacement) gcp,
   switch (gcp) {
   case GC_NS_QUALIFY(UseGC):
     obj = GC_MALLOC(size);
-    if (cleanup != 0 && obj != 0) {
-      GC_REGISTER_FINALIZER_IGNORE_SELF(obj, cleanup, clientData, 0, 0);
-    }
+#   ifndef GC_NO_FINALIZATION
+      if (cleanup != 0 && obj != 0) {
+        GC_REGISTER_FINALIZER_IGNORE_SELF(obj, cleanup, clientData, 0, 0);
+      }
+#   else
+      (void)cleanup;
+      (void)clientData;
+#   endif
     break;
   case GC_NS_QUALIFY(PointerFreeGC):
     obj = GC_MALLOC_ATOMIC(size);

+ 1 - 1
blitz.mod/bdwgc/include/gc/gc_disclaim.h

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.

+ 1 - 1
blitz.mod/bdwgc/include/gc/gc_gcj.h

@@ -8,7 +8,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.

+ 11 - 9
blitz.mod/bdwgc/include/gc/gc_inline.h

@@ -2,12 +2,13 @@
  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
+ * Copyright (c) 2008-2022 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -27,12 +28,13 @@
 /* This interface is most useful for compilers that generate C.         */
 /* It is also used internally for thread-local allocation.              */
 /* Manual use is hereby discouraged.                                    */
+/* Clients should include atomic_ops.h (or similar) before this header. */
 
 #include "gc.h"
 #include "gc_tiny_fl.h"
 
 #if GC_GNUC_PREREQ(3, 0)
-# define GC_EXPECT(expr, outcome) __builtin_expect(expr,outcome)
+# define GC_EXPECT(expr, outcome) __builtin_expect(expr, outcome)
   /* Equivalent to (expr), but predict that usually (expr)==outcome. */
 #else
 # define GC_EXPECT(expr, outcome) (expr)
@@ -59,9 +61,9 @@
 # endif
 #endif
 
-/* Object kinds; must match PTRFREE, NORMAL in gc_priv.h.       */
+/* Object kinds (exposed to public).    */
 #define GC_I_PTRFREE 0
-#define GC_I_NORMAL 1
+#define GC_I_NORMAL  1
 
 /* Store a pointer to a list of newly allocated objects of kind k and   */
 /* size lb in *result.  The caller must make sure that *result is       */
@@ -95,7 +97,7 @@ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
 /* The ultimately general inline allocation macro.  Allocate an object  */
 /* of size granules, putting the resulting pointer in result.  Tiny_fl  */
 /* is a "tiny" free list array, which will be used first, if the size   */
-/* is appropriate.  If granules is too large, we allocate with          */
+/* is appropriate.  If granules argument is too large, we allocate with */
 /* default_expr instead.  If we need to refill the free list, we use    */
 /* GC_generic_malloc_many with the indicated kind.                      */
 /* Tiny_fl should be an array of GC_TINY_FREELISTS void * pointers.     */
@@ -108,16 +110,16 @@ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
 /* size that are used to satisfy size 0 allocation requests.            */
 /* We rely on much of this hopefully getting optimized away in the      */
 /* num_direct = 0 case.                                                 */
-/* Particularly if granules is constant, this should generate a small   */
-/* amount of code.                                                      */
+/* Particularly, if granules argument is constant, this should generate */
+/* a small amount of code.                                              */
 # define GC_FAST_MALLOC_GRANS(result,granules,tiny_fl,num_direct, \
                               kind,default_expr,init) \
   do { \
-    if (GC_EXPECT((granules) >= GC_TINY_FREELISTS,0)) { \
+    if (GC_EXPECT((granules) >= GC_TINY_FREELISTS, 0)) { \
         result = (default_expr); \
     } else { \
         void **my_fl = (tiny_fl) + (granules); \
-        void *my_entry=*my_fl; \
+        void *my_entry = *my_fl; \
         void *next; \
     \
         for (;;) { \

+ 57 - 11
blitz.mod/bdwgc/include/gc/gc_mark.h

@@ -1,12 +1,13 @@
 /*
  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 2001 by Hewlett-Packard Company. All rights reserved.
+ * Copyright (c) 2009-2022 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -33,6 +34,16 @@
   extern "C" {
 #endif
 
+#define GC_PROC_BYTES 100
+
+#if defined(GC_BUILD) || defined(NOT_GCBUILD)
+  struct GC_ms_entry;
+  struct GC_hblk_s;
+#else
+  struct GC_ms_entry { void *opaque; };
+  struct GC_hblk_s { void *opaque; };
+#endif
+
 /* A client supplied mark procedure.  Returns new mark stack pointer.   */
 /* Primary effect should be to push new entries on the mark stack.      */
 /* Mark stack pointer values are passed and returned explicitly.        */
@@ -54,14 +65,10 @@
 /* residing on a free list.  Such objects are cleared, except for a     */
 /* free list link field in the first word.  Thus mark procedures may    */
 /* not count on the presence of a type descriptor, and must handle this */
-/* case correctly somehow.                                              */
-#define GC_PROC_BYTES 100
-
-#if defined(GC_BUILD) || defined(NOT_GCBUILD)
-  struct GC_ms_entry;
-#else
-  struct GC_ms_entry { void *opaque; };
-#endif
+/* case correctly somehow.  Also, a mark procedure should be prepared   */
+/* to be executed concurrently from the marker threads (the later ones  */
+/* are created only if the client has called GC_start_mark_threads()    */
+/* or started a user thread previously).                                */
 typedef struct GC_ms_entry * (*GC_mark_proc)(GC_word * /* addr */,
                                 struct GC_ms_entry * /* mark_stack_ptr */,
                                 struct GC_ms_entry * /* mark_stack_limit */,
@@ -170,6 +177,43 @@ GC_API GC_ATTR_DEPRECATED
 # endif
   size_t GC_debug_header_size;
 
+/* Return the heap block size.  Each heap block is devoted to a single  */
+/* size and kind of object.                                             */
+GC_API GC_ATTR_CONST size_t GC_CALL GC_get_hblk_size(void);
+
+/* Same as GC_walk_hblk_fn but with index of the free list.             */
+typedef void (GC_CALLBACK *GC_walk_free_blk_fn)(struct GC_hblk_s *,
+                                                int /* index */,
+                                                GC_word /* client_data */);
+
+/* Apply fn to each completely empty heap block.  It is the             */
+/* responsibility of the caller to avoid data race during the function  */
+/* execution (e.g. by holding the allocation lock).                     */
+GC_API void GC_CALL GC_iterate_free_hblks(GC_walk_free_blk_fn,
+                                GC_word /* client_data */) GC_ATTR_NONNULL(1);
+
+typedef void (GC_CALLBACK *GC_walk_hblk_fn)(struct GC_hblk_s *,
+                                            GC_word /* client_data */);
+
+/* Apply fn to each allocated heap block.  It is the responsibility     */
+/* of the caller to avoid data race during the function execution (e.g. */
+/* by holding the allocation lock).                                     */
+GC_API void GC_CALL GC_apply_to_all_blocks(GC_walk_hblk_fn,
+                                GC_word /* client_data */) GC_ATTR_NONNULL(1);
+
+/* If there are likely to be false references to a block starting at h  */
+/* of the indicated length, then return the next plausible starting     */
+/* location for h that might avoid these false references.  Otherwise   */
+/* NULL is returned.  Assumes the allocation lock is held but no        */
+/* assertion about it by design.                                        */
+GC_API struct GC_hblk_s *GC_CALL GC_is_black_listed(struct GC_hblk_s *,
+                                                    GC_word /* len */);
+
+/* Return the number of set mark bits for the heap block where object   */
+/* p is located.  Defined only if the library has been compiled         */
+/* without NO_DEBUGGING.                                                */
+GC_API unsigned GC_CALL GC_count_set_marks_in_hblk(const void * /* p */);
+
 /* And some routines to support creation of new "kinds", e.g. with      */
 /* custom mark procedures, by language runtimes.                        */
 /* The _inner versions assume the caller holds the allocation lock.     */
@@ -282,8 +326,10 @@ typedef void (GC_CALLBACK * GC_start_callback_proc)(void);
 GC_API void GC_CALL GC_set_start_callback(GC_start_callback_proc);
 GC_API GC_start_callback_proc GC_CALL GC_get_start_callback(void);
 
-/* Slow/general mark bit manipulation.  The caller must hold the        */
-/* allocation lock.  GC_is_marked returns 1 (TRUE) or 0.                */
+/* Slow/general mark bit manipulation.  The caller should hold the      */
+/* allocation lock.  GC_is_marked returns 1 (true) or 0.  The argument  */
+/* should be the real address of an object (i.e. the address of the     */
+/* debug header if there is one).                                       */
 GC_API int GC_CALL GC_is_marked(const void *) GC_ATTR_NONNULL(1);
 GC_API void GC_CALL GC_clear_mark_bit(const void *) GC_ATTR_NONNULL(1);
 GC_API void GC_CALL GC_set_mark_bit(const void *) GC_ATTR_NONNULL(1);

+ 2 - 2
blitz.mod/bdwgc/include/gc/gc_pthread_redirects.h

@@ -9,7 +9,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -92,7 +92,7 @@
 
 #if !defined(GC_NO_THREAD_REDIRECTS) && !defined(GC_USE_LD_WRAP)
   /* Unless the compiler supports #pragma extern_prefix, the Tru64      */
-  /* UNIX <pthread.h> redefines some POSIX thread functions to use      */
+  /* UNIX pthread.h redefines some POSIX thread functions to use        */
   /* mangled names.  Anyway, it's safe to undef them before redefining. */
 # undef pthread_create
 # undef pthread_join

+ 7 - 7
blitz.mod/bdwgc/include/gc/gc_tiny_fl.h

@@ -5,7 +5,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -51,18 +51,18 @@
         || (defined(__x86_64__) && !defined(__ILP32__)) \
         || defined(__alpha__) || defined(__powerpc64__) \
         || defined(__arch64__)
-#  define GC_GRANULE_BYTES 16
-#  define GC_GRANULE_WORDS 2
+#   define GC_GRANULE_BYTES 16
+#   define GC_GRANULE_WORDS 2
 # else
-#  define GC_GRANULE_BYTES 8
-#  define GC_GRANULE_WORDS 2
+#   define GC_GRANULE_BYTES 8
+#   define GC_GRANULE_WORDS 2
 # endif
 #endif /* !GC_GRANULE_BYTES */
 
 #if GC_GRANULE_WORDS == 2
-#  define GC_WORDS_TO_GRANULES(n) ((n)>>1)
+# define GC_WORDS_TO_GRANULES(n) ((n)>>1)
 #else
-#  define GC_WORDS_TO_GRANULES(n) ((n)*sizeof(void *)/GC_GRANULE_BYTES)
+# define GC_WORDS_TO_GRANULES(n) ((n)*sizeof(void *)/GC_GRANULE_BYTES)
 #endif
 
 /* A "tiny" free list header contains TINY_FREELISTS pointers to        */

+ 1 - 1
blitz.mod/bdwgc/include/gc/gc_typed.h

@@ -7,7 +7,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.

+ 1 - 1
blitz.mod/bdwgc/include/gc/gc_version.h

@@ -9,7 +9,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.

+ 2 - 1
blitz.mod/bdwgc/include/gc/javaxfc.h

@@ -9,7 +9,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -40,6 +40,7 @@
  *    finalizers which create new finalizable objects, though that's
  *    probably unlikely.
  * Thus this is not recommended for general use.
+ * Acquire the allocation lock (to enqueue all finalizers).
  */
 GC_API void GC_CALL GC_finalize_all(void);
 

+ 13 - 2
blitz.mod/bdwgc/include/gc/leak_detector.h

@@ -6,7 +6,7 @@
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  *
  * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
+ * for any purpose, provided the above notices are retained on all copies.
  * Permission to modify the code and to distribute modified code is granted,
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
@@ -15,7 +15,7 @@
 #ifndef GC_LEAK_DETECTOR_H
 #define GC_LEAK_DETECTOR_H
 
-/* Include leak_detector.h (e.g., via GCC --include directive)  */
+/* Include this header file (e.g., via gcc --include directive) */
 /* to turn libgc into a leak detector.                          */
 
 #ifndef GC_DEBUG
@@ -38,6 +38,8 @@
 #define free(p) GC_FREE(p)
 #undef realloc
 #define realloc(p,n) GC_REALLOC(p,n)
+#undef reallocarray
+#define reallocarray(p,m,n) GC_REALLOC(p,(m)*(n))
 
 #undef strdup
 #define strdup(s) GC_STRDUP(s)
@@ -52,11 +54,20 @@
 # define wcsdup(s) GC_WCSDUP(s)
 #endif
 
+#undef aligned_alloc
+#define aligned_alloc(a,n) GC_memalign(a,n) /* identical to memalign */
 #undef memalign
 #define memalign(a,n) GC_memalign(a,n)
 #undef posix_memalign
 #define posix_memalign(p,a,n) GC_posix_memalign(p,a,n)
 
+#ifndef GC_NO_VALLOC
+# undef valloc
+# define valloc(n) GC_valloc(n)
+# undef pvalloc
+# define pvalloc(n) GC_pvalloc(n) /* obsolete */
+#endif /* !GC_NO_VALLOC */
+
 #ifndef CHECK_LEAKS
 # define CHECK_LEAKS() GC_gcollect()
   /* Note 1: CHECK_LEAKS does not have GC prefix (preserved for */

+ 1 - 3
blitz.mod/bdwgc/include/include.am

@@ -3,7 +3,7 @@
 # OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 #
 # Permission is hereby granted to use or copy this program
-# for any purpose,  provided the above notices are retained on all copies.
+# for any purpose, provided the above notices are retained on all copies.
 # Permission to modify the code and to distribute modified code is granted,
 # provided the above notices are retained, and a notice that the code was
 # modified is included with the above copyright notice.
@@ -48,7 +48,6 @@ endif
 #
 dist_noinst_HEADERS += \
         include/private/darwin_semaphore.h \
-        include/private/darwin_stop_world.h \
         include/private/dbg_mlc.h \
         include/private/gc_alloc_ptrs.h \
         include/private/gc_atomic_ops.h \
@@ -57,7 +56,6 @@ dist_noinst_HEADERS += \
         include/private/gc_pmark.h \
         include/private/gc_priv.h \
         include/private/gcconfig.h \
-        include/private/pthread_stop_world.h \
         include/private/pthread_support.h \
         include/private/specific.h \
         include/private/thread_local_alloc.h

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است