# TSan: ThreadSanitizer
# https://github.com/google/sanitizers/wiki/threadsanitizersuppressions
#
# This file describes a number of places where TSAN detects problems in CRuby.
# Many of these indicate bugs. Others are benign (ex. data races that can be
# replaced with relaxed atomic loads)
#
# Usage:
#   Configure with:
#     ./configure cflags='-fsanitize=thread' CC=clang
#   Build and run with:
#     TSAN_OPTIONS="suppressions=$(pwd)/misc/tsan_suppressions.txt:die_after_fork=0"
#
# Other useful TSAN_OPTIONS:
#   * halt_on_error=1
#   * strip_path_prefix=$(pwd)/

# Namespaces
race_top:push_subclass_entry_to_list

# sub_nounderflow includes non-atomic read, possibly other issue
race:objspace_malloc_increase_body

# Signals and ubf
race:unregister_ubf_list

# It's already crashing. We're doing our best
signal:rb_vm_bugreport
race:check_reserved_signal_

race_top:rb_check_deadlock

# vm->ractor.sched.grq_cnt++
race_top:ractor_sched_enq
race_top:ractor_sched_deq

# Race between vm_remove_ractor writing ractor count and
# native_thread_check_and_create_shared reading it during thread creation.
# The write happens when a ractor thread exits, the read happens when
# checking if new shared threads need to be created.
race:vm_remove_ractor

# th->sched.finished at end of co_start
race_top:rb_thread_sched_mark_zombies

# Races against timer thread setting th->sched.waiting_reason.flags
race_top:thread_sched_wait_events

# At thread start
race_top:rb_ractor_set_current_ec_

# TSan reports a lock-order-inversion between thread_sched_lock_ and this lock.
# It's unclear if that can cause a deadlock since the lock is on self
deadlock:ractor_lock_self

# TSan reports a deadlock when reacquiring the this lock after a barrier, but
# we know the other threads have been stopped
deadlock:rb_ractor_sched_barrier_start

# RVALUE_AGE_SET manipulates flag bits on objects which may be accessed in Ractors
race_top:RVALUE_AGE_SET

# Inline caches and call cache updates
# Multiple threads can race when updating shared call caches during method lookups
# and argument forwarding. These races involve reading/writing cd->cc fields.
race_top:vm_cc_call_set
race_top:vm_cc_class_check
race_top:vm_search_cc
race_top:vm_search_method_slowpath0
race_top:rb_vm_opt_getconstant_path
race_top:vm_ic_attr_index_set
race:vm_ic_update
race:vm_caller_setup_fwd_args

# Race in shape_get_next where multiple threads simultaneously access and modify
# RCLASS_MAX_IV_COUNT and RCLASS_VARIATION_COUNT fields in class objects.
# One thread reads the field while another thread calls RCLASS_SET_MAX_IV_COUNT.
# This happens during instance variable shape transitions in multi-threaded code.
race:shape_get_next

# Non-atomic reads/writes
race:gccct_method_search

# Ignore exit for now
race:rb_ec_finalize
race:rb_ec_cleanup

# TSan doesn't work well post-fork, this raises errors when creating the new
# timer thread
race:after_fork_ruby

# Sets objspace->flags.dont_incremental while writebarrier may be running
race_top:objspace_each_exec
race_top:objspace_each_objects_ensure

# Non-atomic lazy initialized static variable
race_top:rbimpl_intern_const

# Setting def->aliased bitfield non-atomically
race_top:method_definition_addref

# Switching to setting up tracing. Likely other ractors should be stopped for this.
race_top:encoded_iseq_trace_instrument
race:rb_iseq_trace_set_all
race:rb_tracepoint_enable

# GC enable/disable flag modifications race with object allocation flag reads
race_top:rb_gc_impl_gc_disable
race_top:rb_gc_impl_gc_enable
