summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hawthorn <[email protected]>2025-05-14 18:28:53 -0700
committerJohn Hawthorn <[email protected]>2025-05-20 09:56:31 -0700
commit05e0e7223acbc9ab223dd8f4b342d5eb6d3ae8c7 (patch)
tree15c3ed684845a6828e0935e87c6d90c2a3c46aec
parentcd15cc250fa7dc6482833327728eeff641d2e41d (diff)
Use atomic load to read interrupt mask
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/13357
-rw-r--r--misc/tsan_suppressions.txt5
-rw-r--r--ruby_atomic.h16
-rw-r--r--thread.c3
-rw-r--r--vm_core.h10
4 files changed, 25 insertions, 9 deletions
diff --git a/misc/tsan_suppressions.txt b/misc/tsan_suppressions.txt
index c788e927dd..7d6c11987c 100644
--- a/misc/tsan_suppressions.txt
+++ b/misc/tsan_suppressions.txt
@@ -25,11 +25,6 @@ race:objspace_malloc_increase_body
race_top:rb_signal_buff_size
race:unregister_ubf_list
-# interrupt flag is set atomically, but read non-atomically
-race_top:RUBY_VM_INTERRUPTED_ANY
-race_top:unblock_function_set
-race_top:threadptr_get_interrupts
-
# It's already crashing. We're doing our best
signal:rb_vm_bugreport
race:check_reserved_signal_
diff --git a/ruby_atomic.h b/ruby_atomic.h
index 57d341082d..085c307ac6 100644
--- a/ruby_atomic.h
+++ b/ruby_atomic.h
@@ -1,3 +1,6 @@
+#ifndef INTERNAL_ATOMIC_H
+#define INTERNAL_ATOMIC_H
+
#include "ruby/atomic.h"
/* shim macros only */
@@ -21,3 +24,16 @@
#define ATOMIC_SUB(var, val) RUBY_ATOMIC_SUB(var, val)
#define ATOMIC_VALUE_CAS(var, oldval, val) RUBY_ATOMIC_VALUE_CAS(var, oldval, val)
#define ATOMIC_VALUE_EXCHANGE(var, val) RUBY_ATOMIC_VALUE_EXCHANGE(var, val)
+
+static inline rb_atomic_t
+rbimpl_atomic_load_relaxed(rb_atomic_t *ptr)
+{
+#if defined(HAVE_GCC_ATOMIC_BUILTINS)
+ return __atomic_load_n(ptr, __ATOMIC_RELAXED);
+#else
+ return *ptr;
+#endif
+}
+#define ATOMIC_LOAD_RELAXED(var) rbimpl_atomic_load_relaxed(&(var))
+
+#endif
diff --git a/thread.c b/thread.c
index 0494524510..dcd5a64f6b 100644
--- a/thread.c
+++ b/thread.c
@@ -2465,8 +2465,9 @@ threadptr_get_interrupts(rb_thread_t *th)
rb_atomic_t interrupt;
rb_atomic_t old;
+ old = ATOMIC_LOAD_RELAXED(ec->interrupt_flag);
do {
- interrupt = ec->interrupt_flag;
+ interrupt = old;
old = ATOMIC_CAS(ec->interrupt_flag, interrupt, interrupt & ec->interrupt_mask);
} while (old != interrupt);
return interrupt & (rb_atomic_t)~ec->interrupt_mask;
diff --git a/vm_core.h b/vm_core.h
index ed6d3fb401..d6afd585d2 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -2102,8 +2102,12 @@ enum {
#define RUBY_VM_SET_TRAP_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TRAP_INTERRUPT_MASK)
#define RUBY_VM_SET_TERMINATE_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TERMINATE_INTERRUPT_MASK)
#define RUBY_VM_SET_VM_BARRIER_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, VM_BARRIER_INTERRUPT_MASK)
-#define RUBY_VM_INTERRUPTED(ec) ((ec)->interrupt_flag & ~(ec)->interrupt_mask & \
- (PENDING_INTERRUPT_MASK|TRAP_INTERRUPT_MASK))
+
+static inline bool
+RUBY_VM_INTERRUPTED(rb_execution_context_t *ec)
+{
+ return (ATOMIC_LOAD_RELAXED(ec->interrupt_flag) & ~(ec->interrupt_mask) & (PENDING_INTERRUPT_MASK|TRAP_INTERRUPT_MASK));
+}
static inline bool
RUBY_VM_INTERRUPTED_ANY(rb_execution_context_t *ec)
@@ -2116,7 +2120,7 @@ RUBY_VM_INTERRUPTED_ANY(rb_execution_context_t *ec)
RUBY_VM_SET_TIMER_INTERRUPT(ec);
}
#endif
- return ec->interrupt_flag & ~(ec)->interrupt_mask;
+ return ATOMIC_LOAD_RELAXED(ec->interrupt_flag) & ~(ec)->interrupt_mask;
}
VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt);