diff --git a/bignum.c b/bignum.c index d95444a56378e3..1c4fc094c2f06c 100644 --- a/bignum.c +++ b/bignum.c @@ -6371,11 +6371,6 @@ rb_big_fdiv_double(VALUE x, VALUE y) return NUM2DBL(v); } -VALUE -rb_big_fdiv(VALUE x, VALUE y) -{ - return DBL2NUM(rb_big_fdiv_double(x, y)); -} VALUE rb_big_pow(VALUE x, VALUE y) diff --git a/bootstraptest/test_gc.rb b/bootstraptest/test_gc.rb index eb68c9845e37c9..6e3dee731437b8 100644 --- a/bootstraptest/test_gc.rb +++ b/bootstraptest/test_gc.rb @@ -32,3 +32,14 @@ end end }, '[ruby-dev:39453]' + +assert_normal_exit %q{ + # A class whose instances start with a complex shape: as.extended must be + # initialized before the fields object allocation can trigger a GC. + ivars = 1024.times.map { |i| "@iv_#{i} = #{i}\n" }.join + klass = Class.new + klass.class_eval "def initialize() #{ivars} end" + GC.stress = true + klass.allocate + GC.stress = false +}, 'complex T_OBJECT marked before as.extended is set' diff --git a/gc.c b/gc.c index 5187c748ee8483..fdb23a8e435520 100644 --- a/gc.c +++ b/gc.c @@ -1231,6 +1231,9 @@ static VALUE class_allocate_complex_instance(VALUE klass, uint32_t capacity) { VALUE obj = rb_newobj_of_with_shape(klass, T_OBJECT, rb_shape_transition_extended(ROOT_COMPLEX_SHAPE_ID), sizeof(struct RObject)); + // The shape already says extended, so a GC during the allocation below + // would mark an uninitialized as.extended. + ROBJECT(obj)->as.extended = Qfalse; VALUE fields_obj = rb_imemo_fields_new_complex(obj, ROOT_COMPLEX_SHAPE_ID, capacity, false); ROBJECT_SET_EXTENDED(obj, fields_obj); return obj; diff --git a/io.c b/io.c index 522c8da0484f66..d446991c281577 100644 --- a/io.c +++ b/io.c @@ -7428,11 +7428,6 @@ rb_io_synchronized(rb_io_t *fptr) fptr->mode |= FMODE_SYNC; } -void -rb_io_unbuffered(rb_io_t *fptr) -{ - rb_io_synchronized(fptr); -} int rb_pipe(int *pipes) diff --git a/lib/resolv.rb b/lib/resolv.rb index ae6d85204571d6..aac5cdd2161af0 100644 --- a/lib/resolv.rb +++ b/lib/resolv.rb @@ -880,20 +880,37 @@ def lazy_initialize @mutex.synchronize { next if @initialized @initialized = true - is_ipv6 = @host.index(':') - sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET) - @socks = [sock] - sock.do_not_reverse_lookup = true - DNS.bind_random_port(sock, is_ipv6 ? "::" : "0.0.0.0") - sock.connect(@host, @port) + connect_socket } self end + # The socket to talk to the nameserver over, opening one if there is + # none yet. #recv_reply may have replaced it since a sender was + # created, so senders ask for it per request instead of holding on to + # one. + def sock + lazy_initialize + @socks[0] + end + def recv_reply(readable_socks, timelimit = nil) lazy_initialize reply = readable_socks[0].recv(UDPSize) return reply, nil + rescue Errno::ECONNREFUSED, Errno::ECONNRESET + # The kernel reports these from an ICMP message, and a second one for + # the same pair of endpoints is not always passed on: macOS 26.1 and + # later deliver every other one. A retry over this socket would then + # wait out its whole timeout rather than fail at once, so start over + # from a new source port. + @mutex.synchronize { + if @initialized + @socks&.each(&:close) + connect_socket + end + } + raise end def sender(msg, data, host=@host, port=@port) @@ -904,7 +921,7 @@ def sender(msg, data, host=@host, port=@port) id = DNS.allocate_request_id(@host, @port) request = msg.encode request[0,2] = [id].pack('n') - return @senders[[nil,id]] = Sender.new(request, data, @socks[0]) + return @senders[[nil,id]] = Sender.new(request, data, self) end def close @@ -919,10 +936,23 @@ def close end end + private def connect_socket + is_ipv6 = @host.index(':') + sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET) + @socks = [sock] + sock.do_not_reverse_lookup = true + DNS.bind_random_port(sock, is_ipv6 ? "::" : "0.0.0.0") + sock.connect(@host, @port) + end + class Sender < Requester::Sender # :nodoc: + def initialize(msg, data, requester) + super(msg, data, nil) + @requester = requester + end + def send - raise "@sock is nil." if @sock.nil? - @sock.send(@msg, 0) + @requester.sock.send(@msg, 0) end attr_reader :data end diff --git a/ractor.c b/ractor.c index 4714ad94a2f16a..3c2b54425cebb8 100644 --- a/ractor.c +++ b/ractor.c @@ -1452,11 +1452,6 @@ rb_ractor_stderr_set(VALUE err) } } -rb_hook_list_t * -rb_ractor_hooks(rb_ractor_t *cr) -{ - return &cr->pub.hooks; -} st_table * rb_ractor_targeted_hooks(rb_ractor_t *cr) diff --git a/spec/syntax_suggest/integration/ruby_command_line_spec.rb b/spec/syntax_suggest/integration/ruby_command_line_spec.rb index 761bd760b5d56a..1cd0615507e0ce 100644 --- a/spec/syntax_suggest/integration/ruby_command_line_spec.rb +++ b/spec/syntax_suggest/integration/ruby_command_line_spec.rb @@ -208,7 +208,7 @@ def lol puts "haha" EOM - out = `SYNTAX_SUGGEST_DEBUG=1 #{ruby} -I#{lib_dir} -rsyntax_suggest -r#{monkeypatch} #{script} 2>&1` + out = IO.popen({"SYNTAX_SUGGEST_DEBUG" => "1"}, "#{ruby} -I#{lib_dir} -rsyntax_suggest -r#{monkeypatch} #{script} 2>&1", &:read) expect($?.success?).to be_falsey expect(out).to include("boom from monkeypatch") diff --git a/test/-ext-/bug_reporter/test_bug_reporter.rb b/test/-ext-/bug_reporter/test_bug_reporter.rb index 4b654acc251c44..0f262864a726c0 100644 --- a/test/-ext-/bug_reporter/test_bug_reporter.rb +++ b/test/-ext-/bug_reporter/test_bug_reporter.rb @@ -6,7 +6,6 @@ class TestBugReporter < Test::Unit::TestCase def test_bug_reporter_add - omit if macos? && ENV["CI"] # we're getting timeouts even after 100s in CI description = RUBY_DESCRIPTION description = description.sub(/\+PRISM /, '') unless ParserSupport.prism_enabled_in_subprocess? expected_stderr = [ @@ -26,7 +25,8 @@ def test_bug_reporter_add args.push("--zjit") if JITSupport.zjit_enabled? args.unshift({"RUBY_ON_BUG" => nil, "RUBY_CRASH_REPORT" => nil}) stdin = "#{no_core}register_sample_bug_reporter(12345); Bug.segv" - assert_in_out_err(args, stdin, [], expected_stderr, encoding: "ASCII-8BIT") + # Writing the report is slow, see TestRubyOptions#assert_segv. + assert_in_out_err(args, stdin, [], expected_stderr, encoding: "ASCII-8BIT", timeout: 60) ensure FileUtils.rm_rf(tmpdir) if tmpdir end diff --git a/test/resolv/test_dns.rb b/test/resolv/test_dns.rb index f2649ac7a75800..5b726054e67c5b 100644 --- a/test/resolv/test_dns.rb +++ b/test/resolv/test_dns.rb @@ -525,8 +525,6 @@ def test_no_server if RUBY_PLATFORM.match?(/mingw/) # cannot repo locally omit 'Timeout Error on MinGW CI' - elsif macos?([26,1]..[]) - omit 'Timeout Error on macOS 26.1+' else raise Timeout::Error end diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb index 59ddc8c9bf468b..8f05c83ebc2d18 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -1821,7 +1821,6 @@ def test_slice_out_of_range end def test_slice_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress { assert_equal([1, 2, 3, 4, 5], (0..10).to_a[1, 5]) } EnvUtil.under_gc_compact_stress do a = [0, 1, 2, 3, 4, 5] diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb index 9b972d7b22e1aa..7a461ff2982d0c 100644 --- a/test/ruby/test_enumerator.rb +++ b/test/ruby/test_enumerator.rb @@ -128,7 +128,6 @@ def test_with_index end def test_with_index_under_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do assert_equal([[1, 0], [2, 1], [3, 2]], @obj.to_enum(:foo, 1, 2, 3).with_index.to_a) assert_equal([[1, 5], [2, 6], [3, 7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a) @@ -864,7 +863,6 @@ def test_lazy_chain end def test_lazy_chain_under_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do ea = (10..).lazy.select(&:even?).take(10) ed = (20..).lazy.select(&:odd?) diff --git a/test/ruby/test_eval.rb b/test/ruby/test_eval.rb index d2145bec5d9f13..b880b03e08f5d8 100644 --- a/test/ruby/test_eval.rb +++ b/test/ruby/test_eval.rb @@ -639,7 +639,6 @@ def test_syntax_error_no_memory_leak def test_outer_local_variable_under_gc_compact_stress omit "compaction is not supported on this platform" unless GC.respond_to?(:compact) - omit "compaction is not supported on s390x" if /s390x/ =~ RUBY_PLATFORM assert_separately([], <<~RUBY) o = Object.new diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb index 9790f9ec9c46fd..0562897afe47b7 100644 --- a/test/ruby/test_exception.rb +++ b/test/ruby/test_exception.rb @@ -1478,8 +1478,6 @@ def test_detailed_message end def test_detailed_message_under_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 - # The first error display lazily requires did_you_mean and friends; inside the # block that library load costs one full mark+compact per allocation, enough to # trip the parallel runner's no-response timeout. Load it here instead. diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb index c4b49b9cd653fa..3e5c6f2aaabf30 100644 --- a/test/ruby/test_gc_compact.rb +++ b/test/ruby/test_gc_compact.rb @@ -1,11 +1,6 @@ # frozen_string_literal: true require 'test/unit' -if RUBY_PLATFORM =~ /s390x/ - warn "Currently, it is known that the compaction does not work well on s390x; contribution is welcome https://github.com/ruby/ruby/pull/5077" - return -end - class TestGCCompact < Test::Unit::TestCase module CompactionSupportInspector def supports_compact? diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb index cf21d9942835b4..6285c9e1a410bf 100644 --- a/test/ruby/test_method.rb +++ b/test/ruby/test_method.rb @@ -492,7 +492,6 @@ def m.bar; :bar; end end def test_clone_under_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do o = Object.new def o.foo; :foo; end diff --git a/test/ruby/test_ractor.rb b/test/ruby/test_ractor.rb index 5b21ee361dfad2..93af32a3a1741d 100644 --- a/test/ruby/test_ractor.rb +++ b/test/ruby/test_ractor.rb @@ -356,7 +356,7 @@ def test_require_non_string # [Bug #21398] def test_port_receive_dnt_with_port_send - omit 'unstable on windows and macos-14' if RUBY_PLATFORM =~ /mswin|mingw|darwin/ + omit 'unstable on windows' if RUBY_PLATFORM =~ /mswin|mingw/ assert_ractor(<<~'RUBY', timeout: 90) THREADS = 10 JOBS_PER_THREAD = 50 diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index 0518f5828e6c4e..a4575ebff9451e 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -73,7 +73,6 @@ def test_to_s end def test_to_s_under_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do str = "abcd\u3042" [:UTF_16BE, :UTF_16LE, :UTF_32BE, :UTF_32LE].each do |es| @@ -471,7 +470,6 @@ def test_inspect end def test_inspect_under_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do assert_equal('/(?-mix:\\/)|/', Regexp.union(/\//, "").inspect) end @@ -904,7 +902,6 @@ def test_match end def test_match_under_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do m = /(?.)(?[^aeiou])?(?.+)/.match("hoge\u3042") assert_equal("h", m.match(:foo)) @@ -2142,7 +2139,6 @@ def test_timeout_shorter_than_global end def test_timeout_longer_than_global - omit "timeout test is too unstable on s390x" if RUBY_PLATFORM =~ /s390x/ per_instance_redos_test(0.01, 0.5, 0.5) end diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index b50926591ebd76..71ccf0ed90f159 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -844,8 +844,12 @@ module SEGVTest KILL_SELF = "Bug.segv" end - def assert_segv(args, message=nil, list: SEGVTest::ExpectedStderrList, **opt, &block) - omit if macos? && ENV["CI"] # we're getting timeouts even after 100s in CI, not sure why. + # Turning the C level backtrace into file:line pairs walks the whole of the + # binary's debug info, and that is nearly all of what a crash costs: 0.8s of + # CPU with the dSYM in place against 0.01s without it, on an idle arm64 macOS + # host. The default subprocess budget of 10 seconds is meant for a child + # that does none of that work. + def assert_segv(args, message=nil, list: SEGVTest::ExpectedStderrList, timeout: 60, **opt, &block) # We want YJIT to be enabled in the subprocess if it's enabled for us # so that the Ruby description matches. env = Hash === args.first ? args.shift : {} @@ -867,7 +871,7 @@ def assert_segv(args, message=nil, list: SEGVTest::ExpectedStderrList, **opt, &b end assert_in_out_err(args, test_stdin, *tests, encoding: "ASCII-8BIT", - **SEGVTest::ExecOptions, **opt, &block) + timeout: timeout, **SEGVTest::ExecOptions, **opt, &block) end def test_segv_test diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index cc7e07fb363f34..2367d6bfd48a1b 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -926,7 +926,6 @@ def test_undump end def test_undump_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 a = S("Test") << 1 << 2 << 3 << 9 << 13 << 10 EnvUtil.under_gc_compact_stress do assert_equal(a, S('"Test\\x01\\x02\\x03\\t\\r\\n"').undump) @@ -1451,7 +1450,6 @@ def test_gsub end def test_gsub_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress { assert_equal(S("hll"), S("hello").gsub(/([aeiou])/, S('<\1>'))) } end @@ -1499,7 +1497,6 @@ def test_gsub! end def test_gsub_bang_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do a = S("hello") a.gsub!(/([aeiou])/, S('<\1>')) @@ -1870,7 +1867,6 @@ def test_scan end def test_scan_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress { assert_equal([["1a"], ["2b"], ["3c"]], S("1a2b3c").scan(/(\d.)/)) } end @@ -2418,7 +2414,6 @@ def o.to_s; self; end end def test_sub_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do m = /&(?.*?);/.match(S("aaa & yyy")) assert_equal("amp", m["foo"]) diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb index fa65dca22508b5..15f1eab78ef2d4 100644 --- a/test/ruby/test_symbol.rb +++ b/test/ruby/test_symbol.rb @@ -122,8 +122,6 @@ def test_inspect end def test_inspect_under_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 - EnvUtil.under_gc_compact_stress do assert_inspect_evaled(':testing') end diff --git a/test/ruby/test_transcode.rb b/test/ruby/test_transcode.rb index 29aff2cb2bbab0..6c3ae3a109f7eb 100644 --- a/test/ruby/test_transcode.rb +++ b/test/ruby/test_transcode.rb @@ -2398,7 +2398,6 @@ def test_ractor_lazy_load_encoding end def test_ractor_lazy_load_encoding_random - omit 'unstable on s390x' if RUBY_PLATFORM =~ /s390x/ assert_ractor("#{<<~"begin;"}\n#{<<~'end;'}", timeout: 30) begin; rs = [] diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb index e138633536dcd9..c7addcf77c162a 100644 --- a/test/ruby/test_variable.rb +++ b/test/ruby/test_variable.rb @@ -521,7 +521,6 @@ def test_external_ivars end def test_exivar_resize_with_compaction_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 objs = 10_000.times.map do ExIvar.new end diff --git a/test/ruby/test_weakkeymap.rb b/test/ruby/test_weakkeymap.rb index 91c1538076f9f4..850949825f1ba5 100644 --- a/test/ruby/test_weakkeymap.rb +++ b/test/ruby/test_weakkeymap.rb @@ -138,7 +138,6 @@ def test_compaction end def test_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress { ObjectSpace::WeakKeyMap.new } end diff --git a/test/ruby/test_weakmap.rb b/test/ruby/test_weakmap.rb index d240e35fd0b707..789a54789ac9ea 100644 --- a/test/ruby/test_weakmap.rb +++ b/test/ruby/test_weakmap.rb @@ -257,7 +257,6 @@ def test_compaction end def test_gc_compact_stress - omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress { ObjectSpace::WeakMap.new } end diff --git a/thread.c b/thread.c index ebaf61d963e075..56e7c2b5c15fd3 100644 --- a/thread.c +++ b/thread.c @@ -2861,7 +2861,7 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing) } if (postponed_job_interrupt) { - rb_postponed_job_flush(th->vm); + rb_postponed_job_flush(); } if (trap_interrupt) { @@ -5947,7 +5947,6 @@ Init_Thread_Mutex(void) { rb_thread_t *th = GET_THREAD(); - rb_native_mutex_initialize(&th->vm->workqueue_lock); rb_native_mutex_initialize(&th->vm->once_lock); rb_native_cond_initialize(&th->vm->once_cond); rb_native_mutex_initialize(&th->interrupt_lock); diff --git a/thread_pthread.c b/thread_pthread.c index 0aaaf5de6f852f..a10570317919c0 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -1226,21 +1226,6 @@ static int timer_thread_set_timeout(rb_vm_t *vm); #include "thread_sched_mn.c" - -void -rb_assert_sig(void) -{ - sigset_t oldmask; - pthread_sigmask(0, NULL, &oldmask); - if (sigismember(&oldmask, SIGVTALRM)) { - rb_bug("!!!"); - } - else { - RUBY_DEBUG_LOG("ok"); - } -} - - /* only use signal-safe system calls here */ static void signal_communication_pipe(int fd) diff --git a/tool/lib/envutil.rb b/tool/lib/envutil.rb index f1de2c8977ea83..176a8a4bc837f7 100644 --- a/tool/lib/envutil.rb +++ b/tool/lib/envutil.rb @@ -365,8 +365,6 @@ def under_gc_stress(stress = true) module_function :under_gc_stress def under_gc_compact_stress(val = :empty, &block) - raise "compaction doesn't work well on s390x. Omit the test in the caller." if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 - if GC.respond_to?(:auto_compact) auto_compact = GC.auto_compact GC.auto_compact = val diff --git a/tool/lib/test/unit.rb b/tool/lib/test/unit.rb index 71a21de62817c9..04e48621293670 100644 --- a/tool/lib/test/unit.rb +++ b/tool/lib/test/unit.rb @@ -1840,7 +1840,12 @@ def puke klass, meth, e "Failure:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n" when Timeout::Error @errors += 1 - "Timeout:\n#{klass}##{meth}\n" + # A worker that stopped responding is reported with a bare + # Timeout::Error and has nothing to say. One raised inside the + # test says what expired and carries the output of the + # subprocess that hung, which is all there is to go on. + detail = e.message == e.class.name ? "" : "#{e.message}\n" + "Timeout:\n#{klass}##{meth}\n#{detail}" else @errors += 1 bt = Test::filter_backtrace(e.backtrace).join "\n " diff --git a/variable.c b/variable.c index 8e7c528aec7627..2d4659637e0bc6 100644 --- a/variable.c +++ b/variable.c @@ -2790,15 +2790,6 @@ get_autoload_data(VALUE autoload_const_value, struct autoload_const **autoload_c return autoload_data; } -void -rb_autoload(VALUE module, ID name, const char *feature) -{ - if (!feature || !*feature) { - rb_raise(rb_eArgError, "empty feature name"); - } - - rb_autoload_str(module, name, rb_fstring_cstr(feature)); -} static void const_set(VALUE klass, ID id, VALUE val); static void const_added(VALUE klass, ID const_name); diff --git a/vm.c b/vm.c index f93fa106a94b80..0efad702883cec 100644 --- a/vm.c +++ b/vm.c @@ -3596,7 +3596,6 @@ ruby_vm_destruct(rb_vm_t *vm) } rb_objspace_free(objspace); } - rb_native_mutex_destroy(&vm->workqueue_lock); rb_native_mutex_destroy(&vm->once_lock); rb_native_cond_destroy(&vm->once_cond); /* after freeing objspace, you *can't* use ruby_xfree() */ @@ -3614,7 +3613,6 @@ ruby_vm_destruct(rb_vm_t *vm) return 0; } -size_t rb_vm_memsize_workqueue(struct ccan_list_head *workqueue); // vm_trace.c // Used for VM memsize reporting. Returns the size of the at_exit list by // looping through the linked list and adding up the size of the structs. @@ -3669,7 +3667,6 @@ vm_memsize(const void *ptr) return ( sizeof(rb_vm_t) + rb_vm_memsize_postponed_job_queue() + - rb_vm_memsize_workqueue(&vm->workqueue) + vm_memsize_at_exit_list(vm->at_exit) + (rb_st_memsize(&vm->ci_table) - sizeof(struct st_table)) + vm_memsize_builtin_function_table(vm->builtin_function_table) + diff --git a/vm_core.h b/vm_core.h index 97b1bfb694a3f7..8372f7ca4aa799 100644 --- a/vm_core.h +++ b/vm_core.h @@ -778,9 +778,6 @@ typedef struct rb_vm_struct { int src_encoding_index; - /* workqueue (thread-safe, NOT async-signal-safe) */ - struct ccan_list_head workqueue; /* <=> rb_workqueue_job.jnode */ - rb_nativethread_lock_t workqueue_lock; /* `once` completion event (see vm_once_dispatch) */ rb_nativethread_lock_t once_lock; @@ -2093,7 +2090,6 @@ void rb_thread_wakeup_timer_thread(int); static inline void rb_vm_living_threads_init(rb_vm_t *vm) { - ccan_list_head_init(&vm->workqueue); ccan_list_head_init(&vm->ractor.set); ccan_list_head_init(&vm->ractor.terminated_set); } @@ -2495,7 +2491,7 @@ int rb_thread_check_trap_pending(void); #define RUBY_EVENT_COVERAGE_LINE 0x010000 #define RUBY_EVENT_COVERAGE_BRANCH 0x020000 -void rb_postponed_job_flush(rb_vm_t *vm); +void rb_postponed_job_flush(void); void rb_postponed_job_trigger_for_ractor(unsigned int h, VALUE running_ractor); // ractor.c diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 4cf24f13c89e00..1f9d8acc805b09 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -6656,11 +6656,6 @@ rb_vm_opt_newarray_pack_buffer(rb_execution_context_t *ec, rb_num_t array_len, c return vm_opt_newarray_pack_buffer(ec, array_len, ptr, fmt, buffer); } -VALUE -rb_vm_opt_newarray_pack(rb_execution_context_t *ec, rb_num_t array_len, const VALUE *ptr, VALUE fmt) -{ - return vm_opt_newarray_pack_buffer(ec, array_len, ptr, fmt, Qundef); -} #undef id_cmp diff --git a/vm_trace.c b/vm_trace.c index 4fe5f0740d0c40..8b99335b95962e 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -1794,62 +1794,12 @@ Init_vm_trace(void) } /* - * Ruby actually has two separate mechanisms for enqueueing work from contexts - * where it is not safe to run Ruby code, to run later on when it is safe. One - * is async-signal-safe but more limited, and accessed through the - * `rb_postponed_job_preregister` and `rb_postponed_job_trigger` functions. The - * other is more flexible but cannot be used in signal handlers, and is accessed - * through the `rb_workqueue_register` function. - * - * The postponed job functions form part of Ruby's extension API, but the - * workqueue functions are for internal use only. + * Work enqueued from a context where it is not safe to run Ruby code, to run + * later on when it is safe. Registering is async-signal-safe, and is part of + * Ruby's extension API: rb_postponed_job_preregister and + * rb_postponed_job_trigger. */ -struct rb_workqueue_job { - struct ccan_list_node jnode; /* <=> vm->workqueue */ - rb_postponed_job_func_t func; - void *data; -}; - -// Used for VM memsize reporting. Returns the size of a list of rb_workqueue_job -// structs. Defined here because the struct definition lives here as well. -size_t -rb_vm_memsize_workqueue(struct ccan_list_head *workqueue) -{ - struct rb_workqueue_job *work = 0; - size_t size = 0; - - ccan_list_for_each(workqueue, work, jnode) { - size += sizeof(struct rb_workqueue_job); - } - - return size; -} - -/* - * thread-safe and called from non-Ruby thread - * returns FALSE on failure (ENOMEM), TRUE otherwise - */ -int -rb_workqueue_register(unsigned flags, rb_postponed_job_func_t func, void *data) -{ - struct rb_workqueue_job *wq_job = malloc(sizeof(*wq_job)); - rb_vm_t *vm = GET_VM(); - - if (!wq_job) return FALSE; - wq_job->func = func; - wq_job->data = data; - - rb_nativethread_lock_lock(&vm->workqueue_lock); - ccan_list_add_tail(&vm->workqueue, &wq_job->jnode); - rb_nativethread_lock_unlock(&vm->workqueue_lock); - - // TODO: current implementation affects only main ractor - RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(rb_vm_main_ractor_ec(vm)); - - return TRUE; -} - #define PJOB_TABLE_SIZE (sizeof(rb_atomic_t) * CHAR_BIT) /* pre-registered jobs table, for async-safe jobs */ typedef struct rb_postponed_job_queue { @@ -1971,20 +1921,13 @@ rb_postponed_job_trigger_for_ractor(unsigned int h, VALUE running_ractor) } void -rb_postponed_job_flush(rb_vm_t *vm) +rb_postponed_job_flush(void) { rb_postponed_job_queues_t *pjq = &postponed_job_queue; rb_execution_context_t *ec = GET_EC(); const rb_atomic_t block_mask = POSTPONED_JOB_INTERRUPT_MASK | TRAP_INTERRUPT_MASK; volatile rb_atomic_t saved_mask = ec->interrupt_mask & block_mask; VALUE volatile saved_errno = ec->errinfo; - struct ccan_list_head tmp; - - ccan_list_head_init(&tmp); - - rb_nativethread_lock_lock(&vm->workqueue_lock); - ccan_list_append_list(&tmp, &vm->workqueue); - rb_nativethread_lock_unlock(&vm->workqueue_lock); volatile rb_atomic_t triggered_bits = RUBY_ATOMIC_EXCHANGE(pjq->triggered_bitset, 0); @@ -2007,16 +1950,6 @@ rb_postponed_job_flush(rb_vm_t *vm) void *data = RUBY_ATOMIC_PTR_LOAD(pjq->table[i].data); (func)(data); } - - /* execute workqueue jobs */ - struct rb_workqueue_job *wq_job; - while ((wq_job = ccan_list_pop(&tmp, struct rb_workqueue_job, jnode))) { - rb_postponed_job_func_t func = wq_job->func; - void *data = wq_job->data; - - free(wq_job); - (func)(data); - } } EC_POP_TAG(); } @@ -2024,17 +1957,8 @@ rb_postponed_job_flush(rb_vm_t *vm) ec->interrupt_mask &= ~(saved_mask ^ block_mask); ec->errinfo = saved_errno; - /* If we threw an exception, there might be leftover workqueue items; carry them over - * to a subsequent execution of flush */ - if (!ccan_list_empty(&tmp)) { - rb_nativethread_lock_lock(&vm->workqueue_lock); - ccan_list_prepend_list(&vm->workqueue, &tmp); - rb_nativethread_lock_unlock(&vm->workqueue_lock); - - RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(GET_EC()); - } - /* likewise with any remaining-to-be-executed bits of the preregistered postponed - * job table. A merged bit can carry a Ractor-directed job that must not run on another + /* If we threw an exception, carry the bits that did not run yet over to a subsequent + * flush. A merged bit can carry a Ractor-directed job that must not run on another * Ractor (rb_postponed_job_trigger_for_ractor), so re-post it to this Ractor's own mask * rather than to the global bitset. */ if (triggered_bits) {