|
25 | 25 | #define FAKE_FRAME_MARK INT2FIX(1) |
26 | 26 | #define FAKE_FRAME_SWEEP INT2FIX(2) |
27 | 27 |
|
28 | | -/* |
29 | | - * As of Ruby 3.0, it should be safe to read stack frames at any time |
30 | | - * See https://github.com/ruby/ruby/commit/0e276dc458f94d9d79a0f7c7669bde84abe80f21 |
31 | | - */ |
32 | | -#if RUBY_API_VERSION_MAJOR < 3 |
33 | | - #define USE_POSTPONED_JOB |
34 | | -#endif |
35 | | - |
36 | 28 | static const char *fake_frame_cstrs[] = { |
37 | 29 | "(garbage collection)", |
38 | 30 | "(marking)", |
39 | 31 | "(sweeping)", |
40 | 32 | }; |
41 | 33 |
|
| 34 | +static int stackprof_use_postponed_job = 1; |
| 35 | + |
42 | 36 | #define TOTAL_FAKE_FRAMES (sizeof(fake_frame_cstrs) / sizeof(char *)) |
43 | 37 |
|
44 | 38 | #ifdef _POSIX_MONOTONIC_CLOCK |
@@ -701,15 +695,13 @@ stackprof_job_record_gc(void *data) |
701 | 695 | stackprof_record_gc_samples(); |
702 | 696 | } |
703 | 697 |
|
704 | | -#ifdef USE_POSTPONED_JOB |
705 | 698 | static void |
706 | 699 | stackprof_job_sample_and_record(void *data) |
707 | 700 | { |
708 | 701 | if (!_stackprof.running) return; |
709 | 702 |
|
710 | 703 | stackprof_sample_and_record(); |
711 | 704 | } |
712 | | -#endif |
713 | 705 |
|
714 | 706 | static void |
715 | 707 | stackprof_job_record_buffer(void *data) |
@@ -740,15 +732,15 @@ stackprof_signal_handler(int sig, siginfo_t *sinfo, void *ucontext) |
740 | 732 | _stackprof.unrecorded_gc_samples++; |
741 | 733 | rb_postponed_job_register_one(0, stackprof_job_record_gc, (void*)0); |
742 | 734 | } else { |
743 | | -#ifdef USE_POSTPONED_JOB |
744 | | - rb_postponed_job_register_one(0, stackprof_job_sample_and_record, (void*)0); |
745 | | -#else |
746 | | - // Buffer a sample immediately, if an existing sample exists this will |
747 | | - // return immediately |
748 | | - stackprof_buffer_sample(); |
749 | | - // Enqueue a job to record the sample |
750 | | - rb_postponed_job_register_one(0, stackprof_job_record_buffer, (void*)0); |
751 | | -#endif |
| 735 | + if (stackprof_use_postponed_job) { |
| 736 | + rb_postponed_job_register_one(0, stackprof_job_sample_and_record, (void*)0); |
| 737 | + } else { |
| 738 | + // Buffer a sample immediately, if an existing sample exists this will |
| 739 | + // return immediately |
| 740 | + stackprof_buffer_sample(); |
| 741 | + // Enqueue a job to record the sample |
| 742 | + rb_postponed_job_register_one(0, stackprof_job_record_buffer, (void*)0); |
| 743 | + } |
752 | 744 | } |
753 | 745 | pthread_mutex_unlock(&lock); |
754 | 746 | } |
@@ -826,9 +818,24 @@ stackprof_atfork_child(void) |
826 | 818 | stackprof_stop(rb_mStackProf); |
827 | 819 | } |
828 | 820 |
|
| 821 | +static VALUE |
| 822 | +stackprof_use_postponed_job_l(VALUE self) |
| 823 | +{ |
| 824 | + stackprof_use_postponed_job = 1; |
| 825 | + return Qnil; |
| 826 | +} |
| 827 | + |
829 | 828 | void |
830 | 829 | Init_stackprof(void) |
831 | 830 | { |
| 831 | + /* |
| 832 | + * As of Ruby 3.0, it should be safe to read stack frames at any time, unless YJIT is enabled |
| 833 | + * See https://github.com/ruby/ruby/commit/0e276dc458f94d9d79a0f7c7669bde84abe80f21 |
| 834 | + */ |
| 835 | + #if RUBY_API_VERSION_MAJOR < 3 |
| 836 | + stackprof_use_postponed_job = 0; |
| 837 | + #endif |
| 838 | + |
832 | 839 | size_t i; |
833 | 840 | #define S(name) sym_##name = ID2SYM(rb_intern(#name)); |
834 | 841 | S(object); |
@@ -890,6 +897,7 @@ Init_stackprof(void) |
890 | 897 | rb_define_singleton_method(rb_mStackProf, "stop", stackprof_stop, 0); |
891 | 898 | rb_define_singleton_method(rb_mStackProf, "results", stackprof_results, -1); |
892 | 899 | rb_define_singleton_method(rb_mStackProf, "sample", stackprof_sample, 0); |
| 900 | + rb_define_singleton_method(rb_mStackProf, "use_postponed_job!", stackprof_use_postponed_job_l, 0); |
893 | 901 |
|
894 | 902 | pthread_atfork(stackprof_atfork_prepare, stackprof_atfork_parent, stackprof_atfork_child); |
895 | 903 | } |
0 commit comments