@@ -803,3 +803,50 @@ static inline int ddtrace_imemo_type(VALUE imemo) {
803803
804804// Is the VM smack in the middle of raising an exception?
805805bool is_raised_flag_set (VALUE thread ) { return thread_struct_from_object (thread )-> ec -> raised_flag > 0 ; }
806+
807+ #ifndef NO_CURRENT_FIBER_FOR
808+ // The following three declarations are all
809+ // taken from upstream cont.c at commit d97884a58be32e829fd03a80cd521f4733d65c79 (February 2025, master branch)
810+ // (See the Ruby project copyright and license above)
811+ // to enable building `current_fiber_for`.
812+ //
813+ // We needed to copy them because they aren't otherwise exposed in any VM APIs or headers.
814+ // @ivoanjo: I manually checked the Ruby 3.1, 3.2, 3.3 and 3.4 branches + master, and the parts we care about in these
815+ // structures have not changed in many years (in fact, last change I spotted was for 2.7).
816+ enum context_type {
817+ CONTINUATION_CONTEXT = 0 ,
818+ FIBER_CONTEXT = 1
819+ };
820+
821+ typedef struct rb_context_struct { // This declaration is incomplete -- only contains up to `self` which is the part we care about
822+ enum context_type type ;
823+ int argc ;
824+ int kw_splat ;
825+ VALUE self ;
826+ } rb_context_t ;
827+
828+ struct rb_fiber_struct { // This declaration is incomplete -- only contains the first entry which is the part we care about
829+ rb_context_t cont ;
830+ };
831+
832+ VALUE current_fiber_for (VALUE thread ) {
833+ VALUE self = thread_struct_from_object (thread )-> ec -> fiber_ptr -> cont .self ;
834+ return self == 0 ? Qnil : self ;
835+ }
836+
837+ void self_test_current_fiber_for (void ) {
838+ VALUE expected_current_fiber = current_fiber_for (rb_thread_current ());
839+ VALUE actual_current_fiber = rb_fiber_current ();
840+
841+ if (expected_current_fiber == Qnil ) {
842+ // On purpose above we tried reading before calling `rb_fiber_current()` so the fiber may have not existed yet.
843+ // But now it should be there.
844+ expected_current_fiber = current_fiber_for (rb_thread_current ());
845+ }
846+
847+ if (expected_current_fiber != actual_current_fiber ) rb_raise (rb_eRuntimeError , "current_fiber_for() self-test failed" );
848+ }
849+ #else
850+ VALUE current_fiber_for (VALUE thread ) { rb_raise (rb_eRuntimeError , "Not implemented for Ruby < 3.1" ); }
851+ void self_test_current_fiber_for (void ) { } // Nothing to do
852+ #endif
0 commit comments