summaryrefslogtreecommitdiff
path: root/test/-ext-/thread/helper.rb
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2023-11-29 15:54:32 -0800
committerJohn Hawthorn <john@hawthorn.email>2023-12-02 10:06:07 -0800
commitad54fbf281ca1935e79f4df1460b0106ba76761e (patch)
treeae560415a2804342a0e7ef13f7cf6e245752960c /test/-ext-/thread/helper.rb
parent715cf9b6902b0cc317fbc5cea0df153e14ff7277 (diff)
Add missing GVL hooks for M:N threads and ractors
[Bug #20019] This fixes GVL instrumentation in three locations it was missing: - Suspending when blocking on a Ractor - Suspending when doing a coroutine transfer from an M:N thread - Resuming after an M:N thread starts Co-authored-by: Matthew Draper <matthew@trebex.net>
Diffstat (limited to 'test/-ext-/thread/helper.rb')
-rw-r--r--test/-ext-/thread/helper.rb51
1 files changed, 51 insertions, 0 deletions
diff --git a/test/-ext-/thread/helper.rb b/test/-ext-/thread/helper.rb
new file mode 100644
index 0000000000..3ea2057d15
--- /dev/null
+++ b/test/-ext-/thread/helper.rb
@@ -0,0 +1,51 @@
+module ThreadInstrumentation
+ module TestHelper
+ private
+
+ def record
+ Bug::ThreadInstrumentation.register_callback(!ENV["GVL_DEBUG"])
+ yield
+ ensure
+ timeline = Bug::ThreadInstrumentation.unregister_callback
+ if $!
+ raise
+ else
+ return timeline
+ end
+ end
+
+ def timeline_for(thread, timeline)
+ timeline.select { |t, _| t == thread }.map(&:last)
+ end
+
+ def assert_consistent_timeline(events)
+ refute_predicate events, :empty?
+
+ previous_event = nil
+ events.each do |event|
+ refute_equal :exited, previous_event, "`exited` must be the final event: #{events.inspect}"
+ case event
+ when :started
+ assert_nil previous_event, "`started` must be the first event: #{events.inspect}"
+ when :ready
+ unless previous_event.nil?
+ assert %i(started suspended).include?(previous_event), "`ready` must be preceded by `started` or `suspended`: #{events.inspect}"
+ end
+ when :resumed
+ unless previous_event.nil?
+ assert_equal :ready, previous_event, "`resumed` must be preceded by `ready`: #{events.inspect}"
+ end
+ when :suspended
+ unless previous_event.nil?
+ assert_equal :resumed, previous_event, "`suspended` must be preceded by `resumed`: #{events.inspect}"
+ end
+ when :exited
+ unless previous_event.nil?
+ assert %i(resumed suspended).include?(previous_event), "`exited` must be preceded by `resumed` or `suspended`: #{events.inspect}"
+ end
+ end
+ previous_event = event
+ end
+ end
+ end
+end