There is again a data race between GC_extend_size_map and GC_size_map[]
readers, though it is again not likely to fail in practice.
It is feasible to just move all of the GC_size_map accesses under the
lock, and this does not look to incur a substantial penalty.
* gcj_mlc.c (GC_gcj_malloc, GC_gcj_malloc_ignore_off_page): Move
lg=GC_size_map[lb] to be right after LOCK() instead of preceding it.
* malloc.c (GC_malloc_kind_global, GC_generic_malloc_uncollectable):
Likewise.
* typd_mlc.c (GC_malloc_explicitly_typed_ignore_off_page): Likewise.
* include/gc.h (GC_get_size_map_at): Update comment to note that the
client should use synchronization when calling the function.
* include/private/gc_priv.h (_GC_arrays._size_map): Add comment about
synchronization.
This is needed to make the size of hb_sz to be the same as of AO_t.
* allchblk.c [USE_MUNMAP] (GC_unmap_old): Cast hhdr->hb_sz to size_t
when passed to GC_unmap().
* allchblk.c (GC_allochblk_nth): Cast hhdr->hb_sz to signed_word when
assigned to size_avail.
* allchblk.c [USE_MUNMAP] (GC_allochblk_nth): Cast hhdr->hb_sz to
size_t when passed to GC_remap().
* alloc.c (GC_set_fl_marks, GC_clear_fl_marks): Change type of sz and
bit_no local variables from size_t/unsigned to word.
* dbg_mlc.c (GC_check_heap_block): Likewise.
* backgraph.c [MAKE_BACK_GRAPH] (per_object_helper): Cast hhdr->hb_sz
to size_t; change type of i local variables from int to size_t.
* checksums.c [CHECKSUMS] (GC_on_free_list): Change type of sz local
variable from size_t to word.
* mark.c (GC_push_marked, GC_push_unconditionally, GC_block_was_dirty):
Likewise.
* reclaim.c (GC_reclaim_small_nonempty_block,
GC_disclaim_and_reclaim_or_free_small_block, GC_reclaim_block,
GC_n_set_marks): Likewise.
* checksums.c [CHECKSUMS] (GC_add_block): Remove bytes local variable
(to avoid casting of hhdr->hb_sz).
* dbg_mlc.c (GC_debug_free): Change type of i and obj_sz local
variables from size_t to word.
* dbg_mlc.c (GC_check_leaked): Likewise.
* extra/pcr_interface.c (GC_enumerate_block): Change type of sz local
variable from int to size_t.
* extra/pcr_interface.c (GC_enumerate_block): Cast hhdr->hb_sz to
size_t when assigned to sz.
* mallocx.c (GC_realloc): Likewise.
* mark.c (GC_set_hdr_marks): Likewise.
* reclaim.c (GC_do_enumerate_reachable_objects): Likewise.
* include/private/gc_pmark.h [MARK_BIT_PER_OBJ] (PUSH_CONTENTS_HDR):
Cast hhdr->hb_sz to size_t in assignment of obj_displ.
* include/private/gc_priv.h (struct hblkhdr): Change type of hb_sz from
size_t to word.
* include/private/gc_priv.h (MARK_BIT_NO): Cast offset argument to word
instead of unsigned.
* malloc.c (GC_free): Cast hhdr->hb_sz to size_t.
* mallocx.c (GC_get_kind_and_size): Likewise.
* mark.c (GC_clear_hdr_marks): Likewise.
* misc.c (GC_size): Likewise.
* misc.c (GC_do_blocking): Remove redundant cast of hhdr->hb_sz.
* reclaim.c (GC_reclaim_clear, GC_reclaim_uninit,
GC_disclaim_and_reclaim, GC_continue_reclaim): Change type of sz
argument from size_t to word.
* typd_mlc.c (GC_array_mark_proc): Change type of sz and nwords local
variables from size_t to word.
Thread Sanitizer reports data races between fill_size_map (called from
GC_extend_size_map) and GC_gcj_malloc[_ignore_off_page],
GC_malloc_kind_global, GC_generic_malloc_uncollectable,
GC_malloc_explicitly_typed_ignore_off_page which read a value from
GC_size_map before acquiring the allocation lock. These races could
be ignored as the value is verified after acquiring the lock.
* alloc.c: Refine comment about GC_allocobj (and GC_size_map) usage
for the case of a multi-threaded environment.
* malloc.c (fill_size_map): New static function (with
GC_ATTR_NO_SANITIZE_THREAD attribute).
* malloc.c (GC_extend_size_map): Use fill_size_map() to fill in
a region of GC_size_map.
(code refactoring)
* include/private/gc_priv.h (GC_extend_size_map): Remove prototype.
* malloc.c (GC_extend_size_map): Move the function definition from
misc.c; change GC_INNER to STATIC; reformat code; remove j and
much_smaller_than_i local variables; add assertions that I_HOLD_LOCK
and GC_size_map[i]==0; remove comment that GC_size_map[i] is expected
to be zero.
* malloc.c (GC_generic_malloc_inner): Capitalize the first letter of
the description comment.
* misc.c (GC_extend_size_map): Remove the definition.
* dbg_mlc.c [REDIRECT_MALLOC && (GC_LINUX_THREADS || GC_SOLARIS_THREADS
|| MSWIN32 || NEED_CALLINFO && GC_HAVE_BUILTIN_BACKTRACE)]
(GC_debug_free): If the object is not in the GC heap then just return
(instead of ABORT).
* malloc.c [REDIRECT_MALLOC && NEED_CALLINFO
&& GC_HAVE_BUILTIN_BACKTRACE] (GC_free): If hhdr is null (i.e. the
object is not in the GC heap) then return without the object
deallocation; add comment.
* os_dep.c [NEED_CALLINFO && GC_HAVE_BUILTIN_BACKTRACE
&& !GC_BACKTRACE_SYMBOLS_BROKEN] (GC_print_callers): Adjust comment
for free().
* gcj_mlc.c [GC_GCJ_SUPPORT] (GC_core_gcj_malloc,
GC_gcj_malloc_ignore_off_page): Cast lg local variable to word before
passing it to GRANULES_TO_BYTES (so that value type widening does not
occur after the value left shift).
* malloc.c (GC_generic_malloc_inner, GC_malloc_kind_global,
GC_generic_malloc_uncollectable): Likewise.
* typd_mlc.c (GC_malloc_explicitly_typed_ignore_off_page): Likewise.
* misc.c (block_add_size): Cast hhdr->hb_sz to word before passing it
to WORDS_TO_BYTES; cast HBLKSIZE-1 to word before "~" operation.
* malloc.c [REDIRECT_MALLOC && GC_LINUX_THREADS] (GC_init_lib_bounds):
Declare cancel_state local variable; DISABLE_CANCEL for GC_text_mapping
(because GC_repeat_read expects the cancellation state off); call
RESTORE_CANCEL on return.
The messages are eliminated for the macros: __int64, _SIGRTMIN,
ARM_THREAD_STATE32, ARM_UNIFIED_THREAD_STATE, FIXUP_POINTER,
GC_COLLECT_AT_MALLOC, GC_FREE_SPACE_DIVISOR, GC_FULL_FREQ,
GC_INITIAL_HEAP_SIZE, GC_MAX_RETRIES, GC_MAXIMUM_HEAP_SIZE,
GC_MIN_MARKERS, GC_SIG_SUSPEND, GC_SIG_THR_RESTART, GC_TIME_LIMIT,
HEURISTIC2_LIMIT, MAP_ANONYMOUS, RTLD_DI_LINKMAP, SAVE_CALL_COUNT,
SIZE_MAX.
* alloc.c (GC_full_freq, GC_free_space_divisor, GC_time_limit): Define
to default immediate value if CPPCHECK.
* darwin_stop_world.c [ARM32 && ARM_THREAD_STATE32]
(GC_ARM_UNIFIED_THREAD_STATE): New macro (defined to
ARM_UNIFIED_THREAD_STATE unless CPPCHECK).
* darwin_stop_world.c [ARM32 && ARM_THREAD_STATE32]
(GC_stack_range_for): Use GC_ARM_UNIFIED_THREAD_STATE; do not use value
of ARM_THREAD_STATE32 if CPPCHECK.
* dyn_load.c [!USE_PROC_FOR_LIBRARIES] (GC_RTLD_DI_LINKMAP): New macro
(defined to RTLD_DI_LINKMAP unless CPPCHECK).
* dyn_load.c [!USE_PROC_FOR_LIBRARIES] (GC_FirstDLOpenedLinkMap): Use
GC_RTLD_DI_LINKMAP.
* include/gc.h (GC_word, GC_signed_word): Do not define to __int64 if
CPPCHECK.
* include/gc.h (GC_INIT_CONF_MAX_RETRIES,
GC_INIT_CONF_FREE_SPACE_DIVISOR, GC_INIT_CONF_FULL_FREQ,
GC_INIT_CONF_TIME_LIMIT, GC_INIT_CONF_SUSPEND_SIGNAL,
GC_INIT_CONF_THR_RESTART_SIGNAL, GC_MAXIMUM_HEAP_SIZE,
GC_INITIAL_HEAP_SIZE): Define to empty if CPPCHECK.
* include/private/gc_priv.h [SIZE_MAX] (GC_SIZE_MAX): Do not define to
SIZE_MAX if CPPCHECK.
* include/private/gc_priv.h [DARWIN && ARM32
&& ARM_UNIFIED_THREAD_STATE] (GC_MACH_THREAD_STATE): Do not define to
ARM_UNIFIED_THREAD_STATE if CPPCHECK.
* include/private/gc_priv.h [GC_PTHREADS && _SIGRTMIN] (SIG_SUSPEND):
Do not define to _SIGRTMIN if CPPCHECK.
* pthread_stop_world.c [!SIG_THR_RESTART && _SIGRTMIN]
(SIG_THR_RESTART): Likewise.
* include/private/gcconfig.h [SAVE_CALL_CHAIN && SAVE_CALL_COUNT]
(NFRAMES): Define to immediate value (do not use value of
SAVE_CALL_COUNT) if CPPCHECK.
* include/private/gcconfig.h [!FIXUP_POINTER && POINTER_MASK]
(FIXUP_POINTER): Define to a sample expression (not using values of
POINTER_MASK and POINTER_SHIFT) if CPPCHECK.
* malloc.c [GC_COLLECT_AT_MALLOC] (GC_dbg_collect_at_malloc_min_lb):
Define to sample value (not using value of GC_COLLECT_AT_MALLOC) if
CPPCHECK.
* misc.c [GC_INITIAL_HEAP_SIZE] (GC_init): Define to default immediate
value if CPPCHECK.
* os_dep.c [!BEOS && !OS2 && !SWIN32 && !GC_OPENBSD_THREADS
&& !STACKBOTTOM && HEURISTIC2_LIMIT] (GC_get_main_stack_base): Do not
use value of HEURISTIC2_LIMIT if CPPCHECK.
* os_dep.c [USE_MMAP_ANON && MAP_ANONYMOUS] (OPT_MAP_ANON): Do not use
value of MAP_ANONYMOUS if CPPCHECK.
* pthread_stop_world.c [GC_ENABLE_SUSPEND_THREAD && !GC_TIME_LIMIT]
(GC_TIME_LIMIT): Do not define.
* pthread_stop_world.c [GC_ENABLE_SUSPEND_THREAD]
(GC_brief_async_signal_safe_sleep): Do not use value of GC_TIME_LIMIT
if CPPCHECK.
* pthread_support.c [PARALLEL_MARK && GC_MIN_MARKERS] (GC_thr_init):
Do not use value of GC_MIN_MARKERS if CPPCHECK.
* win32_threads.c [PARALLEL_MARK && GC_MIN_MARKERS] (GC_thr_init):
Likewise.
* tests/test.c [GC_DEBUG && SAVE_CALL_CHAIN && SAVE_CALL_COUNT]
(check_heap_stats): Use NFRAMES instead of SAVE_CALL_COUNT (i.e. do not
use value of SAVE_CALL_COUNT).
See issue #135 on Github.
* allchblk.c (GC_allochblk, GC_allochblk_nth): Use
OBJ_SZ_TO_BLOCKS_CHECKED instead of OBJ_SZ_TO_BLOCKS.
* malloc.c (GC_alloc_large): Likewise.
* alloc.c (GC_expand_hp_inner): Type of "bytes" local variable changed
from word to size_t; cast ROUNDUP_PAGESIZE argument to size_t; prevent
overflow when computing GC_heapsize+bytes > GC_max_heapsize.
* dbg_mlc.c (GC_debug_malloc, GC_debug_malloc_ignore_off_page,
GC_debug_malloc_atomic_ignore_off_page, GC_debug_generic_malloc,
GC_debug_generic_malloc_inner,
GC_debug_generic_malloc_inner_ignore_off_page,
GC_debug_malloc_stubborn, GC_debug_malloc_atomic,
GC_debug_malloc_uncollectable, GC_debug_malloc_atomic_uncollectable):
Use SIZET_SAT_ADD (instead of "+" operator) to add extra bytes to lb
value.
* fnlz_mlc.c (GC_finalized_malloc): Likewise.
* gcj_mlc.c (GC_debug_gcj_malloc): Likewise.
* include/private/gc_priv.h (ROUNDUP_GRANULE_SIZE, ROUNDED_UP_GRANULES,
ADD_SLOP, ROUNDUP_PAGESIZE): Likewise.
* include/private/gcconfig.h (GET_MEM): Likewise.
* mallocx.c (GC_malloc_many, GC_memalign): Likewise.
* os_dep.c (GC_wince_get_mem, GC_win32_get_mem): Likewise.
* typd_mlc.c (GC_malloc_explicitly_typed,
GC_malloc_explicitly_typed_ignore_off_page,
GC_calloc_explicitly_typed): Likewise.
* headers.c (GC_scratch_alloc): Change type of bytes_to_get from word
to size_t (because ROUNDUP_PAGESIZE_IF_MMAP result type changed).
* include/private/gc_priv.h: Include limits.h (unless SIZE_MAX already
defined).
* include/private/gc_priv.h (GC_SIZE_MAX, GC_SQRT_SIZE_MAX): Move from
malloc.c file.
* include/private/gc_priv.h (SIZET_SAT_ADD): New macro (defined before
include gcconfig.h).
* include/private/gc_priv.h (EXTRA_BYTES, GC_page_size): Change type
to size_t.
* os_dep.c (GC_page_size): Likewise.
* include/private/gc_priv.h (ROUNDUP_GRANULE_SIZE, ROUNDED_UP_GRANULES,
ADD_SLOP, ROUNDUP_PAGESIZE): Add comment about the argument.
* include/private/gcconfig.h (GET_MEM): Likewise.
* include/private/gc_priv.h (ROUNDUP_GRANULE_SIZE, ROUNDED_UP_GRANULES,
ADD_SLOP, OBJ_SZ_TO_BLOCKS, ROUNDUP_PAGESIZE,
ROUNDUP_PAGESIZE_IF_MMAP): Rename argument to "lb".
* include/private/gc_priv.h (OBJ_SZ_TO_BLOCKS_CHECKED): New macro.
* include/private/gcconfig.h (GC_win32_get_mem, GC_wince_get_mem,
GC_unix_get_mem): Change argument type from word to int.
* os_dep.c (GC_unix_mmap_get_mem, GC_unix_get_mem,
GC_unix_sbrk_get_mem, GC_wince_get_mem, GC_win32_get_mem): Likewise.
* malloc.c (GC_alloc_large_and_clear): Call OBJ_SZ_TO_BLOCKS only
if no value wrap around is guaranteed.
* malloc.c (GC_generic_malloc): Do not check for lb_rounded < lb case
(because ROUNDED_UP_GRANULES and GRANULES_TO_BYTES guarantees no value
wrap around).
* mallocx.c (GC_generic_malloc_ignore_off_page): Likewise.
* misc.c (GC_init_size_map): Change "i" local variable type from int
to size_t.
* os_dep.c (GC_write_fault_handler, catch_exception_raise): Likewise.
* misc.c (GC_envfile_init): Cast len to size_t when passed to
ROUNDUP_PAGESIZE_IF_MMAP.
* os_dep.c (GC_setpagesize): Cast GC_sysinfo.dwPageSize and
GETPAGESIZE() to size_t (when setting GC_page_size).
* os_dep.c (GC_unix_mmap_get_mem, GC_unmap_start, GC_remove_protection):
Expand ROUNDUP_PAGESIZE macro but without value wrap-around checking
(the argument is of word type).
* os_dep.c (GC_unix_mmap_get_mem): Replace -GC_page_size with
~GC_page_size+1 (because GC_page_size is unsigned); remove redundant
cast to size_t.
* os_dep.c (GC_unix_sbrk_get_mem): Add explicit cast of GC_page_size
to SBRK_ARG_T.
* os_dep.c (GC_wince_get_mem): Change type of res_bytes local variable
to size_t.
* typd_mlc.c: Do not include limits.h.
* typd_mlc.c (GC_SIZE_MAX, GC_SQRT_SIZE_MAX): Remove (as defined in
gc_priv.h now).
(for GC_NO_FINALIZATION case)
* include/private/gc_priv.h (GC_generic_malloc_inner_ignore_off_page):
Do not declare unless DBG_HDRS_ALL or GC_GCJ_SUPPORT, or
!GC_NO_FINALIZATION.
* malloc.c (GC_generic_malloc_inner_ignore_off_page): Do not define
unless DBG_HDRS_ALL or GC_GCJ_SUPPORT, or !GC_NO_FINALIZATION.