├── .appveyor.yml ├── .clang-format ├── .gitattributes ├── .github └── workflows │ ├── CodeQL.yml │ ├── clang-format-check.yml │ ├── cmake-build.yml │ ├── cmake-cosmo.yml │ ├── zig-build.yml │ └── zig-cross-compile.yml ├── .gitignore ├── .travis.yml ├── AUTHORS ├── CMakeLists.txt ├── ChangeLog ├── Config.cmake.in ├── LICENSE ├── Makefile.am ├── Makefile.direct ├── NT_MAKEFILE ├── README.md ├── WCC_MAKEFILE ├── allchblk.c ├── alloc.c ├── autogen.sh ├── backgraph.c ├── bdw-gc.pc.in ├── blacklst.c ├── build.zig ├── checksums.c ├── configure.ac ├── cord ├── cord.am ├── cordbscs.c ├── cordprnt.c ├── cordxtra.c └── tests │ ├── cordtest.c │ ├── de.c │ ├── de_cmds.h │ ├── de_win.c │ ├── de_win.h │ └── de_win.rc ├── darwin_stop_world.c ├── dbg_mlc.c ├── digimars.mak ├── docs ├── autoconf.md ├── cmake.md ├── cords.md ├── debugging.md ├── environment.md ├── faq.md ├── finalization.md ├── gcdescr.md ├── gcinterface.md ├── leak.md ├── macros.md ├── overview.md ├── platforms │ ├── README.aix │ ├── README.arm_cross │ ├── README.darwin │ ├── README.dgux386 │ ├── README.emscripten │ ├── README.ews4800 │ ├── README.hp │ ├── README.linux │ ├── README.os2 │ ├── README.sgi │ ├── README.solaris2 │ ├── README.symbian │ ├── README.uts │ ├── README.win32 │ └── README.win64 ├── porting.md ├── scale.md ├── simple_example.md └── tree.md ├── dyn_load.c ├── extra ├── gc.c ├── msvc_dbg.c ├── symbian.cpp └── symbian │ ├── global_end.cpp │ ├── global_start.cpp │ └── init_global_static_roots.cpp ├── finalize.c ├── fnlz_mlc.c ├── gc.man ├── gc_badalc.cc ├── gc_badalc.cpp ├── gc_cpp.cc ├── gc_cpp.cpp ├── gc_dlopen.c ├── gcj_mlc.c ├── headers.c ├── ia64_save_regs_in_stack.s ├── include ├── gc.h ├── gc │ ├── cord.h │ ├── cord_pos.h │ ├── ec.h │ ├── gc.h │ ├── gc_allocator.h │ ├── gc_backptr.h │ ├── gc_config_macros.h │ ├── gc_cpp.h │ ├── gc_disclaim.h │ ├── gc_gcj.h │ ├── gc_inline.h │ ├── gc_mark.h │ ├── gc_pthread_redirects.h │ ├── gc_tiny_fl.h │ ├── gc_typed.h │ ├── gc_version.h │ ├── javaxfc.h │ └── leak_detector.h ├── gc_cpp.h ├── include.am └── private │ ├── darwin_semaphore.h │ ├── dbg_mlc.h │ ├── gc_alloc_ptrs.h │ ├── gc_atomic_ops.h │ ├── gc_hdrs.h │ ├── gc_locks.h │ ├── gc_pmark.h │ ├── gc_priv.h │ ├── gcconfig.h │ ├── pthread_support.h │ ├── specific.h │ └── thread_local_alloc.h ├── m4 └── gc_set_version.m4 ├── mach_dep.c ├── malloc.c ├── mallocx.c ├── mark.c ├── mark_rts.c ├── misc.c ├── new_hblk.c ├── obj_map.c ├── os_dep.c ├── pthread_start.c ├── pthread_stop_world.c ├── pthread_support.c ├── ptr_chck.c ├── reclaim.c ├── sparc_mach_dep.S ├── sparc_netbsd_mach_dep.s ├── specific.c ├── tests ├── atomicops.c ├── cpp.cc ├── disclaim.c ├── disclaim_bench.c ├── gctest.c ├── huge.c ├── initfromthread.c ├── leak.c ├── middle.c ├── realloc.c ├── smash.c ├── staticroots.c ├── staticroots_lib.c ├── subthreadcreate.c ├── tests.am ├── threadkey.c ├── threadleak.c ├── trace.c ├── tree.cc └── weakmap.c ├── thread_local_alloc.c ├── tools ├── callprocs.sh ├── if_mach.c ├── if_not_there.c ├── setjmp_t.c └── threadlibs.c ├── typd_mlc.c └── win32_threads.c /.clang-format: -------------------------------------------------------------------------------- 1 | # Clang-format configuration for bdwgc source. 2 | BasedOnStyle: GNU 3 | 4 | AlignEscapedNewlines: Left 5 | BreakBeforeBraces: Linux 6 | IndentCaseBlocks: true 7 | IndentPPDirectives: AfterHash 8 | SpaceBeforeParens: ControlStatements 9 | TabWidth: 2 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Git repo attributes. 2 | 3 | # Ensure shell and configure-related files have LF enforced. 4 | *.ac text eol=lf 5 | *.am text eol=lf 6 | *.m4 text eol=lf 7 | *.sh text eol=lf 8 | 9 | # Ensure all text files have normalized line endings in the repository. 10 | * text=auto 11 | 12 | # These files should use CR/LF line ending: 13 | /digimars.mak -text 14 | 15 | # Note: "core.eol" configuration variable controls which line endings to use 16 | # for the normalized files in the working directory (the default is native). 17 | -------------------------------------------------------------------------------- /.github/workflows/CodeQL.yml: -------------------------------------------------------------------------------- 1 | # CodeQL workflow for GitHub code scanning. 2 | name: CodeQL 3 | 4 | on: [ push, pull_request ] 5 | 6 | jobs: 7 | analyze: 8 | name: Analyze 9 | runs-on: ubuntu-latest 10 | permissions: 11 | actions: read 12 | contents: read 13 | security-events: write 14 | 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | language: [ 'c-cpp' ] 19 | 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v4 23 | 24 | - name: Initialize CodeQL 25 | uses: github/codeql-action/init@v3 26 | with: 27 | languages: ${{ matrix.language }} 28 | 29 | - name: Autobuild 30 | uses: github/codeql-action/autobuild@v3 31 | 32 | - name: Perform CodeQL Analysis 33 | uses: github/codeql-action/analyze@v3 34 | with: 35 | category: "/language:${{ matrix.language }}" 36 | -------------------------------------------------------------------------------- /.github/workflows/clang-format-check.yml: -------------------------------------------------------------------------------- 1 | # Workflow for checking that source code is formatted by clang-format. 2 | name: clang-format check 3 | 4 | on: [ push, pull_request ] 5 | 6 | jobs: 7 | build: 8 | name: Check by clang-format 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | - name: Show clang-format version 15 | run: > 16 | clang-format --version 17 | - name: Perform checking by clang-format 18 | run: > 19 | find . -iname '*.c' -o -iname '*.cc' -o -iname '*.cpp' -o -iname '*.h' 20 | | xargs clang-format --dry-run --Werror 21 | -------------------------------------------------------------------------------- /.github/workflows/cmake-build.yml: -------------------------------------------------------------------------------- 1 | # This workflow is for CMake-based build/test running on multiple platforms. 2 | name: cmake build 3 | 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | build: 8 | name: ${{ matrix.os }} ${{ matrix.c_compiler }} thr:${{ matrix.enable_threads }} rwlock:${{ matrix.enable_rwlock }} redir:${{ matrix.redirect_malloc }} dll:${{ matrix.shared_libs }} cpp:${{ matrix.enable_cplusplus }} 9 | runs-on: ${{ matrix.os }} 10 | timeout-minutes: 6 11 | 12 | strategy: 13 | # Deliver the feedback for all matrix combinations. 14 | fail-fast: false 15 | 16 | matrix: 17 | os: [ macos-latest, ubuntu-latest, windows-latest ] 18 | c_compiler: [ cl, clang, gcc ] 19 | cxx_compiler: [ cl, clang++, g++ ] 20 | enable_cplusplus: [ off, on ] 21 | build_type: [ Release ] 22 | disable_gc_debug: [ off ] 23 | gc_assertions: [ on ] 24 | large_config: [ on ] 25 | enable_threads: [ off, on ] 26 | enable_rwlock: [ off, on ] 27 | redirect_malloc: [ off, on ] 28 | shared_libs: [ off, on ] 29 | exclude: 30 | - os: macos-latest 31 | c_compiler: cl 32 | - os: macos-latest 33 | c_compiler: gcc 34 | - os: ubuntu-latest 35 | c_compiler: cl 36 | - enable_threads: off 37 | enable_rwlock: on 38 | - c_compiler: cl 39 | cxx_compiler: clang++ 40 | - c_compiler: cl 41 | cxx_compiler: g++ 42 | - c_compiler: clang 43 | cxx_compiler: cl 44 | - c_compiler: clang 45 | cxx_compiler: g++ 46 | - c_compiler: gcc 47 | cxx_compiler: cl 48 | - c_compiler: gcc 49 | cxx_compiler: clang++ 50 | - os: macos-latest 51 | enable_cplusplus: off 52 | - os: ubuntu-latest 53 | enable_cplusplus: off 54 | - os: windows-latest 55 | c_compiler: cl 56 | enable_cplusplus: off 57 | - os: windows-latest # TODO: replacement operator cannot be inline 58 | c_compiler: clang 59 | enable_cplusplus: on 60 | - os: windows-latest 61 | c_compiler: gcc 62 | enable_cplusplus: off 63 | - os: windows-latest # TODO: support dependency on libatomic_ops 64 | c_compiler: cl 65 | enable_threads: on 66 | include: 67 | - os: windows-latest 68 | c_compiler: gcc 69 | cmake_generator_opt: '-G "Unix Makefiles"' 70 | - os: windows-latest 71 | c_compiler: clang 72 | cmake_generator_opt: '-G "Unix Makefiles"' 73 | 74 | steps: 75 | - uses: actions/checkout@v4 76 | 77 | - name: Set reusable strings 78 | # Turn repeated input strings into step outputs. 79 | id: strings 80 | shell: bash 81 | run: | 82 | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" 83 | 84 | - name: Configure CMake 85 | # Configure CMake in a 'build' subdirectory. 86 | run: > 87 | cmake -B ${{ steps.strings.outputs.build-output-dir }} 88 | ${{ matrix.cmake_generator_opt }} 89 | -DBUILD_SHARED_LIBS=${{ matrix.shared_libs }} 90 | -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} 91 | -DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} 92 | -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} 93 | -Dbuild_tests=ON 94 | -Ddisable_gc_debug=${{ matrix.disable_gc_debug }} 95 | -Denable_cplusplus=${{ matrix.enable_cplusplus }} 96 | -Denable_gc_assertions=${{ matrix.gc_assertions }} 97 | -Denable_large_config=${{ matrix.large_config }} 98 | -Denable_redirect_malloc=${{ matrix.redirect_malloc }} 99 | -Denable_rwlock=${{ matrix.enable_rwlock }} 100 | -Denable_threads=${{ matrix.enable_threads }} 101 | -Denable_werror=ON 102 | -Werror=dev 103 | -S ${{ github.workspace }} 104 | 105 | - name: Build 106 | # Build the code with the given configuration. 107 | run: > 108 | cmake --build ${{ steps.strings.outputs.build-output-dir }} 109 | --config ${{ matrix.build_type }} --verbose --parallel 110 | 111 | - name: Test 112 | working-directory: ${{ steps.strings.outputs.build-output-dir }} 113 | # Execute tests defined by the CMake configuration. 114 | run: ctest --build-config ${{ matrix.build_type }} --verbose --parallel 8 115 | -------------------------------------------------------------------------------- /.github/workflows/cmake-cosmo.yml: -------------------------------------------------------------------------------- 1 | # This workflow is for cmake-based build/test using Cosmo (Cosmopolitan). 2 | name: cmake cosmo 3 | 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | build: 8 | name: ${{ matrix.os }} thr:${{ matrix.enable_threads }} single-obj:${{ matrix.single_obj_compilation }} 9 | runs-on: ${{ matrix.os }} 10 | timeout-minutes: 4 11 | 12 | strategy: 13 | fail-fast: false 14 | 15 | matrix: 16 | os: [ ubuntu-latest ] # TODO: macos-latest, windows-latest 17 | enable_cplusplus: [ on ] 18 | build_type: [ Debug ] 19 | disable_gc_debug: [ off ] 20 | gc_assertions: [ on ] 21 | large_config: [ on ] 22 | enable_threads: [ off ] # TODO: on 23 | enable_rwlock: [ off ] 24 | single_obj_compilation: [ off, on ] 25 | redirect_malloc: [ off ] 26 | 27 | steps: 28 | - uses: actions/checkout@v4 29 | - uses: bjia56/setup-cosmocc@main 30 | with: 31 | version: latest 32 | 33 | - name: Set reusable strings 34 | # Turn repeated input strings into step outputs. 35 | id: strings 36 | shell: bash 37 | run: | 38 | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" 39 | 40 | - name: Configure CMake targetting Cosmo 41 | run: > 42 | cmake -B ${{ steps.strings.outputs.build-output-dir }} 43 | ${{ matrix.cmake_generator_opt }} 44 | -DBUILD_SHARED_LIBS=OFF 45 | -Denable_single_obj_compilation=${{ matrix.single_obj_compilation }} 46 | -DCMAKE_C_COMPILER=cosmocc 47 | -DCMAKE_CXX_COMPILER=cosmoc++ 48 | -DCMAKE_AR=`type -p cosmoar` 49 | -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} 50 | -Dbuild_tests=ON 51 | -Ddisable_gc_debug=${{ matrix.disable_gc_debug }} 52 | -Denable_cplusplus=${{ matrix.enable_cplusplus }} 53 | -Denable_gc_assertions=${{ matrix.gc_assertions }} 54 | -Denable_large_config=${{ matrix.large_config }} 55 | -Denable_redirect_malloc=${{ matrix.redirect_malloc }} 56 | -Denable_rwlock=${{ matrix.enable_rwlock }} 57 | -Denable_threads=${{ matrix.enable_threads }} 58 | -Denable_werror=ON 59 | -Werror=dev 60 | -S ${{ github.workspace }} 61 | 62 | - name: Build 63 | run: > 64 | cmake --build ${{ steps.strings.outputs.build-output-dir }} 65 | --config ${{ matrix.build_type }} --verbose --parallel 66 | 67 | - name: Test 68 | working-directory: ${{ steps.strings.outputs.build-output-dir }} 69 | run: ctest --build-config ${{ matrix.build_type }} --verbose --parallel 8 70 | -------------------------------------------------------------------------------- /.github/workflows/zig-build.yml: -------------------------------------------------------------------------------- 1 | # This workflow is for zig-based build/test running on Linux, MacOS, Windows. 2 | name: zig build 3 | 4 | on: [ push, pull_request ] 5 | 6 | jobs: 7 | build: 8 | name: ${{ matrix.os }} ${{ matrix.ttriple }} thr:${{ matrix.enable_threads }} rwlock:${{ matrix.enable_rwlock }} redir:${{ matrix.redirect_malloc }} gcdeb:${{ matrix.enable_gc_debug }} munmap:${{ matrix.enable_munmap }} paramark:${{ matrix.parallel_mark }} thrlocal:${{ matrix.thread_local_alloc }} dll:${{ matrix.shared_libs }} 9 | runs-on: ${{ matrix.os }} 10 | timeout-minutes: 7 11 | 12 | strategy: 13 | fail-fast: false 14 | 15 | matrix: 16 | zig_version: [ "0.14.0" ] 17 | os: [ macos-latest, ubuntu-latest, windows-latest ] 18 | ttriple: [ native, native-native-msvc ] 19 | enable_cplusplus: [ true ] 20 | gc_assertions: [ true ] 21 | large_config: [ false ] 22 | enable_threads: [ false, true ] 23 | disable_handle_fork: [ false ] 24 | enable_rwlock: [ false, true ] 25 | redirect_malloc: [ false, true ] 26 | enable_gc_debug: [ false, true ] 27 | enable_munmap: [ false, true ] 28 | parallel_mark: [ false, true ] 29 | thread_local_alloc: [ false, true ] 30 | shared_libs: [ false, true ] 31 | build_cord: [ false, true ] 32 | exclude: 33 | - build_cord: true # FIXME: cordtest hangs if shared lib build by MSVC 34 | shared_libs: true 35 | ttriple: native-native-msvc 36 | - os: macos-latest 37 | ttriple: native-native-msvc 38 | - os: ubuntu-latest 39 | ttriple: native-native-msvc 40 | - os: windows-latest 41 | disable_handle_fork: true 42 | - enable_threads: false 43 | disable_handle_fork: true 44 | - enable_threads: false 45 | parallel_mark: true 46 | - enable_threads: false 47 | enable_rwlock: true 48 | - enable_threads: false 49 | thread_local_alloc: true 50 | # The following ones are long-running jobs, thus excluded. 51 | - os: macos-latest 52 | enable_gc_debug: true 53 | enable_rwlock: true 54 | # The following ones just to reduce amount of jobs. 55 | - build_cord: false 56 | shared_libs: false 57 | - build_cord: false 58 | ttriple: native 59 | - enable_munmap: false 60 | shared_libs: true 61 | - enable_munmap: true 62 | enable_threads: false 63 | shared_libs: false 64 | - enable_gc_debug: true 65 | enable_rwlock: true 66 | thread_local_alloc: false 67 | - parallel_mark: false 68 | redirect_malloc: true 69 | - enable_gc_debug: true 70 | thread_local_alloc: false 71 | - os: macos-latest 72 | enable_munmap: false 73 | enable_threads: false 74 | - os: macos-latest 75 | enable_munmap: false 76 | enable_rwlock: true 77 | - os: macos-latest 78 | enable_rwlock: true 79 | thread_local_alloc: false 80 | - os: macos-latest 81 | enable_rwlock: true 82 | parallel_mark: false 83 | - os: macos-latest 84 | enable_munmap: false 85 | redirect_malloc: false 86 | - os: macos-latest 87 | enable_threads: true 88 | redirect_malloc: false 89 | thread_local_alloc: false 90 | - os: macos-latest 91 | enable_threads: true 92 | parallel_mark: false 93 | redirect_malloc: false 94 | 95 | steps: 96 | - uses: actions/checkout@v4 97 | - uses: korandoru/setup-zig@v1 98 | with: 99 | zig-version: ${{ matrix.zig_version }} 100 | - name: Build 101 | run: > 102 | zig build -Dtarget=${{ matrix.ttriple }} 103 | -DBUILD_SHARED_LIBS=${{ matrix.shared_libs }} 104 | -Dbuild_cord=${{ matrix.build_cord }} 105 | -Ddisable_handle_fork=${{ matrix.disable_handle_fork }} 106 | -Denable_cplusplus=${{ matrix.enable_cplusplus }} 107 | -Denable_gc_assertions=${{ matrix.gc_assertions }} 108 | -Denable_gc_debug=${{ matrix.enable_gc_debug }} 109 | -Denable_large_config=${{ matrix.large_config }} 110 | -Denable_munmap=${{ matrix.enable_munmap }} 111 | -Denable_parallel_mark=${{ matrix.parallel_mark }} 112 | -Denable_redirect_malloc=${{ matrix.redirect_malloc }} 113 | -Denable_rwlock=${{ matrix.enable_rwlock }} 114 | -Denable_thread_local_alloc=${{ matrix.thread_local_alloc }} 115 | -Denable_threads=${{ matrix.enable_threads }} 116 | -Denable_werror 117 | test 118 | -------------------------------------------------------------------------------- /.github/workflows/zig-cross-compile.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses Zig and its excellent cross-compilation support to test 2 | # compiling for multiple platforms. No tests are actually run since it would 3 | # require emulation. 4 | name: zig cross-compile 5 | 6 | on: [ push, pull_request ] 7 | 8 | jobs: 9 | build: 10 | name: ${{ matrix.ttriple }} cpp:${{ matrix.enable_cplusplus }} thr:${{ matrix.enable_threads }} dll:${{ matrix.shared_libs }} 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | zig_version: [ "0.14.0" ] 17 | # Some of the triples are commented out just to speedup this workflow. 18 | ttriple: [ 19 | aarch64-linux-gnu, 20 | #aarch64-linux-musl, 21 | aarch64-macos-none, 22 | aarch64-windows-gnu, 23 | #aarch64_be-linux-gnu, 24 | aarch64_be-linux-musl, 25 | #arc-linux-gnu, # FIXME: __linux__ macro is not predefined 26 | #arm-linux-gnueabi, 27 | arm-linux-gnueabihf, 28 | arm-linux-musleabi, 29 | #arm-linux-musleabihf, 30 | armeb-linux-gnueabi, 31 | #armeb-linux-gnueabihf, 32 | #armeb-linux-musleabi, 33 | armeb-linux-musleabihf, 34 | loongarch64-linux-gnu, 35 | #loongarch64-linux-gnusf, # FIXME: gnu/stubs-lp64s.h not found 36 | loongarch64-linux-musl, 37 | #m68k-linux-gnu, # FIXME: No available targets compatible with triple 38 | #m68k-linux-musl, # FIXME: No available targets compatible with triple 39 | #mips-linux-gnueabi, 40 | #mips-linux-gnueabihf, 41 | mips-linux-musleabi, 42 | mips-linux-musleabihf, 43 | mips64-linux-gnuabi64, 44 | #mips64-linux-gnuabin32, 45 | mips64-linux-muslabi64, 46 | mips64-linux-muslabin32, 47 | #mips64el-linux-gnuabi64, 48 | mips64el-linux-gnuabin32, 49 | mips64el-linux-muslabi64, 50 | mips64el-linux-muslabin32, 51 | mipsel-linux-gnueabi, 52 | #mipsel-linux-gnueabihf, 53 | mipsel-linux-musleabi, 54 | mipsel-linux-musleabihf, 55 | #powerpc-linux-gnueabi, 56 | powerpc-linux-gnueabihf, 57 | #powerpc-linux-musleabi, 58 | powerpc-linux-musleabihf, 59 | #powerpc64-linux-gnu, # FIXME: not implemented correctly in zig 60 | #powerpc64-linux-musl, 61 | #powerpc64le-linux-gnu, 62 | powerpc64le-linux-musl, 63 | riscv32-linux-gnu, 64 | riscv32-linux-musl, 65 | riscv64-linux-gnu, 66 | riscv64-linux-musl, 67 | s390x-linux-gnu, 68 | s390x-linux-musl, 69 | sparc-linux-gnu, 70 | sparc64-linux-gnu, 71 | thumb-linux-musleabi, 72 | #thumb-linux-musleabihf, 73 | thumb-windows-gnu, 74 | #thumbeb-linux-musleabi, 75 | thumbeb-linux-musleabihf, 76 | wasm32-wasi-musl, 77 | #x86-linux-gnu, 78 | x86-linux-musl, 79 | x86-windows-gnu, 80 | x86_64-linux-gnu.2.27, # with a glibc version 81 | x86_64-linux-gnux32, 82 | #x86_64-linux-musl, 83 | x86_64-linux-muslx32, 84 | x86_64-macos-none, 85 | x86_64-windows-gnu, 86 | ] 87 | enable_cplusplus: [ false, true ] 88 | enable_threads: [ false, true ] 89 | shared_libs: [ false, true ] 90 | exclude: 91 | - enable_threads: true 92 | ttriple: wasm32-wasi-musl 93 | - enable_cplusplus: false # excluded to speedup this workflow 94 | shared_libs: false 95 | - shared_libs: true # FIXME: SPARCv8 does not handle f128 in calls 96 | ttriple: sparc-linux-gnu 97 | - shared_libs: true # FIXME: recompile with -fPIC 98 | ttriple: sparc64-linux-gnu 99 | - shared_libs: true # FIXME: recompile with -fPIC 100 | ttriple: x86_64-linux-gnux32 101 | - shared_libs: true # FIXME: recompile with -fPIC 102 | ttriple: x86_64-linux-muslx32 103 | - shared_libs: true # FIXME: creating shared libs is not yet stable 104 | ttriple: wasm32-wasi-musl 105 | - enable_cplusplus: true # FIXME: ignoring -fno-PIC option 106 | ttriple: mips64-linux-muslabi64 107 | - enable_cplusplus: true # FIXME: ignoring -fno-PIC option 108 | ttriple: mips64el-linux-muslabi64 109 | # The following ones have some zig link issue. 110 | - enable_cplusplus: false 111 | ttriple: x86-linux-musl 112 | - enable_cplusplus: true 113 | shared_libs: true 114 | ttriple: x86-linux-musl 115 | 116 | steps: 117 | - uses: actions/checkout@v4 118 | - uses: korandoru/setup-zig@v1 119 | with: 120 | zig-version: ${{ matrix.zig_version }} 121 | - name: Build 122 | run: > 123 | zig build -Dtarget=${{ matrix.ttriple }} 124 | -DBUILD_SHARED_LIBS=${{ matrix.shared_libs }} 125 | -DCFLAGS_EXTRA="${{ matrix.cflags_extra }}" 126 | -Denable_cplusplus=${{ matrix.enable_cplusplus }} 127 | -Denable_threads=${{ matrix.enable_threads }} 128 | -Denable_werror 129 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignored files in bdwgc Git repo. 2 | 3 | # Binary files (in root dir, cord, tests): 4 | *.a 5 | *.dbg 6 | *.dll 7 | *.dylib 8 | *.elf 9 | *.exe 10 | *.gcda 11 | *.gch 12 | *.gcno 13 | *.la 14 | *.lib 15 | *.lo 16 | *.o 17 | *.obj 18 | lib*.so 19 | 20 | *.gc.log 21 | .dirstamp 22 | /*_bench.log 23 | /*_bench.trs 24 | /*_test 25 | /*test.log 26 | /*test.trs 27 | /.libs/ 28 | /Makefile 29 | /add_gc_prefix 30 | /atomicops 31 | /atomicopstest 32 | /base_lib 33 | /bdw-gc.pc 34 | /c++ 35 | /config.cache 36 | /config.log 37 | /config.status 38 | /cord/cordtest 39 | /cord/de 40 | /cord/de_win.rbj 41 | /cord/de_win.res 42 | /cord/tests/de_win.rbj 43 | /cord/tests/de_win.res 44 | /cords 45 | /cordtest 46 | /core 47 | /cpptest 48 | /de 49 | /de.dir/ 50 | /disclaim_bench 51 | /disclaimtest 52 | /dont_ar_1 53 | /dont_ar_2 54 | /dont_ar_3 55 | /dont_ar_4 56 | /gc-* 57 | /gc.log 58 | /gcname 59 | /gctest 60 | /gctest_dyn_link 61 | /gctest_irix_dyn_link 62 | /hugetest 63 | /if_mach 64 | /if_not_there 65 | /initfromthreadtest 66 | /leaktest 67 | /libtool 68 | /middletest 69 | /realloctest 70 | /smashtest 71 | /staticrootstest 72 | /subthreadcreatetest 73 | /sunos5gc.so 74 | /test-suite.log 75 | /test_atomic_ops 76 | /test_atomic_ops.log 77 | /test_atomic_ops.trs 78 | /test_cpp 79 | /test_cpp.cpp 80 | /test_cpp.log 81 | /test_cpp.trs 82 | /test_tree.cpp 83 | /threadkeytest 84 | /threadleaktest 85 | /threadlibs 86 | /tracetest 87 | /treetest 88 | /weakmaptest 89 | 90 | /build/ 91 | /out/ 92 | 93 | # Config, dependency and stamp files generated by configure: 94 | .deps/ 95 | /include/config.h 96 | config.h.in~ 97 | stamp-h1 98 | 99 | # External library (without trailing slash to allow symlinks): 100 | /libatomic_ops* 101 | /pthreads-w32* 102 | 103 | # These files are generated by autoreconf: 104 | /Makefile.in 105 | /aclocal.m4 106 | /autom4te.cache/ 107 | /compile 108 | /config.guess 109 | /config.sub 110 | /configure 111 | /configure~ 112 | /depcomp 113 | /include/config.h.in 114 | /install-sh 115 | /ltmain.sh 116 | /m4/libtool.m4 117 | /m4/ltoptions.m4 118 | /m4/ltsugar.m4 119 | /m4/ltversion.m4 120 | /m4/lt~obsolete.m4 121 | /missing 122 | /mkinstalldirs 123 | /test-driver 124 | 125 | # These files are generated by CMake: 126 | *.tlog 127 | /*.vcxproj 128 | /*.vcxproj.filters 129 | /CMakeCache.txt 130 | /CMakeFiles/ 131 | /DartConfiguration.tcl 132 | /Testing/Temporary/ 133 | /cord/CMakeFiles/ 134 | /cord/Makefile 135 | /gc.sln 136 | /tests/*.vcxproj 137 | /tests/*.vcxproj.filters 138 | /tests/*test 139 | /tests/CMakeFiles/ 140 | /tests/Makefile 141 | /tests/test_cpp 142 | CTestTestfile.cmake 143 | cmake_install.cmake 144 | 145 | # These ones are generated by Zig: 146 | /.zig-cache/ 147 | /zig-out/ 148 | 149 | # Rarely generated files (mostly by some Win/DOS compilers): 150 | /*.copied.c 151 | /*.csm 152 | /*.err 153 | /*.i 154 | /*.lb1 155 | /*.lnk 156 | /*.map 157 | /*.out 158 | /*.rbj 159 | /*.res 160 | /*.stackdump 161 | /*.sym 162 | /*.tmp 163 | *.bsc 164 | *.dll.manifest 165 | *.exp 166 | *.idb 167 | *.ilk 168 | *.pdb 169 | *.sbr 170 | *.tds 171 | gc.def 172 | 173 | # Stuff from VS build system and IDE 174 | *.vcproj.*.user 175 | .vs/ 176 | 177 | # Code analysis tools: 178 | *.c.gcov 179 | *.cc.gcov 180 | *.h.gcov 181 | *.sancov 182 | /.sv*-dir 183 | /cov-int 184 | /coverage.info 185 | /pvs-project.log 186 | /pvs-project.tasks 187 | /strace_out 188 | -------------------------------------------------------------------------------- /Config.cmake.in: -------------------------------------------------------------------------------- 1 | # The BDWgc CMake configuration file. 2 | 3 | @PACKAGE_INIT@ 4 | include("${CMAKE_CURRENT_LIST_DIR}/BDWgcTargets.cmake") 5 | check_required_components(gc) 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT-style License 2 | 3 | Copyright (c) 1988-1989 Hans-J. Boehm, Alan J. Demers 4 | Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved. 5 | Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. 6 | Copyright (c) 1998 by Fergus Henderson. All rights reserved. 7 | Copyright (c) 1999-2001 by Red Hat, Inc. All rights reserved. 8 | Copyright (c) 1999-2011 Hewlett-Packard Development Company, L.P. 9 | Copyright (c) 2004-2005 Andrei Polushin 10 | Copyright (c) 2007 Free Software Foundation, Inc. 11 | Copyright (c) 2008-2022 Ivan Maidanski 12 | Copyright (c) 2011 Ludovic Courtes 13 | Copyright (c) 2018 Petter A. Urkedal 14 | 15 | 16 | THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 17 | OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 18 | 19 | Permission is hereby granted to use or copy this program 20 | for any purpose, provided the above notices are retained on all copies. 21 | Permission to modify the code and to distribute modified code is granted, 22 | provided the above notices are retained, and a notice that the code was 23 | modified is included with the above copyright notice. 24 | 25 | 26 | Several files (gc/gc_allocator.h, extra/msvc_dbg.c) come with slightly 27 | different licenses, though they are all similar in spirit (the exact 28 | licensing terms are given at the beginning of the corresponding source file). 29 | 30 | A few of the files needed to use the GNU-style build procedure come with 31 | a modified GPL license that appears not to significantly restrict use of 32 | the collector, though use of those files for a purpose other than building 33 | the collector may require the resulting code to be covered by the GPL. 34 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # This script creates (or regenerates) configure (as well as aclocal.m4, 5 | # config.h.in, Makefile.in, etc.) missing in the source repository. 6 | # 7 | # If you compile from a distribution tarball, you can skip this. Otherwise, 8 | # make sure that you have Autoconf, Automake and Libtool installed 9 | # on your system, and that the corresponding *.m4 files are visible 10 | # to the aclocal. The latter can be achieved by using packages shipped by 11 | # your OS, or by installing custom versions of all four packages to the same 12 | # prefix. Otherwise, you may need to invoke autoreconf with the appropriate 13 | # -I options to locate the required *.m4 files. 14 | 15 | # Install libtool.m4 and ltmain.sh in the build tree. This command is needed 16 | # if autoreconf and libtoolize are available from the different directories. 17 | # Note: libtoolize might be missing on some platforms. 18 | if (type libtoolize) > /dev/null 2>&1; then 19 | libtoolize -i -c 20 | else 21 | echo "libtoolize is not found, ignoring!" 22 | fi 23 | 24 | autoreconf -i 25 | 26 | echo 27 | echo "Ready to run './configure'." 28 | -------------------------------------------------------------------------------- /bdw-gc.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: Boehm-Demers-Weiser Conservative Garbage Collector 7 | Description: A garbage collector for C and C++ 8 | Version: @PACKAGE_VERSION@ 9 | Libs: -L${libdir} -lgc @THREADDLLIBS@ 10 | Libs.private: @ATOMIC_OPS_LIBS@ 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /checksums.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1992-1994 by Xerox Corporation. All rights reserved. 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | #include "private/gc_priv.h" 15 | 16 | #ifdef CHECKSUMS 17 | 18 | /* This is debugging code intended to verify the results of dirty bit */ 19 | /* computations. Works only in a single threaded environment. */ 20 | # define NSUMS 10000 21 | # define OFFSET 0x10000 22 | 23 | typedef struct { 24 | GC_bool new_valid; 25 | word old_sum; 26 | word new_sum; 27 | 28 | /* Block to which this refers plus OFFSET to hide it from the */ 29 | /* garbage collector. */ 30 | struct hblk *block; 31 | } page_entry; 32 | 33 | page_entry GC_sums[NSUMS]; 34 | 35 | /* Record of pages on which we saw a write fault. */ 36 | STATIC word GC_faulted[NSUMS] = { 0 }; 37 | 38 | STATIC size_t GC_n_faulted = 0; 39 | 40 | # ifdef MPROTECT_VDB 41 | void 42 | GC_record_fault(struct hblk *h) 43 | { 44 | GC_ASSERT(GC_page_size != 0); 45 | if (GC_n_faulted >= NSUMS) 46 | ABORT("write fault log overflowed"); 47 | GC_faulted[GC_n_faulted++] = ADDR(HBLK_PAGE_ALIGNED(h)); 48 | } 49 | # endif 50 | 51 | STATIC GC_bool 52 | GC_was_faulted(struct hblk *h) 53 | { 54 | size_t i; 55 | word page = ADDR(HBLK_PAGE_ALIGNED(h)); 56 | 57 | for (i = 0; i < GC_n_faulted; ++i) { 58 | if (GC_faulted[i] == page) 59 | return TRUE; 60 | } 61 | return FALSE; 62 | } 63 | 64 | STATIC word 65 | GC_checksum(struct hblk *h) 66 | { 67 | word *p; 68 | word *lim = (word *)(h + 1); 69 | word result = 0; 70 | 71 | for (p = (word *)h; ADDR_LT((ptr_t)p, (ptr_t)lim); p++) { 72 | result += *p; 73 | } 74 | return result | SIGNB; /* does not look like pointer */ 75 | } 76 | 77 | int GC_n_dirty_errors = 0; 78 | int GC_n_faulted_dirty_errors = 0; 79 | unsigned long GC_n_clean = 0; 80 | unsigned long GC_n_dirty = 0; 81 | 82 | STATIC void 83 | GC_update_check_page(struct hblk *h, int index) 84 | { 85 | page_entry *pe = GC_sums + index; 86 | hdr *hhdr = HDR(h); 87 | 88 | if (pe->block != 0 && pe->block != h + OFFSET) 89 | ABORT("goofed"); 90 | pe->old_sum = pe->new_sum; 91 | pe->new_sum = GC_checksum(h); 92 | # if !defined(MSWIN32) && !defined(MSWINCE) 93 | if (pe->new_sum != SIGNB && !GC_page_was_ever_dirty(h)) { 94 | GC_err_printf("GC_page_was_ever_dirty(%p) is wrong\n", (void *)h); 95 | } 96 | # endif 97 | if (GC_page_was_dirty(h)) { 98 | GC_n_dirty++; 99 | } else { 100 | GC_n_clean++; 101 | } 102 | if (hhdr != NULL) { 103 | (void)GC_find_starting_hblk(h, &hhdr); 104 | if (pe->new_valid 105 | # ifdef SOFT_VDB 106 | && !HBLK_IS_FREE(hhdr) 107 | # endif 108 | && !IS_PTRFREE(hhdr) && pe->old_sum != pe->new_sum) { 109 | if (!GC_page_was_dirty(h) || !GC_page_was_ever_dirty(h)) { 110 | GC_bool was_faulted = GC_was_faulted(h); 111 | /* Set breakpoint here */ GC_n_dirty_errors++; 112 | if (was_faulted) 113 | GC_n_faulted_dirty_errors++; 114 | } 115 | } 116 | } 117 | pe->new_valid = TRUE; 118 | pe->block = h + OFFSET; 119 | } 120 | 121 | /* Should be called immediately after GC_read_dirty. */ 122 | void 123 | GC_check_dirty(void) 124 | { 125 | int index; 126 | size_t i; 127 | 128 | GC_n_dirty_errors = 0; 129 | GC_n_faulted_dirty_errors = 0; 130 | GC_n_clean = 0; 131 | GC_n_dirty = 0; 132 | 133 | index = 0; 134 | for (i = 0; i < GC_n_heap_sects; i++) { 135 | ptr_t start = GC_heap_sects[i].hs_start; 136 | struct hblk *h; 137 | 138 | for (h = (struct hblk *)start; 139 | ADDR_LT((ptr_t)h, start + GC_heap_sects[i].hs_bytes); h++) { 140 | GC_update_check_page(h, index); 141 | index++; 142 | if (index >= NSUMS) { 143 | i = GC_n_heap_sects; 144 | break; 145 | } 146 | } 147 | } 148 | 149 | GC_COND_LOG_PRINTF("Checked %lu clean and %lu dirty pages\n", GC_n_clean, 150 | GC_n_dirty); 151 | if (GC_n_dirty_errors > 0) { 152 | GC_err_printf("Found %d dirty bit errors (%d were faulted)\n", 153 | GC_n_dirty_errors, GC_n_faulted_dirty_errors); 154 | } 155 | for (i = 0; i < GC_n_faulted; ++i) { 156 | /* Do not expose block addresses to the garbage collector. */ 157 | GC_faulted[i] = 0; 158 | } 159 | GC_n_faulted = 0; 160 | } 161 | 162 | #endif /* CHECKSUMS */ 163 | -------------------------------------------------------------------------------- /cord/cord.am: -------------------------------------------------------------------------------- 1 | ## This file is processed with automake. 2 | 3 | # Info (current:revision:age) for the Libtool versioning system. 4 | # These numbers should be updated at most once just before the release, 5 | # and, optionally, at most once during the development (after the release). 6 | LIBCORD_VER_INFO = 6:1:5 7 | 8 | lib_LTLIBRARIES += libcord.la 9 | 10 | libcord_la_LIBADD = libgc.la 11 | libcord_la_LDFLAGS = -version-info $(LIBCORD_VER_INFO) -no-undefined 12 | libcord_la_CPPFLAGS = $(AM_CPPFLAGS) 13 | 14 | libcord_la_SOURCES = \ 15 | cord/cordbscs.c \ 16 | cord/cordprnt.c \ 17 | cord/cordxtra.c 18 | 19 | TESTS += cordtest$(EXEEXT) 20 | check_PROGRAMS += cordtest 21 | cordtest_SOURCES = cord/tests/cordtest.c 22 | cordtest_LDADD = $(top_builddir)/libcord.la 23 | 24 | ## In case of static libraries build, libgc.a is already referenced in 25 | ## dependency_libs attribute of libcord.la file. 26 | if ENABLE_SHARED 27 | cordtest_LDADD += $(top_builddir)/libgc.la 28 | endif 29 | 30 | EXTRA_DIST += \ 31 | cord/tests/de.c \ 32 | cord/tests/de_cmds.h \ 33 | cord/tests/de_win.c \ 34 | cord/tests/de_win.h \ 35 | cord/tests/de_win.rc 36 | 37 | pkginclude_HEADERS += \ 38 | include/gc/cord.h \ 39 | include/gc/cord_pos.h \ 40 | include/gc/ec.h 41 | -------------------------------------------------------------------------------- /cord/tests/de_cmds.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1994 by Xerox Corporation. All rights reserved. 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | #ifndef DE_CMDS_H 15 | #define DE_CMDS_H 16 | 17 | #define UP 16 /* ^P */ 18 | #define DOWN 14 /* ^N */ 19 | #define LEFT 2 /* ^B */ 20 | #define RIGHT 6 /* ^F */ 21 | #define DEL 127 /* ^? */ 22 | #define BS 8 /* ^H */ 23 | #define UNDO 21 /* ^U */ 24 | #define WRITE 23 /* ^W */ 25 | #define QUIT 4 /* ^D */ 26 | #define REPEAT 18 /* ^R */ 27 | #define LOCATE 12 /* ^L */ 28 | #define TOP 20 /* ^T */ 29 | 30 | /* Execute an editor command. */ 31 | /* The argument is a command character */ 32 | /* or one of the IDM_ commands. */ 33 | void do_command(int); 34 | 35 | /* OS independent initialization. */ 36 | void generic_init(void); 37 | 38 | #endif /* DE_CMDS_H */ 39 | -------------------------------------------------------------------------------- /cord/tests/de_win.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1994 by Xerox Corporation. All rights reserved. 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | #ifndef DE_WIN_H 15 | #define DE_WIN_H 16 | 17 | #include "de_cmds.h" 18 | 19 | #define OTHER_FLAG 0x100 20 | #define EDIT_CMD_FLAG 0x200 21 | #define REPEAT_FLAG 0x400 22 | 23 | #define CHAR_CMD(i) ((i) & (0xff)) 24 | 25 | /* MENU: DE */ 26 | #define IDM_FILESAVE (EDIT_CMD_FLAG + WRITE) 27 | #define IDM_FILEEXIT (OTHER_FLAG + 1) 28 | #define IDM_HELPABOUT (OTHER_FLAG + 2) 29 | #define IDM_HELPCONTENTS (OTHER_FLAG + 3) 30 | 31 | #define IDM_EDITPDOWN (REPEAT_FLAG + EDIT_CMD_FLAG + DOWN) 32 | #define IDM_EDITPUP (REPEAT_FLAG + EDIT_CMD_FLAG + UP) 33 | #define IDM_EDITUNDO (EDIT_CMD_FLAG + UNDO) 34 | #define IDM_EDITLOCATE (EDIT_CMD_FLAG + LOCATE) 35 | #define IDM_EDITDOWN (EDIT_CMD_FLAG + DOWN) 36 | #define IDM_EDITUP (EDIT_CMD_FLAG + UP) 37 | #define IDM_EDITLEFT (EDIT_CMD_FLAG + LEFT) 38 | #define IDM_EDITRIGHT (EDIT_CMD_FLAG + RIGHT) 39 | #define IDM_EDITBS (EDIT_CMD_FLAG + BS) 40 | #define IDM_EDITDEL (EDIT_CMD_FLAG + DEL) 41 | #define IDM_EDITREPEAT (EDIT_CMD_FLAG + REPEAT) 42 | #define IDM_EDITTOP (EDIT_CMD_FLAG + TOP) 43 | 44 | /* Screen dimensions. Maintained by de_win.c. */ 45 | extern int LINES; 46 | extern int COLS; 47 | 48 | /* File being edited. */ 49 | extern char *arg_file_name; 50 | 51 | /* Calls from de_win.c to de.c. */ 52 | 53 | /* Get the contents (CORD) of i-th screen line. */ 54 | /* Relies on COLS. */ 55 | const void *retrieve_screen_line(int i); 56 | 57 | /* Set column, row. Upper left of window = (0,0). */ 58 | void set_position(int x, int y); 59 | 60 | /* Calls from de.c to de_win.c. */ 61 | 62 | /* Physically move the cursor on the display, */ 63 | /* so that it appears at (column, line). */ 64 | void move_cursor(int column, int line); 65 | 66 | /* Invalidate line i on the screen. */ 67 | void invalidate_line(int line); 68 | 69 | /* Display error message. */ 70 | void de_error(const char *s); 71 | 72 | #endif /* DE_WIN_H */ 73 | -------------------------------------------------------------------------------- /cord/tests/de_win.rc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | #include "windows.h" 15 | #include "de_win.h" 16 | 17 | ABOUTBOX DIALOG 19, 21, 163, 47 18 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 19 | CAPTION "About Demonstration Text Editor" 20 | BEGIN 21 | LTEXT "Demonstration Text Editor", -1, 44, 8, 118, 8, WS_CHILD | WS_VISIBLE | WS_GROUP 22 | PUSHBUTTON "OK", IDOK, 118, 27, 24, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP 23 | END 24 | 25 | DE MENU 26 | BEGIN 27 | POPUP "&File" 28 | BEGIN 29 | MENUITEM "&Save\t^W", IDM_FILESAVE 30 | MENUITEM "E&xit\t^D", IDM_FILEEXIT 31 | END 32 | 33 | POPUP "&Edit" 34 | BEGIN 35 | MENUITEM "Page &Down\t^R^N", IDM_EDITPDOWN 36 | MENUITEM "Page &Up\t^R^P", IDM_EDITPUP 37 | MENUITEM "U&ndo\t^U", IDM_EDITUNDO 38 | MENUITEM "&Locate\t^L ... ^L", IDM_EDITLOCATE 39 | MENUITEM "D&own\t^N", IDM_EDITDOWN 40 | MENUITEM "U&p\t^P", IDM_EDITUP 41 | MENUITEM "Le&ft\t^B", IDM_EDITLEFT 42 | MENUITEM "&Right\t^F", IDM_EDITRIGHT 43 | MENUITEM "Delete &Backward\tBS", IDM_EDITBS 44 | MENUITEM "Delete F&orward\tDEL", IDM_EDITDEL 45 | MENUITEM "&Top\t^T", IDM_EDITTOP 46 | END 47 | 48 | POPUP "&Help" 49 | BEGIN 50 | MENUITEM "&Contents", IDM_HELPCONTENTS 51 | MENUITEM "&About...", IDM_HELPABOUT 52 | END 53 | 54 | MENUITEM "Page_&Down", IDM_EDITPDOWN 55 | MENUITEM "Page_&Up", IDM_EDITPUP 56 | END 57 | 58 | DE ACCELERATORS 59 | BEGIN 60 | "^R", IDM_EDITREPEAT 61 | "^N", IDM_EDITDOWN 62 | "^P", IDM_EDITUP 63 | "^L", IDM_EDITLOCATE 64 | "^B", IDM_EDITLEFT 65 | "^F", IDM_EDITRIGHT 66 | "^T", IDM_EDITTOP 67 | VK_DELETE, IDM_EDITDEL, VIRTKEY 68 | VK_BACK, IDM_EDITBS, VIRTKEY 69 | END 70 | -------------------------------------------------------------------------------- /digimars.mak: -------------------------------------------------------------------------------- 1 | # Makefile to build Hans Boehm garbage collector using the Digital Mars 2 | # compiler from www.digitalmars.com 3 | # Written by Walter Bright 4 | 5 | CFLAGS_EXTRA= 6 | DEFINES=-DGC_DLL -DGC_THREADS -DGC_DISCOVER_TASK_THREADS \ 7 | -DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE \ 8 | -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION \ 9 | -DGC_REQUIRE_WCSDUP -DUSE_MUNMAP 10 | CORD_DEFINES=-DGC_DLL -DCORD_NOT_DLL 11 | CFLAGS=-Iinclude -Ilibatomic_ops\src $(DEFINES) -g $(CFLAGS_EXTRA) 12 | CORD_CFLAGS=-Iinclude $(CORD_DEFINES) -g $(CFLAGS_EXTRA) 13 | LFLAGS=/ma/implib/co 14 | CC=sc 15 | 16 | # Must precede other goals. 17 | all: cord.lib gc.lib 18 | 19 | gc.obj: extra\gc.c 20 | $(CC) -c $(CFLAGS) extra\gc.c -ogc.obj 21 | 22 | .cpp.obj: 23 | $(CC) -c $(CFLAGS) -Aa $* 24 | 25 | check: gctest.exe cpptest.exe treetest.exe cordtest.exe 26 | gctest.exe 27 | cpptest.exe 28 | treetest.exe 29 | cordtest.exe 30 | 31 | gc.lib: gc.dll 32 | 33 | gc.dll: gc.obj gc_badalc.obj gc_cpp.obj gc.def digimars.mak 34 | $(CC) -ogc.dll gc.obj gc_badalc.obj gc_cpp.obj -L$(LFLAGS) gc.def kernel32.lib user32.lib 35 | 36 | gc.def: digimars.mak 37 | echo LIBRARY GC >gc.def 38 | echo DESCRIPTION "Boehm-Demers-Weiser Garbage Collector" >>gc.def 39 | echo EXETYPE NT >>gc.def 40 | echo EXPORTS >>gc.def 41 | echo GC_is_visible_print_proc >>gc.def 42 | echo GC_is_valid_displacement_print_proc >>gc.def 43 | 44 | # FIXME: building cord as DLL results in cordtest fail. 45 | cord.lib: cord\cordbscs.obj cord\cordprnt.obj cord\cordxtra.obj 46 | lib -c cord.lib cord\cordbscs.obj cord\cordprnt.obj cord\cordxtra.obj 47 | 48 | cord\cordbscs.obj: cord\cordbscs.c 49 | $(CC) -c $(CORD_CFLAGS) cord\cordbscs.c -ocord\cordbscs.obj 50 | 51 | cord\cordprnt.obj: cord\cordprnt.c 52 | $(CC) -c $(CORD_CFLAGS) cord\cordprnt.c -ocord\cordprnt.obj 53 | 54 | cord\cordxtra.obj: cord\cordxtra.c 55 | $(CC) -c $(CORD_CFLAGS) cord\cordxtra.c -ocord\cordxtra.obj 56 | 57 | clean: 58 | del *.log *.map *.obj gc.def gc.dll gc.lib 59 | del tests\*.obj gctest.exe cpptest.exe treetest.exe 60 | del cord\*.obj cord.lib cord\tests\cordtest.obj cordtest.exe 61 | 62 | gctest.exe: gc.lib tests\gctest.obj 63 | $(CC) -ogctest.exe tests\gctest.obj gc.lib 64 | 65 | tests\gctest.obj: tests\gctest.c 66 | $(CC) -c $(CFLAGS) tests\gctest.c -otests\gctest.obj 67 | 68 | cpptest.exe: gc.lib tests\cpptest.obj 69 | $(CC) -ocpptest.exe tests\cpptest.obj gc.lib 70 | 71 | tests\cpptest.obj: tests\cpp.cc 72 | $(CC) -c $(CFLAGS) -cpp tests\cpp.cc -otests\cpptest.obj 73 | 74 | treetest.exe: gc.lib tests\treetest.obj 75 | $(CC) -otreetest.exe tests\treetest.obj gc.lib 76 | 77 | tests\treetest.obj: tests\tree.cc 78 | $(CC) -c $(CFLAGS) -cpp tests\tree.cc -otests\treetest.obj 79 | 80 | cordtest.exe: cord\tests\cordtest.obj cord.lib gc.lib 81 | $(CC) -ocordtest.exe cord\tests\cordtest.obj cord.lib gc.lib 82 | 83 | cord\tests\cordtest.obj: cord\tests\cordtest.c 84 | $(CC) -c $(CORD_CFLAGS) cord\tests\cordtest.c -ocord\tests\cordtest.obj 85 | 86 | gc_badalc.obj: gc_badalc.cc gc_badalc.cpp 87 | gc_cpp.obj: gc_cpp.cc gc_cpp.cpp 88 | -------------------------------------------------------------------------------- /docs/autoconf.md: -------------------------------------------------------------------------------- 1 | # Building bdwgc with autoconf/automake 2 | 3 | We support GNU-style builds based on `autoconf`, `automake` and `libtool`. 4 | This is based almost entirely on _Tom Tromey_'s work with gcj. 5 | 6 | Type the following to regenerate `configure` (if older than `configure.ac`): 7 | 8 | ```sh 9 | ./autogen.sh 10 | ``` 11 | 12 | Type the following to build, test and install the libraries: 13 | 14 | ```sh 15 | ./configure && make && make check && make install 16 | ``` 17 | 18 | The advantages of this process are: 19 | 20 | 1. It should eventually do a better job of automatically determining the 21 | right compiler to use, etc.; it probably already does in some cases. 22 | 23 | 2. It tries to automatically compute a good set of default bdwgc parameters 24 | for the platform (e.g. threads support); it provides an easier way to 25 | configure some of the other parameters. 26 | 27 | 3. It integrates better with other projects using a GNU-style build process. 28 | 29 | 4. It builds both dynamic and static libraries. 30 | 31 | The known disadvantages are: 32 | 33 | 1. The build scripts are much more complex, and harder to debug and 34 | understand (though they are largely standard); there might be some 35 | redundant stuff. 36 | 37 | 2. It probably does not work on all Unix-like platforms yet; it probably 38 | will never work on some other. 39 | 40 | 3. The scripts might be not yet complete; some of the standard GNU targets 41 | might not work well yet. (Corrections/additions are very welcome.) 42 | 43 | The distribution should contain all files needed to run `configure` and 44 | `make`, as well as the sources needed to regenerate the derived files. 45 | 46 | Note that the distribution comes without `Makefile` which is generated by 47 | `configure`. The distribution also contains `Makefile.direct` which is not 48 | always equivalent to the generated one. 49 | 50 | Important options to configure: 51 | 52 | * `--prefix=PREFIX`: install architecture-independent files in `PREFIX` 53 | (`/usr/local` by default on Unix-like platforms). 54 | 55 | * `--exec-prefix=EPREFIX`: install architecture-dependent files in `EPREFIX` 56 | (same as `prefix` by default). 57 | 58 | * `--enable-threads=TYPE`: choose threading package. 59 | 60 | * `--disable-parallel-mark`: do not parallelize marking and free list 61 | construction. 62 | 63 | * `--enable-gc-debug`: include full support for pointer back-tracing, etc. 64 | 65 | On Unix-like platforms, unless `--prefix` is set (or `--exec-prefix`, or one 66 | of the more obscure options), `make install` will install `libgc.a` and 67 | `libgc.so` in `/usr/local/lib` and `/usr/local/bin`, respectively, which would 68 | typically require the `make install` to be run as root. 69 | 70 | It is not recommended to turn off parallel marking for multiprocessors unless 71 | some issues exist with the feature on the target platform. 72 | -------------------------------------------------------------------------------- /docs/cmake.md: -------------------------------------------------------------------------------- 1 | # Building bdwgc with CMake 2 | 3 | Unix and Win32 binaries (both 32- and 64-bit) can be built using CMake. 4 | CMake is an open-source tool like [`automake`](autoconf.md) - it generates 5 | makefiles. 6 | 7 | CMake (as of v3.14.5) is able to generate: 8 | 9 | * Borland Makefiles 10 | * MSYS Makefiles 11 | * MinGW Makefiles 12 | * NMake Makefiles 13 | * Unix Makefiles 14 | * Visual Studio 16 2019 15 | * Visual Studio 15 2017 16 | * Visual Studio 14 2015 17 | * Visual Studio 12 2013 18 | * Visual Studio 11 2012 19 | * Visual Studio 10 2010 20 | * Visual Studio 9 2008 21 | * Watcom WMake 22 | 23 | 24 | ## Build process 25 | 26 | The steps are: 27 | 28 | 1. Install cmake (e.g. from [cmake.org](https://cmake.org/)); 29 | 30 | 2. Add directory containing `cmake` executable to `PATH` environment 31 | variable; 32 | 33 | 3. Run cmake from the bdwgc root directory, passing the target with `-G` 34 | option - e.g. type `cmake -G "Visual Studio 9 2008"` and use the `gc.sln` 35 | file generated by cmake to build `gc` library. 36 | 37 | Notes: 38 | 39 | * Specify `-Denable_cplusplus=ON` option to build `gccpp` and `gctba` 40 | libraries (i.e. the ones that provide bdwgc C++ support). 41 | 42 | * Specify `-Dbuild_tests=ON` option to the tests (and run them by 43 | `ctest -V`). 44 | 45 | You can also run cmake from a build directory to build outside of the root of 46 | the source tree - just specify the path to the latter, e.g.: 47 | 48 | ```sh 49 | mkdir out 50 | cd out 51 | cmake -G "Visual Studio 9 2008" -Dbuild_tests=ON .. 52 | cmake --build . --config Release 53 | ctest --build-config Release -V 54 | ``` 55 | 56 | Here is a sample for Linux (build, test and install, w/o C++ support): 57 | 58 | ```sh 59 | mkdir out 60 | cd out 61 | cmake -Dbuild_tests=ON .. 62 | cmake --build . 63 | ctest 64 | make install 65 | ``` 66 | 67 | 68 | # Input 69 | 70 | The main input to cmake is `CMakeLists.txt` file (script) in the bdwgc root 71 | directory. For help, go to [cmake.org](https://cmake.org/). 72 | 73 | 74 | # How to import bdwgc 75 | 76 | Another project could add bdwgc as one of its dependencies with something like 77 | this in their `CMakeLists.txt`: 78 | 79 | ```cmake 80 | find_package(BDWgc 8.2.0 REQUIRED) 81 | add_executable(Foo foo.c) 82 | target_link_libraries(Foo BDWgc::gc) 83 | ``` 84 | 85 | Other exported libraries are: `cord`, `gccpp`, `gctba`. 86 | -------------------------------------------------------------------------------- /docs/cords.md: -------------------------------------------------------------------------------- 1 | # Cords package 2 | 3 | Cords package (also known as "cord library") is a string package that uses 4 | a tree-based representation. 5 | 6 | See `cord.h` for a description of the basic functions provided. And, `ec.h` 7 | describes "extensible cords", those are essentially output streams that write 8 | to a cord; these allow for efficient construction of cords without requiring 9 | a bound on the size of a cord. 10 | 11 | The `cord` library is built along with `gc` library by default unless manually 12 | disabled (e.g., in case of cmake-based build, unless `-Dbuild_cord=OFF` option 13 | is passed to `cmake`). 14 | 15 | More details on the data structure can be found in: Boehm, Atkinson, and Plass, 16 | ["Ropes: An Alternative to Strings"](https://ondoc.logand.com/d/686/pdf), 17 | Software Practice and Experience 25, 12, December 1995, pp. 1315-1330. 18 | 19 | A fundamentally similar "rope" data structure is also part of SGI's standard 20 | template library implementation, and its descendants, which include the 21 | GNU C++ library. That uses reference counting by default. There is a short 22 | description of that data structure in 23 | [Rope Implementation Overview](https://www.boostcpp.org/sgi/stl/ropeimpl.html). 24 | 25 | All of these are descendants of the "ropes" in Xerox Cedar. 26 | 27 | `cord/tests/de.c` is a very dumb text editor that illustrates the use of 28 | cords. It maintains a list of file versions. Each version is simply a cord 29 | representing the file contents. Nonetheless, standard editing operations are 30 | efficient, even on very large files. (Its 3-line "user manual" can be 31 | obtained by invoking it without arguments. Note that `^R^N` and `^R^P` move 32 | the cursor by almost a screen. It does not understand tabs, which will show 33 | up as highlighted "I"s. Use the UNIX `expand` program first.) To build the 34 | editor, type `make de` in the bdwgc root directory. 35 | 36 | Note that `CORD_printf` and friends use C functions with variable numbers 37 | of arguments in non-standard-conforming ways. This code is known to break on 38 | some platforms, notably PowerPC. It should be possible to build the remainder 39 | of the library (everything but `cordprnt.c`) on any platform that supports the 40 | collector. 41 | -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- 1 | # FAQ: A garbage collector for C and C++ 2 | 3 | This is the beginning of a "frequently asked questions" file for what has 4 | become known as the "Boehm-Demers-Weiser" garbage collector. Some of these 5 | are likely to apply to any garbage collector whatsoever. 6 | 7 | ## Questions and Answers 8 | 9 | ### I wrote a test program which allocates objects and registers finalizers for them. Only a few (or no) objects are finalized. What's wrong? 10 | 11 | Probably nothing. Finalizers are only executed if all of the following happen 12 | before the process exits: 13 | 14 | * A garbage collection runs. This normally happens only after a significant 15 | amount of allocation. 16 | * The objects in question appear inaccessible at the time of the collection. 17 | It is common for a handful of objects to appear accessible even though they 18 | should not be, e.g. because temporary pointers to them haven't yet been 19 | overwritten. Also note that by default only the first item in a chain of 20 | finalizable objects will be finalized in a collection. 21 | * Another GC_ call notices that there are finalizers waiting to be run and 22 | does so. 23 | 24 | Small test programs typically don't run long enough for this to happen. 25 | 26 | ### Does this mean that the collector might leak memory? 27 | 28 | In the short term yes. But it is unlikely, though not impossible, that this 29 | will result in a leak that grows over time. Under normal circumstances, short 30 | term, or one time leaks are a minor issue. Memory leaks in explicitly managed 31 | programs are feared because they almost always continue to grow over time. 32 | 33 | For (a lot) more details see: 34 | 35 | * "Bounding Space Usage of Conservative Garbage Collectors", Proceedings of 36 | the 2002 ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, 37 | Jan. 2002, pp. 93-100 38 | ([official version](https://dl.acm.org/doi/10.1145/565816.503282)). 39 | 40 | ### How can I get more of the finalizers to run to convince myself that the GC is working? 41 | 42 | Invoke GC_gcollect a couple of times just before process exit. 43 | 44 | ### I want to ensure that all my objects are finalized and reclaimed before process exit. How can I do that? 45 | 46 | You can't, and you do not really want that. This would require finalizing 47 | _reachable_ objects. Finalizers run later would have to be able to handle 48 | this, and would have to be able to run with randomly broken libraries, because 49 | the objects they rely on where previously finalized. In most environments, 50 | you would also be replacing the operating systems mechanism for very 51 | efficiently reclaiming process memory at process exit with a significantly 52 | slower mechanism. 53 | 54 | You do sometimes want to ensure that certain particular resources are 55 | explicitly reclaimed before process exit, whether or not they become 56 | unreachable. Programming techniques for ensuring this are discussed in 57 | 58 | * "Destructors, Finalizers, and Synchronization", Proceedings of the 2003 ACM 59 | SIGPLAN-SIGACT Symposium on Principles of Programming Languages, Jan. 2003, 60 | pp. 262-272 61 | ([official version](https://dl.acm.org/doi/10.1145/604131.604153), 62 | [slides](http://www.hboehm.info/popl03/slides.pdf)). 63 | 64 | ### I wrote a memory allocation loop, and it runs much slower with the garbage collector than when I use malloc/free memory management. Why? 65 | 66 | Odds are your loop allocates very large objects and never initializes them. 67 | Real programs generally don't behave that way. Garbage collectors generally 68 | perform appreciably worse for large object allocations, and they generally 69 | initialize objects, even if you don't. 70 | 71 | ### What can I do to maximize allocation performance? 72 | 73 | Here are some hints: 74 | 75 | * Use `GC_MALLOC_ATOMIC` where possible. 76 | * For a multi-threaded application, ensure the GC library is compiled with 77 | `THREAD_LOCAL_ALLOC` macro defined (this is the default behavior) to avoid 78 | locking on each allocation. 79 | * If you use large statically allocated arrays or mapped files, consider 80 | `GC_exclude_static_roots`. 81 | 82 | ### If my heap uses 2 GB on a 32-bit machine, won't every other integer or other random data be misinterpreted as a pointer by the collector? Thus won't way too much memory be retained? 83 | 84 | Maybe. Probably, if the collector is used purely conservatively, with no 85 | pointer layout information (such as use of `GC_MALLOC_ATOMIC`). 86 | 87 | With a gigabyte heap, you are clearly much better off on a 64-bit machine. 88 | Empirical evidence seems to suggest that some such applications work on 89 | a 32-bit machine, and others don't perform acceptably. 90 | 91 | Simple probability calculations for pointer misidentifications are generally 92 | incorrect. The probability of misinterpreting an integer is typically reduced 93 | significantly by a number of collector features and fortunate accidents. Most 94 | integers are small, and small integers can generally not be heap addresses. 95 | The collector black-listing mechanism avoids allocating areas that are prone 96 | to be targets of misinterpreted references. The collector can be told to 97 | ignore some or all pointers to object interiors. 98 | 99 | ### I have a different question that is not answered here, nor in the other GC documentation. Where else can I go? 100 | 101 | If you can't find the answer in the [GC overview](overview.md) and the linked 102 | files, please see "Feedback, Contribution, Questions and Notifications" section of 103 | the main [README](../README.md). 104 | -------------------------------------------------------------------------------- /docs/platforms/README.aix: -------------------------------------------------------------------------------- 1 | We have so far failed to find a good way to determine the stack base. 2 | It is highly recommended that GC_stackbottom be set explicitly on program 3 | startup. The supplied value sometimes causes failure under AIX 4.1, though 4 | it appears to work under 3.X. HEURISTIC2 seems to work under 4.1, but 5 | involves a substantial performance penalty, and will fail if there is 6 | no limit on stack size. 7 | 8 | There is no thread support. (I assume recent versions of AIX provide 9 | pthreads? I no longer have access to a machine ...) 10 | -------------------------------------------------------------------------------- /docs/platforms/README.arm_cross: -------------------------------------------------------------------------------- 1 | From: Margaret Fleck 2 | 3 | Here's the key details of what worked for me, in case anyone else needs them. 4 | There may well be better ways to do some of this, but .... 5 | -- Margaret 6 | 7 | 8 | The badge4 has a StrongArm-1110 processor and a StrongArm-1111 coprocessor. 9 | 10 | Assume that the garbage collector distribution is unpacked into /home/arm/gc, 11 | which is visible to both the ARM machine and a linux desktop (e.g. via NFS mounting). 12 | 13 | Assume that you have a file /home/arm/config.site with contents something like the 14 | example attached below. Notice that our local ARM toolchain lives in 15 | /skiff/local. 16 | 17 | Go to /home/arm/gc directory. Do 18 | CONFIG_SITE=/home/arm/config.site ./configure --target=arm-linux 19 | --prefix=/home/arm/gc 20 | 21 | On your desktop, do: 22 | make 23 | make install 24 | The main garbage collector library should now be in ../gc/lib/libgc.so. 25 | 26 | To test the garbage collector, first do the following on your desktop 27 | make gctest 28 | ./gctest 29 | Then do the following on the ARM machine 30 | cd .libs 31 | ./lt-gctest 32 | 33 | Do not try to do "make check" (the usual way of running the test 34 | program). This does not work and seems to erase some of the important 35 | files. 36 | 37 | The gctest program claims to have succeeded. Haven't run any further tests 38 | with it, though I'll be doing so in the near future. 39 | 40 | ------------------------------- 41 | # config.site for configure 42 | 43 | HOSTCC=gcc 44 | 45 | # Names of the cross-compilers 46 | CC=/skiff/local/bin/arm-linux-gcc 47 | CXX=/skiff/local/bin/arm-linux-gcc 48 | 49 | # The cross compiler specific options 50 | CFLAGS="-O2 -fno-exceptions" 51 | CXXFLAGS="-O2 -fno-exceptions" 52 | CPPFLAGS="-O2 -fno-exceptions" 53 | LDFLAGS="" 54 | 55 | # Some other programs 56 | AR=/skiff/local/bin/arm-linux-ar 57 | RANLIB=/skiff/local/bin/arm-linux-ranlib 58 | NM=/skiff/local/bin/arm-linux-nm 59 | ac_cv_path_NM=/skiff/local/bin/arm-linux-nm 60 | ac_cv_func_setpgrp_void=yes 61 | x_includes=/skiff/local/arm-linux/include/X11 62 | x_libraries=/skiff/local/arm-linux/lib/X11 63 | -------------------------------------------------------------------------------- /docs/platforms/README.darwin: -------------------------------------------------------------------------------- 1 | Darwin/MacOSX Support - December 16, 2003 2 | 3 | == Build Notes == 4 | 5 | Building can be done with autoconf as normal. If you want to build 6 | a Universal library using autoconf, you need to disable dependency 7 | tracking and specify your desired architectures in CFLAGS: 8 | 9 | CFLAGS="-arch ppc -arch i386 -arch x86_64" ./configure --disable-dependency-tracking 10 | 11 | 12 | == Important Usage Notes == 13 | 14 | GC_INIT() MUST be called before calling any other GC functions. This 15 | is necessary to properly register segments in dynamic libraries. This 16 | call is required even if you code does not use dynamic libraries as the 17 | dyld code handles registering all data segments. 18 | 19 | When your use of the garbage collector is confined to dylibs and you 20 | cannot call GC_INIT() before your libraries' static initializers have 21 | run and perhaps called GC_malloc(), create an initialization routine 22 | for each library to call GC_INIT(), e.g.: 23 | 24 | #include "gc.h" 25 | extern "C" void my_library_init() { GC_INIT(); } 26 | 27 | Compile this code into a my_library_init.o, and link it into your 28 | dylib. When you link the dylib, pass the -init argument with 29 | _my_library_init (e.g. gcc -dynamiclib -o my_library.dylib a.o b.o c.o 30 | my_library_init.o -init _my_library_init). This causes 31 | my_library_init() to be called before any static initializers, and 32 | will initialize the garbage collector properly. 33 | 34 | Note: It doesn't hurt to call GC_INIT() more than once, so it's best, 35 | if you have an application or set of libraries that all use the 36 | garbage collector, to create an initialization routine for each of 37 | them that calls GC_INIT(). Better safe than sorry. 38 | 39 | Thread-local GC allocation will not work with threads that are not 40 | created using the GC-provided override of pthread_create(). Threads 41 | created without the GC-provided pthread_create() do not have the 42 | necessary data structures in the GC to store this data. 43 | 44 | 45 | == Implementation Information == 46 | 47 | Darwin/MacOSX support is nearly complete. Thread support is reliable on 48 | Darwin 6.x (MacOSX 10.2) and there have been reports of success on older 49 | Darwin versions (MacOSX 10.1). Shared library support had also been 50 | added and the gc can be run from a shared library. 51 | 52 | Thread support is implemented in terms of mach thread_suspend and 53 | thread_resume calls. These provide a very clean interface to thread 54 | suspension. This implementation doesn't rely on pthread_kill so the 55 | code works on Darwin < 6.0 (MacOSX 10.1). All the code to stop and 56 | start the world is located in darwin_stop_world.c. 57 | 58 | Since not all uses of the GC enable clients to override pthread_create() 59 | before threads have been created, the code for stopping the world has 60 | been rewritten to look for threads using Mach kernel calls. Each 61 | thread identified in this way is suspended and resumed as above. In 62 | addition, since Mach kernel threads do not contain pointers to their 63 | stacks, a stack-walking function has been written to find the stack 64 | limits. Given an initial stack pointer (for the current thread, a 65 | pointer to a stack-allocated local variable will do; for a non-active 66 | thread, we grab the value of register 1 (on PowerPC)), it 67 | will walk the PPC Mach-O-ABI compliant stack chain until it reaches the 68 | top of the stack. This appears to work correctly for GCC-compiled C, 69 | C++, Objective-C, and Objective-C++ code, as well as for Java 70 | programs that use JNI. If you run code that does not follow the stack 71 | layout or stack pointer conventions laid out in the PPC Mach-O ABI, 72 | then this will likely crash the garbage collector. 73 | 74 | Mach has a very clean interface to exception handing. So, the current 75 | implementation of the incremental collection uses Mach's exception handling. 76 | 77 | Much thanks goes to Andrew Stone, Dietmar Planitzer, Andrew Begel, 78 | Jeff Sturm, and Jesse Rosenstock for all their work on the 79 | Darwin/OS X port. 80 | 81 | -Brian Alliet 82 | -------------------------------------------------------------------------------- /docs/platforms/README.dgux386: -------------------------------------------------------------------------------- 1 | Garbage Collector (parallel version) for x86 DG/UX Release R4.20MU07 2 | 3 | 4 | *READ* the file README.md first. 5 | 6 | You need the GCC-3.0.3 rev (DG/UX) compiler to build this tree. 7 | This compiler has the new "dgux386" threads package implemented. 8 | It also supports the switch "-pthread" needed to link correctly 9 | the DG/UX's -lrte -lthread with -lgcc and the system's -lc. 10 | Finally, we support parallel mark for the SMP DG/UX machines. 11 | To build the garbage collector do: 12 | 13 | ./configure 14 | make 15 | make gctest 16 | 17 | Before you run "gctest" you need to set your LD_LIBRARY_PATH 18 | correctly so that "gctest" can find the shared library libgc. 19 | Alternatively you can do a configuration 20 | 21 | ./configure --disable-shared 22 | 23 | to build only the static version of libgc. 24 | 25 | To enable debugging messages please do: 26 | 1) Add the "--enable-gc-debug" flag during configuration. 27 | 2) Pass "CFLAGS=-DDEBUG_THREADS" to "make". 28 | 29 | In a machine with 4 CPUs (my own machine), parallel mark makes 30 | a BIG difference. 31 | 32 | Takis Psarogiannakopoulos 33 | 34 | Note (HB): 35 | The integration of this patch is currently not complete. 36 | The following patches against 6.1alpha3 where hard to move 37 | to alpha4, and are not integrated. There may also be minor 38 | problems with stylistic corrections made by me. 39 | [The diff for ltconfig and ltmain.sh was removed from this file on 2011-08-22] 40 | -------------------------------------------------------------------------------- /docs/platforms/README.emscripten: -------------------------------------------------------------------------------- 1 | 2 | The build system (at least autotools-based one) should detect and configure 3 | emscripten correctly. 4 | 5 | Due to the limitations of webassembly, finding all roots on the stack needs 6 | more coordination with the code using the collector than on other platforms. 7 | There are two strategies for dealing with this: 8 | 9 | 1. Compile any code relying on the collector with 10 | -sBINARYEN_EXTRA_PASSES='--spill-pointers' option. This instructs the 11 | C compiler to always keep roots in a place where the collector can find 12 | them. This is the simplest option but there is some negative impact on 13 | the code size and performance. 14 | 15 | 2. Only trigger the GC at points where it can be guaranteed that there are 16 | no pointers on the stack. When running in the browser, this can be done, 17 | e.g., in the main event loop using emscripten_set_timeout(). Triggering 18 | the collection manually involves calling GC_enable(), GC_gcollect() and 19 | GC_disable() in succession, having also a GC_disable() call at start. 20 | This method does not have a drawback on the code size and performance but 21 | might lead to the garbage collection running too often or, vice versa, 22 | rarely if the timeouts are chosen incorrectly, as a consequence, leading 23 | to the heap growth. 24 | 25 | As of now, gctest almost passes, except for the tests that involve a_get(). 26 | 27 | No thread support for now. No idea how to stop other threads (perhaps we need 28 | support from JS side). 29 | 30 | How to build (LDFLAGS could be omitted depending on the strategy): 31 | 32 | # source EMSDK first 33 | LDFLAGS="-sBINARYEN_EXTRA_PASSES='--spill-pointers'" emconfigure ./configure 34 | emmake make gctest.html 35 | # point your browser at .libs/gctest.html or call `node .libs/gctest.js` 36 | -------------------------------------------------------------------------------- /docs/platforms/README.ews4800: -------------------------------------------------------------------------------- 1 | GC on EWS4800 2 | ------------- 3 | 4 | 1. About EWS4800 5 | 6 | EWS4800 is a 32/64-bit workstation. 7 | 8 | Vendor: NEC Corporation 9 | OS: UX/4800 R9.* - R13.* (SystemV R4.2) 10 | CPU: R4000, R4400, R10000 (MIPS) 11 | 12 | 2. Compiler 13 | 14 | 32-bit: 15 | Use ANSI C compiler. 16 | CC = /usr/abiccs/bin/cc 17 | 18 | 64-bit: 19 | Use the 64-bit ANSI C compiler. 20 | CC = /usr/ccs64/bin/cc 21 | AR = /usr/ccs64/bin/ar 22 | 23 | 3. ELF file format 24 | *** Caution: The following information is empirical. *** 25 | 26 | 32-bit: 27 | ELF file has a unique format. (See a.out(4) and end(3C).) 28 | 29 | &_start 30 | : text segment 31 | &etext 32 | DATASTART 33 | : data segment (initialized) 34 | &edata 35 | DATASTART2 36 | : data segment (uninitialized) 37 | &end 38 | 39 | Here, DATASTART and DATASTART2 are macros of GC, and are defined as 40 | the following equations. (See include/private/gcconfig.h.) 41 | The algorithm for DATASTART is similar with the function 42 | GC_SysVGetDataStart() in os_dep.c. 43 | 44 | DATASTART = ((&etext + 0x3ffff) & ~0x3ffff) + (&etext & 0xffff) 45 | 46 | Dynamically linked: 47 | DATASTART2 = (&_gp + 0x8000 + 0x3ffff) & ~0x3ffff 48 | 49 | Statically linked: 50 | DATASTART2 = &edata 51 | 52 | GC has to check addresses both between DATASTART and &edata, and 53 | between DATASTART2 and &end. If a program accesses between &etext 54 | and DATASTART, or between &edata and DATASTART2, the segmentation 55 | error occurs and the program stops. 56 | 57 | If a program is statically linked, there is not a gap between 58 | &edata and DATASTART2. The global symbol &_DYNAMIC_LINKING is used 59 | for the detection. 60 | 61 | 64-bit: 62 | ELF file has a simple format. (See end(3C).) 63 | 64 | _ftext 65 | : text segment 66 | _etext 67 | _fdata = DATASTART 68 | : data segment (initialized) 69 | _edata 70 | _fbss 71 | : data segment (uninitialized) 72 | _end = DATAEND 73 | 74 | -- 75 | Hironori SAKAMOTO 76 | 77 | 78 | When using the "./configure; make" build process, please 79 | run configure with the --disable-shared option. "make check" does not 80 | yet pass with dynamic libraries. The reasons for that are not yet 81 | understood. (HB, paraphrasing message from Hironori SAKAMOTO.) 82 | -------------------------------------------------------------------------------- /docs/platforms/README.hp: -------------------------------------------------------------------------------- 1 | Dynamic loading support requires that executables be linked with -ldld. 2 | The alternative is to build the collector without defining DYNAMIC_LOADING 3 | in gcconfig.h and ensuring that all garbage collectible objects are 4 | accessible without considering statically allocated variables in dynamic 5 | libraries. 6 | 7 | The collector should compile with either plain cc or cc -Ae. Cc -Aa 8 | fails to define _HPUX_SOURCE and thus will not configure the collector 9 | correctly. 10 | 11 | Incremental collection support was added recently, and should now work. 12 | 13 | In spite of past claims, pthread support under HP/UX 11 should now work. 14 | Define GC_THREADS macro for the build. Incremental collection still does not 15 | work in combination with it. 16 | 17 | The stack finding code can be confused by putenv calls before collector 18 | initialization. Call GC_malloc() or GC_INIT() before any putenv() calls. 19 | -------------------------------------------------------------------------------- /docs/platforms/README.linux: -------------------------------------------------------------------------------- 1 | See README.alpha for Linux on DEC AXP info. 2 | 3 | This file applies mostly to Linux/Intel IA-32. Ports to Linux on an M68K, 4 | IA-64, SPARC, MIPS, Alpha and PowerPC are integrated too. They should behave 5 | similarly, except that the PowerPC port lacks incremental GC support, and 6 | it is unknown to what extent the Linux threads code is functional. 7 | See below for M68K specific notes. 8 | 9 | Incremental GC is generally supported. 10 | 11 | Dynamic libraries are supported on an ELF system. 12 | 13 | The collector appears to work reliably with Linux threads, but beware 14 | of older versions of glibc and gdb. 15 | 16 | The garbage collector uses SIGPWR and SIGXCPU if it is used with 17 | Linux threads. These should not be touched by the client program. 18 | 19 | To use threads, you need to abide by the following requirements: 20 | 21 | 1) You need to use LinuxThreads or NPTL (which are included in libc6). 22 | 23 | The collector relies on some implementation details of the LinuxThreads 24 | package. This code may not work on other 25 | pthread implementations (in particular it will *not* work with 26 | MIT pthreads). 27 | 28 | 2) You must compile the collector with "-DGC_THREADS -D_REENTRANT" specified 29 | in the Makefile.direct file. 30 | 31 | 3a) Every file that makes thread calls should define GC_THREADS, and then 32 | include gc.h. The latter redefines some of the pthread primitives as 33 | macros which also provide the collector with information it requires. 34 | 35 | 3b) A new alternative to (3a) is to build the collector and compile GC clients 36 | with -DGC_USE_LD_WRAP, and to link the final program with 37 | 38 | (for ld) --wrap dlopen --wrap pthread_create \ 39 | --wrap pthread_join --wrap pthread_detach \ 40 | --wrap pthread_sigmask --wrap pthread_exit --wrap pthread_cancel 41 | 42 | (for gcc) -Wl,--wrap -Wl,dlopen -Wl,--wrap -Wl,pthread_create \ 43 | -Wl,--wrap -Wl,pthread_join -Wl,--wrap -Wl,pthread_detach \ 44 | -Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,pthread_exit \ 45 | -Wl,--wrap -Wl,pthread_cancel 46 | 47 | In any case, _REENTRANT should be defined during compilation. 48 | 49 | 4) Dlopen() disables collection during its execution. (It can't run 50 | concurrently with the collector, since the collector looks at its 51 | data structures. It can't acquire the allocator lock, since arbitrary 52 | user startup code may run as part of dlopen().) Under unusual 53 | conditions, this may cause unexpected heap growth. 54 | 55 | 5) The combination of GC_THREADS, REDIRECT_MALLOC, and incremental 56 | collection is probably not fully reliable, though it now seems to work 57 | in simple cases. 58 | 59 | 6) Thread-local storage (TLS) may not be viewed as part of the root set by the 60 | collector. This probably depends on the LinuxThreads version. For the 61 | time being, any collectible memory referenced by thread-local storage 62 | should also be referenced from elsewhere, or be allocated as uncollectible. 63 | (This is really a bug that should be fixed somehow. Actually, the 64 | collector probably gets things right, on Linux at least, if there are not 65 | too many tls locations and if dlopen is not used.) 66 | -------------------------------------------------------------------------------- /docs/platforms/README.os2: -------------------------------------------------------------------------------- 1 | The code assumes static linking, and a single thread. The editor de has 2 | not been ported; the cord test program has. The supplied WCC_MAKEFILE should 3 | work for OS/2 but was not tested on the target. 4 | 5 | To build the collector, use the command: 6 | wmake -f WCC_MAKEFILE SYSTEM=OS2 ENABLE_STATIC=1 7 | 8 | Since we haven't figured out how to do partial linking or to build static 9 | libraries, clients currently need to link against a long list of executables. 10 | 11 | Notes: 12 | * adding dynamic linking support seems easy, but was not done; 13 | * adding thread support may be nontrivial, since we have not yet figured out 14 | how to look at another thread's registers; 15 | * memory unmapping to the operating system is not supported; 16 | * incremental collection is not supported yet; 17 | * setjmp_test may yield overly optimistic results when compiled without 18 | optimization. 19 | -------------------------------------------------------------------------------- /docs/platforms/README.sgi: -------------------------------------------------------------------------------- 1 | Performance of the incremental collector can be greatly enhanced with 2 | -DNO_EXECUTE_PERMISSION. 3 | 4 | The collector should run with all of the -32, -n32 and -64 ABIs. Remember to 5 | define the AS macro in the Makefile.direct to be "as -64", or "as -n32". 6 | 7 | If you use -DREDIRECT_MALLOC=GC_malloc with C++ code, your code should make 8 | at least one explicit call to malloc instead of new to ensure that the proper 9 | version of malloc is linked in. 10 | 11 | Sproc threads are not supported. 12 | 13 | Pthreads support is provided. This requires that: 14 | 15 | 1) You compile the collector with -DGC_THREADS specified in Makefile.direct. 16 | 17 | 2) You have the latest pthreads patches installed. 18 | 19 | (Though the collector makes only documented pthread calls, 20 | it relies on signal/threads interactions working just right in ways 21 | that are not required by the standard. It is unlikely that this code 22 | will run on other pthreads platforms. But please tell me if it does.) 23 | 24 | 3) Every file that makes thread calls should define GC_THREADS and then 25 | include gc.h. Gc.h redefines some of the pthread primitives as macros which 26 | also provide the collector with information it requires. 27 | 28 | 4) pthread_cond_wait and pthread_cond_timedwait should be prepared for 29 | premature wakeups. (I believe the pthreads and related standards require this 30 | anyway. Irix pthreads often terminate a wait if a signal arrives. 31 | The garbage collector uses signals to stop threads.) 32 | 33 | 5) It is expensive to stop a thread waiting in IO at the time the request is 34 | initiated. Applications with many such threads may not exhibit acceptable 35 | performance with the collector. (Increasing the heap size may help.) 36 | 37 | 6) The collector should not be compiled with -DREDIRECT_MALLOC. This 38 | confuses some library calls made by the pthreads implementation, which 39 | expect the standard malloc. 40 | -------------------------------------------------------------------------------- /docs/platforms/README.solaris2: -------------------------------------------------------------------------------- 1 | The collector supports both incremental collection and threads under 2 | Solaris. The incremental collector normally retrieves page dirty information 3 | through the appropriate /proc calls. But it can also be configured 4 | (by defining MPROTECT_VDB instead of PROC_VDB in gcconfig.h) to use mprotect 5 | and signals. This may result in shorter pause times, but it is no longer 6 | safe to issue arbitrary system calls that write to the heap. 7 | 8 | Under other UNIX versions, 9 | the collector normally obtains memory through sbrk. There is some reason 10 | to expect that this is not safe if the client program also calls the system 11 | malloc, or especially realloc. The sbrk man page strongly suggests this is 12 | not safe: "Many library routines use malloc() internally, so use brk() 13 | and sbrk() only when you know that malloc() definitely will not be used by 14 | any library routine." This doesn't make a lot of sense to me, since there 15 | seems to be no documentation as to which routines can transitively call malloc. 16 | Nonetheless, under Solaris, the collector now allocates memory using mmap by 17 | default. (It defines USE_MMAP in gcconfig.h.) 18 | You may want to reverse this decisions if you use -DREDIRECT_MALLOC=... 19 | 20 | Note: 21 | Before you run "make check", you need to set your LD_LIBRARY_PATH correctly 22 | (e.g., to "/usr/local/lib") so that tests can find the shared library 23 | libgcc_s.so.1. Alternatively, you can configure with --disable-shared. 24 | 25 | SOLARIS THREADS: 26 | 27 | Unless --disable-threads option is given, threads support is on by default in 28 | configure. This causes the collector to be compiled with -D GC_THREADS 29 | ensuring thread safety. This assumes use of the pthread_ interface; old-style 30 | Solaris threads are no longer supported. Thread-local allocation is on by 31 | default. Parallel marking is on by default (it could be disabled manually 32 | by configure --disable-parallel-mark option). 33 | 34 | It is also essential that gc.h be included in files that call pthread_create, 35 | pthread_join, pthread_detach, or dlopen. gc.h macro defines these to also do 36 | GC bookkeeping, etc. gc.h must be included with GC_THREADS macro defined 37 | first, otherwise these replacements are not visible. A collector built in 38 | this way may only be used by programs that are linked with the threads library. 39 | 40 | Unless USE_PROC_FOR_LIBRARIES is defined, dlopen disables collection 41 | temporarily. In some unlikely cases, this can result in unpleasant heap 42 | growth. But it seems better than the race/deadlock issues we had before. 43 | 44 | If threads are used on an i686 or x86_64 processor with malloc redirected to 45 | GC_malloc, it is necessary to call GC_INIT explicitly before forking the 46 | first thread. (This avoids a deadlock arising from calling GC_thr_init 47 | with the allocator lock held.) 48 | 49 | There could be an issue when using gc_cpp.h in conjunction with Solaris 50 | threads and Sun's C++ runtime. Apparently the overloaded new operator 51 | may be invoked by some iostream initialization code before threads are 52 | correctly initialized. This may cause a SIGSEGV during initialization 53 | of the garbage collector. Currently the only known workaround is to not 54 | invoke the garbage collector from a user defined global operator new, or to 55 | have it invoke the garbage-collector's allocators only after main has started. 56 | (Note that the latter requires a moderately expensive test in operator 57 | delete.) 58 | 59 | I encountered "symbol : offset .... is non-aligned" errors. These 60 | appear to be traceable to the use of the GNU assembler with the Sun linker. 61 | The former appears to generate a relocation not understood by the latter. 62 | The fix appears to be to use a consistent toolchain. (As a non-Solaris-expert 63 | my solution involved hacking the libtool script, but I'm sure you can 64 | do something less ugly.) 65 | 66 | Hans-J. Boehm 67 | (The above contains my personal opinions, which are probably not shared 68 | by anyone else.) 69 | -------------------------------------------------------------------------------- /docs/platforms/README.symbian: -------------------------------------------------------------------------------- 1 | Instructions for Symbian: 2 | 1. Build: use libgc.mmp (the sample for s60v3 is provided below) 3 | 2. Limitations 4 | 2.1. No multi-threaded support yet 5 | 2.2. Be careful with limitation that emulator introduces: Static roots are not 6 | dynamically accessible (there are Symbian APIs for this purpose but are just 7 | stubs, returning irrelevant values). 8 | Consequently, on emulator, you can only use dlls or exe, and retrieve static 9 | roots by calling global_init_static_root per dll (or exe). 10 | On target, only libs are supported, because static roots are retrieved by 11 | linker flags, by calling global_init_static_root in main exe. 12 | 13 | 14 | bld.inf sample contents: 15 | 16 | PRJ_PLATFORMS 17 | default armv5 18 | 19 | PRJ_MMPFILES 20 | libgc.mmp 21 | 22 | 23 | libgc.mmp sample contents: 24 | 25 | TARGET libgc.dll 26 | 27 | TARGETTYPE dll 28 | UID 0x1000008d 0x200107C2 // check uid 29 | 30 | EXPORTUNFROZEN 31 | EPOCALLOWDLLDATA 32 | 33 | CAPABILITY PowerMgmt ReadDeviceData ReadUserData WriteDeviceData WriteUserData SwEvent LocalServices NetworkServices UserEnvironment 34 | 35 | MACRO ALL_INTERIOR_POINTERS 36 | MACRO NO_EXECUTE_PERMISSION 37 | MACRO USE_MMAP 38 | MACRO GC_ATOMIC_UNCOLLECTABLE 39 | MACRO GC_DONT_REGISTER_MAIN_STATIC_DATA 40 | MACRO GC_DLL 41 | MACRO JAVA_FINALIZATION 42 | MACRO SYMBIAN 43 | MACRO ENABLE_DISCLAIM 44 | 45 | USERINCLUDE .\include 46 | USERINCLUDE .\include\private 47 | 48 | SYSTEMINCLUDE \epoc32\include 49 | SYSTEMINCLUDE \epoc32\include\stdapis 50 | 51 | SOURCEPATH . 52 | 53 | SOURCE extra/gc.c 54 | SOURCE extra/symbian.cpp 55 | 56 | SOURCE extra/symbian/global_end.cpp 57 | SOURCE extra/symbian/global_start.cpp 58 | SOURCE extra/symbian/init_global_static_roots.cpp 59 | 60 | STATICLIBRARY libcrt0.lib 61 | LIBRARY libc.lib 62 | LIBRARY euser.lib 63 | LIBRARY efsrv.lib 64 | LIBRARY avkon.lib 65 | LIBRARY eikcore.lib 66 | -------------------------------------------------------------------------------- /docs/platforms/README.uts: -------------------------------------------------------------------------------- 1 | Alistair Crooks supplied the port. He used Lexa C version 2.1.3 with 2 | -Xa to compile. 3 | -------------------------------------------------------------------------------- /docs/platforms/README.win64: -------------------------------------------------------------------------------- 1 | 64-bit Windows on AMD64/Intel EM64T (x64) is supported. A collector can be 2 | built with Microsoft Visual C++ 2005 or with mingw-w64 gcc. 3 | 4 | NT_MAKEFILE has been used in this environment. Type 5 | "nmake -f NT_MAKEFILE cpu=AMD64 nodebug=1" in a Visual C++ command line 6 | window to build the release variant of the dynamic library with threads 7 | support. 8 | To verify that the collector is at least somewhat functional, 9 | type "nmake -f NT_MAKEFILE cpu=AMD64 check" to build and run the usual test 10 | programs. This should create gctest.gc.log after a few seconds. 11 | 12 | cpptest.exe might not run correctly in case of dynamic GC linking. (It seems 13 | that we're getting wrong instances of operator new/delete in some cases.) 14 | 15 | This process is completely analogous to NT_MAKEFILE usage 16 | for the 32-bit library version. 17 | 18 | A similar procedure using NT_MAKEFILE is applicable to build the static 19 | library - just pass "enable_static=1" as an extra argument to nmake. 20 | If needed, it is also possible to build the library without threads 21 | support - this could be done by passing "disable_threads=1" argument to nmake. 22 | 23 | Note that some warnings have been explicitly turned off in the makefile. 24 | 25 | VC++ note: to suppress warnings -D_CRT_SECURE_NO_DEPRECATE is used. 26 | -------------------------------------------------------------------------------- /extra/gc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1994 by Xerox Corporation. All rights reserved. 3 | * Copyright (c) 1996 by Silicon Graphics. All rights reserved. 4 | * Copyright (c) 1998 by Fergus Henderson. All rights reserved. 5 | * Copyright (c) 2000-2009 by Hewlett-Packard Development Company. 6 | * All rights reserved. 7 | * Copyright (c) 2009-2018 Ivan Maidanski 8 | * 9 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 10 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 11 | * 12 | * Permission is hereby granted to use or copy this program 13 | * for any purpose, provided the above notices are retained on all copies. 14 | * Permission to modify the code and to distribute modified code is granted, 15 | * provided the above notices are retained, and a notice that the code was 16 | * modified is included with the above copyright notice. 17 | */ 18 | 19 | /* This file could be used for the following purposes: */ 20 | /* - get the complete GC as a single link object file (module); */ 21 | /* - enable more compiler optimizations. */ 22 | 23 | /* Tip: to get the highest level of compiler optimizations, the typical */ 24 | /* compiler options (GCC) to use are: */ 25 | /* -O3 -march=native -Wall -fprofile-generate/use */ 26 | 27 | /* Warning: GCC for Linux (for C++ clients only): Use -fexceptions both */ 28 | /* for GC and the client otherwise GC_thread_exit_proc() is not */ 29 | /* guaranteed to be invoked (see the comments in pthread_start.c). */ 30 | 31 | #define GC_SINGLE_OBJ_BUILD 32 | 33 | #ifndef __cplusplus 34 | /* static is desirable here for more efficient linkage. */ 35 | /* TODO: Enable this in case of the compilation as C++ code. */ 36 | # define GC_INNER STATIC 37 | # define GC_EXTERN GC_INNER 38 | /* STATIC is defined in gcconfig.h. */ 39 | #endif 40 | 41 | /* Small files go first... */ 42 | #include "../backgraph.c" 43 | #include "../blacklst.c" 44 | #include "../checksums.c" 45 | #include "../gcj_mlc.c" 46 | #include "../headers.c" 47 | #include "../new_hblk.c" 48 | #include "../obj_map.c" 49 | #include "../ptr_chck.c" 50 | 51 | #include "../allchblk.c" 52 | #include "../alloc.c" 53 | #include "../dbg_mlc.c" 54 | #include "../finalize.c" 55 | #include "../fnlz_mlc.c" 56 | #include "../malloc.c" 57 | #include "../mallocx.c" 58 | #include "../mark.c" 59 | #include "../mark_rts.c" 60 | #include "../reclaim.c" 61 | #include "../typd_mlc.c" 62 | 63 | #include "../misc.c" 64 | #include "../os_dep.c" 65 | #include "../thread_local_alloc.c" 66 | 67 | /* Most platform-specific files go here... */ 68 | #include "../darwin_stop_world.c" 69 | #include "../dyn_load.c" 70 | #include "../gc_dlopen.c" 71 | #if !defined(PLATFORM_MACH_DEP) 72 | # include "../mach_dep.c" 73 | #endif 74 | #if !defined(PLATFORM_STOP_WORLD) 75 | # include "../pthread_stop_world.c" 76 | #endif 77 | #include "../pthread_support.c" 78 | #include "../specific.c" 79 | #include "../win32_threads.c" 80 | 81 | #ifndef GC_PTHREAD_START_STANDALONE 82 | # include "../pthread_start.c" 83 | #endif 84 | 85 | /* Restore pthread calls redirection (if altered in */ 86 | /* pthread_stop_world.c, pthread_support.c or win32_threads.c). */ 87 | /* This is only useful if directly included from application */ 88 | /* (instead of linking gc). */ 89 | #if !defined(GC_NO_THREAD_REDIRECTS) && defined(GC_PTHREADS) 90 | # define GC_PTHREAD_REDIRECTS_ONLY 91 | # include "gc/gc_pthread_redirects.h" 92 | #endif 93 | 94 | /* The files from "extra" folder are not included. */ 95 | -------------------------------------------------------------------------------- /extra/symbian.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | extern "C" { 10 | 11 | int 12 | GC_get_main_symbian_stack_base() 13 | { 14 | TThreadStackInfo aInfo; 15 | TInt err = RThread().StackInfo(aInfo); 16 | if (!err) { 17 | return aInfo.iBase; 18 | } else { 19 | return 0; 20 | } 21 | } 22 | 23 | char * 24 | GC_get_private_path_and_zero_file() 25 | { 26 | // Always on c: drive. 27 | RFs fs; 28 | fs.Connect(); 29 | fs.CreatePrivatePath(EDriveC); 30 | TFileName path; 31 | fs.PrivatePath(path); 32 | fs.Close(); 33 | _LIT(KCDrive, "c:"); 34 | path.Insert(0, KCDrive); 35 | 36 | // Convert to char*, assume ASCII. 37 | TBuf8 path8; 38 | path8.Copy(path); 39 | _LIT8(KZero8, "zero"); 40 | path8.Append(KZero8); 41 | 42 | size_t size = path8.Length() + 1; 43 | char *copyChar = static_cast(malloc(size)); 44 | if (copyChar) 45 | memcpy(copyChar, path8.PtrZ(), size); 46 | 47 | // Ownership passed. 48 | return copyChar; 49 | } 50 | 51 | } /* extern "C" */ 52 | -------------------------------------------------------------------------------- /extra/symbian/global_end.cpp: -------------------------------------------------------------------------------- 1 | // Symbian-specific file. 2 | 3 | extern "C" { 4 | 5 | int winscw_data_end; 6 | 7 | } /* extern "C" */ 8 | -------------------------------------------------------------------------------- /extra/symbian/global_start.cpp: -------------------------------------------------------------------------------- 1 | // Symbian-specific file. 2 | 3 | extern "C" { 4 | 5 | int winscw_data_start; 6 | 7 | } /* extern "C" */ 8 | -------------------------------------------------------------------------------- /extra/symbian/init_global_static_roots.cpp: -------------------------------------------------------------------------------- 1 | // Symbian-specific file. 2 | 3 | #include 4 | 5 | #include "gc.h" 6 | 7 | extern "C" { 8 | 9 | #if defined(__WINS__) 10 | extern int winscw_data_start, winscw_data_end; 11 | #else 12 | extern int Image$$RW$$Limit[], Image$$RW$$Base[]; 13 | #endif 14 | 15 | GC_API void GC_CALL 16 | GC_init_global_static_roots() 17 | { 18 | void *dataStart; 19 | void *dataEnd; 20 | 21 | #if defined(__WINS__) 22 | dataStart = &winscw_data_start; 23 | dataEnd = &winscw_data_end; 24 | #else 25 | dataStart = (void *)Image$$RW$$Base; 26 | dataEnd = (void *)Image$$RW$$Limit; 27 | #endif 28 | GC_add_roots(dataStart, dataEnd); 29 | } 30 | 31 | } /* extern "C" */ 32 | -------------------------------------------------------------------------------- /fnlz_mlc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 by Hewlett-Packard Company. All rights reserved. 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | #include "private/gc_priv.h" 15 | 16 | #ifdef ENABLE_DISCLAIM 17 | 18 | # include "gc/gc_disclaim.h" 19 | # include "private/dbg_mlc.h" /* for oh type */ 20 | 21 | # if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH) 22 | /* The first bit is already used for a debug purpose. */ 23 | # define FINALIZER_CLOSURE_FLAG 0x2 24 | # else 25 | # define FINALIZER_CLOSURE_FLAG 0x1 26 | # endif 27 | 28 | STATIC int GC_CALLBACK 29 | GC_finalized_disclaim(void *obj) 30 | { 31 | # ifdef AO_HAVE_load 32 | ptr_t fc_p = GC_cptr_load((volatile ptr_t *)obj); 33 | # else 34 | ptr_t fc_p = *(ptr_t *)obj; 35 | # endif 36 | 37 | if ((ADDR(fc_p) & FINALIZER_CLOSURE_FLAG) != 0) { 38 | /* The disclaim function may be passed fragments from the */ 39 | /* free-list, on which it should not run finalization. */ 40 | /* To recognize this case, we use the fact that the value of */ 41 | /* the first pointer of such fragments is always, at least, */ 42 | /* multiple of a pointer size (a link to the next fragment, or */ 43 | /* NULL). If it is desirable to have a finalizer which does */ 44 | /* not use the first pointer for storing the finalization */ 45 | /* information, GC_disclaim_and_reclaim() must be extended to */ 46 | /* clear fragments so that the assumption holds for the */ 47 | /* selected pointer location. */ 48 | const struct GC_finalizer_closure *fc 49 | = (struct GC_finalizer_closure *)CPTR_CLEAR_FLAGS( 50 | fc_p, FINALIZER_CLOSURE_FLAG); 51 | 52 | GC_ASSERT(!GC_find_leak_inner); 53 | fc->proc((ptr_t *)obj + 1, fc->cd); 54 | } 55 | return 0; 56 | } 57 | 58 | STATIC void 59 | GC_register_disclaim_proc_inner(unsigned kind, GC_disclaim_proc proc, 60 | GC_bool mark_unconditionally) 61 | { 62 | GC_ASSERT(kind < MAXOBJKINDS); 63 | if (EXPECT(GC_find_leak_inner, FALSE)) 64 | return; 65 | 66 | GC_obj_kinds[kind].ok_disclaim_proc = proc; 67 | GC_obj_kinds[kind].ok_mark_unconditionally = mark_unconditionally; 68 | } 69 | 70 | GC_API void GC_CALL 71 | GC_init_finalized_malloc(void) 72 | { 73 | /* Initialize the collector just in case it is not done yet. */ 74 | GC_init(); 75 | 76 | LOCK(); 77 | if (GC_finalized_kind != 0) { 78 | UNLOCK(); 79 | return; 80 | } 81 | 82 | /* The finalizer closure is placed in the first pointer of the */ 83 | /* object in order to use the lower bits to distinguish live */ 84 | /* objects from objects on the free list. The downside of this is */ 85 | /* that we need one-pointer offset interior pointers, and that */ 86 | /* GC_base() does not return the start of the user region. */ 87 | GC_register_displacement_inner(sizeof(ptr_t)); 88 | 89 | /* And, the pointer to the finalizer closure object itself is */ 90 | /* displaced due to baking in this indicator. */ 91 | GC_register_displacement_inner(FINALIZER_CLOSURE_FLAG); 92 | GC_register_displacement_inner(sizeof(oh) | FINALIZER_CLOSURE_FLAG); 93 | 94 | GC_finalized_kind 95 | = GC_new_kind_inner(GC_new_free_list_inner(), GC_DS_LENGTH, TRUE, TRUE); 96 | GC_ASSERT(GC_finalized_kind != 0); 97 | GC_register_disclaim_proc_inner(GC_finalized_kind, GC_finalized_disclaim, 98 | TRUE); 99 | UNLOCK(); 100 | } 101 | 102 | GC_API void GC_CALL 103 | GC_register_disclaim_proc(int kind, GC_disclaim_proc proc, 104 | int mark_unconditionally) 105 | { 106 | LOCK(); 107 | GC_register_disclaim_proc_inner((unsigned)kind, proc, 108 | (GC_bool)mark_unconditionally); 109 | UNLOCK(); 110 | } 111 | 112 | GC_API GC_ATTR_MALLOC void *GC_CALL 113 | GC_finalized_malloc(size_t lb, const struct GC_finalizer_closure *fclos) 114 | { 115 | void *op; 116 | ptr_t fc_p; 117 | 118 | # ifndef LINT2 119 | /* Actually, there is no data race because the variable is set once. */ 120 | GC_ASSERT(GC_finalized_kind != 0); 121 | # endif 122 | GC_ASSERT(NONNULL_ARG_NOT_NULL(fclos)); 123 | GC_ASSERT((ADDR(fclos) & FINALIZER_CLOSURE_FLAG) == 0); 124 | op = GC_malloc_kind(SIZET_SAT_ADD(lb, sizeof(ptr_t)), 125 | (int)GC_finalized_kind); 126 | if (EXPECT(NULL == op, FALSE)) 127 | return NULL; 128 | 129 | /* Set the flag (w/o conversion to a numeric type) and store */ 130 | /* the finalizer closure. */ 131 | fc_p = CPTR_SET_FLAGS(GC_CAST_AWAY_CONST_PVOID(fclos), 132 | FINALIZER_CLOSURE_FLAG); 133 | # ifdef AO_HAVE_store 134 | GC_cptr_store((volatile ptr_t *)op, fc_p); 135 | # else 136 | *(ptr_t *)op = fc_p; 137 | # endif 138 | GC_dirty(op); 139 | REACHABLE_AFTER_DIRTY(fc_p); 140 | return (ptr_t *)op + 1; 141 | } 142 | 143 | #endif /* ENABLE_DISCLAIM */ 144 | -------------------------------------------------------------------------------- /gc_badalc.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 Ivan Maidanski 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | * 13 | */ 14 | 15 | // This file provides the implementation of GC_throw_bad_alloc() which 16 | // is invoked by GC operator "new" in case of an out-of-memory event. 17 | 18 | #ifdef HAVE_CONFIG_H 19 | # include "config.h" 20 | #endif 21 | 22 | #ifndef GC_BUILD 23 | # define GC_BUILD 24 | #endif 25 | 26 | #define GC_DONT_INCL_WINDOWS_H 27 | #include "gc/gc.h" 28 | 29 | #include // for bad_alloc, precedes include of gc_cpp.h 30 | 31 | #if defined(GC_NEW_ABORTS_ON_OOM) || defined(_LIBCPP_NO_EXCEPTIONS) 32 | # define GC_ALLOCATOR_THROW_OR_ABORT() GC_abort_on_oom() 33 | #else 34 | # define GC_ALLOCATOR_THROW_OR_ABORT() throw std::bad_alloc() 35 | #endif 36 | 37 | GC_API void GC_CALL 38 | GC_throw_bad_alloc() 39 | { 40 | GC_ALLOCATOR_THROW_OR_ABORT(); 41 | } 42 | -------------------------------------------------------------------------------- /gc_badalc.cpp: -------------------------------------------------------------------------------- 1 | // Visual C++ seems to prefer a .cpp extension to .cc one. 2 | #include "gc_badalc.cc" 3 | -------------------------------------------------------------------------------- /gc_cpp.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1994 by Xerox Corporation. All rights reserved. 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | /* 15 | This implementation module for gc_cpp.h provides an implementation of 16 | the global operators "new" and "delete" that calls the Boehm 17 | allocator. All objects allocated by this implementation will be 18 | uncollectible but part of the root set of the collector. 19 | 20 | You should ensure (using implementation-dependent techniques) that the 21 | linker finds this module before the library that defines the default 22 | built-in "new" and "delete". 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | # include "config.h" 27 | #endif 28 | 29 | #ifndef GC_BUILD 30 | # define GC_BUILD 31 | #endif 32 | 33 | #define GC_DONT_INCL_WINDOWS_H 34 | #include "gc/gc.h" 35 | 36 | #ifndef GC_INCLUDE_NEW 37 | # define GC_INCLUDE_NEW 38 | #endif 39 | #include "gc/gc_cpp.h" 40 | 41 | #if (!defined(_MSC_VER) && !defined(__DMC__) \ 42 | || defined(GC_NO_INLINE_STD_NEW)) \ 43 | && !defined(GC_INLINE_STD_NEW) && !defined(SKIP_GCCPP_DEFINITIONS) 44 | 45 | # if defined(GC_NEW_ABORTS_ON_OOM) || defined(_LIBCPP_NO_EXCEPTIONS) 46 | # define GC_ALLOCATOR_THROW_OR_ABORT() GC_abort_on_oom() 47 | # else 48 | // Use bad_alloc() directly instead of GC_throw_bad_alloc() call. 49 | # define GC_ALLOCATOR_THROW_OR_ABORT() throw std::bad_alloc() 50 | # endif 51 | 52 | void * 53 | operator new(GC_SIZE_T size) GC_DECL_NEW_THROW 54 | { 55 | void *obj = GC_MALLOC_UNCOLLECTABLE(size); 56 | if (0 == obj) 57 | GC_ALLOCATOR_THROW_OR_ABORT(); 58 | return obj; 59 | } 60 | 61 | # ifdef _MSC_VER 62 | // This new operator is used by VC++ in case of Debug builds. 63 | void * 64 | operator new(GC_SIZE_T size, int /* nBlockUse */, const char *szFileName, 65 | int nLine) 66 | { 67 | # ifdef GC_DEBUG 68 | void *obj = GC_debug_malloc_uncollectable(size, szFileName, nLine); 69 | # else 70 | void *obj = GC_MALLOC_UNCOLLECTABLE(size); 71 | (void)szFileName; 72 | (void)nLine; 73 | # endif 74 | if (0 == obj) 75 | GC_ALLOCATOR_THROW_OR_ABORT(); 76 | return obj; 77 | } 78 | # endif // _MSC_VER 79 | 80 | void 81 | operator delete(void *obj) GC_NOEXCEPT 82 | { 83 | GC_FREE(obj); 84 | } 85 | 86 | # ifdef GC_OPERATOR_NEW_NOTHROW 87 | void * 88 | operator new(GC_SIZE_T size, const std::nothrow_t &) GC_NOEXCEPT 89 | { 90 | return GC_MALLOC_UNCOLLECTABLE(size); 91 | } 92 | 93 | void 94 | operator delete(void *obj, const std::nothrow_t &) GC_NOEXCEPT 95 | { 96 | GC_FREE(obj); 97 | } 98 | # endif // GC_OPERATOR_NEW_NOTHROW 99 | 100 | # if defined(GC_OPERATOR_NEW_ARRAY) && !defined(CPPCHECK) 101 | void * 102 | operator new[](GC_SIZE_T size) GC_DECL_NEW_THROW 103 | { 104 | void *obj = GC_MALLOC_UNCOLLECTABLE(size); 105 | if (0 == obj) 106 | GC_ALLOCATOR_THROW_OR_ABORT(); 107 | return obj; 108 | } 109 | 110 | # ifdef _MSC_VER 111 | // This new operator is used by VC++ 7+ in Debug builds. 112 | void * 113 | operator new[](GC_SIZE_T size, int nBlockUse, const char *szFileName, 114 | int nLine) 115 | { 116 | return operator new(size, nBlockUse, szFileName, nLine); 117 | } 118 | # endif // _MSC_VER 119 | 120 | void 121 | operator delete[](void *obj) GC_NOEXCEPT 122 | { 123 | GC_FREE(obj); 124 | } 125 | 126 | # ifdef GC_OPERATOR_NEW_NOTHROW 127 | void * 128 | operator new[](GC_SIZE_T size, const std::nothrow_t &) GC_NOEXCEPT 129 | { 130 | return GC_MALLOC_UNCOLLECTABLE(size); 131 | } 132 | 133 | void 134 | operator delete[](void *obj, const std::nothrow_t &) GC_NOEXCEPT 135 | { 136 | GC_FREE(obj); 137 | } 138 | # endif 139 | # endif // GC_OPERATOR_NEW_ARRAY 140 | 141 | # ifdef GC_OPERATOR_SIZED_DELETE 142 | void 143 | operator delete(void *obj, GC_SIZE_T) GC_NOEXCEPT 144 | { 145 | GC_FREE(obj); 146 | } 147 | 148 | # if defined(GC_OPERATOR_NEW_ARRAY) && !defined(CPPCHECK) 149 | void 150 | operator delete[](void *obj, GC_SIZE_T) GC_NOEXCEPT 151 | { 152 | GC_FREE(obj); 153 | } 154 | # endif 155 | # endif // GC_OPERATOR_SIZED_DELETE 156 | 157 | #endif // !_MSC_VER && !__DMC__ || GC_NO_INLINE_STD_NEW 158 | -------------------------------------------------------------------------------- /gc_cpp.cpp: -------------------------------------------------------------------------------- 1 | // Visual C++ seems to prefer a .cpp extension to .cc 2 | #include "gc_cpp.cc" 3 | -------------------------------------------------------------------------------- /gc_dlopen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. 3 | * Copyright (c) 1997 by Silicon Graphics. All rights reserved. 4 | * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved. 5 | * 6 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 7 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 8 | * 9 | * Permission is hereby granted to use or copy this program 10 | * for any purpose, provided the above notices are retained on all copies. 11 | * Permission to modify the code and to distribute modified code is granted, 12 | * provided the above notices are retained, and a notice that the code was 13 | * modified is included with the above copyright notice. 14 | */ 15 | 16 | #include "private/gc_priv.h" 17 | 18 | /* This used to be in dyn_load.c. It was extracted into a separate */ 19 | /* file to avoid having to link against libdl.{a,so} if the client */ 20 | /* doesn't call dlopen. Of course this fails if the collector is in */ 21 | /* a dynamic library. -HB */ 22 | #if defined(GC_PTHREADS) && !defined(GC_NO_DLOPEN) 23 | 24 | # undef GC_MUST_RESTORE_REDEFINED_DLOPEN 25 | # if defined(dlopen) && !defined(GC_USE_LD_WRAP) 26 | /* To support various threads pkgs, gc.h interposes on dlopen by */ 27 | /* defining "dlopen" to be "GC_dlopen", which is implemented below. */ 28 | /* However, both GC_FirstDLOpenedLinkMap() and GC_dlopen() use the */ 29 | /* real system dlopen() in their implementation. We first remove */ 30 | /* gc.h's dlopen definition and restore it later, after GC_dlopen(). */ 31 | # undef dlopen 32 | # define GC_MUST_RESTORE_REDEFINED_DLOPEN 33 | # endif 34 | 35 | /* Make sure we're not in the middle of a collection, and make sure we */ 36 | /* don't start any. This is invoked prior to a dlopen call to avoid */ 37 | /* synchronization issues. We cannot just acquire the allocator lock, */ 38 | /* since startup code in dlopen may try to allocate. This solution */ 39 | /* risks heap growth (or, even, heap overflow) in the presence of many */ 40 | /* dlopen calls in either a multi-threaded environment, or if the */ 41 | /* library initialization code allocates substantial amounts of GC'ed */ 42 | /* memory. */ 43 | # ifndef USE_PROC_FOR_LIBRARIES 44 | static void 45 | disable_gc_for_dlopen(void) 46 | { 47 | LOCK(); 48 | while (GC_incremental && GC_collection_in_progress()) { 49 | GC_collect_a_little_inner(1000); 50 | } 51 | ++GC_dont_gc; 52 | UNLOCK(); 53 | } 54 | # endif 55 | 56 | /* Redefine dlopen to guarantee mutual exclusion with */ 57 | /* GC_register_dynamic_libraries. Should probably happen for */ 58 | /* other operating systems, too. */ 59 | 60 | /* This is similar to WRAP/REAL_FUNC() in pthread_support.c. */ 61 | # ifdef GC_USE_LD_WRAP 62 | # define WRAP_DLFUNC(f) __wrap_##f 63 | # define REAL_DLFUNC(f) __real_##f 64 | void *REAL_DLFUNC(dlopen)(const char *, int); 65 | # else 66 | # define WRAP_DLFUNC(f) GC_##f 67 | # define REAL_DLFUNC(f) f 68 | # endif 69 | 70 | # define GC_wrap_dlopen WRAP_DLFUNC(dlopen) 71 | GC_API void * 72 | GC_wrap_dlopen(const char *path, int mode) 73 | { 74 | void *result; 75 | 76 | # ifndef USE_PROC_FOR_LIBRARIES 77 | /* Disable collections. This solution risks heap growth (or, */ 78 | /* even, heap overflow) but there seems no better solutions. */ 79 | disable_gc_for_dlopen(); 80 | # endif 81 | result = REAL_DLFUNC(dlopen)(path, mode); 82 | # ifndef USE_PROC_FOR_LIBRARIES 83 | /* This undoes disable_gc_for_dlopen(). */ 84 | GC_enable(); 85 | # endif 86 | return result; 87 | } 88 | # undef GC_wrap_dlopen 89 | 90 | # ifdef GC_USE_LD_WRAP 91 | /* Define GC_ function as an alias for the plain one, which will be */ 92 | /* intercepted. This allows files which include gc.h, and hence */ 93 | /* generate references to the GC_ symbol, to see the right symbol. */ 94 | GC_API void * 95 | GC_dlopen(const char *path, int mode) 96 | { 97 | return dlopen(path, mode); 98 | } 99 | # endif /* GC_USE_LD_WRAP */ 100 | 101 | # ifdef GC_MUST_RESTORE_REDEFINED_DLOPEN 102 | # define dlopen GC_dlopen 103 | # endif 104 | 105 | #endif /* GC_PTHREADS && !GC_NO_DLOPEN */ 106 | -------------------------------------------------------------------------------- /ia64_save_regs_in_stack.s: -------------------------------------------------------------------------------- 1 | .text 2 | .align 16 3 | .global GC_save_regs_in_stack 4 | .proc GC_save_regs_in_stack 5 | GC_save_regs_in_stack: 6 | .body 7 | flushrs 8 | ;; 9 | mov r8=ar.bsp 10 | br.ret.sptk.few rp 11 | .endp GC_save_regs_in_stack 12 | -------------------------------------------------------------------------------- /include/gc.h: -------------------------------------------------------------------------------- 1 | /* This file is installed for backward compatibility. */ 2 | #include "gc/gc.h" 3 | -------------------------------------------------------------------------------- /include/gc/cord_pos.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved. 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | /* This should never be included directly; included only from cord.h. */ 15 | #if !defined(CORD_POSITION_H) && defined(CORD_H) 16 | # define CORD_POSITION_H 17 | 18 | # ifdef __cplusplus 19 | extern "C" { 20 | # endif 21 | 22 | /* The representation of CORD_position. This is private to the */ 23 | /* implementation, but the size is known to clients. Also */ 24 | /* the implementation of some exported macros relies on it. */ 25 | /* Don't use anything defined here and not in cord.h. */ 26 | 27 | /* The maximum depth of a balanced cord + 1. */ 28 | /* We do not let cords get deeper than this maximum. */ 29 | # define CORD_MAX_DEPTH 48 30 | 31 | struct CORD_pe { 32 | CORD pe_cord; 33 | size_t pe_start_pos; 34 | }; 35 | 36 | /* A structure describing an entry on the path from the root */ 37 | /* to current position. */ 38 | typedef struct CORD_Pos { 39 | size_t cur_pos; 40 | 41 | int path_len; 42 | 43 | /* path_len is CORD_POS_INVALID if and only if position is invalid. */ 44 | # define CORD_POS_INVALID 0x55555555 45 | 46 | /* Current leaf, if it is a string. If the current leaf is */ 47 | /* a function, then this may point to function_buf */ 48 | /* containing the next few characters. Always points to a */ 49 | /* valid string containing the current character unless */ 50 | /* cur_end is 0. */ 51 | const char *cur_leaf; 52 | 53 | /* Start position of cur_leaf. */ 54 | size_t cur_start; 55 | 56 | /* Ending position of cur_leaf; 0 if cur_leaf is invalid. */ 57 | size_t cur_end; 58 | 59 | /* path[path_len] is the leaf corresponding to cur_pos; */ 60 | /* path[0].pe_cord is the cord we point to. */ 61 | struct CORD_pe path[CORD_MAX_DEPTH + 1]; 62 | 63 | # define CORD_FUNCTION_BUF_SZ 8 64 | 65 | /* Space for next few chars from function node. */ 66 | char function_buf[CORD_FUNCTION_BUF_SZ]; 67 | } CORD_pos[1]; 68 | 69 | /* Extract the cord from a position. */ 70 | CORD_API CORD CORD_pos_to_cord(CORD_pos); 71 | 72 | /* Extract the current index from a position. */ 73 | CORD_API size_t CORD_pos_to_index(CORD_pos); 74 | 75 | /* Fetch the character located at the given position. */ 76 | CORD_API char CORD_pos_fetch(CORD_pos); 77 | 78 | /* Initialize the position to refer to the given cord and index. */ 79 | /* Note that this is the most expensive function on positions. */ 80 | CORD_API void CORD_set_pos(CORD_pos, CORD, size_t /* index */); 81 | 82 | /* Advance the position to the next character. p must be */ 83 | /* initialized and valid. Invalidates p if past end. */ 84 | CORD_API void CORD_next(CORD_pos /* p */); 85 | 86 | /* Move the position to the preceding character. p must be */ 87 | /* initialized and valid. Invalidates p if past beginning. */ 88 | CORD_API void CORD_prev(CORD_pos /* p */); 89 | 90 | /* Is the position valid, i.e. inside the cord? */ 91 | CORD_API int CORD_pos_valid(CORD_pos); 92 | 93 | CORD_API char CORD__pos_fetch(CORD_pos); 94 | CORD_API void CORD__next(CORD_pos); 95 | CORD_API void CORD__prev(CORD_pos); 96 | 97 | # define CORD_pos_fetch(p) \ 98 | ((p)[0].cur_end != 0 ? (p)[0].cur_leaf[(p)[0].cur_pos - (p)[0].cur_start] \ 99 | : CORD__pos_fetch(p)) 100 | 101 | # define CORD_next(p) \ 102 | ((p)[0].cur_pos + 1 < (p)[0].cur_end ? (p)[0].cur_pos++ \ 103 | : (CORD__next(p), 0U)) 104 | 105 | # define CORD_prev(p) \ 106 | ((p)[0].cur_end != 0 && (p)[0].cur_pos > (p)[0].cur_start \ 107 | ? (p)[0].cur_pos-- \ 108 | : (CORD__prev(p), 0U)) 109 | 110 | # define CORD_pos_to_index(p) ((p)[0].cur_pos) 111 | 112 | # define CORD_pos_to_cord(p) ((p)[0].path[0].pe_cord) 113 | 114 | # define CORD_pos_valid(p) ((p)[0].path_len != CORD_POS_INVALID) 115 | 116 | /* Some grubby stuff for performance-critical friends: */ 117 | 118 | /* Number of characters in cache. A non-positive value means none. */ 119 | # define CORD_pos_chars_left(p) ((long)(p)[0].cur_end - (long)(p)[0].cur_pos) 120 | 121 | /* Advance position by n characters; n should be positive and less */ 122 | /* than CORD_pos_chars_left(p). */ 123 | # define CORD_pos_advance(p, n) \ 124 | ((p)[0].cur_pos += (n) - (size_t)1, CORD_next(p)) 125 | 126 | /* Address of the current character in cache. */ 127 | # define CORD_pos_cur_char_addr(p) \ 128 | ((p)[0].cur_leaf + ((p)[0].cur_pos - (p)[0].cur_start)) 129 | 130 | # ifdef __cplusplus 131 | } /* extern "C" */ 132 | # endif 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /include/gc/ec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved. 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | #ifndef EC_H 15 | #define EC_H 16 | 17 | #ifndef CORD_H 18 | # include "cord.h" 19 | #endif 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /* Extensible cords are strings that may be destructively appended to. */ 26 | /* They allow fast construction of cords from characters that are */ 27 | /* being read from a stream. */ 28 | 29 | /* 30 | * A client might look like: 31 | * 32 | * { 33 | * CORD_ec x; 34 | * CORD result; 35 | * char c; 36 | * FILE *f; 37 | * 38 | * ... 39 | * CORD_ec_init(x); 40 | * while (...) { 41 | * c = getc(f); 42 | * ... 43 | * CORD_ec_append(x, c); 44 | * } 45 | * result = CORD_balance(CORD_ec_to_cord(x)); 46 | * 47 | * If a C string is desired as the final result, the call to CORD_balance 48 | * may be replaced by a call to CORD_to_char_star. 49 | */ 50 | 51 | #ifndef CORD_BUFSZ 52 | # define CORD_BUFSZ 128 53 | #endif 54 | 55 | /* This structure represents the concatenation of ec_cord with */ 56 | /* ec_buf[0 .. ec_bufptr-ec_buf-1]. */ 57 | typedef struct CORD_ec_struct { 58 | CORD ec_cord; 59 | char *ec_bufptr; 60 | char ec_buf[CORD_BUFSZ + 1]; 61 | } CORD_ec[1]; 62 | 63 | /* Flush the buffer part of the extended cord into ec_cord. */ 64 | CORD_API void CORD_ec_flush_buf(CORD_ec); 65 | 66 | /* Convert an extensible cord to a cord. */ 67 | #define CORD_ec_to_cord(x) (CORD_ec_flush_buf(x), (x)[0].ec_cord) 68 | 69 | /* Initialize an extensible cord. */ 70 | #define CORD_ec_init(x) \ 71 | ((x)[0].ec_cord = 0, (void)((x)[0].ec_bufptr = (x)[0].ec_buf)) 72 | 73 | /* Append a character to an extensible cord. */ 74 | #define CORD_ec_append(x, c) \ 75 | ((void)((x)[0].ec_bufptr == (x)[0].ec_buf + CORD_BUFSZ \ 76 | ? (CORD_ec_flush_buf(x), 0) \ 77 | : 0), \ 78 | (void)(*(x)[0].ec_bufptr++ = (c))) 79 | 80 | /* Append a cord to an extensible cord. Structure remains shared with */ 81 | /* original. */ 82 | CORD_API void CORD_ec_append_cord(CORD_ec, CORD); 83 | 84 | #ifdef __cplusplus 85 | } /* extern "C" */ 86 | #endif 87 | 88 | #endif /* EC_H */ 89 | -------------------------------------------------------------------------------- /include/gc/gc_backptr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1994 by Xerox Corporation. All rights reserved. 3 | * Copyright (c) 1996 by Silicon Graphics. All rights reserved. 4 | * Copyright (c) 1998 by Fergus Henderson. All rights reserved. 5 | * Copyright (c) 2000-2009 by Hewlett-Packard Development Company. 6 | * All rights reserved. 7 | * 8 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 9 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 10 | * 11 | * Permission is hereby granted to use or copy this program 12 | * for any purpose, provided the above notices are retained on all copies. 13 | * Permission to modify the code and to distribute modified code is granted, 14 | * provided the above notices are retained, and a notice that the code was 15 | * modified is included with the above copyright notice. 16 | */ 17 | 18 | /* This is a simple API to implement pointer back tracing, i.e. */ 19 | /* to answer questions such as "who is pointing to this" or */ 20 | /* "why is this object being retained by the collector". */ 21 | /* Most of these calls yield useful information on only after */ 22 | /* a garbage collection. Usually the client will first force */ 23 | /* a full collection and then gather information, preferably */ 24 | /* before much intervening allocation. */ 25 | /* The implementation of the interface is only about 99.9999% */ 26 | /* correct. It is intended to be good enough for profiling, */ 27 | /* but is not intended to be used with production code. */ 28 | /* Results are likely to be much more useful if all allocation */ 29 | /* is accomplished through the debugging allocators. */ 30 | 31 | /* 32 | * The implementation idea is due to A. Demers. 33 | */ 34 | 35 | #ifndef GC_BACKPTR_H 36 | #define GC_BACKPTR_H 37 | 38 | #ifndef GC_H 39 | # include "gc.h" 40 | #endif 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | typedef enum { 47 | GC_UNREFERENCED, /* No reference info available. */ 48 | GC_NO_SPACE, /* Dest not allocated with debug alloc. */ 49 | GC_REFD_FROM_ROOT, /* Referenced directly by root *base_p. */ 50 | GC_REFD_FROM_REG, /* Referenced from a register, i.e. */ 51 | /* a root without an address. */ 52 | GC_REFD_FROM_HEAP, /* Referenced from another heap obj. */ 53 | GC_FINALIZER_REFD /* Finalizable and hence accessible. */ 54 | } GC_ref_kind; 55 | 56 | /* Store information about the object referencing dest in *base_p */ 57 | /* and *offset_p. */ 58 | /* If multiple objects or roots point to dest, then the one */ 59 | /* reported will be the last one used by the garbage collector to */ 60 | /* trace the object. */ 61 | /* If source is root, then *base_p = address and *offset_p = 0. */ 62 | /* If source is heap object, then *base_p != 0, *offset_p = offset. */ 63 | /* Dest can be any address within a heap object. */ 64 | /* The allocator lock is not acquired by design (despite of the */ 65 | /* possibility of a race); anyway the function should not be used */ 66 | /* in production code. */ 67 | GC_API GC_ref_kind GC_CALL GC_get_back_ptr_info(void * /* dest */, 68 | void ** /* base_p */, 69 | size_t * /* offset_p */) 70 | GC_ATTR_NONNULL(1); 71 | 72 | /* Generate a random heap address. The resulting address is */ 73 | /* in the heap, but not necessarily inside a valid object. */ 74 | /* The caller should hold the allocator lock. */ 75 | GC_API void *GC_CALL GC_generate_random_heap_address(void); 76 | 77 | /* Generate a random address inside a valid marked heap object. */ 78 | /* The caller should hold the allocator lock. */ 79 | GC_API void *GC_CALL GC_generate_random_valid_address(void); 80 | 81 | /* Force a garbage collection and generate a backtrace from a */ 82 | /* random heap address. */ 83 | /* This uses the GC logging mechanism (GC_printf) to produce */ 84 | /* output. It can often be called from a debugger. */ 85 | GC_API void GC_CALL GC_generate_random_backtrace(void); 86 | 87 | /* Print a backtrace from a specific address. Used by the */ 88 | /* above. The client should call GC_gcollect() immediately */ 89 | /* before invocation. */ 90 | GC_API void GC_CALL GC_print_backtrace(void *) GC_ATTR_NONNULL(1); 91 | 92 | #ifdef __cplusplus 93 | } /* extern "C" */ 94 | #endif 95 | 96 | #endif /* GC_BACKPTR_H */ 97 | -------------------------------------------------------------------------------- /include/gc/gc_disclaim.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2011 by Hewlett-Packard Company. All rights reserved. 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | #ifndef GC_DISCLAIM_H 15 | #define GC_DISCLAIM_H 16 | 17 | #include "gc.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /* This API is defined only if the library has been suitably compiled */ 24 | /* (i.e. with ENABLE_DISCLAIM defined). */ 25 | 26 | /* Prepare the object kind used by GC_finalized_malloc. Call it from */ 27 | /* your initialization code or, at least, at some point before using */ 28 | /* finalized allocations. The function is thread-safe. */ 29 | GC_API void GC_CALL GC_init_finalized_malloc(void); 30 | 31 | /* Type of a disclaim callback. Called with the allocator lock held. */ 32 | typedef int(GC_CALLBACK *GC_disclaim_proc)(void * /* obj */); 33 | 34 | /* Register proc to be called on each object (of given kind) ready to */ 35 | /* be reclaimed. If proc() returns non-zero, the collector will not */ 36 | /* reclaim the object on this GC cycle (proc() should not try to */ 37 | /* resurrect the object otherwise); objects reachable from proc() */ 38 | /* (including the referred closure object) will be protected from */ 39 | /* collection if mark_from_all is non-zero, but at the expense that */ 40 | /* long chains of objects will take many cycles to reclaim. Any call */ 41 | /* to GC_free() deallocates the object (pointed by the argument) */ 42 | /* without inquiring proc(). Acquires the allocator lock. No-op in */ 43 | /* the find-leak mode. */ 44 | GC_API void GC_CALL GC_register_disclaim_proc(int /* kind */, 45 | GC_disclaim_proc /* proc */, 46 | int /* mark_from_all */); 47 | 48 | /* The finalizer closure used by GC_finalized_malloc. */ 49 | struct GC_finalizer_closure { 50 | GC_finalization_proc proc; 51 | void *cd; 52 | }; 53 | 54 | /* Allocate an object which is to be finalized by the given closure. */ 55 | /* This uses a dedicated object kind with a disclaim procedure, and is */ 56 | /* more efficient than GC_register_finalizer and friends. */ 57 | /* GC_init_finalized_malloc must be called before using this. */ 58 | /* The collector will reclaim the object during this GC cycle (thus, */ 59 | /* fc->proc() should not try to resurrect the object). The other */ 60 | /* objects reachable from fc->proc (including the closure object in */ 61 | /* case it is a heap-allocated one) will be protected from collection. */ 62 | /* Note that GC_size (applied to such allocated object) returns a value */ 63 | /* slightly bigger than the specified allocation size, and that GC_base */ 64 | /* result points to a word prior to the start of the allocated object. */ 65 | /* The disclaim procedure is not invoked in the find-leak mode. */ 66 | /* There is no debugging version of this allocation API. */ 67 | GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL 68 | GC_finalized_malloc(size_t /* size */, 69 | const struct GC_finalizer_closure * /* fc */) 70 | GC_ATTR_NONNULL(2); 71 | 72 | #ifdef __cplusplus 73 | } /* extern "C" */ 74 | #endif 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /include/gc/gc_gcj.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers 3 | * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. 4 | * Copyright 1996-1999 by Silicon Graphics. All rights reserved. 5 | * Copyright 1999 by Hewlett-Packard Company. All rights reserved. 6 | * 7 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 8 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 9 | * 10 | * Permission is hereby granted to use or copy this program 11 | * for any purpose, provided the above notices are retained on all copies. 12 | * Permission to modify the code and to distribute modified code is granted, 13 | * provided the above notices are retained, and a notice that the code was 14 | * modified is included with the above copyright notice. 15 | */ 16 | 17 | /* This file assumes the collector has been compiled with GC_GCJ_SUPPORT. */ 18 | 19 | /* 20 | * We allocate objects whose first word contains a pointer to a struct 21 | * describing the object type. This struct contains a garbage collector mark 22 | * descriptor at offset GC_GCJ_MARK_DESCR_OFFSET. Alternatively, the objects 23 | * may be marked by the mark procedure passed to GC_init_gcj_malloc_mp. 24 | */ 25 | 26 | #ifndef GC_GCJ_H 27 | #define GC_GCJ_H 28 | 29 | #ifndef GC_H 30 | # include "gc.h" 31 | #endif 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | /* The offset of the garbage collector mark descriptor inside the */ 38 | /* structure describing the object type (vtable). gcj keeps the mark */ 39 | /* descriptor as the second "pointer-sized" word of vtable. Probably */ 40 | /* this needs to be adjusted for other clients. It is assumed that */ 41 | /* this offset is not smaller than the size of a pointer (the */ 42 | /* assumption allows objects on the free list to be marked normally). */ 43 | #ifndef GC_GCJ_MARK_DESCR_OFFSET 44 | # define GC_GCJ_MARK_DESCR_OFFSET GC_SIZEOF_PTR 45 | #endif 46 | 47 | /* This function must be called before the gcj allocators are invoked. */ 48 | /* mp_index and mp are the index and mark proc (see gc_mark.h), */ 49 | /* respectively, for the allocated objects. mp will be used to build */ 50 | /* the descriptor for objects allocated through the debugging */ 51 | /* interface; it will be invoked on all such objects with an */ 52 | /* "environment" value of 1. The client may choose to use the same */ 53 | /* mark proc for some of its generated mark descriptors. */ 54 | /* In that case, it should use a different "environment" value to */ 55 | /* detect the presence or absence of the debug header. */ 56 | /* mp is really of type GC_mark_proc, as defined in gc_mark.h; we do */ 57 | /* not want to include that here for namespace pollution reasons. */ 58 | /* Passing in mp_index here instead of having GC_init_gcj_malloc() */ 59 | /* internally call GC_new_proc() is quite ugly, but in typical usage */ 60 | /* scenarios a compiler also has to know about mp_index, so */ 61 | /* generating it dynamically is not acceptable. The mp_index will */ 62 | /* typically be an integer less than RESERVED_MARK_PROCS, so that it */ 63 | /* does not collide with indices allocated by GC_new_proc. If the */ 64 | /* application needs no other reserved indices, zero */ 65 | /* (GC_GCJ_RESERVED_MARK_PROC_INDEX in gc_mark.h) is an obvious choice. */ 66 | /* Deprecated, portable clients should include gc_mark.h and use */ 67 | /* GC_init_gcj_malloc_mp() instead. */ 68 | GC_API GC_ATTR_DEPRECATED void GC_CALL GC_init_gcj_malloc(int /* mp_index */, 69 | void * /* mp */); 70 | 71 | /* Allocate an object, clear it, and store the pointer to the type */ 72 | /* structure (vtable in gcj). This adds a byte at the end of the */ 73 | /* object if GC_malloc() would. In case of out of memory, GC_oom_fn() */ 74 | /* is called and its result is returned. */ 75 | GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL 76 | GC_gcj_malloc(size_t /* lb */, const void * /* vtable_ptr */); 77 | 78 | /* Similar to GC_gcj_malloc, but add the debug info. This is allocated */ 79 | /* with GC_gcj_debug_kind. */ 80 | GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL 81 | GC_debug_gcj_malloc(size_t /* lb */, const void * /* vtable_ptr */, 82 | GC_EXTRA_PARAMS); 83 | 84 | /* Similar to GC_gcj_malloc, but assumes that a pointer to near the */ 85 | /* beginning (i.e. within the first heap block) of the allocated object */ 86 | /* is always maintained. */ 87 | GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL 88 | GC_gcj_malloc_ignore_off_page(size_t /* lb */, 89 | const void * /* vtable_ptr */); 90 | 91 | /* The kind numbers of normal and debug gcj objects. Useful only for */ 92 | /* debug support, we hope. */ 93 | GC_API int GC_gcj_kind; 94 | GC_API int GC_gcj_debug_kind; 95 | 96 | #ifdef GC_DEBUG 97 | # define GC_GCJ_MALLOC(s, d) GC_debug_gcj_malloc(s, d, GC_EXTRAS) 98 | # define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s, d) GC_GCJ_MALLOC(s, d) 99 | #else 100 | # define GC_GCJ_MALLOC(s, d) GC_gcj_malloc(s, d) 101 | # define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s, d) \ 102 | GC_gcj_malloc_ignore_off_page(s, d) 103 | #endif 104 | 105 | #ifdef __cplusplus 106 | } /* extern "C" */ 107 | #endif 108 | 109 | #endif /* GC_GCJ_H */ 110 | -------------------------------------------------------------------------------- /include/gc/gc_pthread_redirects.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1994 by Xerox Corporation. All rights reserved. 3 | * Copyright (c) 1996 by Silicon Graphics. All rights reserved. 4 | * Copyright (c) 1998 by Fergus Henderson. All rights reserved. 5 | * Copyright (c) 2000-2010 by Hewlett-Packard Development Company. 6 | * All rights reserved. 7 | * 8 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 9 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 10 | * 11 | * Permission is hereby granted to use or copy this program 12 | * for any purpose, provided the above notices are retained on all copies. 13 | * Permission to modify the code and to distribute modified code is granted, 14 | * provided the above notices are retained, and a notice that the code was 15 | * modified is included with the above copyright notice. 16 | */ 17 | 18 | /* Our pthread support normally needs to intercept a number of thread */ 19 | /* calls. We arrange to do that here, if appropriate. */ 20 | 21 | #ifndef GC_PTHREAD_REDIRECTS_H 22 | #define GC_PTHREAD_REDIRECTS_H 23 | 24 | /* Included from gc.h only. Included only if GC_PTHREADS. */ 25 | #if defined(GC_H) && defined(GC_PTHREADS) 26 | 27 | /* We need to intercept calls to many of the threads primitives, so */ 28 | /* that we can locate thread stacks and stop the world. */ 29 | /* Note also that the collector cannot always see thread specific data. */ 30 | /* Thread specific data should generally consist of pointers to */ 31 | /* uncollectible objects (allocated with GC_malloc_uncollectable, */ 32 | /* not the system malloc), which are deallocated using the destructor */ 33 | /* facility in thr_keycreate. Alternatively, keep a redundant pointer */ 34 | /* to thread specific data on the thread stack. */ 35 | 36 | # ifndef GC_PTHREAD_REDIRECTS_ONLY 37 | 38 | # include 39 | # ifndef GC_NO_DLOPEN 40 | # include 41 | # endif 42 | # ifndef GC_NO_PTHREAD_SIGMASK 43 | # include /* needed anyway for proper redirection */ 44 | # endif 45 | 46 | # ifdef __cplusplus 47 | extern "C" { 48 | # endif 49 | 50 | # ifndef GC_SUSPEND_THREAD_ID 51 | # define GC_SUSPEND_THREAD_ID pthread_t 52 | # endif 53 | 54 | # ifndef GC_NO_DLOPEN 55 | GC_API void *GC_dlopen(const char * /* path */, int /* mode */); 56 | # endif /* !GC_NO_DLOPEN */ 57 | 58 | # ifndef GC_NO_PTHREAD_SIGMASK 59 | # if defined(GC_PTHREAD_SIGMASK_NEEDED) || defined(__COSMOPOLITAN__) \ 60 | || defined(GC_HAVE_PTHREAD_SIGMASK) || defined(_BSD_SOURCE) \ 61 | || defined(_GNU_SOURCE) || defined(_NETBSD_SOURCE) \ 62 | || (_POSIX_C_SOURCE >= 199506L) || (_XOPEN_SOURCE >= 500) \ 63 | || (__POSIX_VISIBLE >= 199506) /* xBSD internal macro */ 64 | 65 | GC_API int GC_pthread_sigmask(int /* how */, const sigset_t *, 66 | sigset_t * /* oset */); 67 | # else 68 | # define GC_NO_PTHREAD_SIGMASK 69 | # endif 70 | # endif /* !GC_NO_PTHREAD_SIGMASK */ 71 | 72 | # ifndef GC_PTHREAD_CREATE_CONST 73 | /* This is used for pthread_create() only. */ 74 | # define GC_PTHREAD_CREATE_CONST const 75 | # endif 76 | 77 | GC_API int GC_pthread_create(pthread_t *, 78 | GC_PTHREAD_CREATE_CONST pthread_attr_t *, 79 | void *(*)(void *), void * /* arg */); 80 | GC_API int GC_pthread_join(pthread_t, void ** /* retval */); 81 | GC_API int GC_pthread_detach(pthread_t); 82 | 83 | # ifndef GC_NO_PTHREAD_CANCEL 84 | GC_API int GC_pthread_cancel(pthread_t); 85 | # endif 86 | 87 | # if defined(GC_HAVE_PTHREAD_EXIT) && !defined(GC_PTHREAD_EXIT_DECLARED) 88 | # define GC_PTHREAD_EXIT_DECLARED 89 | GC_API void GC_pthread_exit(void *) GC_PTHREAD_EXIT_ATTRIBUTE; 90 | # endif 91 | 92 | # ifdef __cplusplus 93 | } /* extern "C" */ 94 | # endif 95 | 96 | # endif /* !GC_PTHREAD_REDIRECTS_ONLY */ 97 | 98 | # if !defined(GC_NO_THREAD_REDIRECTS) && !defined(GC_USE_LD_WRAP) 99 | /* Unless the compiler supports #pragma extern_prefix, the Tru64 */ 100 | /* UNIX pthread.h redefines some POSIX thread functions to use */ 101 | /* mangled names. Anyway, it's safe to undef them before redefining. */ 102 | # undef pthread_create 103 | # undef pthread_join 104 | # undef pthread_detach 105 | # define pthread_create GC_pthread_create 106 | # define pthread_join GC_pthread_join 107 | # define pthread_detach GC_pthread_detach 108 | 109 | # ifndef GC_NO_PTHREAD_SIGMASK 110 | # undef pthread_sigmask 111 | # define pthread_sigmask GC_pthread_sigmask 112 | # endif 113 | # ifndef GC_NO_DLOPEN 114 | # undef dlopen 115 | # define dlopen GC_dlopen 116 | # endif 117 | # ifndef GC_NO_PTHREAD_CANCEL 118 | # undef pthread_cancel 119 | # define pthread_cancel GC_pthread_cancel 120 | # endif 121 | # ifdef GC_HAVE_PTHREAD_EXIT 122 | # undef pthread_exit 123 | # define pthread_exit GC_pthread_exit 124 | # endif 125 | # endif /* !GC_NO_THREAD_REDIRECTS */ 126 | 127 | #endif /* GC_PTHREADS */ 128 | 129 | #endif /* GC_PTHREAD_REDIRECTS_H */ 130 | -------------------------------------------------------------------------------- /include/gc/gc_tiny_fl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999-2005 Hewlett-Packard Development Company, L.P. 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | #ifndef GC_TINY_FL_H 15 | #define GC_TINY_FL_H 16 | 17 | /* Constants and data structures for "tiny" free lists. These are */ 18 | /* used for thread-local allocation or in-lined allocators. */ 19 | /* Each global free list also essentially starts with one of these. */ 20 | /* However, global free lists are known to the GC. "Tiny" free lists */ 21 | /* are basically private to the client. Their contents are viewed as */ 22 | /* "in use" and marked accordingly by the core of the GC. */ 23 | /* Note that inlined code might know about the layout of these and the */ 24 | /* constants involved. Thus any change here may invalidate clients, */ 25 | /* and such changes should be avoided. Hence we keep this as simple */ 26 | /* as possible. */ 27 | 28 | /* We always set GC_GRANULE_BYTES to twice the length of a pointer. */ 29 | /* This means that all allocation requests are rounded up to the next */ 30 | /* multiple of 16 on 64-bit architectures or 8 on 32-bit architectures. */ 31 | /* This appears to be a reasonable compromise between fragmentation */ 32 | /* overhead and space usage for mark bits (usually mark bytes). */ 33 | /* On many 64-bit architectures some memory references require 16-byte */ 34 | /* alignment, making this necessary anyway. For a few 32-bit */ 35 | /* architectures (e.g. i686), we may also need 16-byte alignment for */ 36 | /* certain memory references. But currently that does not seem to be */ 37 | /* the default for all conventional malloc implementations, so we */ 38 | /* ignore that problem. */ 39 | /* It would always be safe, and often useful, to be able to allocate */ 40 | /* very small objects with smaller alignment. But that would cost us */ 41 | /* mark bit space, so we no longer do so. */ 42 | /* GC_GRANULE_BYTES should not be overridden in any instances of the GC */ 43 | /* library that may be shared between applications, since it affects */ 44 | /* the binary interface to the library. */ 45 | #if defined(CPPCHECK) && GC_GRANULE_BYTES == 1 46 | # undef GC_GRANULE_BYTES 47 | #endif 48 | #ifdef GC_GRANULE_BYTES 49 | # define GC_GRANULE_PTRS (GC_GRANULE_BYTES / GC_SIZEOF_PTR) 50 | #else 51 | # define GC_GRANULE_PTRS 2 /* in pointers */ 52 | # define GC_GRANULE_BYTES (GC_GRANULE_PTRS * GC_SIZEOF_PTR) 53 | #endif /* !GC_GRANULE_BYTES */ 54 | 55 | /* Convert size in pointers to that in granules. */ 56 | #define GC_PTRS_TO_GRANULES(n) ((n) / GC_GRANULE_PTRS) 57 | 58 | /* Convert size in pointers to that in granules, but rounding up the */ 59 | /* result. */ 60 | #define GC_PTRS_TO_WHOLE_GRANULES(n) \ 61 | GC_PTRS_TO_GRANULES((n) + GC_GRANULE_PTRS - 1) 62 | 63 | /* A "tiny" free-list header contains GC_TINY_FREELISTS pointers to */ 64 | /* singly linked lists of objects of different sizes, the i-th one */ 65 | /* containing objects i granules in size. Note that there is a list */ 66 | /* of size zero objects. */ 67 | #ifndef GC_TINY_FREELISTS 68 | # if GC_GRANULE_BYTES >= 16 69 | # define GC_TINY_FREELISTS 25 70 | # else 71 | # define GC_TINY_FREELISTS 33 /* Up to and including 256 bytes */ 72 | # endif 73 | #endif /* !GC_TINY_FREELISTS */ 74 | 75 | /* The i-th free list corresponds to size i*GC_GRANULE_BYTES. */ 76 | /* Internally to the collector, the index can be computed with */ 77 | /* ALLOC_REQUEST_GRANS(). The later also depends on the */ 78 | /* values returned by GC_get_dont_add_byte_at_end() and */ 79 | /* GC_get_all_interior_pointers(). */ 80 | 81 | /* Convert a free-list index to the actual size of objects */ 82 | /* on that list, including extra space we added. Not an */ 83 | /* inverse of the above. */ 84 | #define GC_RAW_BYTES_FROM_INDEX(i) (GC_GRANULE_BYTES * (i)) 85 | 86 | /* Deprecated. Use GC_GRANULE_PTRS instead. */ 87 | #undef GC_GRANULE_WORDS 88 | #define GC_GRANULE_WORDS GC_GRANULE_PTRS 89 | 90 | /* Deprecated. Use GC_PTRS_TO_GRANULES() instead. */ 91 | #define GC_WORDS_TO_GRANULES(n) GC_PTRS_TO_GRANULES(n) 92 | 93 | /* Deprecated. */ 94 | #define GC_WORDS_TO_WHOLE_GRANULES(n) GC_PTRS_TO_WHOLE_GRANULES(n) 95 | 96 | #endif /* GC_TINY_FL_H */ 97 | -------------------------------------------------------------------------------- /include/gc/gc_version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1994 by Xerox Corporation. All rights reserved. 3 | * Copyright (c) 1996 by Silicon Graphics. All rights reserved. 4 | * Copyright (c) 1998 by Fergus Henderson. All rights reserved. 5 | * Copyright (c) 2000-2009 by Hewlett-Packard Development Company. 6 | * All rights reserved. 7 | * 8 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 9 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 10 | * 11 | * Permission is hereby granted to use or copy this program 12 | * for any purpose, provided the above notices are retained on all copies. 13 | * Permission to modify the code and to distribute modified code is granted, 14 | * provided the above notices are retained, and a notice that the code was 15 | * modified is included with the above copyright notice. 16 | */ 17 | 18 | /* This should never be included directly; it is included only from gc.h. */ 19 | #if defined(GC_H) 20 | 21 | /* The policy regarding version numbers: development code has odd */ 22 | /* "minor" number (and "micro" part is 0); when development is finished */ 23 | /* and a release is prepared, "minor" number is incremented (keeping */ 24 | /* "micro" number still zero), whenever a defect is fixed a new release */ 25 | /* is prepared incrementing "micro" part to odd value (the most stable */ 26 | /* release has the biggest "micro" number). */ 27 | 28 | /* The version here should match that in configure/configure.ac */ 29 | /* Eventually this one may become unnecessary. For now we need */ 30 | /* it to keep the old-style build process working. */ 31 | # define GC_TMP_VERSION_MAJOR 8 32 | # define GC_TMP_VERSION_MINOR 3 33 | # define GC_TMP_VERSION_MICRO 0 /* 8.3.0 */ 34 | 35 | # ifdef GC_VERSION_MAJOR 36 | # if GC_TMP_VERSION_MAJOR != GC_VERSION_MAJOR \ 37 | || GC_TMP_VERSION_MINOR != GC_VERSION_MINOR \ 38 | || GC_TMP_VERSION_MICRO != GC_VERSION_MICRO 39 | # error Inconsistent version info. Check README.md, include/gc_version.h and configure.ac. 40 | # endif 41 | # else 42 | # define GC_VERSION_MAJOR GC_TMP_VERSION_MAJOR 43 | # define GC_VERSION_MINOR GC_TMP_VERSION_MINOR 44 | # define GC_VERSION_MICRO GC_TMP_VERSION_MICRO 45 | # endif /* !GC_VERSION_MAJOR */ 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /include/gc/javaxfc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1994 by Xerox Corporation. All rights reserved. 3 | * Copyright (c) 1996 by Silicon Graphics. All rights reserved. 4 | * Copyright (c) 1998 by Fergus Henderson. All rights reserved. 5 | * Copyright (c) 2000-2009 by Hewlett-Packard Development Company. 6 | * All rights reserved. 7 | * 8 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 9 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 10 | * 11 | * Permission is hereby granted to use or copy this program 12 | * for any purpose, provided the above notices are retained on all copies. 13 | * Permission to modify the code and to distribute modified code is granted, 14 | * provided the above notices are retained, and a notice that the code was 15 | * modified is included with the above copyright notice. 16 | */ 17 | 18 | #ifndef GC_JAVAXFC_H 19 | #define GC_JAVAXFC_H 20 | 21 | #ifndef GC_H 22 | # include "gc.h" 23 | #endif 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* 30 | * Invoke all remaining finalizers that haven't yet been run. (Since the 31 | * notifier is not called, this should be called from a separate thread.) 32 | * This function is needed for strict compliance with the Java standard, 33 | * which can make the runtime guarantee that all finalizers are run. 34 | * This is problematic for several reasons: 35 | * 1) It means that finalizers, and all methods called by them, 36 | * must be prepared to deal with objects that have been finalized in 37 | * spite of the fact that they are still referenced by statically 38 | * allocated pointer variables. 39 | * 2) It may mean that we get stuck in an infinite loop running 40 | * finalizers which create new finalizable objects, though that's 41 | * probably unlikely. 42 | * Thus this is not recommended for general use. 43 | * Acquires the allocator lock (to enqueue all finalizers). 44 | */ 45 | GC_API void GC_CALL GC_finalize_all(void); 46 | 47 | #ifdef GC_THREADS 48 | /* External thread suspension support. No thread suspension count */ 49 | /* (so a thread which has been suspended numerous times will be */ 50 | /* resumed with the very first call to GC_resume_thread). */ 51 | /* Acquires the allocator lock. Thread should be registered in GC. */ 52 | /* Unimplemented on some platforms. Not recommended for general use. */ 53 | # ifndef GC_SUSPEND_THREAD_ID 54 | # define GC_SUSPEND_THREAD_ID void * 55 | # endif 56 | GC_API void GC_CALL GC_suspend_thread(GC_SUSPEND_THREAD_ID); 57 | GC_API void GC_CALL GC_resume_thread(GC_SUSPEND_THREAD_ID); 58 | 59 | /* Is the given thread suspended externally? The result is either */ 60 | /* 1 (true) or 0. Acquires the allocator lock in the reader mode. */ 61 | /* Note: returns false if the thread is not registered in GC. */ 62 | /* Unimplemented on some platforms (same as GC_suspend_thread). */ 63 | GC_API int GC_CALL GC_is_thread_suspended(GC_SUSPEND_THREAD_ID); 64 | #endif /* GC_THREADS */ 65 | 66 | #ifdef __cplusplus 67 | } /* extern "C" */ 68 | #endif 69 | 70 | #endif /* GC_JAVAXFC_H */ 71 | -------------------------------------------------------------------------------- /include/gc/leak_detector.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2011 by Hewlett-Packard Development Company. 3 | * All rights reserved. 4 | * 5 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 6 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 7 | * 8 | * Permission is hereby granted to use or copy this program 9 | * for any purpose, provided the above notices are retained on all copies. 10 | * Permission to modify the code and to distribute modified code is granted, 11 | * provided the above notices are retained, and a notice that the code was 12 | * modified is included with the above copyright notice. 13 | */ 14 | 15 | #ifndef GC_LEAK_DETECTOR_H 16 | #define GC_LEAK_DETECTOR_H 17 | 18 | /* Include this header file (e.g., via gcc --include directive) */ 19 | /* to turn libgc into a leak detector. */ 20 | 21 | #ifndef GC_DEBUG 22 | # define GC_DEBUG 23 | #endif 24 | #include "gc.h" 25 | 26 | #ifndef GC_DONT_INCLUDE_STDLIB 27 | /* We ensure stdlib.h and string.h are included before */ 28 | /* redirecting malloc() and the accompanying functions. */ 29 | # include 30 | # include 31 | #endif 32 | 33 | #undef malloc 34 | #define malloc(n) GC_MALLOC(n) 35 | #undef calloc 36 | #define calloc(m, n) GC_MALLOC((m) * (n)) 37 | #undef free 38 | #define free(p) GC_FREE(p) 39 | #undef realloc 40 | #define realloc(p, n) GC_REALLOC(p, n) 41 | #undef reallocarray 42 | #define reallocarray(p, m, n) GC_REALLOC(p, (m) * (n)) 43 | 44 | #undef strdup 45 | #define strdup(s) GC_STRDUP(s) 46 | #undef strndup 47 | #define strndup(s, n) GC_STRNDUP(s, n) 48 | 49 | #ifdef GC_REQUIRE_WCSDUP 50 | /* The collector should be built with GC_REQUIRE_WCSDUP */ 51 | /* defined as well to redirect wcsdup(). */ 52 | # include 53 | # undef wcsdup 54 | # define wcsdup(s) GC_WCSDUP(s) 55 | #endif 56 | 57 | /* The following routines for the aligned objects allocation */ 58 | /* (aligned_alloc, valloc, etc.) do not have their debugging */ 59 | /* counterparts. Note that free() called for such objects */ 60 | /* may output a warning that the pointer has no debugging info. */ 61 | 62 | #undef aligned_alloc 63 | #define aligned_alloc(a, n) GC_memalign(a, n) /* identical to memalign */ 64 | #undef memalign 65 | #define memalign(a, n) GC_memalign(a, n) 66 | #undef posix_memalign 67 | #define posix_memalign(p, a, n) GC_posix_memalign(p, a, n) 68 | 69 | /* These are defined in the C23 standard. */ 70 | #undef free_sized 71 | #define free_sized(p, n) (free(p), (void)(n)) 72 | #undef free_aligned_sized 73 | #define free_aligned_sized(p, a, n) \ 74 | (GC_free(p) /* non-debug */, (void)(a), (void)(n)) 75 | 76 | #undef _aligned_malloc 77 | #define _aligned_malloc(n, a) GC_memalign(a, n) /* reverse args order */ 78 | #undef _aligned_free 79 | #define _aligned_free(p) GC_free(p) /* non-debug */ 80 | 81 | #ifndef GC_NO_VALLOC 82 | # undef valloc 83 | # define valloc(n) GC_valloc(n) 84 | # undef pvalloc 85 | # define pvalloc(n) GC_pvalloc(n) /* obsolete */ 86 | #endif 87 | 88 | #undef malloc_usable_size /* available in glibc */ 89 | #define malloc_usable_size(p) GC_size(p) 90 | #undef malloc_size /* available on Darwin */ 91 | #define malloc_size(p) GC_size(p) 92 | #undef _msize /* available in Windows CRT */ 93 | #define _msize(p) GC_size(p) 94 | 95 | #ifndef CHECK_LEAKS 96 | # define CHECK_LEAKS() GC_gcollect() 97 | /* Note 1: CHECK_LEAKS does not have GC prefix (preserved for */ 98 | /* backward compatibility). */ 99 | /* Note 2: GC_gcollect() is also called automatically in the */ 100 | /* find-leak mode at program exit. */ 101 | #endif 102 | 103 | #endif /* GC_LEAK_DETECTOR_H */ 104 | -------------------------------------------------------------------------------- /include/gc_cpp.h: -------------------------------------------------------------------------------- 1 | /* This file is installed for backward compatibility. */ 2 | #include "gc/gc_cpp.h" 3 | -------------------------------------------------------------------------------- /include/include.am: -------------------------------------------------------------------------------- 1 | # 2 | # THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 3 | # OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 4 | # 5 | # Permission is hereby granted to use or copy this program 6 | # for any purpose, provided the above notices are retained on all copies. 7 | # Permission to modify the code and to distribute modified code is granted, 8 | # provided the above notices are retained, and a notice that the code was 9 | # modified is included with the above copyright notice. 10 | 11 | ## Process this file with automake to produce part of Makefile.in. 12 | 13 | # installed headers 14 | # 15 | pkginclude_HEADERS += \ 16 | include/gc/gc.h \ 17 | include/gc/gc_backptr.h \ 18 | include/gc/gc_config_macros.h \ 19 | include/gc/gc_inline.h \ 20 | include/gc/gc_mark.h \ 21 | include/gc/gc_tiny_fl.h \ 22 | include/gc/gc_typed.h \ 23 | include/gc/gc_version.h \ 24 | include/gc/javaxfc.h \ 25 | include/gc/leak_detector.h 26 | 27 | if ENABLE_DISCLAIM 28 | pkginclude_HEADERS += include/gc/gc_disclaim.h 29 | endif 30 | 31 | if ENABLE_GCJ_SUPPORT 32 | pkginclude_HEADERS += include/gc/gc_gcj.h 33 | endif 34 | 35 | if THREADS 36 | pkginclude_HEADERS += include/gc/gc_pthread_redirects.h 37 | endif 38 | 39 | if CPLUSPLUS 40 | pkginclude_HEADERS += \ 41 | include/gc/gc_allocator.h \ 42 | include/gc/gc_cpp.h 43 | 44 | include_HEADERS += include/gc_cpp.h 45 | endif 46 | 47 | # headers which are not installed 48 | # 49 | dist_noinst_HEADERS += \ 50 | include/private/darwin_semaphore.h \ 51 | include/private/dbg_mlc.h \ 52 | include/private/gc_alloc_ptrs.h \ 53 | include/private/gc_atomic_ops.h \ 54 | include/private/gc_hdrs.h \ 55 | include/private/gc_locks.h \ 56 | include/private/gc_pmark.h \ 57 | include/private/gc_priv.h \ 58 | include/private/gcconfig.h \ 59 | include/private/pthread_support.h \ 60 | include/private/specific.h \ 61 | include/private/thread_local_alloc.h 62 | 63 | # unprefixed header 64 | include_HEADERS += \ 65 | include/gc.h 66 | -------------------------------------------------------------------------------- /include/private/darwin_semaphore.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1994 by Xerox Corporation. All rights reserved. 3 | * Copyright (c) 1996 by Silicon Graphics. All rights reserved. 4 | * Copyright (c) 1998 by Fergus Henderson. All rights reserved. 5 | * Copyright (c) 2000-2009 by Hewlett-Packard Development Company. 6 | * All rights reserved. 7 | * 8 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 9 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 10 | * 11 | * Permission is hereby granted to use or copy this program 12 | * for any purpose, provided the above notices are retained on all copies. 13 | * Permission to modify the code and to distribute modified code is granted, 14 | * provided the above notices are retained, and a notice that the code was 15 | * modified is included with the above copyright notice. 16 | */ 17 | 18 | #ifndef GC_DARWIN_SEMAPHORE_H 19 | #define GC_DARWIN_SEMAPHORE_H 20 | 21 | #include "gc_priv.h" 22 | 23 | #if !defined(DARWIN) && !defined(GC_WIN32_THREADS) || !defined(GC_PTHREADS) 24 | # error darwin_semaphore.h included for improper target 25 | #endif 26 | 27 | #include 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | /* This is a very simple semaphore implementation based on pthreads. */ 34 | /* It is not async-signal safe. But this is not a problem because */ 35 | /* signals are not used to suspend threads on the target. */ 36 | 37 | typedef struct { 38 | pthread_mutex_t mutex; 39 | pthread_cond_t cond; 40 | int value; 41 | } sem_t; 42 | 43 | GC_INLINE int 44 | sem_init(sem_t *sem, int pshared, int value) 45 | { 46 | int err; 47 | 48 | if (EXPECT(pshared != 0, FALSE)) { 49 | errno = EPERM; /* unsupported */ 50 | return -1; 51 | } 52 | sem->value = value; 53 | err = pthread_mutex_init(&sem->mutex, NULL); 54 | if (EXPECT(err != 0, FALSE)) { 55 | errno = err; 56 | return -1; 57 | } 58 | err = pthread_cond_init(&sem->cond, NULL); 59 | if (EXPECT(err != 0, FALSE)) { 60 | (void)pthread_mutex_destroy(&sem->mutex); 61 | errno = err; 62 | return -1; 63 | } 64 | return 0; 65 | } 66 | 67 | GC_INLINE int 68 | sem_post(sem_t *sem) 69 | { 70 | int err = pthread_mutex_lock(&sem->mutex); 71 | 72 | if (EXPECT(err != 0, FALSE)) { 73 | errno = err; 74 | return -1; 75 | } 76 | sem->value++; 77 | err = pthread_cond_signal(&sem->cond); 78 | if (EXPECT(err != 0, FALSE)) { 79 | (void)pthread_mutex_unlock(&sem->mutex); 80 | errno = err; 81 | return -1; 82 | } 83 | err = pthread_mutex_unlock(&sem->mutex); 84 | if (EXPECT(err != 0, FALSE)) { 85 | errno = err; 86 | return -1; 87 | } 88 | return 0; 89 | } 90 | 91 | GC_INLINE int 92 | sem_wait(sem_t *sem) 93 | { 94 | int err = pthread_mutex_lock(&sem->mutex); 95 | 96 | if (EXPECT(err != 0, FALSE)) { 97 | errno = err; 98 | return -1; 99 | } 100 | while (0 == sem->value) { 101 | err = pthread_cond_wait(&sem->cond, &sem->mutex); 102 | if (EXPECT(err != 0, FALSE)) { 103 | (void)pthread_mutex_unlock(&sem->mutex); 104 | errno = err; 105 | return -1; 106 | } 107 | } 108 | sem->value--; 109 | err = pthread_mutex_unlock(&sem->mutex); 110 | if (EXPECT(err != 0, FALSE)) { 111 | errno = err; 112 | return -1; 113 | } 114 | return 0; 115 | } 116 | 117 | GC_INLINE int 118 | sem_destroy(sem_t *sem) 119 | { 120 | int err = pthread_cond_destroy(&sem->cond); 121 | 122 | if (EXPECT(err != 0, FALSE)) { 123 | errno = err; 124 | return -1; 125 | } 126 | err = pthread_mutex_destroy(&sem->mutex); 127 | if (EXPECT(err != 0, FALSE)) { 128 | errno = err; 129 | return -1; 130 | } 131 | return 0; 132 | } 133 | 134 | #ifdef __cplusplus 135 | } /* extern "C" */ 136 | #endif 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /include/private/gc_alloc_ptrs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1996-1998 by Silicon Graphics. All rights reserved. 3 | * Copyright (c) 2018-2021 Ivan Maidanski 4 | * 5 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 6 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 7 | * 8 | * Permission is hereby granted to use or copy this program 9 | * for any purpose, provided the above notices are retained on all copies. 10 | * Permission to modify the code and to distribute modified code is granted, 11 | * provided the above notices are retained, and a notice that the code was 12 | * modified is included with the above copyright notice. 13 | */ 14 | 15 | /* This file is kept for a binary compatibility purpose only. */ 16 | 17 | #ifndef GC_ALLOC_PTRS_H 18 | #define GC_ALLOC_PTRS_H 19 | 20 | #include "gc/gc.h" 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | #ifndef GC_API_PRIV 27 | # define GC_API_PRIV GC_API 28 | #endif 29 | 30 | /* Some compilers do not accept "const" together with the dllimport */ 31 | /* attribute, so the symbols below are exported as non-constant ones. */ 32 | #ifndef GC_APIVAR_CONST 33 | # if defined(GC_BUILD) || !defined(GC_DLL) 34 | # define GC_APIVAR_CONST const 35 | # else 36 | # define GC_APIVAR_CONST /* empty */ 37 | # endif 38 | #endif 39 | 40 | GC_API_PRIV void **GC_APIVAR_CONST GC_objfreelist_ptr; 41 | GC_API_PRIV void **GC_APIVAR_CONST GC_aobjfreelist_ptr; 42 | GC_API_PRIV void **GC_APIVAR_CONST GC_uobjfreelist_ptr; 43 | 44 | #ifdef GC_ATOMIC_UNCOLLECTABLE 45 | GC_API_PRIV void **GC_APIVAR_CONST GC_auobjfreelist_ptr; 46 | #endif 47 | 48 | /* Manually update the number of bytes allocated during the current */ 49 | /* collection cycle and the number of explicitly deallocated bytes of */ 50 | /* memory since the last collection, respectively. Both functions are */ 51 | /* unsynchronized, GC_call_with_alloc_lock() should be used to avoid */ 52 | /* data race. */ 53 | GC_API_PRIV void GC_CALL GC_incr_bytes_allocd(size_t /* bytes */); 54 | GC_API_PRIV void GC_CALL GC_incr_bytes_freed(size_t /* bytes */); 55 | 56 | #ifdef __cplusplus 57 | } /* extern "C" */ 58 | #endif 59 | 60 | #endif /* GC_ALLOC_PTRS_H */ 61 | -------------------------------------------------------------------------------- /m4/gc_set_version.m4: -------------------------------------------------------------------------------- 1 | # 2 | # THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 3 | # OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 4 | # 5 | # Permission is hereby granted to use or copy this program 6 | # for any purpose, provided the above notices are retained on all copies. 7 | # Permission to modify the code and to distribute modified code is granted, 8 | # provided the above notices are retained, and a notice that the code was 9 | # modified is included with the above copyright notice. 10 | 11 | # GC_SET_VERSION 12 | # sets and AC_DEFINEs GC_VERSION_MAJOR, GC_VERSION_MINOR and GC_VERSION_MICRO 13 | # based on the contents of PACKAGE_VERSION; PACKAGE_VERSION must conform to 14 | # [0-9]+[.][0-9]+[.][0-9]+ 15 | # 16 | AC_DEFUN([GC_SET_VERSION], [ 17 | AC_MSG_CHECKING(GC version numbers) 18 | GC_VERSION_MAJOR=`echo $PACKAGE_VERSION | sed 's/^\([[0-9]][[0-9]]*\)[[.]].*$/\1/g'` 19 | GC_VERSION_MINOR=`echo $PACKAGE_VERSION | sed 's/^[[^.]]*[[.]]\([[0-9]][[0-9]]*\).*$/\1/g'` 20 | GC_VERSION_MICRO=`echo $PACKAGE_VERSION | sed 's/^[[^.]]*[[.]][[^.]]*[[.]]\([[0-9]][[0-9]]*\)$/\1/g'` 21 | 22 | if test :$GC_VERSION_MAJOR: = :: \ 23 | -o :$GC_VERSION_MINOR: = :: \ 24 | -o :$GC_VERSION_MICRO: = :: ; 25 | then 26 | AC_MSG_RESULT(invalid) 27 | AC_MSG_ERROR([nonconforming PACKAGE_VERSION='$PACKAGE_VERSION']) 28 | fi 29 | 30 | AC_DEFINE_UNQUOTED([GC_VERSION_MAJOR], $GC_VERSION_MAJOR, 31 | [The major version number of this GC release.]) 32 | AC_DEFINE_UNQUOTED([GC_VERSION_MINOR], $GC_VERSION_MINOR, 33 | [The minor version number of this GC release.]) 34 | AC_DEFINE_UNQUOTED([GC_VERSION_MICRO], $GC_VERSION_MICRO, 35 | [The micro version number of this GC release.]) 36 | AC_MSG_RESULT(major=$GC_VERSION_MAJOR minor=$GC_VERSION_MINOR \ 37 | micro=$GC_VERSION_MICRO) 38 | ]) 39 | 40 | sinclude(libtool.m4) 41 | -------------------------------------------------------------------------------- /obj_map.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers 3 | * Copyright (c) 1991, 1992 by Xerox Corporation. All rights reserved. 4 | * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved. 5 | * 6 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 7 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 8 | * 9 | * Permission is hereby granted to use or copy this program 10 | * for any purpose, provided the above notices are retained on all copies. 11 | * Permission to modify the code and to distribute modified code is granted, 12 | * provided the above notices are retained, and a notice that the code was 13 | * modified is included with the above copyright notice. 14 | */ 15 | 16 | #include "private/gc_priv.h" 17 | 18 | /* Routines for maintaining maps describing heap block 19 | * layouts for various object sizes. Allows fast pointer validity checks 20 | * and fast location of object start locations on machines (such as SPARC) 21 | * with slow division. 22 | */ 23 | 24 | /* Consider pointers that are offset bytes displaced from the beginning */ 25 | /* of an object to be valid. */ 26 | 27 | GC_API void GC_CALL 28 | GC_register_displacement(size_t offset) 29 | { 30 | LOCK(); 31 | GC_register_displacement_inner(offset); 32 | UNLOCK(); 33 | } 34 | 35 | GC_INNER void 36 | GC_register_displacement_inner(size_t offset) 37 | { 38 | GC_ASSERT(I_HOLD_LOCK()); 39 | if (offset >= VALID_OFFSET_SZ) { 40 | ABORT("Bad argument to GC_register_displacement"); 41 | } 42 | if (!GC_valid_offsets[offset]) { 43 | GC_valid_offsets[offset] = TRUE; 44 | GC_modws_valid_offsets[offset % sizeof(ptr_t)] = TRUE; 45 | } 46 | } 47 | 48 | #ifndef MARK_BIT_PER_OBJ 49 | GC_INNER GC_bool 50 | GC_add_map_entry(size_t lg) 51 | { 52 | size_t displ; 53 | hb_map_entry_t *new_map; 54 | 55 | GC_ASSERT(I_HOLD_LOCK()); 56 | /* Ensure displ % lg fits into hb_map_entry_t. Note: the maximum */ 57 | /* value is computed in this way to avoid compiler complains about */ 58 | /* constant truncation or expression overflow. */ 59 | GC_STATIC_ASSERT( 60 | MAXOBJGRANULES - 1 61 | <= (~(size_t)0 >> ((sizeof(size_t) - sizeof(hb_map_entry_t)) * 8))); 62 | 63 | if (lg > MAXOBJGRANULES) 64 | lg = 0; 65 | if (EXPECT(GC_obj_map[lg] != NULL, TRUE)) 66 | return TRUE; 67 | 68 | new_map = (hb_map_entry_t *)GC_scratch_alloc(OBJ_MAP_LEN 69 | * sizeof(hb_map_entry_t)); 70 | if (EXPECT(NULL == new_map, FALSE)) 71 | return FALSE; 72 | 73 | GC_COND_LOG_PRINTF("Adding block map for size of %u granules (%u bytes)\n", 74 | (unsigned)lg, (unsigned)GRANULES_TO_BYTES(lg)); 75 | if (0 == lg) { 76 | for (displ = 0; displ < OBJ_MAP_LEN; displ++) { 77 | /* Set to a nonzero to get us out of the marker fast path. */ 78 | new_map[displ] = 1; 79 | } 80 | } else { 81 | for (displ = 0; displ < OBJ_MAP_LEN; displ++) { 82 | new_map[displ] = (hb_map_entry_t)(displ % lg); 83 | } 84 | } 85 | GC_obj_map[lg] = new_map; 86 | return TRUE; 87 | } 88 | #endif /* !MARK_BIT_PER_OBJ */ 89 | 90 | GC_INNER void 91 | GC_initialize_offsets(void) 92 | { 93 | size_t i; 94 | 95 | if (GC_all_interior_pointers) { 96 | for (i = 0; i < VALID_OFFSET_SZ; ++i) 97 | GC_valid_offsets[i] = TRUE; 98 | } else { 99 | BZERO(GC_valid_offsets, sizeof(GC_valid_offsets)); 100 | for (i = 0; i < sizeof(ptr_t); ++i) 101 | GC_modws_valid_offsets[i] = FALSE; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /pthread_start.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1994 by Xerox Corporation. All rights reserved. 3 | * Copyright (c) 1996 by Silicon Graphics. All rights reserved. 4 | * Copyright (c) 1998 by Fergus Henderson. All rights reserved. 5 | * Copyright (c) 2000-2010 by Hewlett-Packard Development Company. 6 | * All rights reserved. 7 | * 8 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 9 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 10 | * 11 | * Permission is hereby granted to use or copy this program 12 | * for any purpose, provided the above notices are retained on all copies. 13 | * Permission to modify the code and to distribute modified code is granted, 14 | * provided the above notices are retained, and a notice that the code was 15 | * modified is included with the above copyright notice. 16 | */ 17 | 18 | /* We want to make sure that GC_thread_exit_proc() is unconditionally */ 19 | /* invoked, even if the client is not compiled with -fexceptions, but */ 20 | /* the GC is. The workaround is to put GC_pthread_start_inner() in its */ 21 | /* own file (pthread_start.c), and undefine __EXCEPTIONS in the GCC */ 22 | /* case at the top of the file. FIXME: it's still unclear whether this */ 23 | /* will actually cause the exit handler to be invoked last when */ 24 | /* thread_exit is called (and if -fexceptions is used). */ 25 | #if !defined(DONT_UNDEF_EXCEPTIONS) && defined(__GNUC__) && defined(__linux__) 26 | /* We undefine __EXCEPTIONS to avoid using GCC __cleanup__ attribute. */ 27 | /* The current NPTL implementation of pthread_cleanup_push uses */ 28 | /* __cleanup__ attribute when __EXCEPTIONS is defined (-fexceptions). */ 29 | /* The stack unwinding and cleanup with __cleanup__ attributes work */ 30 | /* correctly when everything is compiled with -fexceptions, but it is */ 31 | /* not the requirement for this library clients to use -fexceptions */ 32 | /* everywhere. With __EXCEPTIONS undefined, the cleanup routines are */ 33 | /* registered with __pthread_register_cancel thus should work anyway. */ 34 | # undef __EXCEPTIONS 35 | #endif 36 | 37 | #include "private/pthread_support.h" 38 | 39 | #if defined(GC_PTHREADS) && !defined(PLATFORM_THREADS) \ 40 | && !defined(SN_TARGET_PSP2) 41 | 42 | /* Invoked from GC_pthread_start. */ 43 | GC_INNER_PTHRSTART void *GC_CALLBACK 44 | GC_pthread_start_inner(struct GC_stack_base *sb, void *arg) 45 | { 46 | void *(*start)(void *); 47 | void *start_arg; 48 | void *result; 49 | volatile GC_thread me 50 | = GC_start_rtn_prepare_thread(&start, &start_arg, sb, arg); 51 | 52 | # ifndef NACL 53 | pthread_cleanup_push(GC_thread_exit_proc, (/* no volatile */ void *)me); 54 | # endif 55 | result = (*start)(start_arg); 56 | # if defined(DEBUG_THREADS) && !defined(GC_PTHREAD_START_STANDALONE) 57 | GC_log_printf("Finishing thread %p\n", PTHREAD_TO_VPTR(pthread_self())); 58 | # endif 59 | me->status = result; 60 | /* Note: we cannot use GC_dirty() instead. */ 61 | GC_end_stubborn_change(me); 62 | 63 | /* Cleanup acquires the allocator lock, ensuring that we cannot exit */ 64 | /* while a collection that thinks we are alive is trying to stop us. */ 65 | # ifdef NACL 66 | GC_thread_exit_proc((/* no volatile */ void *)me); 67 | # else 68 | pthread_cleanup_pop(1); 69 | # endif 70 | return result; 71 | } 72 | 73 | #endif /* GC_PTHREADS */ 74 | -------------------------------------------------------------------------------- /sparc_mach_dep.S: -------------------------------------------------------------------------------- 1 | ! SPARCompiler 3.0 and later apparently no longer handles 2 | ! asm outside functions. So we need a separate .s file 3 | ! This is only set up for SunOS 5, not SunOS 4. 4 | ! Assumes this is called before the stack contents are 5 | ! examined. 6 | 7 | .seg "text" 8 | .globl GC_save_regs_in_stack 9 | GC_save_regs_in_stack: 10 | #if defined(__arch64__) || defined(__sparcv9) 11 | save %sp,-128,%sp 12 | flushw 13 | ret 14 | restore %sp,2047+128,%o0 15 | #else /* 32 bit SPARC */ 16 | ta 0x3 ! ST_FLUSH_WINDOWS 17 | mov %sp,%o0 18 | retl 19 | nop 20 | #endif /* 32 bit SPARC */ 21 | .GC_save_regs_in_stack_end: 22 | .size GC_save_regs_in_stack,.GC_save_regs_in_stack_end-GC_save_regs_in_stack 23 | 24 | ! GC_clear_stack_inner(arg, limit) clears stack area up to limit and 25 | ! returns arg. Stack clearing is crucial on SPARC, so we supply 26 | ! an assembly version that s more careful. Assumes limit is hotter 27 | ! than sp, and limit is 8 byte aligned. 28 | .globl GC_clear_stack_inner 29 | GC_clear_stack_inner: 30 | #if defined(__arch64__) || defined(__sparcv9) 31 | mov %sp,%o2 ! Save sp 32 | add %sp,2047-8,%o3 ! p = sp+bias-8 33 | add %o1,-2047-192,%sp ! Move sp out of the way, 34 | ! so that traps still work. 35 | ! Includes some extra words 36 | ! so we can be sloppy below. 37 | loop: 38 | stx %g0,[%o3] ! *(long *)p = 0 39 | cmp %o3,%o1 40 | bgu,pt %xcc, loop ! if (p > limit) goto loop 41 | add %o3,-8,%o3 ! p -= 8 (delay slot) 42 | retl 43 | mov %o2,%sp ! Restore sp., delay slot 44 | #else /* 32 bit SPARC */ 45 | mov %sp,%o2 ! Save sp 46 | add %sp,-8,%o3 ! p = sp-8 47 | clr %g1 ! [g0,g1] = 0 48 | add %o1,-0x60,%sp ! Move sp out of the way, 49 | ! so that traps still work. 50 | ! Includes some extra words 51 | ! so we can be sloppy below. 52 | loop: 53 | std %g0,[%o3] ! *(long long *)p = 0 54 | cmp %o3,%o1 55 | bgu loop ! if (p > limit) goto loop 56 | add %o3,-8,%o3 ! p -= 8 (delay slot) 57 | retl 58 | mov %o2,%sp ! Restore sp., delay slot 59 | #endif /* 32 bit SPARC */ 60 | .GC_clear_stack_inner_end: 61 | .size GC_clear_stack_inner,.GC_clear_stack_inner_end-GC_clear_stack_inner 62 | -------------------------------------------------------------------------------- /sparc_netbsd_mach_dep.s: -------------------------------------------------------------------------------- 1 | ! SPARCompiler 3.0 and later apparently no longer handles 2 | ! asm outside functions. So we need a separate .s file 3 | ! This is only set up for SunOS 4. 4 | ! Assumes this is called before the stack contents are 5 | ! examined. 6 | 7 | #include "machine/asm.h" 8 | 9 | .seg "text" 10 | .globl _C_LABEL(GC_save_regs_in_stack) 11 | _C_LABEL(GC_save_regs_in_stack): 12 | ta 0x3 ! ST_FLUSH_WINDOWS 13 | mov %sp,%o0 14 | retl 15 | nop 16 | 17 | .globl _C_LABEL(GC_clear_stack_inner) 18 | _C_LABEL(GC_clear_stack_inner): 19 | mov %sp,%o2 ! Save sp 20 | add %sp,-8,%o3 ! p = sp-8 21 | clr %g1 ! [g0,g1] = 0 22 | add %o1,-0x60,%sp ! Move sp out of the way, 23 | ! so that traps still work. 24 | ! Includes some extra words 25 | ! so we can be sloppy below. 26 | loop: 27 | std %g0,[%o3] ! *(long long *)p = 0 28 | cmp %o3,%o1 29 | bgu loop ! if (p > limit) goto loop 30 | add %o3,-8,%o3 ! p -= 8 (delay slot) 31 | retl 32 | mov %o2,%sp ! Restore sp., delay slot 33 | -------------------------------------------------------------------------------- /tests/atomicops.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Ivan Maidanski 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | /* Minimal testing of atomic operations used by the BDWGC. Primary use */ 15 | /* is to determine whether compiler atomic intrinsics can be relied on. */ 16 | 17 | #ifdef HAVE_CONFIG_H 18 | # include "config.h" 19 | #endif 20 | 21 | #include 22 | 23 | #if defined(GC_BUILTIN_ATOMIC) || defined(GC_THREADS) 24 | 25 | # include 26 | 27 | # ifdef PARALLEL_MARK 28 | # define AO_REQUIRE_CAS 29 | # if !defined(__GNUC__) && !defined(AO_ASSUME_WINDOWS98) 30 | # define AO_ASSUME_WINDOWS98 31 | # endif 32 | # endif 33 | 34 | # include "private/gc_atomic_ops.h" 35 | 36 | # define TA_assert(e) \ 37 | if (!(e)) { \ 38 | fprintf(stderr, "Assertion failure, line %d: " #e "\n", __LINE__); \ 39 | exit(-1); \ 40 | } 41 | 42 | int 43 | main(void) 44 | { 45 | AO_t x = 13; 46 | # if defined(AO_HAVE_char_load) || defined(AO_HAVE_char_store) 47 | unsigned char c = 117; 48 | # endif 49 | # ifdef AO_HAVE_test_and_set_acquire 50 | AO_TS_t z = AO_TS_INITIALIZER; 51 | 52 | TA_assert(AO_test_and_set_acquire(&z) == AO_TS_CLEAR); 53 | TA_assert(AO_test_and_set_acquire(&z) == AO_TS_SET); 54 | AO_CLEAR(&z); 55 | # endif 56 | AO_compiler_barrier(); 57 | # ifdef AO_HAVE_nop_full 58 | AO_nop_full(); 59 | # endif 60 | # ifdef AO_HAVE_char_load 61 | TA_assert(AO_char_load(&c) == 117); 62 | # endif 63 | # ifdef AO_HAVE_char_store 64 | AO_char_store(&c, 119); 65 | TA_assert(c == 119); 66 | # endif 67 | # ifdef AO_HAVE_load_acquire 68 | TA_assert(AO_load_acquire(&x) == 13); 69 | # endif 70 | # if defined(AO_HAVE_fetch_and_add) && defined(AO_HAVE_fetch_and_add1) \ 71 | && defined(AO_HAVE_fetch_and_sub1) 72 | TA_assert(AO_fetch_and_add(&x, 42) == 13); 73 | TA_assert(AO_fetch_and_add(&x, (AO_t)(-43)) == 55); 74 | TA_assert(AO_fetch_and_add1(&x) == 12); 75 | TA_assert(AO_fetch_and_sub1(&x) == 13); 76 | TA_assert(AO_fetch_and_add1(&x) == 12); /* 2nd call */ 77 | # endif 78 | # ifdef AO_HAVE_compare_and_swap_release 79 | TA_assert(!AO_compare_and_swap_release(&x, 14, 42)); 80 | TA_assert(x == 13); 81 | TA_assert(AO_compare_and_swap_release(&x, 13, 42)); 82 | TA_assert(x == 42); 83 | # ifdef AO_REQUIRE_CAS 84 | { 85 | char *cptr = (char *)NULL; 86 | 87 | TA_assert(GC_cptr_compare_and_swap(&cptr, (char *)NULL, (char *)&x)); 88 | TA_assert(cptr == (char *)&x); 89 | } 90 | # endif 91 | # else 92 | if (*(volatile AO_t *)&x == 13) 93 | *(volatile AO_t *)&x = 42; 94 | # endif 95 | # ifdef AO_HAVE_or 96 | AO_or(&x, 66); 97 | TA_assert(x == 106); 98 | # endif 99 | # ifdef AO_HAVE_store_release 100 | AO_store_release(&x, 113); 101 | TA_assert(x == 113); 102 | # endif 103 | return 0; 104 | } 105 | 106 | #else 107 | 108 | int 109 | main(void) 110 | { 111 | printf("test skipped\n"); 112 | return 0; 113 | } 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /tests/disclaim_bench.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 by Hewlett-Packard Company. All rights reserved. 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | #ifdef HAVE_CONFIG_H 15 | # include "config.h" 16 | #endif 17 | 18 | #include "gc/gc_disclaim.h" 19 | 20 | #define NOT_GCBUILD 21 | #include "private/gc_priv.h" 22 | 23 | #include 24 | 25 | #undef rand 26 | static GC_RAND_STATE_T seed; 27 | #define rand() GC_RAND_NEXT(&seed) 28 | 29 | #define my_assert(e) \ 30 | if (!(e)) { \ 31 | fprintf(stderr, "Assertion failure, line %d: " #e "\n", __LINE__); \ 32 | exit(-1); \ 33 | } 34 | 35 | #define CHECK_OUT_OF_MEMORY(p) \ 36 | do { \ 37 | if (NULL == (p)) { \ 38 | fprintf(stderr, "Out of memory\n"); \ 39 | exit(69); \ 40 | } \ 41 | } while (0) 42 | 43 | static int free_count = 0; 44 | 45 | struct testobj_s { 46 | struct testobj_s *keep_link; 47 | int i; 48 | }; 49 | 50 | typedef struct testobj_s *testobj_t; 51 | 52 | static void GC_CALLBACK 53 | testobj_finalize(void *obj, void *carg) 54 | { 55 | ++*(int *)carg; 56 | my_assert(((testobj_t)obj)->i == 109); 57 | ((testobj_t)obj)->i = 110; 58 | } 59 | 60 | static const struct GC_finalizer_closure fclos 61 | = { testobj_finalize, &free_count }; 62 | 63 | static testobj_t 64 | testobj_new(int model) 65 | { 66 | testobj_t obj; 67 | switch (model) { 68 | #ifndef GC_NO_FINALIZATION 69 | case 0: 70 | obj = (struct testobj_s *)GC_malloc(sizeof(struct testobj_s)); 71 | if (obj != NULL) 72 | GC_register_finalizer_no_order(obj, testobj_finalize, &free_count, NULL, 73 | NULL); 74 | break; 75 | #endif 76 | case 1: 77 | obj = (testobj_t)GC_finalized_malloc(sizeof(struct testobj_s), &fclos); 78 | break; 79 | case 2: 80 | obj = (struct testobj_s *)GC_malloc(sizeof(struct testobj_s)); 81 | break; 82 | default: 83 | exit(-1); 84 | } 85 | CHECK_OUT_OF_MEMORY(obj); 86 | my_assert(obj->i == 0 && obj->keep_link == NULL); 87 | obj->i = 109; 88 | return obj; 89 | } 90 | 91 | #define ALLOC_CNT (2 * 1024 * 1024) 92 | #define KEEP_CNT (32 * 1024) 93 | 94 | static char const *model_str[3] 95 | = { "regular finalization", "finalize on reclaim", "no finalization" }; 96 | 97 | int 98 | main(int argc, const char *argv[]) 99 | { 100 | int i; 101 | int model, model_min, model_max; 102 | testobj_t *keep_arr; 103 | 104 | GC_INIT(); 105 | GC_init_finalized_malloc(); 106 | if (argc == 2 && strcmp(argv[1], "--help") == 0) { 107 | fprintf(stderr, 108 | "Usage: %s [FINALIZATION_MODEL]\n" 109 | "\t0 -- original finalization\n" 110 | "\t1 -- finalization on reclaim\n" 111 | "\t2 -- no finalization\n", 112 | argv[0]); 113 | return 1; 114 | } 115 | if (argc == 2) { 116 | model_min = model_max = (int)COVERT_DATAFLOW(atoi(argv[1])); 117 | if (model_min < 0 || model_max > 2) 118 | exit(2); 119 | } else { 120 | #ifndef GC_NO_FINALIZATION 121 | model_min = 0; 122 | #else 123 | model_min = 1; 124 | #endif 125 | model_max = 2; 126 | } 127 | if (GC_get_find_leak()) 128 | printf("This test program is not designed for leak detection mode\n"); 129 | 130 | keep_arr = (testobj_t *)GC_malloc(sizeof(void *) * KEEP_CNT); 131 | CHECK_OUT_OF_MEMORY(keep_arr); 132 | printf("\t\t\tfin. ratio time/s time/fin.\n"); 133 | for (model = model_min; model <= model_max; ++model) { 134 | double t = 0.0; 135 | #ifndef NO_CLOCK 136 | CLOCK_TYPE tI, tF; 137 | 138 | GET_TIME(tI); 139 | #endif 140 | free_count = 0; 141 | for (i = 0; i < ALLOC_CNT; ++i) { 142 | int k = rand() % KEEP_CNT; 143 | keep_arr[k] = testobj_new(model); 144 | } 145 | GC_gcollect(); 146 | #ifndef NO_CLOCK 147 | GET_TIME(tF); 148 | t = (double)MS_TIME_DIFF(tF, tI) * 1e-3; 149 | #endif 150 | 151 | #ifdef EMBOX 152 | /* Workaround some issue with %g processing in Embox libc. */ 153 | # define PRINTF_SPEC_12g "%12f" 154 | #else 155 | # define PRINTF_SPEC_12g "%12g" 156 | #endif 157 | if (model < 2 && free_count > 0) { 158 | printf("%20s: %12.4f " PRINTF_SPEC_12g " " PRINTF_SPEC_12g "\n", 159 | model_str[model], free_count / (double)ALLOC_CNT, t, 160 | t / free_count); 161 | } else { 162 | printf("%20s: %12.4f " PRINTF_SPEC_12g " %12s\n", model_str[model], 0.0, 163 | t, "N/A"); 164 | } 165 | } 166 | return 0; 167 | } 168 | -------------------------------------------------------------------------------- /tests/huge.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #ifndef GC_IGNORE_WARN 7 | /* Ignore misleading "Out of Memory!" warning (which is printed on */ 8 | /* every GC_MALLOC call below) by defining this macro before "gc.h" */ 9 | /* inclusion. */ 10 | # define GC_IGNORE_WARN 11 | #endif 12 | 13 | #ifndef GC_MAXIMUM_HEAP_SIZE 14 | # define GC_MAXIMUM_HEAP_SIZE (100 * 1024 * 1024) 15 | # define GC_INITIAL_HEAP_SIZE (GC_MAXIMUM_HEAP_SIZE / 20) 16 | /* Otherwise heap expansion aborts when deallocating large block. */ 17 | /* That's OK. We test this corner case mostly to make sure that */ 18 | /* it fails predictably. */ 19 | #endif 20 | 21 | #ifndef GC_ATTR_ALLOC_SIZE 22 | /* Omit alloc_size attribute to avoid compiler warnings about */ 23 | /* exceeding maximum object size when values close to GC_SWORD_MAX */ 24 | /* are passed to GC_MALLOC. */ 25 | # define GC_ATTR_ALLOC_SIZE(argnum) /* empty */ 26 | #endif 27 | 28 | #include "gc.h" 29 | 30 | /* 31 | * Check that very large allocation requests fail. "Success" would usually 32 | * indicate that the size was somehow converted to a negative 33 | * number. Clients shouldn't do this, but we should fail in the 34 | * expected manner. 35 | */ 36 | 37 | #define CHECK_ALLOC_FAILED(r, sz_str) \ 38 | do { \ 39 | if (NULL != (r)) { \ 40 | fprintf(stderr, "Size " sz_str " allocation unexpectedly succeeded\n"); \ 41 | exit(1); \ 42 | } \ 43 | } while (0) 44 | 45 | #undef SIZE_MAX 46 | #define SIZE_MAX (~(size_t)0) 47 | 48 | #define U_SSIZE_MAX (SIZE_MAX >> 1) /* unsigned */ 49 | 50 | int 51 | main(void) 52 | { 53 | GC_INIT(); 54 | 55 | CHECK_ALLOC_FAILED(GC_MALLOC(U_SSIZE_MAX - 4096), "SSIZE_MAX-4096"); 56 | /* Skip other checks to avoid "exceeds maximum object size" gcc warning. */ 57 | #if !(defined(_FORTIFY_SOURCE) && defined(__x86_64__) && defined(__ILP32__)) 58 | CHECK_ALLOC_FAILED(GC_MALLOC(U_SSIZE_MAX - 1024), "SSIZE_MAX-1024"); 59 | CHECK_ALLOC_FAILED(GC_MALLOC(U_SSIZE_MAX), "SSIZE_MAX"); 60 | #endif 61 | #if !defined(_FORTIFY_SOURCE) 62 | CHECK_ALLOC_FAILED(GC_MALLOC(U_SSIZE_MAX + 1), "SSIZE_MAX+1"); 63 | CHECK_ALLOC_FAILED(GC_MALLOC(U_SSIZE_MAX + 1024), "SSIZE_MAX+1024"); 64 | CHECK_ALLOC_FAILED(GC_MALLOC(SIZE_MAX - 1024), "SIZE_MAX-1024"); 65 | CHECK_ALLOC_FAILED(GC_MALLOC(SIZE_MAX - 16), "SIZE_MAX-16"); 66 | CHECK_ALLOC_FAILED(GC_MALLOC(SIZE_MAX - 8), "SIZE_MAX-8"); 67 | CHECK_ALLOC_FAILED(GC_MALLOC(SIZE_MAX - 4), "SIZE_MAX-4"); 68 | CHECK_ALLOC_FAILED(GC_MALLOC(SIZE_MAX), "SIZE_MAX"); 69 | #endif 70 | printf("SUCCEEDED\n"); 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /tests/initfromthread.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Ludovic Courtes 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | /* Make sure GC_INIT() can be called from threads other than the */ 15 | /* initial thread. */ 16 | 17 | #ifdef HAVE_CONFIG_H 18 | # include "config.h" 19 | #endif 20 | 21 | #ifndef GC_THREADS 22 | # define GC_THREADS 23 | #endif 24 | 25 | /* Do not redirect thread creation and join calls. */ 26 | #define GC_NO_THREAD_REDIRECTS 1 27 | 28 | #include "gc.h" 29 | 30 | #ifdef GC_PTHREADS 31 | # include 32 | # include 33 | #else 34 | # ifndef WIN32_LEAN_AND_MEAN 35 | # define WIN32_LEAN_AND_MEAN 1 36 | # endif 37 | # define NOSERVICE 38 | # include 39 | #endif /* !GC_PTHREADS */ 40 | 41 | #include 42 | #include 43 | 44 | #define CHECK_OUT_OF_MEMORY(p) \ 45 | do { \ 46 | if (NULL == (p)) { \ 47 | fprintf(stderr, "Out of memory\n"); \ 48 | exit(69); \ 49 | } \ 50 | } while (0) 51 | 52 | #ifdef GC_PTHREADS 53 | static void * 54 | thread(void *arg) 55 | #else 56 | static DWORD WINAPI 57 | thread(LPVOID arg) 58 | #endif 59 | { 60 | GC_INIT(); 61 | CHECK_OUT_OF_MEMORY(GC_MALLOC(123)); 62 | CHECK_OUT_OF_MEMORY(GC_MALLOC(12345)); 63 | #ifdef GC_PTHREADS 64 | return arg; 65 | #else 66 | return (DWORD)(GC_uintptr_t)arg; 67 | #endif 68 | } 69 | 70 | #include "private/gcconfig.h" 71 | 72 | int 73 | main(void) 74 | { 75 | #ifdef GC_PTHREADS 76 | int err; 77 | pthread_t t; 78 | 79 | # ifdef LINT2 80 | /* Explicitly initialize t to some value. */ 81 | t = pthread_self(); 82 | # endif 83 | #else 84 | HANDLE t; 85 | DWORD thread_id; 86 | #endif 87 | #if !(defined(ANY_MSWIN) || defined(BEOS) \ 88 | || (defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP)) \ 89 | || ((defined(FREEBSD) || defined(LINUX) || defined(NETBSD) \ 90 | || defined(HOST_ANDROID)) \ 91 | && !defined(NO_PTHREAD_ATTR_GET_NP) \ 92 | && !defined(NO_PTHREAD_GETATTR_NP)) \ 93 | || (defined(SOLARIS) && !defined(_STRICT_STDC)) \ 94 | || ((!defined(SPECIFIC_MAIN_STACKBOTTOM) || defined(HEURISTIC1)) \ 95 | && !defined(STACKBOTTOM))) 96 | /* GC_INIT() must be called from main thread only. */ 97 | GC_INIT(); 98 | #endif 99 | 100 | /* Linking fails if no threads support. */ 101 | (void)GC_get_suspend_signal(); 102 | 103 | if (GC_get_find_leak()) 104 | printf("This test program is not designed for leak detection mode\n"); 105 | #ifdef GC_PTHREADS 106 | err = pthread_create(&t, NULL, thread, NULL); 107 | if (err != 0) { 108 | fprintf(stderr, "Thread #0 creation failed: %s\n", strerror(err)); 109 | return 1; 110 | } 111 | err = pthread_join(t, NULL); 112 | if (err != 0) { 113 | fprintf(stderr, "Thread #0 join failed: %s\n", strerror(err)); 114 | return 1; 115 | } 116 | #else 117 | t = CreateThread(NULL, 0, thread, 0, 0, &thread_id); 118 | if (t == NULL) { 119 | fprintf(stderr, "Thread #0 creation failed, errcode= %d\n", 120 | (int)GetLastError()); 121 | return 1; 122 | } 123 | if (WaitForSingleObject(t, INFINITE) != WAIT_OBJECT_0) { 124 | fprintf(stderr, "Thread #0 join failed, errcode= %d\n", 125 | (int)GetLastError()); 126 | CloseHandle(t); 127 | return 1; 128 | } 129 | CloseHandle(t); 130 | #endif 131 | printf("SUCCEEDED\n"); 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /tests/leak.c: -------------------------------------------------------------------------------- 1 | 2 | #ifdef HAVE_CONFIG_H 3 | # include "config.h" 4 | #endif 5 | 6 | #include 7 | #include 8 | 9 | #include "gc/leak_detector.h" 10 | 11 | #define N_TESTS 100 12 | 13 | #define CHECK_OUT_OF_MEMORY(p) \ 14 | do { \ 15 | if (NULL == (p)) { \ 16 | fprintf(stderr, "Out of memory\n"); \ 17 | exit(69); \ 18 | } \ 19 | } while (0) 20 | 21 | int 22 | main(void) 23 | { 24 | char *p[N_TESTS]; 25 | unsigned i; 26 | 27 | #ifndef NO_FIND_LEAK 28 | /* Just in case the code is compiled without FIND_LEAK defined. */ 29 | GC_set_find_leak(1); 30 | #endif 31 | /* Needed if thread-local allocation is enabled. */ 32 | /* FIXME: This is not ideal. */ 33 | GC_INIT(); 34 | 35 | p[0] = (char *)aligned_alloc(8, 50 /* size */); 36 | if (NULL == p[0]) { 37 | fprintf(stderr, "aligned_alloc failed\n"); 38 | return 1; 39 | } 40 | free_aligned_sized(p[0], 8, 50); 41 | 42 | p[0] = (char *)_aligned_malloc(70 /* size */, 16); 43 | if (NULL == p[0]) { 44 | fprintf(stderr, "_aligned_malloc failed\n"); 45 | return 1; 46 | } 47 | _aligned_free(p[0]); 48 | 49 | for (i = 0; i < N_TESTS; ++i) { 50 | p[i] = i > 0 ? (char *)malloc(sizeof(int) + i) : strdup("abc"); 51 | CHECK_OUT_OF_MEMORY(p[i]); 52 | (void)malloc_usable_size(p[i]); 53 | } 54 | CHECK_LEAKS(); 55 | for (i = 3; i < N_TESTS / 2; ++i) { 56 | p[i] = (char *)((i & 1) != 0 ? reallocarray(p[i], i, 43) 57 | : realloc(p[i], i * 16 + 1)); 58 | CHECK_OUT_OF_MEMORY(p[i]); 59 | } 60 | CHECK_LEAKS(); 61 | for (i = 2; i < N_TESTS; ++i) { 62 | free(p[i]); 63 | } 64 | for (i = 0; i < N_TESTS / 8; ++i) { 65 | p[i] = i < 3 || i > 6 ? (char *)malloc(sizeof(int) + i) 66 | : strndup("abcd", i); 67 | CHECK_OUT_OF_MEMORY(p[i]); 68 | if (i == 3) 69 | free_sized(p[i], i /* strlen(p[i]) */ + 1); 70 | } 71 | #ifdef GC_REQUIRE_WCSDUP 72 | { 73 | static const wchar_t ws[] = { 'w', 0 }; 74 | 75 | p[0] = (char *)wcsdup(ws); 76 | CHECK_OUT_OF_MEMORY(p[0]); 77 | } 78 | #endif 79 | CHECK_LEAKS(); 80 | CHECK_LEAKS(); 81 | CHECK_LEAKS(); 82 | printf("SUCCEEDED\n"); 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /tests/middle.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Test at the boundary between small and large objects. 3 | * Inspired by a test case from Zoltan Varga. 4 | */ 5 | 6 | #ifdef HAVE_CONFIG_H 7 | # include "config.h" 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | #define NOT_GCBUILD 14 | #include "private/gc_priv.h" 15 | 16 | #undef rand 17 | static GC_RAND_STATE_T seed; 18 | #define rand() GC_RAND_NEXT(&seed) 19 | 20 | #define N_TESTS 32000 21 | 22 | /* Typical page size. */ 23 | #define ALLOC_SZ 4096 24 | 25 | #define CHECK_OUT_OF_MEMORY(p) \ 26 | do { \ 27 | if (NULL == (p)) { \ 28 | fprintf(stderr, "Out of memory\n"); \ 29 | exit(69); \ 30 | } \ 31 | } while (0) 32 | 33 | int 34 | main(void) 35 | { 36 | int i; 37 | 38 | GC_set_all_interior_pointers(0); 39 | GC_INIT(); 40 | if (GC_get_find_leak()) 41 | printf("This test program is not designed for leak detection mode\n"); 42 | 43 | for (i = 0; i < N_TESTS; ++i) { 44 | CHECK_OUT_OF_MEMORY(GC_malloc_atomic(ALLOC_SZ)); 45 | CHECK_OUT_OF_MEMORY(GC_malloc(ALLOC_SZ)); 46 | } 47 | 48 | /* Test delayed start of marker threads, if they are enabled. */ 49 | GC_start_mark_threads(); 50 | 51 | for (i = 0; i < N_TESTS; ++i) { 52 | CHECK_OUT_OF_MEMORY(GC_malloc_atomic(ALLOC_SZ / 2)); 53 | CHECK_OUT_OF_MEMORY(GC_malloc(ALLOC_SZ / 2)); 54 | } 55 | 56 | for (i = 0; i < N_TESTS; ++i) { 57 | CHECK_OUT_OF_MEMORY(GC_malloc_atomic((unsigned)rand() % ALLOC_SZ)); 58 | CHECK_OUT_OF_MEMORY(GC_malloc((unsigned)rand() % (ALLOC_SZ / 8))); 59 | } 60 | 61 | printf("Final heap size is %lu\n", (unsigned long)GC_get_heap_size()); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /tests/realloc.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "gc.h" 6 | 7 | #define COUNT 10000000 8 | 9 | #define CHECK_OUT_OF_MEMORY(p) \ 10 | do { \ 11 | if (NULL == (p)) { \ 12 | fprintf(stderr, "Out of memory\n"); \ 13 | exit(69); \ 14 | } \ 15 | } while (0) 16 | 17 | int 18 | main(void) 19 | { 20 | int i; 21 | unsigned long last_heap_size = 0; 22 | 23 | GC_INIT(); 24 | if (GC_get_find_leak()) 25 | printf("This test program is not designed for leak detection mode\n"); 26 | 27 | for (i = 0; i < COUNT; i++) { 28 | int **p = GC_NEW(int *); 29 | int *q; 30 | 31 | CHECK_OUT_OF_MEMORY(p); 32 | q = (int *)GC_MALLOC_ATOMIC(sizeof(int)); 33 | CHECK_OUT_OF_MEMORY(q); 34 | if (*p != NULL) { 35 | fprintf(stderr, "GC_malloc returned garbage (or NULL)\n"); 36 | exit(1); 37 | } 38 | 39 | *p = (int *)GC_REALLOC(q, (i % 8 != 0 ? 2 : 4) * sizeof(int)); 40 | CHECK_OUT_OF_MEMORY(*p); 41 | 42 | if (i % 10 == 0) { 43 | unsigned long heap_size = (unsigned long)GC_get_heap_size(); 44 | 45 | if (heap_size != last_heap_size) { 46 | printf("Heap size: %lu\n", heap_size); 47 | last_heap_size = heap_size; 48 | } 49 | } 50 | } 51 | printf("SUCCEEDED\n"); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /tests/smash.c: -------------------------------------------------------------------------------- 1 | /* Test that overwrite error detection works reasonably. */ 2 | 3 | #ifndef GC_DEBUG 4 | # define GC_DEBUG 5 | #endif 6 | 7 | #include "gc.h" 8 | 9 | #include 10 | #include 11 | 12 | #define COUNT 7000 13 | #define SIZE 40 14 | 15 | #define CHECK_OUT_OF_MEMORY(p) \ 16 | do { \ 17 | if (NULL == (p)) { \ 18 | fprintf(stderr, "Out of memory\n"); \ 19 | exit(69); \ 20 | } \ 21 | } while (0) 22 | 23 | char *A[COUNT]; 24 | 25 | char *volatile q; 26 | 27 | int 28 | main(void) 29 | { 30 | int i; 31 | char *p; 32 | 33 | GC_INIT(); 34 | for (i = 0; i < COUNT; ++i) { 35 | A[i] = p = (char *)GC_MALLOC(SIZE); 36 | CHECK_OUT_OF_MEMORY(p); 37 | if (i % 3000 == 0) { 38 | q = NULL; 39 | GC_gcollect(); 40 | } else if (i % 5678 == 0) { 41 | /* Write a byte past the end of the allocated object */ 42 | /* but not beyond the last word of the object's memory. */ 43 | /* A volatile intermediate pointer variable is used to */ 44 | /* avoid a compiler complain of out-of-bounds access. */ 45 | q = &p[(SIZE + i / 2000) /* 42 */]; 46 | *q = 42; 47 | } 48 | } 49 | printf("SUCCEEDED\n"); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /tests/staticroots.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #ifndef GC_DEBUG 6 | # define GC_DEBUG 7 | #endif 8 | 9 | #include "gc.h" 10 | #include "gc/gc_backptr.h" 11 | 12 | #ifndef GC_TEST_IMPORT_API 13 | # define GC_TEST_IMPORT_API extern 14 | #endif 15 | 16 | /* Should match that in staticroots_lib.c. */ 17 | struct treenode { 18 | struct treenode *x; 19 | struct treenode *y; 20 | }; 21 | 22 | struct treenode *root[10] = { NULL }; 23 | 24 | /* Same as "root" variable but initialized to some non-zero value (to */ 25 | /* be placed to .data section instead of .bss). */ 26 | struct treenode *root_nz[10] = { (struct treenode *)(GC_uintptr_t)1 }; 27 | 28 | /* Note: this is static intentionally. */ 29 | static char *staticroot; 30 | 31 | GC_TEST_IMPORT_API struct treenode *libsrl_mktree(int i); 32 | GC_TEST_IMPORT_API void *libsrl_init(void); 33 | GC_TEST_IMPORT_API struct treenode **libsrl_getpelem(int i, int j); 34 | 35 | GC_TEST_IMPORT_API struct treenode **libsrl_getpelem2(int i, int j); 36 | 37 | static void 38 | init_staticroot(void) 39 | { 40 | /* Intentionally put staticroot initialization in a function other */ 41 | /* than main to prevent CSA warning that staticroot variable can be */ 42 | /* changed to be a local one). */ 43 | staticroot = (char *)libsrl_init(); 44 | } 45 | 46 | int 47 | main(void) 48 | { 49 | int i, j; 50 | 51 | #ifdef STATICROOTSLIB_INIT_IN_MAIN 52 | GC_INIT(); 53 | #endif 54 | init_staticroot(); 55 | if (GC_get_find_leak()) 56 | printf("This test program is not designed for leak detection mode\n"); 57 | if (NULL == staticroot) { 58 | fprintf(stderr, "GC_malloc returned NULL\n"); 59 | return 2; 60 | } 61 | memset(staticroot, 0x42, sizeof(struct treenode)); 62 | GC_gcollect(); 63 | for (j = 0; j < 4; j++) { 64 | for (i = 0; i < (int)(sizeof(root) / sizeof(root[0])); ++i) { 65 | #ifdef STATICROOTSLIB2 66 | *libsrl_getpelem2(i, j) = libsrl_mktree(12); 67 | #endif 68 | *libsrl_getpelem(i, j) = libsrl_mktree(12); 69 | ((j & 1) != 0 ? root_nz : root)[i] = libsrl_mktree(12); 70 | GC_gcollect(); 71 | } 72 | for (i = 0; i < (int)sizeof(struct treenode); ++i) { 73 | if (staticroot[i] != 0x42) { 74 | fprintf(stderr, "Memory check failed\n"); 75 | return 1; 76 | } 77 | } 78 | } 79 | printf("SUCCEEDED\n"); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /tests/staticroots_lib.c: -------------------------------------------------------------------------------- 1 | 2 | /* This test file is intended to be compiled into a DLL. */ 3 | 4 | #include 5 | #include 6 | 7 | #ifndef GC_DEBUG 8 | # define GC_DEBUG 9 | #endif 10 | 11 | #include "gc.h" 12 | 13 | #ifndef GC_TEST_EXPORT_API 14 | # if defined(GC_VISIBILITY_HIDDEN_SET) && !defined(__CEGCC__) \ 15 | && !defined(__CYGWIN__) && !defined(__MINGW32__) 16 | # define GC_TEST_EXPORT_API \ 17 | extern __attribute__((__visibility__("default"))) 18 | # else 19 | # define GC_TEST_EXPORT_API extern 20 | # endif 21 | #endif 22 | 23 | #define CHECK_OUT_OF_MEMORY(p) \ 24 | do { \ 25 | if (NULL == (p)) { \ 26 | fprintf(stderr, "Out of memory\n"); \ 27 | exit(69); \ 28 | } \ 29 | } while (0) 30 | 31 | struct treenode { 32 | struct treenode *x; 33 | struct treenode *y; 34 | }; 35 | 36 | static struct treenode *root[10] = { 0 }; 37 | static struct treenode *root_nz[10] = { (struct treenode *)(GC_uintptr_t)2 }; 38 | 39 | /* Declare it to avoid "no previous prototype" clang warning. */ 40 | GC_TEST_EXPORT_API struct treenode **libsrl_getpelem(int i, int j); 41 | 42 | #ifdef STATICROOTSLIB2 43 | # define libsrl_getpelem libsrl_getpelem2 44 | #else 45 | 46 | GC_TEST_EXPORT_API struct treenode *libsrl_mktree(int i); 47 | GC_TEST_EXPORT_API void *libsrl_init(void); 48 | 49 | GC_TEST_EXPORT_API struct treenode * 50 | libsrl_mktree(int i) 51 | { 52 | struct treenode *r = GC_NEW(struct treenode); 53 | struct treenode *x, *y; 54 | 55 | CHECK_OUT_OF_MEMORY(r); 56 | if (0 == i) 57 | return 0; 58 | if (1 == i) { 59 | r = (struct treenode *)GC_MALLOC_ATOMIC(sizeof(struct treenode)); 60 | CHECK_OUT_OF_MEMORY(r); 61 | } 62 | x = libsrl_mktree(i - 1); 63 | y = libsrl_mktree(i - 1); 64 | r->x = x; 65 | r->y = y; 66 | if (i != 1) { 67 | GC_END_STUBBORN_CHANGE(r); 68 | GC_reachable_here(x); 69 | GC_reachable_here(y); 70 | } 71 | return r; 72 | } 73 | 74 | GC_TEST_EXPORT_API void * 75 | libsrl_init(void) 76 | { 77 | # ifdef TEST_MANUAL_VDB 78 | GC_set_manual_vdb_allowed(1); 79 | # endif 80 | # ifndef STATICROOTSLIB_INIT_IN_MAIN 81 | GC_INIT(); 82 | # endif 83 | # ifndef NO_INCREMENTAL 84 | GC_enable_incremental(); 85 | # endif 86 | return GC_MALLOC(sizeof(struct treenode)); 87 | } 88 | 89 | #endif /* !STATICROOTSLIB2 */ 90 | 91 | GC_TEST_EXPORT_API struct treenode ** 92 | libsrl_getpelem(int i, int j) 93 | { 94 | #if defined(CPPCHECK) 95 | struct treenode node = { NULL, NULL }; 96 | 97 | GC_noop1_ptr(node.x); 98 | GC_noop1_ptr(node.y); 99 | #endif 100 | return &((j & 1) != 0 ? root_nz : root)[i]; 101 | } 102 | -------------------------------------------------------------------------------- /tests/subthreadcreate.c: -------------------------------------------------------------------------------- 1 | 2 | #ifdef HAVE_CONFIG_H 3 | /* For GC_THREADS and PARALLEL_MARK. */ 4 | # include "config.h" 5 | #endif 6 | 7 | #ifdef GC_THREADS 8 | # undef GC_NO_THREAD_REDIRECTS 9 | # include "gc.h" 10 | 11 | # ifdef PARALLEL_MARK 12 | # define AO_REQUIRE_CAS 13 | # if !defined(__GNUC__) && !defined(AO_ASSUME_WINDOWS98) 14 | # define AO_ASSUME_WINDOWS98 15 | # endif 16 | # endif 17 | # include "private/gc_atomic_ops.h" 18 | #endif /* GC_THREADS */ 19 | 20 | #include 21 | 22 | #ifdef AO_HAVE_fetch_and_add1 23 | 24 | # ifdef GC_PTHREADS 25 | # include /* for EAGAIN */ 26 | # include 27 | # include 28 | # else 29 | # ifndef WIN32_LEAN_AND_MEAN 30 | # define WIN32_LEAN_AND_MEAN 1 31 | # endif 32 | # define NOSERVICE 33 | # include 34 | # endif /* !GC_PTHREADS */ 35 | 36 | # include 37 | 38 | # ifndef NTHREADS 39 | # define NTHREADS 5 40 | # endif 41 | 42 | /* Number of threads to create. */ 43 | # define NTHREADS_INNER (NTHREADS * 6) 44 | 45 | # ifndef MAX_SUBTHREAD_DEPTH 46 | # define MAX_ALIVE_THREAD_COUNT 55 47 | # define MAX_SUBTHREAD_DEPTH 7 48 | # define MAX_SUBTHREAD_COUNT 200 49 | # endif 50 | 51 | # ifndef DECAY_NUMER 52 | # define DECAY_NUMER 15 53 | # define DECAY_DENOM 16 54 | # endif 55 | 56 | volatile AO_t thread_created_cnt = 0; 57 | volatile AO_t thread_ended_cnt = 0; 58 | 59 | # ifdef GC_PTHREADS 60 | static void * 61 | entry(void *arg) 62 | # else 63 | static DWORD WINAPI 64 | entry(LPVOID arg) 65 | # endif 66 | { 67 | int thread_num = (int)AO_fetch_and_add1(&thread_created_cnt); 68 | GC_word my_depth = (GC_word)(GC_uintptr_t)arg + 1; 69 | 70 | if (my_depth <= MAX_SUBTHREAD_DEPTH && thread_num < MAX_SUBTHREAD_COUNT 71 | && (thread_num % DECAY_DENOM) < DECAY_NUMER 72 | && thread_num - (int)AO_load(&thread_ended_cnt) 73 | <= MAX_ALIVE_THREAD_COUNT) { 74 | # ifdef GC_PTHREADS 75 | int err; 76 | pthread_t th; 77 | 78 | err = pthread_create(&th, NULL, entry, (void *)(GC_uintptr_t)my_depth); 79 | if (err != 0) { 80 | fprintf(stderr, "Thread #%d creation failed from other thread: %s\n", 81 | thread_num, strerror(err)); 82 | if (err != EAGAIN) 83 | exit(2); 84 | } else { 85 | err = pthread_detach(th); 86 | if (err != 0) { 87 | fprintf(stderr, "Thread #%d detach failed: %s\n", thread_num, 88 | strerror(err)); 89 | exit(2); 90 | } 91 | } 92 | # else 93 | HANDLE th; 94 | DWORD thread_id; 95 | 96 | th = CreateThread(NULL, 0, entry, (LPVOID)my_depth, 0, &thread_id); 97 | if (th == NULL) { 98 | fprintf(stderr, "Thread #%d creation failed, errcode= %d\n", thread_num, 99 | (int)GetLastError()); 100 | exit(2); 101 | } 102 | CloseHandle(th); 103 | # endif 104 | } 105 | 106 | (void)AO_fetch_and_add1(&thread_ended_cnt); 107 | return 0; 108 | } 109 | 110 | int 111 | main(void) 112 | { 113 | # if NTHREADS > 0 114 | int i, n; 115 | # ifdef GC_PTHREADS 116 | int err; 117 | pthread_t th[NTHREADS_INNER]; 118 | # else 119 | HANDLE th[NTHREADS_INNER]; 120 | # endif 121 | int th_nums[NTHREADS_INNER]; 122 | 123 | GC_INIT(); 124 | for (i = 0; i < NTHREADS_INNER; ++i) { 125 | th_nums[i] = (int)AO_fetch_and_add1(&thread_created_cnt); 126 | # ifdef GC_PTHREADS 127 | err = pthread_create(&th[i], NULL, entry, 0); 128 | if (err != 0) { 129 | fprintf(stderr, "Thread #%d creation failed: %s\n", th_nums[i], 130 | strerror(err)); 131 | if (i > 0 && EAGAIN == err) 132 | break; 133 | exit(1); 134 | } 135 | # else 136 | { 137 | DWORD thread_id; 138 | 139 | th[i] = CreateThread(NULL, 0, entry, 0, 0, &thread_id); 140 | } 141 | if (th[i] == NULL) { 142 | fprintf(stderr, "Thread #%d creation failed, errcode= %d\n", th_nums[i], 143 | (int)GetLastError()); 144 | exit(1); 145 | } 146 | # endif 147 | } 148 | n = i; 149 | for (i = 0; i < n; ++i) { 150 | # ifdef GC_PTHREADS 151 | void *res; 152 | 153 | err = pthread_join(th[i], &res); 154 | if (err != 0) { 155 | fprintf(stderr, "Thread #%d join failed: %s\n", th_nums[i], 156 | strerror(err)); 157 | exit(1); 158 | } 159 | # else 160 | if (WaitForSingleObject(th[i], INFINITE) != WAIT_OBJECT_0) { 161 | fprintf(stderr, "Thread #%d join failed, errcode= %d\n", th_nums[i], 162 | (int)GetLastError()); 163 | CloseHandle(th[i]); 164 | exit(1); 165 | } 166 | CloseHandle(th[i]); 167 | # endif 168 | } 169 | # else 170 | (void)entry(NULL); 171 | # endif 172 | printf("Created %d threads (%d ended)\n", (int)AO_load(&thread_created_cnt), 173 | (int)AO_load(&thread_ended_cnt)); 174 | return 0; 175 | } 176 | 177 | #else 178 | 179 | int 180 | main(void) 181 | { 182 | printf("test skipped\n"); 183 | return 0; 184 | } 185 | 186 | #endif /* !AO_HAVE_fetch_and_add1 */ 187 | -------------------------------------------------------------------------------- /tests/threadkey.c: -------------------------------------------------------------------------------- 1 | 2 | #ifdef HAVE_CONFIG_H 3 | # include "config.h" 4 | #endif 5 | 6 | #ifndef GC_THREADS 7 | # define GC_THREADS 8 | #endif 9 | 10 | #define GC_NO_THREAD_REDIRECTS 1 11 | 12 | #include "gc.h" 13 | 14 | #include 15 | #include 16 | 17 | #if (!defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS) \ 18 | || defined(__native_client__)) \ 19 | && !defined(SKIP_THREADKEY_TEST) 20 | /* FIXME: Skip this test on Solaris for now. The test may fail on */ 21 | /* other targets as well. Currently, tested only on Linux, Cygwin */ 22 | /* and Darwin. */ 23 | # define SKIP_THREADKEY_TEST 24 | #endif 25 | 26 | #ifdef SKIP_THREADKEY_TEST 27 | 28 | int 29 | main(void) 30 | { 31 | printf("test skipped\n"); 32 | return 0; 33 | } 34 | 35 | #else 36 | 37 | # include /* for EAGAIN */ 38 | # include 39 | # include 40 | 41 | pthread_key_t key; 42 | 43 | /* TODO: use pthread_once_t on Solaris. */ 44 | pthread_once_t key_once = PTHREAD_ONCE_INIT; 45 | 46 | static void * 47 | entry(void *arg) 48 | { 49 | pthread_setspecific(key, 50 | (void *)GC_HIDE_NZ_POINTER(GC_STRDUP("hello, world"))); 51 | return arg; 52 | } 53 | 54 | static void *GC_CALLBACK 55 | on_thread_exit_inner(struct GC_stack_base *sb, void *arg) 56 | { 57 | int res = GC_register_my_thread(sb); 58 | pthread_t t; 59 | /* This is used to suppress a warning about unchecked */ 60 | /* pthread_create() result. */ 61 | int creation_res; 62 | pthread_attr_t attr; 63 | 64 | if (pthread_attr_init(&attr) != 0 65 | || pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) { 66 | fprintf(stderr, "Thread attribute init or setdetachstate failed\n"); 67 | exit(2); 68 | } 69 | creation_res = GC_pthread_create(&t, &attr, entry, NULL); 70 | (void)pthread_attr_destroy(&attr); 71 | if (res == GC_SUCCESS) 72 | GC_unregister_my_thread(); 73 | 74 | # if defined(CPPCHECK) 75 | GC_noop1_ptr(sb); 76 | GC_noop1_ptr(arg); 77 | # endif 78 | return arg ? (void *)(GC_uintptr_t)creation_res : 0; 79 | } 80 | 81 | static void 82 | on_thread_exit(void *v) 83 | { 84 | (void)GC_call_with_stack_base(on_thread_exit_inner, v); 85 | } 86 | 87 | static void 88 | make_key(void) 89 | { 90 | pthread_key_create(&key, on_thread_exit); 91 | } 92 | 93 | # ifndef NTHREADS 94 | # define NTHREADS 5 95 | # endif 96 | 97 | /* Number of threads to create. */ 98 | # define NTHREADS_INNER (NTHREADS * 6) 99 | 100 | int 101 | main(void) 102 | { 103 | int i; 104 | 105 | GC_INIT(); 106 | if (GC_get_find_leak()) 107 | printf("This test program is not designed for leak detection mode\n"); 108 | /* TODO: call make_key() instead on Solaris. */ 109 | pthread_once(&key_once, make_key); 110 | 111 | for (i = 0; i < NTHREADS_INNER; i++) { 112 | pthread_t t; 113 | void *res; 114 | int err = GC_pthread_create(&t, NULL, entry, NULL); 115 | 116 | if (err != 0) { 117 | fprintf(stderr, "Thread #%d creation failed: %s\n", i, strerror(err)); 118 | if (i > 0 && EAGAIN == err) 119 | break; 120 | exit(2); 121 | } 122 | 123 | if ((i & 1) != 0) { 124 | err = GC_pthread_join(t, &res); 125 | if (err != 0) { 126 | fprintf(stderr, "Thread #%d join failed: %s\n", i, strerror(err)); 127 | exit(2); 128 | } 129 | } else { 130 | err = GC_pthread_detach(t); 131 | if (err != 0) { 132 | fprintf(stderr, "Thread #%d detach failed: %s\n", i, strerror(err)); 133 | exit(2); 134 | } 135 | } 136 | } 137 | printf("SUCCEEDED\n"); 138 | return 0; 139 | } 140 | 141 | #endif /* !SKIP_THREADKEY_TEST */ 142 | -------------------------------------------------------------------------------- /tests/threadleak.c: -------------------------------------------------------------------------------- 1 | 2 | #ifdef HAVE_CONFIG_H 3 | # include "config.h" 4 | #endif 5 | 6 | #ifndef GC_THREADS 7 | # define GC_THREADS 8 | #endif 9 | 10 | #undef GC_NO_THREAD_REDIRECTS 11 | #include "gc/leak_detector.h" 12 | 13 | #ifdef GC_PTHREADS 14 | # include /* for EAGAIN */ 15 | # include 16 | # include 17 | #else 18 | # ifndef WIN32_LEAN_AND_MEAN 19 | # define WIN32_LEAN_AND_MEAN 1 20 | # endif 21 | # define NOSERVICE 22 | # include 23 | #endif /* !GC_PTHREADS */ 24 | 25 | #include 26 | #include 27 | 28 | #define N_TESTS 100 29 | 30 | #define CHECK_OUT_OF_MEMORY(p) \ 31 | do { \ 32 | if (NULL == (p)) { \ 33 | fprintf(stderr, "Out of memory\n"); \ 34 | exit(69); \ 35 | } \ 36 | } while (0) 37 | 38 | #ifdef GC_PTHREADS 39 | static void * 40 | test(void *arg) 41 | #else 42 | static DWORD WINAPI 43 | test(LPVOID arg) 44 | #endif 45 | { 46 | int *p[N_TESTS]; 47 | int i; 48 | for (i = 0; i < N_TESTS; ++i) { 49 | p[i] = (int *)malloc(sizeof(int) + i); 50 | CHECK_OUT_OF_MEMORY(p[i]); 51 | } 52 | CHECK_LEAKS(); 53 | for (i = 1; i < N_TESTS; ++i) { 54 | free(p[i]); 55 | } 56 | #ifdef GC_PTHREADS 57 | return arg; 58 | #else 59 | return (DWORD)(GC_uintptr_t)arg; 60 | #endif 61 | } 62 | 63 | #ifndef NTHREADS 64 | # define NTHREADS 5 65 | #endif 66 | 67 | int 68 | main(void) 69 | { 70 | #if NTHREADS > 0 71 | int i, n; 72 | # ifdef GC_PTHREADS 73 | pthread_t t[NTHREADS]; 74 | # else 75 | HANDLE t[NTHREADS]; 76 | # endif 77 | #endif 78 | 79 | #ifndef NO_FIND_LEAK 80 | /* Just in case the code is compiled without FIND_LEAK defined. */ 81 | GC_set_find_leak(1); 82 | #endif 83 | GC_INIT(); 84 | /* This is optional if pthread_create() redirected. */ 85 | GC_allow_register_threads(); 86 | 87 | #if NTHREADS > 0 88 | for (i = 0; i < NTHREADS; ++i) { 89 | # ifdef GC_PTHREADS 90 | int err = pthread_create(t + i, 0, test, 0); 91 | 92 | if (err != 0) { 93 | fprintf(stderr, "Thread #%d creation failed: %s\n", i, strerror(err)); 94 | if (i > 1 && EAGAIN == err) 95 | break; 96 | exit(2); 97 | } 98 | # else 99 | DWORD thread_id; 100 | 101 | t[i] = CreateThread(NULL, 0, test, 0, 0, &thread_id); 102 | if (NULL == t[i]) { 103 | fprintf(stderr, "Thread #%d creation failed, errcode= %d\n", i, 104 | (int)GetLastError()); 105 | exit(2); 106 | } 107 | # endif 108 | } 109 | n = i; 110 | for (i = 0; i < n; ++i) { 111 | int err; 112 | 113 | # ifdef GC_PTHREADS 114 | err = pthread_join(t[i], 0); 115 | # else 116 | err = WaitForSingleObject(t[i], INFINITE) == WAIT_OBJECT_0 117 | ? 0 118 | : (int)GetLastError(); 119 | # endif 120 | if (err != 0) { 121 | fprintf(stderr, "Thread #%d join failed, errcode= %d\n", i, err); 122 | exit(2); 123 | } 124 | } 125 | #else 126 | (void)test(NULL); 127 | #endif 128 | 129 | CHECK_LEAKS(); 130 | CHECK_LEAKS(); 131 | CHECK_LEAKS(); 132 | printf("SUCCEEDED\n"); 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /tests/trace.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #ifndef GC_DEBUG 6 | # define GC_DEBUG 7 | #endif 8 | 9 | #include "gc.h" 10 | #include "gc/gc_backptr.h" 11 | 12 | #define CHECK_OUT_OF_MEMORY(p) \ 13 | do { \ 14 | if (NULL == (p)) { \ 15 | fprintf(stderr, "Out of memory\n"); \ 16 | exit(69); \ 17 | } \ 18 | } while (0) 19 | 20 | struct treenode { 21 | struct treenode *x; 22 | struct treenode *y; 23 | }; 24 | 25 | static struct treenode *root[10]; 26 | 27 | static struct treenode * 28 | mktree(int i) 29 | { 30 | struct treenode *r = GC_NEW(struct treenode); 31 | struct treenode *x, *y; 32 | 33 | CHECK_OUT_OF_MEMORY(r); 34 | if (0 == i) 35 | return NULL; 36 | if (1 == i) { 37 | r = (struct treenode *)GC_MALLOC_ATOMIC(sizeof(struct treenode)); 38 | CHECK_OUT_OF_MEMORY(r); 39 | } 40 | x = mktree(i - 1); 41 | y = mktree(i - 1); 42 | r->x = x; 43 | r->y = y; 44 | if (i != 1) { 45 | GC_END_STUBBORN_CHANGE(r); 46 | GC_reachable_here(x); 47 | GC_reachable_here(y); 48 | } 49 | return r; 50 | } 51 | 52 | int 53 | main(void) 54 | { 55 | int i; 56 | 57 | GC_INIT(); 58 | if (GC_get_find_leak()) 59 | printf("This test program is not designed for leak detection mode\n"); 60 | for (i = 0; i < 10; ++i) { 61 | root[i] = mktree(12); 62 | } 63 | GC_generate_random_backtrace(); 64 | GC_generate_random_backtrace(); 65 | GC_generate_random_backtrace(); 66 | GC_generate_random_backtrace(); 67 | printf("SUCCEEDED\n"); 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /tests/tree.cc: -------------------------------------------------------------------------------- 1 | 2 | // The program tests part of the C++ functionality provided by gc_cpp.h (and 3 | // gctba library) by creating balanced trees of various depth and arity. 4 | 5 | #ifdef HAVE_CONFIG_H 6 | # include "config.h" 7 | #endif 8 | 9 | #undef GC_BUILD 10 | 11 | #define GC_DONT_INCL_WINDOWS_H 12 | #define GC_NAMESPACE 13 | #include "gc_cpp.h" 14 | 15 | #include 16 | #include 17 | 18 | #define NO_GC GC_NS_QUALIFY(NoGC) 19 | #define PTRFREE_GC GC_NS_QUALIFY(PointerFreeGC) 20 | #define USE_GC GC_NS_QUALIFY(UseGC) 21 | 22 | #ifdef GC_ATOMIC_UNCOLLECTABLE 23 | # define PTRFREE_NOGC GC_NS_QUALIFY(PointerFreeNoGC) 24 | #endif 25 | 26 | class Tree; 27 | 28 | class PTree : public GC_NS_QUALIFY(gc) 29 | { 30 | public: 31 | Tree *ptr; 32 | }; 33 | 34 | class Tree : public GC_NS_QUALIFY(gc) 35 | { 36 | public: 37 | GC_ATTR_EXPLICIT 38 | Tree(int a, int d, bool uncollectable); 39 | ~Tree(); 40 | void verify(); 41 | 42 | private: 43 | void verify(int a, int d); 44 | void verify_node(int a, int d); 45 | int arity, depth; 46 | PTree *m_nodes; 47 | }; 48 | 49 | Tree::Tree(int a, int d, bool uncollectable) : arity(a), depth(d) 50 | { 51 | PTree *nodes = 0; 52 | if (depth > 0) { 53 | #ifdef GC_OPERATOR_NEW_ARRAY 54 | nodes = 55 | # ifndef CPPCHECK 56 | uncollectable ? new (NO_GC) PTree[arity] : 57 | # endif 58 | new (USE_GC) PTree[arity]; 59 | #else 60 | nodes = reinterpret_cast( 61 | uncollectable 62 | ? GC_MALLOC_UNCOLLECTABLE(sizeof(PTree) * (unsigned)arity) 63 | : GC_MALLOC(sizeof(PTree) * (unsigned)arity)); 64 | GC_OP_NEW_OOM_CHECK(nodes); 65 | #endif 66 | for (int i = 0; i < arity; i++) { 67 | Tree const *pnode 68 | = depth > 1 69 | ? (uncollectable ? new (NO_GC) Tree(arity, depth - 1, true) 70 | : new (USE_GC) Tree(arity, depth - 1, false)) 71 | : 72 | #ifdef GC_ATOMIC_UNCOLLECTABLE 73 | uncollectable ? new (PTRFREE_NOGC) Tree(arity, 0, true) 74 | : 75 | #endif 76 | new (PTRFREE_GC) Tree(arity, 0, uncollectable); 77 | GC_PTR_STORE_AND_DIRTY(&nodes[i].ptr, pnode); 78 | } 79 | } 80 | this->m_nodes = nodes; 81 | GC_END_STUBBORN_CHANGE(this); 82 | GC_reachable_here(nodes); 83 | } 84 | 85 | Tree::~Tree() 86 | { 87 | if (depth > 0) { 88 | for (int i = 0; i < arity; i++) { 89 | delete m_nodes[i].ptr; 90 | } 91 | #ifdef GC_OPERATOR_NEW_ARRAY 92 | delete[] m_nodes; 93 | #else 94 | GC_FREE(m_nodes); 95 | #endif 96 | } 97 | } 98 | 99 | void 100 | Tree::verify() 101 | { 102 | verify(arity, depth); 103 | } 104 | 105 | void 106 | Tree::verify_node(int a, int d) 107 | { 108 | if (a != arity || d != depth) { 109 | fprintf(stderr, "Wrong stored arity or depth! arity=%d, depth=%d\n", arity, 110 | depth); 111 | exit(1); 112 | } 113 | if (0 == depth) { 114 | if (m_nodes != 0) { 115 | fprintf(stderr, "Found non-empty node!\n"); 116 | exit(1); 117 | } 118 | } else if (0 == m_nodes) { 119 | fprintf(stderr, "Found empty node! depth=%d\n", depth); 120 | exit(1); 121 | } 122 | } 123 | 124 | void 125 | Tree::verify(int a, int d) 126 | { 127 | verify_node(a, d); 128 | if (0 == depth) 129 | return; 130 | for (int i = 0; i < arity; i++) { 131 | m_nodes[i].ptr->verify(a, d - 1); 132 | } 133 | } 134 | 135 | #ifndef MAX_ARITY 136 | # define MAX_ARITY 5 137 | #endif 138 | 139 | #ifndef MAX_DEPTH 140 | # define MAX_DEPTH 9 141 | #endif 142 | 143 | #ifndef DEL_EVERY_N_TREE 144 | # define DEL_EVERY_N_TREE 7 145 | #endif 146 | 147 | static void 148 | create_trees(bool is_find_leak, bool uncollectable) 149 | { 150 | int trees_cnt = 0; 151 | for (int arity = 2; arity <= MAX_ARITY; arity++) { 152 | for (int depth = 1; depth <= MAX_DEPTH; depth++) { 153 | Tree *tree = new (USE_GC) Tree(arity, depth, uncollectable); 154 | tree->verify(); 155 | if (is_find_leak || uncollectable || ++trees_cnt % DEL_EVERY_N_TREE == 0) 156 | delete tree; 157 | } 158 | } 159 | } 160 | 161 | int 162 | main(void) 163 | { 164 | #ifdef TEST_MANUAL_VDB 165 | GC_set_manual_vdb_allowed(1); 166 | #endif 167 | #ifndef CPPCHECK 168 | GC_INIT(); 169 | #endif 170 | bool is_find_leak = static_cast(GC_get_find_leak()); 171 | #ifndef NO_INCREMENTAL 172 | GC_enable_incremental(); 173 | #endif 174 | Tree *keep_tree = new (USE_GC) Tree(MAX_ARITY, MAX_DEPTH, false); 175 | keep_tree->verify(); 176 | create_trees(is_find_leak, false); 177 | create_trees(is_find_leak, true); 178 | keep_tree->verify(); // recheck 179 | if (is_find_leak) 180 | delete keep_tree; 181 | printf("SUCCEEDED\n"); 182 | return 0; 183 | } 184 | -------------------------------------------------------------------------------- /tools/callprocs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | GC_DEBUG=1 3 | export GC_DEBUG 4 | $* 2>&1 | awk '{print "0x3e=c\""$0"\""};/^\t##PC##=/ {if ($2 != 0) {print $2"?i"}}' | adb $1 | sed "s/^ >/>/" 5 | -------------------------------------------------------------------------------- /tools/if_mach.c: -------------------------------------------------------------------------------- 1 | /* Conditionally execute a command based on machine and OS from gcconfig.h */ 2 | 3 | #define NOT_GCBUILD 4 | #include "private/gc_priv.h" 5 | 6 | #include 7 | #include 8 | 9 | #ifdef __cplusplus 10 | # define EXECV_ARGV_T char ** 11 | #else 12 | /* The 2nd argument of execvp() prototype may be either char**, or */ 13 | /* char* const*, or const char* const*. */ 14 | # define EXECV_ARGV_T void * 15 | #endif 16 | 17 | int 18 | main(int argc, char **argv) 19 | { 20 | if (argc < 4) 21 | goto Usage; 22 | if (strcmp(MACH_TYPE, argv[1]) != 0) 23 | return 0; 24 | if (strlen(OS_TYPE) > 0 && strlen(argv[2]) > 0 25 | && strcmp(OS_TYPE, argv[2]) != 0) 26 | return 0; 27 | fprintf(stderr, "^^^^Starting command^^^^\n"); 28 | fflush(stdout); 29 | execvp(TRUSTED_STRING(argv[3]), (EXECV_ARGV_T)(argv + 3)); 30 | perror("Couldn't execute"); 31 | 32 | Usage: 33 | fprintf(stderr, "Usage: %s mach_type os_type command\n", argv[0]); 34 | fprintf(stderr, "Currently mach_type = %s, os_type = %s\n", MACH_TYPE, 35 | OS_TYPE); 36 | return 1; 37 | } 38 | -------------------------------------------------------------------------------- /tools/if_not_there.c: -------------------------------------------------------------------------------- 1 | /* Conditionally execute the command argv[2] based if the file argv[1] */ 2 | /* does not exist. If the command is omitted (and the file does not */ 3 | /* exist) then just exit with a non-zero code. */ 4 | 5 | #define NOT_GCBUILD 6 | #include "private/gc_priv.h" 7 | 8 | #include 9 | 10 | #ifdef __DJGPP__ 11 | # include 12 | #endif 13 | 14 | #ifdef __cplusplus 15 | # define EXECV_ARGV_T char ** 16 | #else 17 | # define EXECV_ARGV_T void * /* see the comment in if_mach.c */ 18 | #endif 19 | 20 | int 21 | main(int argc, char **argv) 22 | { 23 | FILE *f; 24 | #ifdef __DJGPP__ 25 | DIR *d; 26 | #endif /* __DJGPP__ */ 27 | const char *fname; 28 | 29 | if (argc < 2 || argc > 3) 30 | goto Usage; 31 | 32 | fname = TRUSTED_STRING(argv[1]); 33 | f = fopen(fname, "rb"); 34 | if (f != NULL) { 35 | fclose(f); 36 | return 0; 37 | } 38 | f = fopen(fname, "r"); 39 | if (f != NULL) { 40 | fclose(f); 41 | return 0; 42 | } 43 | #ifdef __DJGPP__ 44 | if ((d = opendir(fname)) != 0) { 45 | closedir(d); 46 | return 0; 47 | } 48 | #endif 49 | printf("^^^^Starting command^^^^\n"); 50 | fflush(stdout); 51 | if (argc == 2) { 52 | /* The file is missing, but no command is given. */ 53 | return 2; 54 | } 55 | 56 | execvp(TRUSTED_STRING(argv[2]), (EXECV_ARGV_T)(argv + 2)); 57 | exit(1); 58 | 59 | Usage: 60 | fprintf(stderr, "Usage: %s file_name [command]\n", argv[0]); 61 | return 1; 62 | } 63 | -------------------------------------------------------------------------------- /tools/setjmp_t.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. 3 | * 4 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 5 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 6 | * 7 | * Permission is hereby granted to use or copy this program 8 | * for any purpose, provided the above notices are retained on all copies. 9 | * Permission to modify the code and to distribute modified code is granted, 10 | * provided the above notices are retained, and a notice that the code was 11 | * modified is included with the above copyright notice. 12 | */ 13 | 14 | /* Check whether setjmp actually saves registers in jmp_buf. */ 15 | /* If it doesn't, the generic mark_regs code won't work. */ 16 | /* Compilers vary as to whether they will put x in a */ 17 | /* (callee-save) register without -O. The code is */ 18 | /* contrived such that any decent compiler should put x in */ 19 | /* a callee-save register with -O. Thus it is */ 20 | /* recommended that this be run optimized. (If the machine */ 21 | /* has no callee-save registers, then the generic code is */ 22 | /* safe, but this will not be noticed by this piece of */ 23 | /* code.) This test appears to be far from perfect. */ 24 | 25 | #define NOT_GCBUILD 26 | #include "private/gc_priv.h" 27 | 28 | #include 29 | 30 | #ifdef OS2 31 | # define INCL_DOSERRORS 32 | # define INCL_DOSFILEMGR 33 | # define INCL_DOSMISC 34 | # include 35 | 36 | /* Similar to that in os_dep.c but use fprintf() to report a failure. */ 37 | /* GETPAGESIZE() macro is defined to os2_getpagesize(). */ 38 | static int 39 | os2_getpagesize(void) 40 | { 41 | ULONG result[1]; 42 | 43 | if (DosQuerySysInfo(QSV_PAGE_SIZE, QSV_PAGE_SIZE, (void *)result, 44 | sizeof(ULONG)) 45 | != NO_ERROR) { 46 | fprintf(stderr, "DosQuerySysInfo failed\n"); 47 | result[0] = 4096; 48 | } 49 | return (int)result[0]; 50 | } 51 | 52 | #elif defined(ANY_MSWIN) 53 | static int 54 | win32_getpagesize(void) 55 | { 56 | SYSTEM_INFO sysinfo; 57 | GetSystemInfo(&sysinfo); 58 | return sysinfo.dwPageSize; 59 | } 60 | # define GETPAGESIZE() win32_getpagesize() 61 | #endif 62 | 63 | struct a_s { 64 | char a_a; 65 | char *a_b; 66 | } a; 67 | 68 | GC_ATTR_NOINLINE 69 | static word 70 | nested_sp(void) 71 | { 72 | volatile ptr_t sp; 73 | 74 | STORE_APPROX_SP_TO(sp); 75 | return ADDR(sp); 76 | } 77 | 78 | /* To prevent nested_sp inlining. */ 79 | word (*volatile nested_sp_fn)(void) = nested_sp; 80 | 81 | int g(int x); 82 | 83 | #if (defined(CPPCHECK) || !defined(__cplusplus)) && !defined(WASI) 84 | const char *a_str = "a"; 85 | #else 86 | # define a_str "a" 87 | #endif 88 | 89 | int 90 | main(void) 91 | { 92 | volatile ptr_t sp; 93 | unsigned ps = GETPAGESIZE(); 94 | #ifndef WASI 95 | JMP_BUF b; 96 | # if (!defined(__cplusplus) || __cplusplus < 201703L /* before c++17 */) \ 97 | && (!defined(__GNUC__) || defined(__OPTIMIZE__)) 98 | register 99 | # endif 100 | int x 101 | = (int)strlen(a_str); /* 1, slightly disguised */ 102 | static volatile int y = 0; 103 | #endif 104 | 105 | STORE_APPROX_SP_TO(sp); 106 | printf("This appears to be a %s running %s\n", MACH_TYPE, OS_TYPE); 107 | #if defined(CPPCHECK) 108 | (void)nested_sp(); /* to workaround a bug in cppcheck */ 109 | #endif 110 | if (nested_sp_fn() < ADDR(sp)) { 111 | printf("Stack appears to grow down, which is the default.\n"); 112 | printf("A good guess for STACKBOTTOM on this machine is 0x%lx.\n", 113 | ((unsigned long)ADDR(sp) + ps) & ~(unsigned long)(ps - 1)); 114 | } else { 115 | printf("Stack appears to grow up.\n"); 116 | printf("Define STACK_GROWS_UP in gc_priv.h\n"); 117 | /* Note: sp is rounded down. */ 118 | printf("A good guess for STACKBOTTOM on this machine is 0x%lx.\n", 119 | (unsigned long)ADDR(sp) & ~(unsigned long)(ps - 1)); 120 | } 121 | printf("Note that this may vary between machines of ostensibly\n"); 122 | printf("the same architecture (e.g. Sun 3/50s and 3/80s).\n"); 123 | printf("On many machines the value is not fixed.\n"); 124 | printf("A good guess for ALIGNMENT on this machine is %lu.\n", 125 | (unsigned long)(ADDR(&a.a_b) - ADDR(&a))); 126 | #ifndef WASI 127 | printf("The following is a very dubious test of one root marking" 128 | " strategy.\n"); 129 | printf("Results may not be accurate/useful:\n"); 130 | /* Encourage the compiler to keep x in a callee-save register */ 131 | x = 2 * x - 1; 132 | printf("\n"); 133 | x = 2 * x - 1; 134 | (void)SETJMP(b); 135 | if (y == 1) { 136 | if (x == 2) { 137 | printf("setjmp-based generic mark_regs code probably won't work.\n"); 138 | printf("But we rarely try that anymore. If you have getcontect()\n"); 139 | printf("this probably doesn't matter.\n"); 140 | } else if (x == 1) { 141 | printf("setjmp-based register marking code may work.\n"); 142 | } else { 143 | printf("Very strange setjmp implementation.\n"); 144 | } 145 | } 146 | y++; 147 | x = 2; 148 | if (y == 1) 149 | LONGJMP(b, 1); 150 | #endif 151 | printf("Some GC internal configuration stuff: \n"); 152 | printf("\tWORDSZ = %lu, ALIGNMENT = %d, GC_GRANULE_BYTES = %d\n", 153 | (unsigned long)CPP_WORDSZ, ALIGNMENT, GC_GRANULE_BYTES); 154 | printf("\tUsing one mark "); 155 | #ifdef USE_MARK_BYTES 156 | printf("byte"); 157 | #else 158 | printf("bit"); 159 | #endif 160 | #ifdef MARK_BIT_PER_OBJ 161 | printf(" per object.\n"); 162 | #else 163 | printf(" per granule.\n"); 164 | #endif 165 | #ifdef THREAD_LOCAL_ALLOC 166 | printf("Thread-local allocation enabled.\n"); 167 | #endif 168 | #ifdef PARALLEL_MARK 169 | printf("Parallel marking enabled.\n"); 170 | #endif 171 | #ifdef WASI 172 | (void)g(0); 173 | #else 174 | (void)g(x); 175 | #endif 176 | return 0; 177 | } 178 | 179 | int 180 | g(int x) 181 | { 182 | return x; 183 | } 184 | -------------------------------------------------------------------------------- /tools/threadlibs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1994 by Xerox Corporation. All rights reserved. 3 | * Copyright (c) 1996 by Silicon Graphics. All rights reserved. 4 | * Copyright (c) 1998 by Fergus Henderson. All rights reserved. 5 | * Copyright (c) 2000-2010 by Hewlett-Packard Development Company. 6 | * All rights reserved. 7 | * 8 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED 9 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 10 | * 11 | * Permission is hereby granted to use or copy this program 12 | * for any purpose, provided the above notices are retained on all copies. 13 | * Permission to modify the code and to distribute modified code is granted, 14 | * provided the above notices are retained, and a notice that the code was 15 | * modified is included with the above copyright notice. 16 | */ 17 | 18 | #ifdef HAVE_CONFIG_H 19 | # include "config.h" 20 | #endif 21 | 22 | #include "private/gcconfig.h" 23 | 24 | #include 25 | 26 | int 27 | main(void) 28 | { 29 | #if defined(GC_USE_LD_WRAP) 30 | printf("-Wl,--wrap -Wl,dlopen " 31 | "-Wl,--wrap -Wl,pthread_create -Wl,--wrap -Wl,pthread_join " 32 | "-Wl,--wrap -Wl,pthread_detach -Wl,--wrap -Wl,pthread_sigmask " 33 | "-Wl,--wrap -Wl,pthread_exit -Wl,--wrap -Wl,pthread_cancel\n"); 34 | #endif 35 | #ifdef THREADS 36 | # if defined(AIX) || defined(DARWIN) || defined(HURD) || defined(IRIX5) \ 37 | || (defined(LINUX) && !defined(HOST_ANDROID)) || defined(NACL) 38 | # ifdef GC_USE_DLOPEN_WRAP 39 | printf("-ldl -lpthread\n"); 40 | # else 41 | printf("-lpthread\n"); 42 | # endif 43 | # endif 44 | # ifdef OPENBSD 45 | printf("-pthread\n"); 46 | # endif 47 | # ifdef FREEBSD 48 | # ifdef GC_USE_DLOPEN_WRAP 49 | printf("-ldl "); 50 | # endif 51 | # if (__FREEBSD_version < 500000) 52 | printf("-pthread\n"); 53 | # else /* __FREEBSD__ || __DragonFly__ */ 54 | printf("-lpthread\n"); 55 | # endif 56 | # endif 57 | # if defined(HPUX) || defined(NETBSD) 58 | printf("-lpthread -lrt\n"); 59 | # endif 60 | # if defined(OSF1) 61 | /* DOB: must be -pthread, not -lpthread. */ 62 | printf("-pthread -lrt\n"); 63 | # endif 64 | # ifdef SOLARIS 65 | /* Is this right for recent versions? */ 66 | printf("-lthread -lposix4\n"); 67 | # endif 68 | # ifdef CYGWIN32 69 | printf("-lpthread\n"); 70 | # endif 71 | # if defined(GC_WIN32_PTHREADS) 72 | # ifdef PTW32_STATIC_LIB 73 | /* Assume suffix "s" for static version of the pthreads-win32 library. */ 74 | printf("-lpthreadGC2s -lws2_32\n"); 75 | # else 76 | printf("-lpthreadGC2\n"); 77 | # endif 78 | # endif 79 | # ifdef DGUX 80 | /* You need GCC 3.0.3 to build this one! */ 81 | /* DG/UX native gcc doesn't know what "-pthread" is. */ 82 | printf("-ldl -pthread\n"); 83 | # endif 84 | #endif 85 | return 0; 86 | } 87 | --------------------------------------------------------------------------------