Skip to content

Commit cd2222b

Browse files
committedJan 26, 2022
Move GVL instrumentation tests in their own files
1 parent 316c44d commit cd2222b

File tree

7 files changed

+282
-67
lines changed

7 files changed

+282
-67
lines changed
 

‎ext/-test-/gvl/call_without_gvl/call_without_gvl.c

-50
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "ruby/ruby.h"
22
#include "ruby/thread.h"
3-
#include "ruby/thread_native.h"
43

54
static void*
65
native_sleep_callback(void *data)
@@ -69,60 +68,11 @@ thread_ubf_async_safe(VALUE thread, VALUE notify_fd)
6968
return Qnil;
7069
}
7170

72-
void
73-
ex_callback(uint32_t e, struct gvl_hook_event_args args) {
74-
fprintf(stderr, "calling callback\n");
75-
}
76-
77-
static gvl_hook_t * single_hook = NULL;
78-
79-
static VALUE
80-
thread_register_gvl_callback(VALUE thread) {
81-
single_hook = rb_gvl_event_new(*ex_callback, RUBY_INTERNAL_EVENT_GVL_ACQUIRE_ENTER);
82-
83-
return Qnil;
84-
}
85-
86-
static VALUE
87-
thread_unregister_gvl_callback(VALUE thread) {
88-
if (single_hook) {
89-
rb_gvl_event_delete(single_hook);
90-
single_hook = NULL;
91-
}
92-
93-
return Qnil;
94-
}
95-
96-
static VALUE
97-
thread_call_gvl_callback(VALUE thread) {
98-
rb_gvl_execute_hooks(RUBY_INTERNAL_EVENT_GVL_ACQUIRE_ENTER, 1);
99-
return Qnil;
100-
}
101-
102-
static VALUE
103-
thread_register_and_unregister_gvl_callback(VALUE thread) {
104-
gvl_hook_t * hooks[5];
105-
for (int i = 0; i < 5; i++) {
106-
hooks[i] = rb_gvl_event_new(*ex_callback, RUBY_INTERNAL_EVENT_GVL_ACQUIRE_ENTER);
107-
}
108-
109-
if (!rb_gvl_event_delete(hooks[4])) return Qfalse;
110-
if (!rb_gvl_event_delete(hooks[0])) return Qfalse;
111-
if (!rb_gvl_event_delete(hooks[3])) return Qfalse;
112-
if (!rb_gvl_event_delete(hooks[2])) return Qfalse;
113-
if (!rb_gvl_event_delete(hooks[1])) return Qfalse;
114-
return Qtrue;
115-
}
116-
11771
void
11872
Init_call_without_gvl(void)
11973
{
12074
VALUE mBug = rb_define_module("Bug");
12175
VALUE klass = rb_define_module_under(mBug, "Thread");
12276
rb_define_singleton_method(klass, "runnable_sleep", thread_runnable_sleep, 1);
12377
rb_define_singleton_method(klass, "ubf_async_safe", thread_ubf_async_safe, 1);
124-
rb_define_singleton_method(klass, "register_callback", thread_register_gvl_callback, 0);
125-
rb_define_singleton_method(klass, "unregister_callback", thread_unregister_gvl_callback, 0);
126-
rb_define_singleton_method(klass, "register_and_unregister_callbacks", thread_register_and_unregister_gvl_callback, 0);
127-
rb_define_singleton_method(klass, "call_callbacks", thread_call_gvl_callback, 0);
12878
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# AUTOGENERATED DEPENDENCIES START
2+
call_without_gvl.o: $(RUBY_EXTCONF_H)
3+
call_without_gvl.o: $(arch_hdrdir)/ruby/config.h
4+
call_without_gvl.o: $(hdrdir)/ruby/assert.h
5+
call_without_gvl.o: $(hdrdir)/ruby/backward.h
6+
call_without_gvl.o: $(hdrdir)/ruby/backward/2/assume.h
7+
call_without_gvl.o: $(hdrdir)/ruby/backward/2/attributes.h
8+
call_without_gvl.o: $(hdrdir)/ruby/backward/2/bool.h
9+
call_without_gvl.o: $(hdrdir)/ruby/backward/2/inttypes.h
10+
call_without_gvl.o: $(hdrdir)/ruby/backward/2/limits.h
11+
call_without_gvl.o: $(hdrdir)/ruby/backward/2/long_long.h
12+
call_without_gvl.o: $(hdrdir)/ruby/backward/2/stdalign.h
13+
call_without_gvl.o: $(hdrdir)/ruby/backward/2/stdarg.h
14+
call_without_gvl.o: $(hdrdir)/ruby/defines.h
15+
call_without_gvl.o: $(hdrdir)/ruby/intern.h
16+
call_without_gvl.o: $(hdrdir)/ruby/internal/anyargs.h
17+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic.h
18+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
19+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/double.h
20+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
21+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
22+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/int.h
23+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
24+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/long.h
25+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
26+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
27+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
28+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
29+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/short.h
30+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
31+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
32+
call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
33+
call_without_gvl.o: $(hdrdir)/ruby/internal/assume.h
34+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
35+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/artificial.h
36+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/cold.h
37+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/const.h
38+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/constexpr.h
39+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/deprecated.h
40+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
41+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
42+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/error.h
43+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
44+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/forceinline.h
45+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/format.h
46+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
47+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noalias.h
48+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
49+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noexcept.h
50+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noinline.h
51+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/nonnull.h
52+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noreturn.h
53+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/pure.h
54+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/restrict.h
55+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
56+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/warning.h
57+
call_without_gvl.o: $(hdrdir)/ruby/internal/attr/weakref.h
58+
call_without_gvl.o: $(hdrdir)/ruby/internal/cast.h
59+
call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is.h
60+
call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
61+
call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
62+
call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
63+
call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
64+
call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
65+
call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
66+
call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_since.h
67+
call_without_gvl.o: $(hdrdir)/ruby/internal/config.h
68+
call_without_gvl.o: $(hdrdir)/ruby/internal/constant_p.h
69+
call_without_gvl.o: $(hdrdir)/ruby/internal/core.h
70+
call_without_gvl.o: $(hdrdir)/ruby/internal/core/rarray.h
71+
call_without_gvl.o: $(hdrdir)/ruby/internal/core/rbasic.h
72+
call_without_gvl.o: $(hdrdir)/ruby/internal/core/rbignum.h
73+
call_without_gvl.o: $(hdrdir)/ruby/internal/core/rclass.h
74+
call_without_gvl.o: $(hdrdir)/ruby/internal/core/rdata.h
75+
call_without_gvl.o: $(hdrdir)/ruby/internal/core/rfile.h
76+
call_without_gvl.o: $(hdrdir)/ruby/internal/core/rhash.h
77+
call_without_gvl.o: $(hdrdir)/ruby/internal/core/robject.h
78+
call_without_gvl.o: $(hdrdir)/ruby/internal/core/rregexp.h
79+
call_without_gvl.o: $(hdrdir)/ruby/internal/core/rstring.h
80+
call_without_gvl.o: $(hdrdir)/ruby/internal/core/rstruct.h
81+
call_without_gvl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
82+
call_without_gvl.o: $(hdrdir)/ruby/internal/ctype.h
83+
call_without_gvl.o: $(hdrdir)/ruby/internal/dllexport.h
84+
call_without_gvl.o: $(hdrdir)/ruby/internal/dosish.h
85+
call_without_gvl.o: $(hdrdir)/ruby/internal/error.h
86+
call_without_gvl.o: $(hdrdir)/ruby/internal/eval.h
87+
call_without_gvl.o: $(hdrdir)/ruby/internal/event.h
88+
call_without_gvl.o: $(hdrdir)/ruby/internal/fl_type.h
89+
call_without_gvl.o: $(hdrdir)/ruby/internal/gc.h
90+
call_without_gvl.o: $(hdrdir)/ruby/internal/glob.h
91+
call_without_gvl.o: $(hdrdir)/ruby/internal/globals.h
92+
call_without_gvl.o: $(hdrdir)/ruby/internal/has/attribute.h
93+
call_without_gvl.o: $(hdrdir)/ruby/internal/has/builtin.h
94+
call_without_gvl.o: $(hdrdir)/ruby/internal/has/c_attribute.h
95+
call_without_gvl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
96+
call_without_gvl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
97+
call_without_gvl.o: $(hdrdir)/ruby/internal/has/extension.h
98+
call_without_gvl.o: $(hdrdir)/ruby/internal/has/feature.h
99+
call_without_gvl.o: $(hdrdir)/ruby/internal/has/warning.h
100+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/array.h
101+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/bignum.h
102+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/class.h
103+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/compar.h
104+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/complex.h
105+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/cont.h
106+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/dir.h
107+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/enum.h
108+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/enumerator.h
109+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/error.h
110+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/eval.h
111+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/file.h
112+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/gc.h
113+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/hash.h
114+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/io.h
115+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/load.h
116+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/marshal.h
117+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/numeric.h
118+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/object.h
119+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/parse.h
120+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/proc.h
121+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/process.h
122+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/random.h
123+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/range.h
124+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/rational.h
125+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/re.h
126+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/ruby.h
127+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/select.h
128+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
129+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/signal.h
130+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
131+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/string.h
132+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/struct.h
133+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/thread.h
134+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/time.h
135+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/variable.h
136+
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/vm.h
137+
call_without_gvl.o: $(hdrdir)/ruby/internal/interpreter.h
138+
call_without_gvl.o: $(hdrdir)/ruby/internal/iterator.h
139+
call_without_gvl.o: $(hdrdir)/ruby/internal/memory.h
140+
call_without_gvl.o: $(hdrdir)/ruby/internal/method.h
141+
call_without_gvl.o: $(hdrdir)/ruby/internal/module.h
142+
call_without_gvl.o: $(hdrdir)/ruby/internal/newobj.h
143+
call_without_gvl.o: $(hdrdir)/ruby/internal/rgengc.h
144+
call_without_gvl.o: $(hdrdir)/ruby/internal/scan_args.h
145+
call_without_gvl.o: $(hdrdir)/ruby/internal/special_consts.h
146+
call_without_gvl.o: $(hdrdir)/ruby/internal/static_assert.h
147+
call_without_gvl.o: $(hdrdir)/ruby/internal/stdalign.h
148+
call_without_gvl.o: $(hdrdir)/ruby/internal/stdbool.h
149+
call_without_gvl.o: $(hdrdir)/ruby/internal/symbol.h
150+
call_without_gvl.o: $(hdrdir)/ruby/internal/value.h
151+
call_without_gvl.o: $(hdrdir)/ruby/internal/value_type.h
152+
call_without_gvl.o: $(hdrdir)/ruby/internal/variable.h
153+
call_without_gvl.o: $(hdrdir)/ruby/internal/warning_push.h
154+
call_without_gvl.o: $(hdrdir)/ruby/internal/xmalloc.h
155+
call_without_gvl.o: $(hdrdir)/ruby/missing.h
156+
call_without_gvl.o: $(hdrdir)/ruby/ruby.h
157+
call_without_gvl.o: $(hdrdir)/ruby/st.h
158+
call_without_gvl.o: $(hdrdir)/ruby/subst.h
159+
call_without_gvl.o: $(hdrdir)/ruby/thread.h
160+
call_without_gvl.o: call_without_gvl.c
161+
# AUTOGENERATED DEPENDENCIES END
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# frozen_string_literal: false
2+
create_makefile("-test-/gvl/instrumentation")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#include "ruby/ruby.h"
2+
#include "ruby/atomic.h"
3+
#include "ruby/thread.h"
4+
#include "ruby/thread_native.h"
5+
6+
static rb_atomic_t acquire_enter_count = 0;
7+
static rb_atomic_t acquire_exit_count = 0;
8+
static rb_atomic_t release_count = 0;
9+
10+
void
11+
ex_callback(rb_event_flag_t event, gvl_hook_event_args_t args)
12+
{
13+
switch(event) {
14+
case RUBY_INTERNAL_EVENT_GVL_ACQUIRE_ENTER:
15+
RUBY_ATOMIC_INC(acquire_enter_count);
16+
break;
17+
case RUBY_INTERNAL_EVENT_GVL_ACQUIRE_EXIT:
18+
RUBY_ATOMIC_INC(acquire_exit_count);
19+
break;
20+
case RUBY_INTERNAL_EVENT_GVL_RELEASE:
21+
RUBY_ATOMIC_INC(release_count);
22+
break;
23+
}
24+
}
25+
26+
static gvl_hook_t * single_hook = NULL;
27+
28+
static VALUE
29+
thread_counters(VALUE thread)
30+
{
31+
VALUE array = rb_ary_new2(3);
32+
rb_ary_push(array, UINT2NUM(acquire_enter_count));
33+
rb_ary_push(array, UINT2NUM(acquire_exit_count));
34+
rb_ary_push(array, UINT2NUM(release_count));
35+
return array;
36+
}
37+
38+
static VALUE
39+
thread_reset_counters(VALUE thread)
40+
{
41+
RUBY_ATOMIC_SET(acquire_enter_count, 0);
42+
RUBY_ATOMIC_SET(acquire_exit_count, 0);
43+
RUBY_ATOMIC_SET(release_count, 0);
44+
return Qtrue;
45+
}
46+
47+
static VALUE
48+
thread_register_gvl_callback(VALUE thread)
49+
{
50+
single_hook = rb_gvl_event_new(
51+
*ex_callback,
52+
RUBY_INTERNAL_EVENT_GVL_ACQUIRE_ENTER | RUBY_INTERNAL_EVENT_GVL_ACQUIRE_EXIT | RUBY_INTERNAL_EVENT_GVL_RELEASE
53+
);
54+
55+
return Qnil;
56+
}
57+
58+
static VALUE
59+
thread_unregister_gvl_callback(VALUE thread)
60+
{
61+
if (single_hook) {
62+
rb_gvl_event_delete(single_hook);
63+
single_hook = NULL;
64+
}
65+
66+
return Qnil;
67+
}
68+
69+
static VALUE
70+
thread_register_and_unregister_gvl_callback(VALUE thread)
71+
{
72+
gvl_hook_t * hooks[5];
73+
for (int i = 0; i < 5; i++) {
74+
hooks[i] = rb_gvl_event_new(*ex_callback, RUBY_INTERNAL_EVENT_GVL_ACQUIRE_ENTER);
75+
}
76+
77+
if (!rb_gvl_event_delete(hooks[4])) return Qfalse;
78+
if (!rb_gvl_event_delete(hooks[0])) return Qfalse;
79+
if (!rb_gvl_event_delete(hooks[3])) return Qfalse;
80+
if (!rb_gvl_event_delete(hooks[2])) return Qfalse;
81+
if (!rb_gvl_event_delete(hooks[1])) return Qfalse;
82+
return Qtrue;
83+
}
84+
85+
void
86+
Init_instrumentation(void)
87+
{
88+
VALUE mBug = rb_define_module("Bug");
89+
VALUE klass = rb_define_module_under(mBug, "GVLInstrumentation");
90+
rb_define_singleton_method(klass, "counters", thread_counters, 0);
91+
rb_define_singleton_method(klass, "reset_counters", thread_reset_counters, 0);
92+
rb_define_singleton_method(klass, "register_callback", thread_register_gvl_callback, 0);
93+
rb_define_singleton_method(klass, "unregister_callback", thread_unregister_gvl_callback, 0);
94+
rb_define_singleton_method(klass, "register_and_unregister_callbacks", thread_register_and_unregister_gvl_callback, 0);
95+
}

‎include/ruby/thread.h

-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,6 @@ void *rb_nogvl(void *(*func)(void *), void *data1,
190190
*/
191191
#define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_
192192

193-
194193
RBIMPL_SYMBOL_EXPORT_END()
195194

196195
#endif /* RUBY_THREAD_H */
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: false
2+
class TestGVLInstrumentation < Test::Unit::TestCase
3+
def test_gvl_instrumentation
4+
require '-test-/gvl/instrumentation'
5+
Bug::GVLInstrumentation.reset_counters
6+
Bug::GVLInstrumentation::register_callback
7+
8+
begin
9+
threads = 5.times.map { Thread.new { sleep 0.05; 1 + 1; sleep 0.02 } }
10+
threads.each(&:join)
11+
Bug::GVLInstrumentation.counters.each do |c|
12+
assert_predicate c,:nonzero?
13+
end
14+
ensure
15+
Bug::GVLInstrumentation::unregister_callback
16+
end
17+
end
18+
19+
def test_gvl_instrumentation_unregister
20+
require '-test-/gvl/instrumentation'
21+
assert Bug::GVLInstrumentation::register_and_unregister_callbacks
22+
end
23+
end
24+

‎test/-ext-/gvl/test_last_thread.rb

-16
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,5 @@ def test_last_thread
1818
assert_in_delta(1.0, t, 0.16)
1919
end;
2020
end
21-
22-
def test_gvl_instrumentation
23-
require '-test-/gvl/call_without_gvl'
24-
Bug::Thread::register_callback
25-
26-
begin
27-
Bug::Thread::call_callbacks
28-
ensure
29-
Bug::Thread::unregister_callback
30-
end
31-
end
32-
33-
def test_gvl_instrumentation_unregister
34-
require '-test-/gvl/call_without_gvl'
35-
assert Bug::Thread::register_and_unregister_callbacks
36-
end
3721
end
3822

0 commit comments

Comments
 (0)
Failed to load comments.