summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--cont.c5
-rw-r--r--include/ruby/ruby.h1
-rw-r--r--test/ruby/test_settracefunc.rb51
-rw-r--r--vm_trace.c3
5 files changed, 68 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index f06c010eab..162112f41d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Fri Aug 21 18:49:22 2015 Koichi Sasada <ko1@atdot.net>
+
+ * include/ruby/ruby.h, cont.c, vm_trace.c: add a new event
+ fiber_switch. We need more discussion about this feature
+ so that I don't write it on NEWS.
+ [Feature #11348]
+
+ * test/ruby/test_settracefunc.rb: add tests.
+
Fri Aug 21 17:32:42 2015 Koichi Sasada <ko1@atdot.net>
* vm_insnhelper.c (vm_invoke_block): we should not expect ci->argc is
diff --git a/cont.c b/cont.c
index fc0cf53655..774a026bd5 100644
--- a/cont.c
+++ b/cont.c
@@ -1260,8 +1260,9 @@ rb_fiber_start(void)
th->errinfo = Qnil;
th->root_lep = rb_vm_ep_local_ep(proc->block.ep);
th->root_svar = Qfalse;
-
fib->status = RUNNING;
+
+ EXEC_EVENT_HOOK(th, RUBY_EVENT_FIBER_SWITCH, th->self, 0, 0, Qnil);
cont->value = rb_vm_invoke_proc(th, proc, argc, argv, 0);
}
TH_POP_TAG();
@@ -1451,6 +1452,8 @@ fiber_switch(rb_fiber_t *fib, int argc, const VALUE *argv, int is_resume)
value = fiber_store(fib, th);
RUBY_VM_CHECK_INTS(th);
+ EXEC_EVENT_HOOK(th, RUBY_EVENT_FIBER_SWITCH, th->self, 0, 0, Qnil);
+
return value;
}
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index f0d53b3e11..515a27aa0b 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -1825,6 +1825,7 @@ int ruby_native_thread_p(void);
#define RUBY_EVENT_B_RETURN 0x0200
#define RUBY_EVENT_THREAD_BEGIN 0x0400
#define RUBY_EVENT_THREAD_END 0x0800
+#define RUBY_EVENT_FIBER_SWITCH 0x1000
#define RUBY_EVENT_TRACEPOINT_ALL 0xffff
/* special events */
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index 916705f7c8..8308f31f55 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -1349,4 +1349,55 @@ class TestSetTraceFunc < Test::Unit::TestCase
assert_equal([:call, :return], evs)
end
+
+ require 'fiber'
+ def test_fiber_switch
+ # test for resume/yield
+ evs = []
+ TracePoint.new(:fiber_switch){|tp|
+ next unless target_thread?
+ evs << tp.event
+ }.enable{
+ f = Fiber.new{
+ Fiber.yield
+ Fiber.yield
+ Fiber.yield
+ }
+ f.resume
+ f.resume
+ f.resume
+ f.resume
+ begin
+ f.resume
+ rescue FiberError
+ end
+ }
+ assert_equal 8, evs.size
+ evs.each{|ev|
+ assert_equal ev, :fiber_switch
+ }
+
+ # test for transfer
+ evs = []
+ TracePoint.new(:fiber_switch){|tp|
+ next unless target_thread?
+ evs << tp.event
+ }.enable{
+ f1 = f2 = nil
+ f1 = Fiber.new{
+ f2.transfer
+ f2.transfer
+ Fiber.yield :ok
+ }
+ f2 = Fiber.new{
+ f1.transfer
+ f1.transfer
+ }
+ assert_equal :ok, f1.resume
+ }
+ assert_equal 6, evs.size
+ evs.each{|ev|
+ assert_equal ev, :fiber_switch
+ }
+ end
end
diff --git a/vm_trace.c b/vm_trace.c
index 529cb720df..1ce11f9548 100644
--- a/vm_trace.c
+++ b/vm_trace.c
@@ -595,6 +595,7 @@ get_event_id(rb_event_flag_t event)
C(b_return, B_RETURN);
C(thread_begin, THREAD_BEGIN);
C(thread_end, THREAD_END);
+ C(fiber_switch, FIBER_SWITCH);
C(specified_line, SPECIFIED_LINE);
case RUBY_EVENT_LINE | RUBY_EVENT_SPECIFIED_LINE: CONST_ID(id, "line"); return id;
#undef C
@@ -700,6 +701,7 @@ symbol2event_flag(VALUE v)
C(b_return, B_RETURN);
C(thread_begin, THREAD_BEGIN);
C(thread_end, THREAD_END);
+ C(fiber_switch, FIBER_SWITCH);
C(specified_line, SPECIFIED_LINE);
C(a_call, A_CALL);
C(a_return, A_RETURN);
@@ -1445,6 +1447,7 @@ Init_vm_trace(void)
* +:b_return+:: event hook at block ending
* +:thread_begin+:: event hook at thread beginning
* +:thread_end+:: event hook at thread ending
+ * +:fiber_siwtch+:: event hook at fiber switch
*
*/
rb_cTracePoint = rb_define_class("TracePoint", rb_cObject);