summaryrefslogtreecommitdiff
path: root/tests
Commit message (Collapse)AuthorAgeFilesLines
* Fix GC_unregister_my_thread call before GC functions usageIvan Maidanski2023-05-141-5/+4
| | | | | | | | | | | | (fix of commit d7e3062a0) * tests/gctest.c [THREADS] (check_heap_stats): Do not call GC_unregister_my_thread(). * tests/gctest.c [GC_WIN32_THREADS && !GC_PTHREADS] (main): Call GC_unregister_my_thread() just before return. * tests/gctest.c [GC_PTHREADS && !PTW32_STATIC_LIB] (main): Likewise. * tests/gctest.c [GC_PTHREADS && !GC_NO_DLOPEN && !DARWIN && !GC_WIN32_THREADS] (main): Add comment for GC_dlopen argument.
* Allow single signal usage for both world suspend and resume in gctestIvan Maidanski2023-05-091-1/+5
| | | | | | | | | | By default, 2 distinct signals are used for suspend and resume of the world except for platforms where the signal context is not used. * tests/gctest.c [GC_PTHREADS] (main): Move GC_set_suspend_signal() call to be before GC_COND_INIT() one. * tests/gctest.c [GC_PTHREADS && TEST_REUSE_SIG_SUSPEND] (main): Pass value of GC_get_thr_restart_signal() to GC_set_suspend_signal().
* Add API to get total stopped-world marking timeIvan Maidanski2023-05-041-1/+2
| | | | | | | | | | | | | | | | | | | | New public function is GC_get_stopped_mark_total_time(). * alloc.c [!NO_CLOCK] (stopped_mark_total_time, stopped_mark_total_ns_frac): New static variable. * alloc.c [!NO_CLOCK] (GC_get_stopped_mark_total_time): New API function definition. * alloc.c [!NO_CLOCK] (GC_stopped_mark): Define start_time_valid, ns_frac_diff local variables; call GET_TIME() also if measure_performance; add TODO item (about code duplication); update stopped_mark_total_time and stopped_mark_total_ns_frac values. * alloc.c (GC_stopped_mark): Move logging of "Marking for collection" upper to be before GET_TIME(start_time). * include/gc/gc.h (GC_get_full_gc_total_time): Refine documentation. * include/gc/gc.h (GC_get_stopped_mark_total_time): New API prototype. * tests/gctest.c [!NO_CLOCK] (check_heap_stats): Call GC_get_stopped_mark_total_time() to report total stopped-world marking time.
* More clear message about total duration of full collections in gctestIvan Maidanski2023-05-031-9/+8
| | | | | | * tests/gctest.c [!NO_CLOCK] (check_heap_stats): Print value of GC_get_full_gc_total_time() on a standalone line (and with the proper message).
* Fix missing cast of typed calloc result in gctestIvan Maidanski2023-04-271-1/+2
| | | | | | | (fix of commit fef1ce084) * tests/gctest.c [!NO_TYPED_TEST && !GC_DEBUG] (typed_test): Cast result of GC_calloc_do_explicitly_typed() to GC_word* type.
* New API for more optimal usage of GC_calloc_explicitly_typedIvan Maidanski2023-04-261-3/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If the client needs to allocate many typed object arrays of same layout and amount of elements, then "calloc" descriptor could be created once (by GC_calloc_prepare_explicitly_typed) followed by multiple allocations (by GC_calloc_do_explicitly_typed) referring to the same descriptor. * include/gc/gc_typed.h (GC_CALLOC_TYPED_DESCR_WORDS): New macro. * include/gc/gc_typed.h (GC_calloc_typed_descr_s): New struct type. * include/gc/gc_typed.h (GC_calloc_prepare_explicitly_typed, GC_calloc_do_explicitly_typed): New function declaration. * tests/gctest.c [!NO_TYPED_TEST && !GC_DEBUG] (typed_test): Define ctd_l local variable; call GC_calloc_prepare_explicitly_typed() before loop; call GC_calloc_do_explicitly_typed() instead of GC_CALLOC_EXPLICITLY_TYPED(1001). * typd_mlc.c (GC_calloc_typed_descr_s.alloc_lb): Change type from size_t to word. * typd_mlc.c (GC_calloc_typed_descr_s.descr_type): Change type from int to signed_word. * typd_mlc.c (GC_calloc_prepare_explicitly_typed, GC_calloc_do_explicitly_typed): Change from STATIC to GC_API; add ctd_sz argument; check ctd_sz in assertion; add casts for alloc_lb field. * typd_mlc.c (GC_calloc_prepare_explicitly_typed): Add static assertion about size of GC_calloc_typed_descr_s and GC_CALLOC_TYPED_DESCR_WORDS; change return type from void to it. * typd_mlc.c (GC_calloc_explicitly_typed): Pass sizeof(ctd) to GC_calloc_prepare_explicitly_typed(), GC_calloc_do_explicitly_typed().
* Do incremental mark some in GC_collect_a_little even if GC is disabledIvan Maidanski2023-04-251-2/+1
| | | | | | | | | | | | | | | | | | | | Previous behavior was not documented but this API function did nothing in this case. That might cause a deadlock in the client code if the incremental collection was ongoing and the client called GC_collect_a_little() repeatedly (while the result is true). The new behavior, for the cause of disabled garbage collection, is to perform some amount of marking if the incremental collection is ongoing (but not stopping the world and, thus, not causing the memory reclaim to start), returning true if there is something more to mark. * alloc.c (GC_try_to_collect_inner): Change a loop to do-while one. * alloc.c (GC_collect_a_little): Do not check GC_dont_gc (i.e. call GC_collect_a_little_inner() unconditionally); add comment. * include/gc/gc.h (GC_collect_a_little): Update comment (describe the case when GC is disabled). * tests/gctest.c (check_heap_stats): Do not call GC_is_disabled(); add comment.
* Fix infinite loop in disable_gc_for_dlopen and GC_wait_for_gc_completionIvan Maidanski2023-04-251-1/+2
| | | | | | | | | | | | | Issue #257 (bdwgc). * alloc.c (GC_start_incremental_collection, GC_collect_a_little): Do not call GC_collect_a_little_inner() and ENTER/EXIT_GC() if GC_dont_gc. * alloc.c (GC_collect_a_little_inner): Call GC_mark_some() (in a loop) even if GC_dont_gc. * alloc.c (GC_allocobj): Do not call GC_collect_a_little_inner() if GC_dont_gc. * tests/gctest.c (check_heap_stats): Do not call GC_collect_a_little() (repeatedly) if GC_is_disabled().
* Allow gc_allocator<T> and friends to be defined in namespace boehmgcIvan Maidanski2023-04-171-0/+4
| | | | | | | | | | | | | | | | The client should define GC_NAMESPACE_ALLOCATOR before include gc_allocator.h to have all symbols of the latter to be defined in namespace boehmgc. * docs/README.macros (GC_NAMESPACE_ALLOCATOR): Document. * include/gc/gc_allocator.h [GC_NAMESPACE_ALLOCATOR] (GC_true_type, GC_false_type, GC_type_traits, GC_DECLARE_PTRFREE, GC_selective_alloc, gc_allocator, gc_allocator_ignore_off_page, traceable_allocator): Define symbols (all) in boehmgc namespace. * tests/cpp.cc (GC_NAMESPACE_ALLOCATOR): Define macro (before include gc_allocator.h). * tests/cpp.cc (gc_allocator, gc_allocator_ignore_off_page, traceable_allocator): Using the symbol of namespace boehmgc.
* Redirect _aligned_malloc/free() in leak_detector.hIvan Maidanski2023-04-171-0/+7
| | | | | | | | | | * include/gc/leak_detector.h (_aligned_malloc, _aligned_free): Redefine macro. * include/gc/leak_detector.h (_aligned_free): Use GC_base (because GC_memalign might return a pointer inside the allocated object to ensure the requested alignment). * tests/leak.c (main): Call _aligned_malloc() and _aligned_free(); print error and exit in case of _aligned_malloc() failure.
* Increment allocated objects count after GC_GCJ_MALLOC() in gctestIvan Maidanski2023-03-241-0/+1
| | | | | * tests/gctest.c [GC_GCJ_SUPPORT] (gcj_cons): Increment collectable_count.
* Avoid code duplication in IGNORE_OFF_PAGE-specific malloc functionsIvan Maidanski2023-03-241-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (refactoring) * alloc.c: Update comment regarding GC_generic_malloc_inner usage. * alloc.c (GC_collect_or_expand): Replace ignore_off_page argument to flags (check IGNORE_OFF_PAGE bit only in it); update comment. * alloc.c (GC_allocobj): Pass 0 as flags to GC_collect_or_expand. * dbg_mlc.c (GC_debug_generic_malloc, GC_debug_generic_or_special_malloc): Rename knd argument to k. * mallocx.c (GC_generic_or_special_malloc): Likewise. * dbg_mlc.c (GC_debug_generic_malloc): Use GC_generic_malloc_aligned() instead of GC_generic_malloc(). * dbg_mlc.c (GC_debug_generic_malloc_inner): Add flags argument. * gcj_mlc.c [GC_GCJ_SUPPORT] (GC_core_gcj_malloc): Likewise. * include/private/gc_priv.h (C_generic_malloc_aligned, GC_generic_malloc_inner): Likewise. * include/private/gc_priv.h [THREAD_LOCAL_ALLOC && GC_GCJ_SUPPORT] (GC_core_gcj_malloc): Likewise. * include/private/gc_priv.h [DBG_HDRS_ALL] (GC_debug_generic_malloc_inner): Likewise. * malloc.c (GC_generic_malloc_inner, GC_generic_malloc_aligned): Likewise. * dbg_mlc.c (GC_debug_generic_malloc_inner): Use GC_generic_malloc_inner() instead of GC_generic_malloc_inner_ignore_off_page(). * dbg_mlc.c [DBG_HDRS_ALL] (GC_debug_generic_malloc_inner_ignore_off_page): Remove GC_INNER function. * include/private/gc_priv.h [DBG_HDRS_ALL || GC_GCJ_SUPPORT || !GC_NO_FINALIZATION] (GC_generic_malloc_inner_ignore_off_page): Likewise. * include/private/gc_priv.h [DBG_HDRS_ALL] (GC_debug_generic_malloc_inner_ignore_off_page): Likewise. * malloc.c [DBG_HDRS_ALL || GC_GCJ_SUPPORT || !GC_NO_FINALIZATION] (GC_generic_malloc_inner_ignore_off_page): Likewise. * gcj_mlc.c [GC_GCJ_SUPPORT && !THREAD_LOCAL_ALLOC] (GC_gcj_malloc): Define as STATIC GC_core_gcj_malloc. * gcj_mlc.c [GC_GCJ_SUPPORT] (GC_core_gcj_malloc): Reformat comment; pass flags to GC_generic_malloc_inner(). * gcj_mlc.c [GC_GCJ_SUPPORT && !THREAD_LOCAL_ALLOC] (GC_gcj_malloc): Redirect to GC_core_gcj_malloc() passing 0 to flags argument. * thread_local_alloc.c [THREAD_LOCAL_ALLOC && GC_GCJ_SUPPORT] (GC_gcj_malloc): Likewise. * gcj_mlc.c [GC_GCJ_SUPPORT] (GC_gcj_malloc_ignore_off_page): Redirect to GC_core_gcj_malloc() passing IGNORE_OFF_PAGE. * gcj_mlc.c [GC_GCJ_SUPPORT] (GC_debug_gcj_malloc): Pass 0 as flags to GC_generic_malloc_inner(). * include/private/gc_priv.h (GC_generic_malloc_inner): Update comment. * mallocx.c (GC_generic_malloc_many): Likewise. * include/private/gc_priv.h (GC_collect_or_expand): Replace GC_bool ignore_off_page argument to unsigned flags. * include/private/gc_priv.h (GC_INTERNAL_MALLOC, GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE): Specify macro arguments. * include/private/gc_priv.h (GC_INTERNAL_MALLOC): Pass 0 as flags argument to GC_[debug_]generic_malloc_inner(). * include/private/gc_priv.h (GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE): Pass IGNORE_OFF_PAGE to GC_[debug_]generic_malloc_inner(). * malloc.c (GC_alloc_large): Pass flags (instead of flags!=0) to GC_collect_or_expand(). * malloc.c (GC_generic_malloc_inner_small): New STATIC function (move most of code from GC_generic_malloc_inner). * malloc.c (GC_generic_malloc_inner): Move comment to gc_priv.h; call GC_generic_malloc_inner_small(). * malloc.c (GC_generic_malloc_aligned): Call GC_generic_malloc_inner_small() instead of GC_generic_malloc_inner(); pass flags (instead of 0) to GC_alloc_large(); do not cast result of GC_alloc_large() to ptr_t. * malloc.c (GC_generic_malloc): Pass 0 as flags to GC_generic_malloc_aligned(). * malloc.c (GC_memalign): Likewise. * malloc.c (GC_malloc_kind_global, GC_generic_malloc_uncollectable): Call GC_generic_malloc_aligned() instead of GC_generic_malloc(). * mallocx.c (GC_generic_malloc_many): Likewise. * malloc.c (free_internal): Rename knd local variable to k. * mallocx.c (GC_generic_malloc_ignore_off_page, GC_malloc_ignore_off_page, GC_malloc_atomic_ignore_off_page): Redirect to GC_generic_malloc_aligned() passing IGNORE_OFF_PAGE. * typd_mlc.c (GC_generic_malloc_ignore_off_page): Likewise. * tests/gctest.c (run_one_test): Call GC_generic_malloc_ignore_off_page() (with size larger than HBLKSIZE); increment collectable_count.
* Define counter variables as static in gctestIvan Maidanski2023-03-161-7/+8
| | | | | | | | | (refactoring) * tests/gctest.c (uncollectable_count, collectable_count, atomic_count, realloc_count, extra_count): Define as static variable. * tests/gctest.c [GC_PTHREADS] (gcollect_threads_cnt): Likewise. * tests/gctest.c [!DBG_HDRS_ALL] (fail_count): Likewise.
* Define GC_print_stats as GC_INNERIvan Maidanski2023-03-161-1/+1
| | | | | | | | | | | | | | (refactoring) * extra/MacOS.c [USE_TEMPORARY_MEMORY && !SHARED_LIBRARY_BUILD] (GC_MacFreeTemporaryMemory): Do not use GC_print_stats (assume it is always zero). * include/private/gc_priv.h [!NO_CLOCK || !SMALL_CONFIG] (GC_print_stats): Declared as GC_EXTERN; refine comment. * misc.c [!NO_CLOCK || !SMALL_CONFIG] (GC_print_stats): Define as GC_INNER. * tests/gctest.c [!GC_PRINT_VERBOSE_STATS && !GCTEST_PRINT_VERBOSE] (GC_print_stats): Update comment.
* Do not pass GC_malloc result to GC_size w/o checking in gctestIvan Maidanski2023-03-151-1/+1
| | | | | | | (fix of commit 051f57762) * tests/gctest.c (run_one_test): Do not call GC_malloc(0) inside GC_printf argument.
* Remove EXPORTED_FUNCTIONS linker flag for gctest (Emscripten)Bruce Mitchener2023-03-031-3/+0
| | | | | | | | | | | | | | | | Issue #532 (bdwgc). When mmap was used, there was apparently a need to export memalign and memset from the WebAssembly code to JS for the mmap emulation code to use. The mmap code path is no longer used with the Emscripten support, so this export is no longer needed. The explicit export of _main is not required; according to the Emscripten code: by default if this setting is not specified on the command line the _main function will be implicitly exported. * tests/tests.am [EMSCRIPTEN] (gctest_html_LDFLAGS): Remove.
* Add callback API to support ephemeron markingJonathan Chambers2023-02-141-0/+1
| | | | | | | | | | | | | | | | | | | | | | (cherry-pick of 1a65adc, bb5ba42, 6f41d8d from Unity-Technologies/bdwgc) When ephemerons marking results in pushing a large number of objects, the mark stack may overflow. While the processing could be batched, the simplest approach is to allow the callback to return false to indicate a failure and increasing the mark stack size. * include/gc/gc_mark.h (GC_on_mark_stack_empty_proc): New public type. * include/gc/gc_mark.h (GC_set_on_mark_stack_empty, GC_get_on_mark_stack_empty): New public function declaration. * mark.c (GC_on_mark_stack_empty): New static variable. * mark.c (GC_set_on_mark_stack_empty, GC_get_on_mark_stack_empty): New function implementation. * mark.c (GC_mark_some_inner): If GC_on_mark_stack_empty is non-zero then call it and break if pushed new items or overflowed. * tests/gctest.c [GC_PTHREADS] (main): Call GC_set_on_mark_stack_empty and GC_get_on_mark_stack_empty. Co-authored-by: Ivan Maidanski <ivmai@mail.ru>
* Add testing of remaining API functions (gctest and leaktest)Ivan Maidanski2023-02-112-140/+224
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously the functions were marked as UNTESTED in gctest. * tests/gctest.c: Include javaxfc.h unconditionally. * tests/gctest.c (tiny_reverse_test_inner): New function. * tests/gctest.c [!GC_NO_FINALIZATION] (dummy_finalizer): Likewise. * tests/gctest.c [THREADS && GC_PTHREADS && !MSWINCE && !MSWIN_XBOX1 && !NO_CRT && !NO_TEST_ENDTHREADEX] (TEST_ENDTHREADEX): Define macro. * tests/gctest.c [THREADS && GC_PTHREADS && !MSWINCE && !MSWIN_XBOX1 && !NO_CRT && !NO_TEST_ENDTHREADEX] (tiny_reverse_test): Specify return type to unsigned. * tests/gctest.c [THREADS] (tiny_reverse_test): Call tiny_reverse_test_inner() instead of check_ints() calls. * tests/gctest.c [THREADS && GC_PTHREADS && !GC_NO_PTHREAD_CANCEL] (tiny_reverse_test): Call GC_pthread_cancel(). * tests/gctest.c [THREADS && GC_PTHREADS && GC_HAVE_PTHREAD_EXIT] (tiny_reverse_test): Call GC_pthread_exit(). * tests/gctest.c [THREADS && GC_WIN32_THREADS && !GC_PTHREADS] (tiny_reverse_test): Call GC_endthreadex(0) or GC_ExitThread(0). * tests/gctest.c [THREADS && !GC_PTHREADS && GC_WIN32_THREADS && TEST_ENDTHREADEX] (fork_a_thread): Define thread_id local variable of unsigned type instead of DWORD; call GC_beginthreadex() instead of CreateThread(). * tests/gctest.c (finalizer): Do not define if GC_NO_FINALIZATION. * tests/gctest.c (run_one_test): Define x local variable even if DBG_HDRS_ALL. * tests/gctest.c [!DBG_HDRS_ALL] (run_one_test): Call GC_posix_memalign(). * tests/gctest.c (run_one_test): Call GC_STRNDUP() and strlen(). * tests/gctest.c [GC_REQUIRE_WCSDUP] (run_one_test): Call GC_WCSDUP(). * tests/gctest.c [!GC_NO_FINALIZATION] (run_one_test): Call GC_MALLOC_ATOMIC() and pass its result to GC_register_disappearing_link(), GC_REGISTER_FINALIZER_UNREACHABLE(). * tests/gctest.c [!NO_TEST_HANDLE_FORK && THREADS] (run_one_test): Call tiny_reverse_test_inner() instead of tiny_reverse_test(). * tests/gctest [!GC_NO_FINALIZATION && !GC_TOGGLE_REFS_NOT_NEEDED] (run_one_test): Call GC_toggleref_add(). * tests/gctest.c [!NO_DEBUGGING] (run_one_test): Call GC_is_tmp_root() and GC_count_set_marks_in_hblk(dp). * tests/gctest.c [CPPCHECK] (main): Remove UNTESTED() for GC_debug_generic_or_special_malloc, GC_debug_register_displacement, GC_post_incr, GC_pre_incr, GC_debug_gcj_malloc, GC_debug_strndup, GC_strndup, GC_posix_memalign, GC_clear_roots, GC_is_tmp_root, GC_print_trace, GC_debug_register_finalizer_unreachable, GC_register_disappearing_link, GC_should_invoke_finalizers, GC_finalize_all, GC_stop_world_external, GC_start_world_external, GC_pthread_cancel, GC_pthread_exit, GC_pthread_sigmask, GC_atfork_child, GC_atfork_parent, GC_atfork_prepare, GC_set_handle_fork, GC_start_mark_threads, GC_exclude_static_roots, GC_new_proc, GC_register_describe_type_fn, GC_register_has_static_roots_callback. * tests/gctest.c [CPPCHECK && !NO_DEBUGGING] (main): Remove UNTESTED() for GC_count_set_marks_in_hblk. * tests/gctest.c [CPPCHECK && !GC_NO_FINALIZATION && !GC_TOGGLE_REFS_NOT_NEEDED] (main): Remove UNTESTED() for GC_toggleref_add. * tests/gctest.c [CPPCHECK && !OS2 && !MACOS && !GC_ANDROID_LOG && !MSWIN32 && !MSWINCE] (main): Remove UNTESTED() for GC_set_log_fd. * tests/gctest.c [CPPCHECK && !REDIRECT_MALLOC_IN_HEADER && REDIRECT_MALLOC] (main): Remove UNTESTED() for strndup, strdup. * tests/gctest.c [CPPCHECK && !REDIRECT_MALLOC_IN_HEADER && REDIRECT_REALLOC] (main): Remove UNTESTED() for realloc(). * tests/gctest.c [CPPCHECK && GC_WIN32_THREADS] (main): Remove UNTESTED() for GC_ExitThread, GC_beginthreadex, GC_endthreadex. * tests/gctest.c [!PCR && !GC_WIN32_THREADS && !GC_PTHREADS && !GC_ANDROID_LOG && !MACOS && !OS2 && !MSWIN32 && !MSWINCE] (main): Call GC_set_log_fd(). * tests/gctest.c [GC_PTHREADS] (describe_norm_type, has_static_roots): New function. * tests/gctest.c [GC_PTHREADS && TRACE_BUF] (main): Call GC_print_trace(). * tests/gctest.c [GC_PTHREADS && GC_NO_PTHREAD_SIGMASK] (main): Define blocked local variable and call GC_pthread_sigmask() (twice). * tests/gctest.c [GC_PTHREADS] (main): Call GC_exclude_static_roots(), GC_register_has_static_roots_callback, GC_register_describe_type_fn (after set_print_procs). * tests/gctest.c [GC_PTHREADS && GC_GCJ_SUPPORT] (main): Call GC_new_proc(). * tests/gctest.c [GC_PTHREADS] (main): Call GC_stop_world_external(), GC_start_world_external(), and GC_clear_roots() (almost at the end of main). * tests/gctest.c [GC_PTHREADS && !GC_NO_FINALIZATION && !JAVA_FINALIZATION_NOT_NEEDED] (main): Call GC_finalize_all(). * tests/gctest.c [GC_PTHREADS && CPPCHECK && !GC_NO_DLOPEN] (main): Remove UNTESTED() for GC_dlopen. * tests/gctest.c [GC_PTHREADS && !GC_NO_DLOPEN && !DARWIN && !GC_WIN32_THREADS] (main): Call GC_dlopen() and dlclose(). * tests/leak.c (main): Call strdup() instead of malloc() on loop iteration 0; do not call reallocarray() or realloc() for loop iterations 1 and 2; do not call free() for loop iteration 1; call strndup() instead of malloc() on iteration 3..6 of the last loop; reduce number of iteration from N_TESTS/2 to N_TESTS/8 of the last loop.
* Generalize finalizers interruption APIIvan Maidanski2023-02-081-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (fix of commit e71a7d653) * finalize.c (GC_interrupt_finalizers): Move definition upper (to be before GC_enqueue_all_finalizers); change type from GC_bool to unsigned; update comment. * finalize.c [!JAVA_FINALIZATION_NOT_NEEDED] (GC_finalize_all): Set GC_interrupt_finalizers to 0 after GC_enqueue_all_finalizers() call. * finalize.c (GC_set_interrupt_finalizers): Add unsigned argument; set GC_interrupt_finalizers to the argument value. * finalize.c (GC_set_interrupt_finalizers, GC_invoke_finalizers): Wrap access to GC_interrupt_finalizers into LOCK/UNLOCK. * finalize.c (GC_get_interrupt_finalizers): New public function definition. * finalize.c (GC_invoke_finalizers): Do not break the loop (because of non-zero GC_interrupt_finalizers) on the first iteration or if iteration number is smaller than GC_interrupt_finalizers value. * finalize.c (GC_notify_or_invoke_finalizers): Update comment for the reset of *pnested. * finalize.c [!THREADS] (GC_notify_or_invoke_finalizers): Allow finalize_now to be non-null in the assertion in case of a non-zero value of GC_interrupt_finalizers. * include/gc/gc.h (GC_set_interrupt_finalizers): Update comment; add unsigned argument. * include/gc/gc.h (GC_get_interrupt_finalizers): New public function declaration. * tests/gctest.c [GC_PTHREADS && !GC_NO_FINALIZATION] (main): Call GC_set_interrupt_finalizers() and GC_get_interrupt_finalizers().
* Do not mix debug and non-debug allocations in disclaim testsIvan Maidanski2023-01-312-10/+10
| | | | | | | | | | | | | | | * include/gc/gc_disclaim.h (GC_finalized_malloc): Add comment that the debugging version of the function is missing. * tests/disclaim_bench.c (testobj_new): Use GC_malloc() instead of GC_NEW(). * tests/weakmap.c (weakmap_add, weakmap_new): Likewise. * tests/disclaim_bench.c (testobj_new): Use GC_register_finalizer_no_order() instead of GC_REGISTER_FINALIZER_NO_ORDER(). * tests/disclaim_bench.c (main): Use GC_malloc() instead of GC_MALLOC(). * tests/weakmap.c (weakmap_add, weakmap_new): Use GC_ptr_store_and_dirty() instead of GC_PTR_STORE_AND_DIRTY().
* Do not mix debug/non-debug variants of explicitly-typed alloc in gctestIvan Maidanski2023-01-311-1/+1
| | | | | | | | (fix of commit f55e46c34) * tests/gctest.c [!NO_TYPED_TEST] (typed_test): Call GC_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE() instead of GC_malloc_explicitly_typed_ignore_off_page().
* Fix pointer visibility in gcj_consIvan Maidanski2023-01-311-1/+1
| | | | | | | | | | | | (fix of commit fcbfe2a78) The issue is caused by the mixture of debug and non-debug routine calls (the pointer is allocated by GC_gcj_malloc_ignore_off_page but accessed by the debug variant of GC_PTR_STORE_AND_DIRTY). * tests/gctest.c [GC_GCJ_SUPPORT] (gcj_cons): Call GC_GCJ_MALLOC_IGNORE_OFF_PAGE() instead of GC_gcj_malloc_ignore_off_page().
* Export setter and getter for pointer checking print proceduresIvan Maidanski2023-01-301-3/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Direct access to GC_same_obj_print_proc, GC_is_visible_print_proc and GC_is_valid_displacement_print_proc is now deprecated. * include/gc/gc.h (GC_same_obj_print_proc, GC_is_valid_displacement_print_proc, GC_is_visible_print_proc): Move the declaration upper (to be right after GC_get_finalizer_notifier); improve comment; add GC_ATTR_DEPRECATED attribute. * include/gc/gc.h (GC_valid_ptr_print_proc_t, GC_same_obj_print_proc_t): New public type. * include/gc/gc.h (GC_same_obj_print_proc): Use GC_same_obj_print_proc_t type. * ptr_chck.c (GC_same_obj_print_proc): Likewise. * include/gc/gc.h (GC_is_valid_displacement_print_proc, GC_is_visible_print_proc): Use GC_valid_ptr_print_proc_t type. * ptr_chck.c (GC_is_valid_displacement_print_proc, GC_is_visible_print_proc): Likewise. * include/gc/gc.h (GC_set_same_obj_print_proc, GC_get_same_obj_print_proc, GC_set_is_valid_displacement_print_proc, GC_get_is_valid_displacement_print_proc, GC_set_is_visible_print_proc, GC_get_is_visible_print_proc): New public function declaration. * ptr_chck.c (GC_set_same_obj_print_proc, GC_get_same_obj_print_proc, GC_set_is_valid_displacement_print_proc, GC_get_is_valid_displacement_print_proc, GC_set_is_visible_print_proc, GC_get_is_visible_print_proc): New function definition. * tests/gctest.c [!DBG_HDRS_ALL] (set_print_procs): Use GC_set_is_valid_displacement_print_proc() and GC_set_is_visible_print_proc() instead of setting GC_is_valid_displacement_print_proc and GC_set_is_visible_print_proc variables. * tests/gctest.c [GC_PTHREADS] (main): Call GC_get_is_valid_displacement_print_proc(), GC_get_is_visible_print_proc(), GC_get_same_obj_print_proc() and GC_set_same_obj_print_proc().
* Add minimal testing of GC_malloc_explicitly_typed_ignore_off_pageIvan Maidanski2023-01-281-3/+7
| | | | | | | | | | | | * tests/gctest.c [!NO_TYPED_TEST] (typed_test): Call GC_malloc_explicitly_typed_ignore_off_page() instead of GC_MALLOC_EXPLICITLY_TYPED() every 1/256th iteration of the loop; replace GC_malloc_explicitly_typed to GC_calloc_explicitly_typed in the error message if a test fails after GC_calloc_explicitly_typed() invocation. * tests/gctest.c [!PCR && !GC_WIN32_THREADS && !GC_PTHREADS && CPPCHECK] (main): Remove UNTESTED(GC_malloc_explicitly_typed_ignore_off_page).
* Add minimal testing of GC_gcj_malloc_ignore_off_pageIvan Maidanski2023-01-281-9/+7
| | | | | | | | | | | * tests/gctest.c [GC_GCJ_SUPPORT] (gcj_cons): Define cnt, d, lb local variables; change type of r local variable from GC_word* to void*; if (cnt&2)!=0 then call GC_gcj_malloc_ignore_off_page() instead of GC_GCJ_MALLOC(); pass size larger than lb for several invocation of GC_gcj_malloc_ignore_off_page(). * tests/gctest.c [!PCR && !GC_WIN32_THREADS && !GC_PTHREADS && GC_GCJ_SUPPORT && CPPCHECK] (main): Remove UNTESTED(GC_gcj_malloc_ignore_off_page).
* Support GC_memalign with alignments greater than HBLKSIZEIvan Maidanski2023-01-241-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Issue #510 (bdwgc). * allchblk.c (GC_allochblk_nth, GC_allochblk, next_hblk_fits_better, find_nonbl_hblk): Add align_m1 argument. * include/private/gc_priv.h (GC_allochblk, GC_alloc_large): Likewise. * malloc.c (GC_alloc_large): Likewise. * allchblk.c (GC_allochblk): Check that there is no overflow in blocks*HBLKSIZE+align_m1; pass align_m1 to GC_allochblk_nth; try start_list again (with may_split) if non-zero align_m1. * allchblk.c (ALIGN_PAD_SZ): New macro. * allchblk.c (next_hblk_fits_better): Define and use next_ofs local variable; adjust next_hbp passed to GC_is_black_listed(). * allchblk.c (find_nonbl_hblk): Adjust search_end and last_hbp based on align_m1 value. * allchblk.c (GC_allochblk_nth): Add assertion that align_m1+1 is a power of two and that align_m1+1 is 1 or a multiple of HBLKSIZE; define and use align_ofs local variable; add assertion that last_hbp (before GC_install_header() call) is multiple of align_m1+1. * include/gc/gc.h (GC_memalign): Update comment to mention the restriction on align value (should be a power of two and not less than size of a pointer). * include/private/gc_priv.h (GC_allochblk, GC_alloc_large): Update comment (to mention align_m1 argument). * include/private/gc_priv.h (GC_generic_malloc_aligned): Declare function. * include/private/gcconfig.h [(NACL || I386 && (EMSCRIPTEN || WASI)) && !HBLKSIZE && !GC_NO_VALLOC] (HBLKSIZE): Do not define (to 65536 or GETPAGESIZE()); remove TODO item. * malloc.c (GC_alloc_large): Add alignment to n_blocks value (but not to GC_large_allocd_bytes); pass align_m1 to GC_allochblk(); add assertion that result is aligned to align_m1+1. * malloc.c (GC_alloc_large_and_clear): Pass zero align_m1 to GC_alloc_large(). * mallocx.c (GC_generic_malloc_ignore_off_page): Likewise. * malloc.c (GC_generic_malloc_aligned): Move code from GC_generic_malloc; adjust align_m1 to be either zero or not less than HBLKSIZE-1, and pass it to GC_alloc_large(); add comment that the result of GC_oom_fn(lb) might be unaligned. * malloc.c (GC_generic_malloc): Call GC_generic_malloc_aligned() with zero align_m1. * mallocx.c (GC_generic_malloc_ignore_off_page): Expect result of GC_alloc_large() is unlikely to be NULL. * mallocx.c (GC_generic_malloc_many): Pass zero align_m1 to GC_allochblk(). * new_hblk.c (GC_new_hblk): Likewise. * mallocx.c: Do not include limits.h. * mallocx.c (GC_memalign): Remove new_lb local variable; define and use align_m1 local variable; if align is smaller than sizeof(void*) or is not a power of two than return NULL; call GC_generic_malloc_aligned and GC_clear_stack (instead of GC_oom_fn() or GC_malloc()) if align or lb is at least HBLKSIZE/2; replace result%align to result&align_m1; do not result+=offset if offset is zero. * new_hblk.c (GC_new_hblk): Expect result of GC_allochblk() is unlikely to be NULL. * tests/gctest.c (run_one_test): Call GC_memalign() also for bigger alignment values (up to HBLKSIZE*4).
* Increment allocated objects count after GC_memalign in gctestIvan Maidanski2023-01-031-5/+9
| | | | | | | * tests/gctest.c [!DBG_HDRS_ALL] (run_one_test): Check no out-of-memory in GC_malloc(17); define p local variable (of void* type) instead of result one; call CHECK_OUT_OF_MEMORY() and increment collectable_count after GC_memalign() call.
* Fix allocated objects count increment in alloc8bytes of gctestIvan Maidanski2023-01-031-14/+11
| | | | | | | | | | * tests/gctest.c [!GC_PTHREADS] (alloc8bytes): Define a function instead of a macro; increment atomic_count. * tests/gctest.c [GC_PTHREADS && !SMALL_CONFIG && !GC_DEBUG] (alloc8bytes): Return NULL (intead of fail) if out of memory. * tests/gctest.c (alloc_small): Do not increment atomic_count here; define p local variable; call CHECK_OUT_OF_MEMORY(p) instead of direct checking of p and fail.
* Increment allocated objects count after GC_[p]valloc calls in gctestIvan Maidanski2023-01-031-3/+7
| | | | | | | | | (fix of commit d4c81638d) * tests/gctest.c [!DBG_HDRS_ALL && !GC_NO_VALLOC] (run_one_test): Increment collectable_count after GC_valloc() and GC_pvalloc() calls; call CHECK_OUT_OF_MEMORY(p) instead of direct checking that p is not null.
* Fix potential SIGSEGV on out-of-memory in gctestIvan Maidanski2023-01-031-11/+26
| | | | | | | | | | (fix of commits 463d083ff, ff6c3d9fb) * tests/gctest.c (test_generic_malloc_or_special): Call CHECK_OUT_OF_MEMORY() before GC_get_kind_and_size(). * tests/gctest.c [DBG_HDRS_ALL] (run_one_test): Set y to fail_proc1 right before its use; call CHECK_OUT_OF_MEMORY() before each GC_size() invocation; call CHECK_OUT_OF_MEMORY() before GC_base().
* Always print error details message when gctest failsIvan Maidanski2023-01-031-9/+31
| | | | | | | | * tests/gctest.c (run_one_test): Add GC_printf() call (with the error details) before FAIL where missing. * tests/gctest.c [GC_WIN32_THREADS && !GC_PTHREADS && MSWINCE] (thr_window, WinMain): Likewise. * tests/gctest.c [GC_PTHREADS] (main): Likewise.
* Document that GC_unregister_my_thread result value is dummyIvan Maidanski2022-12-191-1/+1
| | | | | | | | | | * include/gc/gc.h [GC_THREADS] (GC_unregister_my_thread): Refine comment (mention that GC_SUCCESS is always returned). * tests/gctest.c [THREADS] (check_heap_stats): Cast call of GC_unregister_my_thread() to void. * win32_threads.c (GC_win32_start_inner, GC_ExitThread): Likewise. * win32_threads.c [!CYGWIN32 && !MSWINCE && !MSWIN_XBOX1 && !NO_CRT] (GC_endthreadex): Likewise.
* Remove OpenBSD uthreads (GC_OPENBSD_UTHREADS) supportGreg Steuck2022-11-251-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Issue #512 (bdwgc). Userland threads were replaced by rthreads on OpenBSD about a decade ago. Prior to OpenBSD 5.2 release (2012), the OS had user threads and required special handling. * include/private/gc_priv.h [GC_OPENBSD_THREADS && !GC_USESIGRT_SIGNALS] (SIG_SUSPEND): Do not check GC_OPENBSD_UTHREADS (assume not defined). * include/private/gcconfig.h [OPENBSD] (NEED_FIND_LIMIT): Likewise. * include/private/gcconfig.h [PTHREAD_STOP_WORLD_IMPL && !NACL] (SIGNAL_BASED_STOP_WORLD): Likewise. * os_dep.c [OPENBSD] (GC_register_data_segments): Likewise. * pthread_stop_world.c (GC_usleep, GC_suspend_all, GC_stop_world, GC_start_world, GC_stop_init): Likewise. * tests/initfromthread.c (main): Likewise. * include/private/gcconfig.h [GC_OPENBSD_THREADS && OpenBSD<201211] (GC_OPENBSD_UTHREADS): Do not define. * os_dep.c [OPENBSD && GC_OPENBSD_UTHREADS]: Do not include sys/syscall.h. * os_dep.c [OPENBSD && GC_OPENBSD_UTHREADS] (__syscall): Do not declare. * os_dep.c [OPENBSD && GC_OPENBSD_UTHREADS] (GC_find_limit_openbsd): Remove. * os_dep.c [NEED_FIND_LIMIT || USE_PROC_FOR_LIBRARIES && THREADS] (GC_find_limit_with_bound): Move comment from GC_find_limit_openbsd. * pthread_stop_world.c [!NACL && GC_OPENBSD_UTHREADS]: Do not include pthread_np.h. Co-authored-by: Kurt Miller <bsdkurt@gmail.com>
* Fix typo in comment related to Emscripten linker bug memalign/memsetIvan Maidanski2022-11-231-2/+2
| | | | | | | | (fix of commit 1431bda1a) * tests/tests.am [EMSCRIPTEN]: Fix a typo ("_memalign and _memset") in comment (i.e. mention also _memset instead of mentioning _memalign twice).
* Redirect reallocarray() in leak_detector.hIvan Maidanski2022-11-021-1/+2
| | | | | | | | | Issue #491 (bdwgc). * doc/leak.md: Mention reallocarray function; reorder redirected functions list. * include/gc/leak_detector.h (reallocarray): Redefine to GC_REALLOC(). * tests/leak.c (main): Call reallocarray() in a loop.
* Test realloc() in leaktestIvan Maidanski2022-11-021-0/+5
| | | | | * tests/leak.c (main): Call realloc() N_TESTS/2-1 times and then call CHECK_LEAKS().
* Define public GC_[p]valloc() and redirect to them in leak_detector.hIvan Maidanski2022-10-281-0/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Issue #495 (bdwgc). * doc/README.macros (GC_NO_VALLOC): Document. * doc/leak.md: Mention GNU valloc and pvalloc functions. * include/gc/gc.h (GC_memalign): Remove comment that it is not tested; add comment describing the functionality and a note. * include/gc/gc.h [!GC_NO_VALLOC] (GC_valloc, GC_pvalloc): Declare new API function. * include/gc/leak_detector.h [!GC_NO_VALLOC] (valloc, pvalloc): Redefine to the corresponding GC_ function. * include/private/gc_priv.h (GC_page_size): Add comment. * include/private/gc_priv.h (GC_real_page_size): Declare new variable (or as a macro). * include/private/gcconfig.h [NACL] (GETPAGESIZE): Add TODO item. * mallocx.c (GC_memalign): Likewise. * tests/gctest.c (run_one_test): Likewise. * include/private/gcconfig.h [CYGWIN32 && (MPROTECT_VDB || USE_MUNMAP) || !MSWIN32 && !MSWINCE && !CYGWIN32 && (GC_DISABLE_INCREMENTAL || DEFAULT_VDB) && !USE_MMAP] (ALT_PAGESIZE_USED): Define macro. * include/private/gcconfig.h [CYGWIN32 && (MPROTECT_VDB || USE_MUNMAP) || !MSWIN32 && !MSWINCE && !CYGWIN32 && (GC_DISABLE_INCREMENTAL || DEFAULT_VDB) && !USE_MMAP && !GC_NO_VALLOC] (REAL_PAGESIZE_NEEDED): Likewise. * mallocx.c (GC_strdup): Reformat comment. * mallocx.c [!GC_NO_VALLOC] (GC_valloc, GC_pvalloc): Implement. * os_dep.c [REAL_PAGESIZE_NEEDED] (GC_real_page_size): Define variable. * os_dep.c [MSWIN32 || MSWINCE || CYGWIN32] (GC_setpagesize): Replace CYGWIN32&&(MPROTECT_VDB||USE_MUNMAP) to ALT_PAGESIZE_USED; remove comment that a separate variable could be added; reformat comment; assert about GC_pagesize only if REAL_PAGESIZE_NEEDED. * os_dep.c [ALT_PAGESIZE_USED && REAL_PAGESIZE_NEEDED] (GC_setpagesize): Set GC_real_page_size. * os_dep.c [!MSWIN32 && !MSWINCE && !CYGWIN32] (GC_setpagesize): Replace MPROTECT_VDB||PROC_VDB||SOFT_VDB||USE_MMAP to !ALT_PAGESIZE_USED. * tests/gctest.c [!GC_NO_VALLOC] (run_one_test): Call GC_valloc() and GC_pvalloc().
* Replace C-style casts in cpptestIvan Maidanski2022-10-201-8/+14
| | | | | | | | | (refactoring) * tests/cpp.cc (A::A, D::CleanUp, main): Use static_cast or reinterpret_cast instead of C-style cast. * tests/cpp.cc (Disguise): Use GC_HIDE_POINTER macro. * tests/cpp.cc (Undisguise): Use GC_REVEAL_POINTER macro.
* Eliminate 'struct treenode member is never used' cppcheck warningIvan Maidanski2022-10-201-0/+4
| | | | | * tests/staticroots_lib.c [CPPCHECK] (libsrl_getpelem): Define node local variable (of treenode type) and pass its fields to GC_noop1().
* Include stdio.h and stdlib.h only from gc_priv.hIvan Maidanski2022-09-262-8/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | (refactoring) * allchblk.c: Do not include stdio.h directly. * alloc.c: Likewise. * dyn_load.c [(DYNAMIC_LOADING || MSWIN32 || MSWINCE || CYGWIN32) && !PCR]: Likewise. * mach_dep.c [!PLATFORM_MACH_DEP && !SN_TARGET_PSP2]: Likewise. * malloc.c: Likewise. * mallocx.c: Likewise. * mark.c: Likewise. * mark_rts.c: Likewise. * misc.c: Likewise. * new_hblk.c: Likewise. * os_dep.c: Likewise. * reclaim.c: Likewise. * tests/disclaim_bench.c: Likewise. * tests/gctest.c: Likewise. * dbg_mlc.c [KEEP_BACK_PTRS && !LINT2]: Do not include stdlib.h directly. * dyn_load.c [MSWIN32 || MSWINCE || CYGWIN32]: Likewise. * os_dep.c [HAIKU]: Likewise. * pthread_support.c [GC_PTHREADS && !GC_WIN32_THREADS]: Likewise. * tests/disclaim_bench.c: Likewise. * tests/gctest.c [!mips || !SYSTYPE_BSD43]: Likewise. * thread_local_alloc.c: Likewise. * include/private/gc_priv.h: Include stdio.h.
* Use cast to void instead of the attribute to indicate unused argumentsIvan Maidanski2022-09-151-19/+34
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (refactoring) * CMakeLists.txt [BORLAND] (add_compile_options): Remove "/w-par"; reorder options. * CMakeLists.txt [!BORLAND && MSVC] (add_compile_options): Remove "/wd4100"; update comment. * NT_MAKEFILE (.c.obj): Likewise. * allchblk.c [!NO_DEBUGGING || GC_ASSERTIONS] (add_hb_sz): Use UNUSED_ARG() instead of GC_ATTR_UNUSED. * allchblk.c [USE_MUNMAP] (GC_adjust_num_unmapped): Likewise. * backgraph.c [MAKE_BACK_GRAPH] (pop_in_progress, reset_back_edge, update_max_height): Likewise. * checksums.c [CHECKSUMS] (GC_add_block): Likewise. * darwin_stop_world.c (GC_stack_range_for): Likewise. * dbg_mlc.c (GC_store_debug_info_inner, GC_debug_change_stubborn, GC_check_heap_block): Likewise. * finalize.c [!GC_NO_FINALIZATION] (GC_null_finalize_mark_proc): Likewise. * gcj_mlc.c [GC_GCJ_SUPPORT] (GC_gcj_fake_mark_proc): Likewise. * mallocx.c [!CPPCHECK] (GC_change_stubborn): Likewise. * mark.c (GC_noop6, clear_marks_for_block): Likewise. * mark.c [WRAP_MARK_SOME && (MSWIN32 || MSWINCE) && __GNUC__] (mark_ex_handler): Likewise. * mark.c [GC_DISABLE_INCREMENTAL] (GC_push_conditional): Likewise. * mark_rts.c (GC_push_current_stack, GC_push_roots): Likewise. * misc.c (GC_default_oom_fn, GC_set_handle_fork): Likewise. * misc.c [THREADS && !SIGNAL_BASED_STOP_WORLD] (GC_set_suspend_signal, GC_set_thr_restart_signal): Likewise. * misc.c [THREADS && UNIX_LIKE && !NO_GETCONTEXT] (callee_saves_pushed_dummy_fn): Likewise. * misc.c [!THREADS] (GC_do_blocking_inner): Likewise. * misc.c [!PARALLEL_MARK] (GC_set_markers_count): Likewise. * os_dep.c [OPENBSD] (GC_fault_handler_openbsd): Likewise. * os_dep.c [NEED_FIND_LIMIT || WRAP_MARK_SOME && !MSWIN32 && !MSWINCE || USE_PROC_FOR_LIBRARIES && THREADS] (GC_fault_handler): Likewise. * os_dep.c [!HAVE_GET_STACK_BASE && !NEED_FIND_LIMIT] (GC_get_stack_base): Likewise. * os_dep.c [MPROTECT_VDB && DARWIN] (catch_exception_raise_state, catch_exception_raise_state_identity, catch_exception_raise): Likewise. * pthread_stop_world.c [!NACL && !GC_OPENBSD_UTHREADS && !SUSPEND_HANDLER_NO_CONTEXT] (GC_suspend_sigaction): Likewise. * pthread_stop_world.c [!NACL && !GC_OPENBSD_UTHREADS] (GC_suspend_handler_inner): Likewise. * pthread_support.c (GC_do_blocking_inner): Likewise. * pthread_support.c [GC_ENABLE_SUSPEND_THREAD && SIGNAL_BASED_STOP_WORLD] (GC_suspend_self_blocked): Likewise. * tests/gctest.c [!DBG_HDRS_ALL] (fail_proc1): Likewise. * tests/gctest.c [(MSWIN32 && !__MINGW32__ || MSWINCE) && !NO_WINMAIN_ENTRY] (WinMain): Likewise. * tests/gctest.c [!PCR && !GC_WIN32_THREADS && !GC_PTHREADS && CPPCHECK && RTEMS] (Init): Likewise. * tests/gctest.c [GC_WIN32_THREADS && !GC_PTHREADS] (thr_run_one_test): Likewise. * tests/gctest.c [MSWINCE] (thr_window): Likewise. * tests/gctest.c [GC_PTHREADS] (thr_run_one_test): Likewise. * typd_mlc.c (GC_array_mark_proc): Likewise. * win32_threads.c (GC_register_altstack, GC_do_blocking_inner): Likewise. * win32_threads.c [!GC_PTHREADS && !GC_NO_THREADS_DISCOVERY] (GC_DllMain): Likewise. * cord/cordxtra.c (CORD_ATTR_UNUSED): Remove. * include/private/gc_priv.h [!GC_ATTR_UNUSED] (GC_ATTR_UNUSED): Likewise. * cord/cordxtra.c (CORD_nul_func): Cast unused argument to void instead of using CORD_ATTR_UNUSED. * cord/cordxtra.c [!GC_NO_FINALIZATION] (CORD_lf_close_proc): Likewise. * include/private/gc_priv.h [!UNUSED_ARG] (UNUSED_ARG): Define macro.
* Eliminate 'unused but set variable' gcc warning in cpptestIvan Maidanski2022-08-121-3/+3
| | | | | | | (fix of commit e870802a1) * tests/cpp.cc (main): Pass xio, d, a local variables to GC_reachable_here().
* New GC_count_set_marks_in_hblk API functionIvan Maidanski2022-08-051-0/+1
| | | | | | | | | | | Issue #460 (bdwgc). Note: available on if the collector is built without NO_DEBUGGING. * include/gc/gc_mark.h (GC_count_set_marks_in_hblk): New API function. * reclaim.c [!NO_DEBUGGING] (GC_count_set_marks_in_hblk): Implement. * tests/gctest.c [!PCR && !GC_WIN32_THREADS && !GC_PTHREADS && CPPCHECK && !NO_DEBUGGING] (main): Call UNTESTED(GC_count_set_marks_in_hblk).
* New API function (GC_get_hblk_size) to get HBLKSIZE valueIvan Maidanski2022-08-031-0/+1
| | | | | | | | | Issue #460 (bdwgc). * include/gc/gc_mark.h (GC_get_hblk_size): New API function (declared as const). * misc.c (GC_get_hblk_size): Implement (returns HBLKSIZE). * tests/gctest.c [GC_PTHREADS] (main): Call GC_get_hblk_size().
* Workaround stack overflow in gctest collect_from_other_thread on musl arm64Ivan Maidanski2022-07-141-1/+1
| | | | | | | (fix of commit 3159afddb) * tests/gctest.c [!BIG && (MACOS || UNIX_LIKE && NO_GETCONTEXT) && __aarch64__] (BIG): Define to 600 (instead of 1000).
* Test world stop while other thread in deep recursion in gctest (pthreads)Ivan Maidanski2022-07-111-0/+38
| | | | | | | | | | | | * tests/gctest.c [GC_PTHREADS]: Add TODO item. * tests/gctest.c [GC_PTHREADS] (do_gcollect, collect_from_other_thread): New function. * tests/gctest.c [GC_PTHREADS] (MAX_GCOLLECT_THREADS): New macro. * tests/gctest.c [GC_PTHREADS] (gcollect_threads_cnt): New variable. * tests/gctest.c [GC_PTHREADS] (ints): If up<0 and low>-up then increment gcollect_threads_cnt atomically and call collect_from_other_thread() instead of GC_gcollect_and_unmap unless gcollect_threads_cnt exceeds limit (MAX_GCOLLECT_THREADS).
* Test garbage collection from a deep recursion in gctestIvan Maidanski2022-07-081-2/+5
| | | | | | | * tests/gctest.c (ints): If up is negative and low>-up then call GC_gcollect_and_unmap(). * tests/gctest.c (reverse_test_inner): Call ints(1,-BIG) instead of ints(1,BIG); add comment.
* Avoid duplication of magic numbers in disclaim.c and weakmap.cIvan Maidanski2022-06-022-17/+19
| | | | | | | | | | | | | | (refactoring) * tests/disclaim.c (MEM_FILL_BYTE, CSUM_SEED): Define macro. * tests/weakmap.c (CSUM_SEED): Likewise. * tests/disclaim.c (misc_sizes_dct, test_misc_sizes): Use MEM_FILL_BYTE instead of 0x56. * tests/disclaim.c (pair_dct, pair_new, pair_check_rec): Use CSUM_SEED instead of 782. * tests/weakmap.c (pair_new, pair_check_rec): Likewise. * tests/disclaim.c (pair_check_rec): Use same formula for updating p as in the similar function of weakmap.c.
* Prevent (fix) parallel custom mark procs run in single-threaded clientsIvan Maidanski2022-06-011-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If the collector is built with parallel marker support then marking is performed in parallel on multi-core targets. Thus, if the client provides custom mark procedures, then they could be executed in parallel. In case of a single-threaded client (developed for the older libgc version with the parallel mark support off), its custom mark procedures might not be prepared to be launched in parallel. Now, the parallel mark threads are not launched, even if available, until the client starts a (user) thread (e.g. calls pthread_create or GC_allow_register_threads) or tells the collector explicitly to start the mark threads (by calling GC_start_mark_threads). * doc/README.macros (GC_ALWAYS_MULTITHREADED): Update documentation. * doc/scale.md (Options for enhanced scalability): Likewise. * include/gc/gc.h [GC_THREADS] (GC_parallel, GC_allow_register_threads): Update comment. * include/gc/gc.h (GC_set_markers_count, GC_start_mark_threads): Likewise. * include/gc/gc_mark.h (GC_mark_proc): Likewise. * include/gc/gc_mark.h (GC_PROC_BYTES, GC_ms_entry): Move upper to be before the comment belonging to GC_mark_proc. * misc.c [THREADS && PARALLEL_MARK] (GC_init): Do not call GC_start_mark_threads_inner(). * misc.c [PARALLEL_MARK] (GC_start_mark_threads): Call GC_start_mark_threads_inner() even if THREAD_SANITIZER or no CAN_HANDLE_FORK. * misc.c [THREADS] (GC_get_parallel): Remove comment. * pthread_support.c [PARALLEL_MARK && !CAN_HANDLE_FORK] (available_markers_m1): Define as a variable. * win32_threads.c [PARALLEL_MARK && !CAN_HANDLE_FORK] (available_markers_m1): Likewise. * pthread_support.c [PARALLEL_MARK && !CAN_HANDLE_FORK] (GC_wait_for_gc_completion): Declare. * pthread_support.c [PARALLEL_MARK && !CAN_HANDLE_FORK] (GC_start_mark_threads_inner): If GC_parallel then return; call GC_wait_for_gc_completion(); set GC_markers_m1 value from available_markers_m1. * win32_threads.c [PARALLEL_MARK && (!GC_PTHREADS_PARAMARK || !CAN_HANDLE_FORK)] (GC_start_mark_threads_inner): Likewise. * pthread_support.c [CAN_HANDLE_FORK && PARALLEL_MARK && THREAD_SANITIZER] (fork_child_proc): Set available_markers_m1 to 0. * pthread_support.c [CAN_HANDLE_FORK]: Move GC_remove_all_threads_but_me() call to be after setting available_markers_m1. * pthread_support.c (GC_allow_register_threads): Call GC_start_mark_threads(). * tests/middle.c (main): Likewise. * win32_threads.c (GC_allow_register_threads): Likewise. * pthread_support.c [PARALLEL_MARK] (pthread_create): Call GC_start_mark_threads() unless GC_parallel or available_markers_m1<=0. * win32_threads.c (START_MARK_THREADS): Define macro (to call GC_start_mark_threads() if PARALLEL_MARK). * win32_threads.c (GC_CreateThread): Call START_MARK_THREADS() (right before set_need_to_lock). * win32_threads.c [!CYGWIN32 && !MSWINCE && !MSWIN_XBOX1 && !NO_CRT] (GC_beginthreadex): Likewise. * win32_threads.c [GC_PTHREADS] (GC_pthread_create): Likewise.
* Fix abort in Win32 DllMain if PARALLEL_MARKIvan Maidanski2022-05-301-2/+1
| | | | | | | | | | | | | | (fix of commit f1b257a66) Also, enable GC_use_threads_discovery() on Windows even in case of PARALLEL_MARK. * tests/gctest.c [GC_WIN32_THREADS && !GC_PTHREADS && GC_DLL && !GC_NO_THREADS_DISCOVERY && !MSWINCE && !THREAD_LOCAL_ALLOC] (WinMain): Call GC_use_threads_discovery() regardless of PARALLEL_MARK. * win32_threads.c [!GC_PTHREADS && !GC_NO_THREADS_DISCOVERY && PARALLEL_MARK] (GC_DllMain): Do not abort if DLL_PROCESS_ATTACH or DLL_THREAD_ATTACH (call GC_register_my_thread_inner instead).