diff --git a/ext/-test-/thread/instrumentation/extconf.rb b/ext/-test-/thread/instrumentation/extconf.rb index a48ba3c0451218..0d2c63c6a94ced 100644 --- a/ext/-test-/thread/instrumentation/extconf.rb +++ b/ext/-test-/thread/instrumentation/extconf.rb @@ -1,2 +1,3 @@ # frozen_string_literal: false +$INCFLAGS << " -I$(topdir) -I$(top_srcdir)" create_makefile("-test-/thread/instrumentation") diff --git a/ext/-test-/thread/instrumentation/instrumentation.c b/ext/-test-/thread/instrumentation/instrumentation.c index 25e2902a78601b..25965890179b16 100644 --- a/ext/-test-/thread/instrumentation/instrumentation.c +++ b/ext/-test-/thread/instrumentation/instrumentation.c @@ -1,6 +1,7 @@ #include "ruby/ruby.h" #include "ruby/atomic.h" #include "ruby/thread.h" +#include "internal/gc.h" #ifndef RB_THREAD_LOCAL_SPECIFIER # define RB_THREAD_LOCAL_SPECIFIER @@ -19,9 +20,11 @@ static rb_atomic_t timeline_cursor; static void event_timeline_gc_mark(void *ptr) { + /* Hook sees every Ractor's threads; validate membership before marking. */ + rb_atomic_t n = RUBY_ATOMIC_LOAD(timeline_cursor); rb_atomic_t cursor; - for (cursor = 0; cursor < timeline_cursor; cursor++) { - rb_gc_mark(event_timeline[cursor].thread); + for (cursor = 0; cursor < n; cursor++) { + rb_gc_mark_maybe(event_timeline[cursor].thread); } } @@ -42,14 +45,12 @@ reset_timeline(void) static rb_event_flag_t find_last_event(VALUE thread) { - rb_atomic_t cursor = timeline_cursor; - if (cursor) { - do { - if (event_timeline[cursor].thread == thread){ - return event_timeline[cursor].event; - } - cursor--; - } while (cursor > 0); + rb_atomic_t cursor = RUBY_ATOMIC_LOAD(timeline_cursor); + while (cursor > 0) { + cursor--; + if (event_timeline[cursor].thread == thread) { + return event_timeline[cursor].event; + } } return 0; } @@ -166,6 +167,7 @@ event_symbol(rb_event_flag_t event) } } +// NOTE: only safe when there's a single active Ractor static VALUE thread_unregister_callback(VALUE thread) { @@ -174,11 +176,15 @@ thread_unregister_callback(VALUE thread) single_hook = NULL; } - VALUE events = rb_ary_new_capa(timeline_cursor); + rb_atomic_t n = RUBY_ATOMIC_LOAD(timeline_cursor); + VALUE events = rb_ary_new_capa(n); rb_atomic_t cursor; - for (cursor = 0; cursor < timeline_cursor; cursor++) { + for (cursor = 0; cursor < n; cursor++) { + VALUE th = event_timeline[cursor].thread; + /* Skip foreign-objspace threads: pushing them into this Array would violate containment. */ + if (rb_objspace_foreign_object_p(th)) continue; VALUE pair = rb_ary_new_capa(2); - rb_ary_push(pair, event_timeline[cursor].thread); + rb_ary_push(pair, th); rb_ary_push(pair, event_symbol(event_timeline[cursor].event)); rb_ary_push(events, pair); } diff --git a/ext/digest/blake3/extconf.rb b/ext/digest/blake3/extconf.rb index c4706593ba6cd2..b02bb074c1447e 100644 --- a/ext/digest/blake3/extconf.rb +++ b/ext/digest/blake3/extconf.rb @@ -29,7 +29,9 @@ def blake3_disable(macro) end # Probe used to confirm the compiler both accepts +flag+ and can compile the -# intrinsics the backend relies on. +# intrinsics the backend relies on. It compiles the backend source itself: +# a small snippet misses assemblers that reject what the compiler emits (e.g. +# binutils 2.30 on RHEL 8 rejects AVX-512 code from gcc 8.5). def blake3_have_isa?(name, flag, snippet) checking_for("#{name} intrinsics" + (flag ? " (#{flag})" : "")) do try_compile(snippet, flag) @@ -40,23 +42,15 @@ def blake3_have_isa?(name, flag, snippet) when /\A(x86_64|amd64|x64)\z/i # Try to detect which SIMD features this x86 machine and compiler has x86_backends = [ - ["blake3_sse2", "SSE2", ["-msse2", "-arch:SSE2"], - "#include \nint main(void){ volatile __m128i x = _mm_setzero_si128(); (void)x; return 0; }\n", - "BLAKE3_NO_SSE2"], - ["blake3_sse41", "SSE4.1", ["-msse4.1", "-arch:AVX"], - "#include \nint main(void){ volatile __m128i x = _mm_setzero_si128(); return _mm_testz_si128(x, x); }\n", - "BLAKE3_NO_SSE41"], - ["blake3_avx2", "AVX2", ["-mavx2", "-arch:AVX2"], - "#include \nint main(void){ volatile __m256i x = _mm256_setzero_si256(); (void)x; return 0; }\n", - "BLAKE3_NO_AVX2"], - ["blake3_avx512", "AVX-512", ["-mavx512f -mavx512vl", "-arch:AVX512"], - "#include \nint main(void){ volatile __m512i x = _mm512_setzero_si512(); (void)x; return 0; }\n", - "BLAKE3_NO_AVX512"], + ["blake3_sse2", "SSE2", ["-msse2", "-arch:SSE2"], "BLAKE3_NO_SSE2"], + ["blake3_sse41", "SSE4.1", ["-msse4.1", "-arch:AVX"], "BLAKE3_NO_SSE41"], + ["blake3_avx2", "AVX2", ["-mavx2", "-arch:AVX2"], "BLAKE3_NO_AVX2"], + ["blake3_avx512", "AVX-512", ["-mavx512f -mavx512vl", "-arch:AVX512"], "BLAKE3_NO_AVX512"], ] - x86_backends.each do |obj, name, flags, snippet, no_macro| + x86_backends.each do |obj, name, flags, no_macro| [nil, *flags].any? do |flag| - if blake3_have_isa?(name, flag, snippet) + if blake3_have_isa?(name, flag, %{#include "#{$srcdir}/#{obj}.c"\n}) objs << obj simd_cflags[obj] = flag true diff --git a/test/-ext-/thread/test_instrumentation_api.rb b/test/-ext-/thread/test_instrumentation_api.rb index 04dddc7496e808..55c50a28b04acc 100644 --- a/test/-ext-/thread/test_instrumentation_api.rb +++ b/test/-ext-/thread/test_instrumentation_api.rb @@ -134,8 +134,6 @@ def test_queue_releases_gvl end def test_blocking_on_ractor - # TODO: turn back on and fix when ractor-local GC (rlgc) lands - omit "this is failing CI and rlgc will change how this works so let's wait until it lands to fix it" if ENV["GITHUB_WORKFLOW"] assert_ractor(<<-"RUBY", require_relative: "helper", require: "-test-/thread/instrumentation") include ThreadInstrumentation::TestHelper @@ -163,9 +161,6 @@ def test_blocking_on_ractor end def test_sleeping_inside_ractor - # TODO: turn back and fix when ractor-local GC (rlgc) lands - omit "This test is flaky and intermittently failing" if ENV['GITHUB_WORKFLOW'] - assert_ractor(<<-"RUBY", require_relative: "helper", require: "-test-/thread/instrumentation") include ThreadInstrumentation::TestHelper