diff options
Diffstat (limited to 'ext/-test-/thread')
| -rw-r--r-- | ext/-test-/thread/id/depend | 163 | ||||
| -rw-r--r-- | ext/-test-/thread/id/extconf.rb | 3 | ||||
| -rw-r--r-- | ext/-test-/thread/id/id.c | 15 | ||||
| -rw-r--r-- | ext/-test-/thread/instrumentation/depend | 5 | ||||
| -rw-r--r-- | ext/-test-/thread/instrumentation/instrumentation.c | 213 | ||||
| -rw-r--r-- | ext/-test-/thread/lock_native_thread/depend | 163 | ||||
| -rw-r--r-- | ext/-test-/thread/lock_native_thread/extconf.rb | 2 | ||||
| -rw-r--r-- | ext/-test-/thread/lock_native_thread/lock_native_thread.c | 50 |
8 files changed, 544 insertions, 70 deletions
diff --git a/ext/-test-/thread/id/depend b/ext/-test-/thread/id/depend new file mode 100644 index 0000000000..6b76b31ddc --- /dev/null +++ b/ext/-test-/thread/id/depend @@ -0,0 +1,163 @@ +# AUTOGENERATED DEPENDENCIES START +id.o: $(RUBY_EXTCONF_H) +id.o: $(arch_hdrdir)/ruby/config.h +id.o: $(hdrdir)/ruby.h +id.o: $(hdrdir)/ruby/assert.h +id.o: $(hdrdir)/ruby/backward.h +id.o: $(hdrdir)/ruby/backward/2/assume.h +id.o: $(hdrdir)/ruby/backward/2/attributes.h +id.o: $(hdrdir)/ruby/backward/2/bool.h +id.o: $(hdrdir)/ruby/backward/2/inttypes.h +id.o: $(hdrdir)/ruby/backward/2/limits.h +id.o: $(hdrdir)/ruby/backward/2/long_long.h +id.o: $(hdrdir)/ruby/backward/2/stdalign.h +id.o: $(hdrdir)/ruby/backward/2/stdarg.h +id.o: $(hdrdir)/ruby/defines.h +id.o: $(hdrdir)/ruby/intern.h +id.o: $(hdrdir)/ruby/internal/abi.h +id.o: $(hdrdir)/ruby/internal/anyargs.h +id.o: $(hdrdir)/ruby/internal/arithmetic.h +id.o: $(hdrdir)/ruby/internal/arithmetic/char.h +id.o: $(hdrdir)/ruby/internal/arithmetic/double.h +id.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +id.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/int.h +id.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/long.h +id.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +id.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/short.h +id.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +id.o: $(hdrdir)/ruby/internal/assume.h +id.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +id.o: $(hdrdir)/ruby/internal/attr/artificial.h +id.o: $(hdrdir)/ruby/internal/attr/cold.h +id.o: $(hdrdir)/ruby/internal/attr/const.h +id.o: $(hdrdir)/ruby/internal/attr/constexpr.h +id.o: $(hdrdir)/ruby/internal/attr/deprecated.h +id.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +id.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +id.o: $(hdrdir)/ruby/internal/attr/error.h +id.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +id.o: $(hdrdir)/ruby/internal/attr/forceinline.h +id.o: $(hdrdir)/ruby/internal/attr/format.h +id.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +id.o: $(hdrdir)/ruby/internal/attr/noalias.h +id.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +id.o: $(hdrdir)/ruby/internal/attr/noexcept.h +id.o: $(hdrdir)/ruby/internal/attr/noinline.h +id.o: $(hdrdir)/ruby/internal/attr/nonnull.h +id.o: $(hdrdir)/ruby/internal/attr/noreturn.h +id.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +id.o: $(hdrdir)/ruby/internal/attr/pure.h +id.o: $(hdrdir)/ruby/internal/attr/restrict.h +id.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +id.o: $(hdrdir)/ruby/internal/attr/warning.h +id.o: $(hdrdir)/ruby/internal/attr/weakref.h +id.o: $(hdrdir)/ruby/internal/cast.h +id.o: $(hdrdir)/ruby/internal/compiler_is.h +id.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +id.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +id.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +id.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +id.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +id.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +id.o: $(hdrdir)/ruby/internal/compiler_since.h +id.o: $(hdrdir)/ruby/internal/config.h +id.o: $(hdrdir)/ruby/internal/constant_p.h +id.o: $(hdrdir)/ruby/internal/core.h +id.o: $(hdrdir)/ruby/internal/core/rarray.h +id.o: $(hdrdir)/ruby/internal/core/rbasic.h +id.o: $(hdrdir)/ruby/internal/core/rbignum.h +id.o: $(hdrdir)/ruby/internal/core/rclass.h +id.o: $(hdrdir)/ruby/internal/core/rdata.h +id.o: $(hdrdir)/ruby/internal/core/rfile.h +id.o: $(hdrdir)/ruby/internal/core/rhash.h +id.o: $(hdrdir)/ruby/internal/core/robject.h +id.o: $(hdrdir)/ruby/internal/core/rregexp.h +id.o: $(hdrdir)/ruby/internal/core/rstring.h +id.o: $(hdrdir)/ruby/internal/core/rstruct.h +id.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +id.o: $(hdrdir)/ruby/internal/ctype.h +id.o: $(hdrdir)/ruby/internal/dllexport.h +id.o: $(hdrdir)/ruby/internal/dosish.h +id.o: $(hdrdir)/ruby/internal/error.h +id.o: $(hdrdir)/ruby/internal/eval.h +id.o: $(hdrdir)/ruby/internal/event.h +id.o: $(hdrdir)/ruby/internal/fl_type.h +id.o: $(hdrdir)/ruby/internal/gc.h +id.o: $(hdrdir)/ruby/internal/glob.h +id.o: $(hdrdir)/ruby/internal/globals.h +id.o: $(hdrdir)/ruby/internal/has/attribute.h +id.o: $(hdrdir)/ruby/internal/has/builtin.h +id.o: $(hdrdir)/ruby/internal/has/c_attribute.h +id.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +id.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +id.o: $(hdrdir)/ruby/internal/has/extension.h +id.o: $(hdrdir)/ruby/internal/has/feature.h +id.o: $(hdrdir)/ruby/internal/has/warning.h +id.o: $(hdrdir)/ruby/internal/intern/array.h +id.o: $(hdrdir)/ruby/internal/intern/bignum.h +id.o: $(hdrdir)/ruby/internal/intern/class.h +id.o: $(hdrdir)/ruby/internal/intern/compar.h +id.o: $(hdrdir)/ruby/internal/intern/complex.h +id.o: $(hdrdir)/ruby/internal/intern/cont.h +id.o: $(hdrdir)/ruby/internal/intern/dir.h +id.o: $(hdrdir)/ruby/internal/intern/enum.h +id.o: $(hdrdir)/ruby/internal/intern/enumerator.h +id.o: $(hdrdir)/ruby/internal/intern/error.h +id.o: $(hdrdir)/ruby/internal/intern/eval.h +id.o: $(hdrdir)/ruby/internal/intern/file.h +id.o: $(hdrdir)/ruby/internal/intern/hash.h +id.o: $(hdrdir)/ruby/internal/intern/io.h +id.o: $(hdrdir)/ruby/internal/intern/load.h +id.o: $(hdrdir)/ruby/internal/intern/marshal.h +id.o: $(hdrdir)/ruby/internal/intern/numeric.h +id.o: $(hdrdir)/ruby/internal/intern/object.h +id.o: $(hdrdir)/ruby/internal/intern/parse.h +id.o: $(hdrdir)/ruby/internal/intern/proc.h +id.o: $(hdrdir)/ruby/internal/intern/process.h +id.o: $(hdrdir)/ruby/internal/intern/random.h +id.o: $(hdrdir)/ruby/internal/intern/range.h +id.o: $(hdrdir)/ruby/internal/intern/rational.h +id.o: $(hdrdir)/ruby/internal/intern/re.h +id.o: $(hdrdir)/ruby/internal/intern/ruby.h +id.o: $(hdrdir)/ruby/internal/intern/select.h +id.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +id.o: $(hdrdir)/ruby/internal/intern/set.h +id.o: $(hdrdir)/ruby/internal/intern/signal.h +id.o: $(hdrdir)/ruby/internal/intern/sprintf.h +id.o: $(hdrdir)/ruby/internal/intern/string.h +id.o: $(hdrdir)/ruby/internal/intern/struct.h +id.o: $(hdrdir)/ruby/internal/intern/thread.h +id.o: $(hdrdir)/ruby/internal/intern/time.h +id.o: $(hdrdir)/ruby/internal/intern/variable.h +id.o: $(hdrdir)/ruby/internal/intern/vm.h +id.o: $(hdrdir)/ruby/internal/interpreter.h +id.o: $(hdrdir)/ruby/internal/iterator.h +id.o: $(hdrdir)/ruby/internal/memory.h +id.o: $(hdrdir)/ruby/internal/method.h +id.o: $(hdrdir)/ruby/internal/module.h +id.o: $(hdrdir)/ruby/internal/newobj.h +id.o: $(hdrdir)/ruby/internal/scan_args.h +id.o: $(hdrdir)/ruby/internal/special_consts.h +id.o: $(hdrdir)/ruby/internal/static_assert.h +id.o: $(hdrdir)/ruby/internal/stdalign.h +id.o: $(hdrdir)/ruby/internal/stdbool.h +id.o: $(hdrdir)/ruby/internal/stdckdint.h +id.o: $(hdrdir)/ruby/internal/symbol.h +id.o: $(hdrdir)/ruby/internal/value.h +id.o: $(hdrdir)/ruby/internal/value_type.h +id.o: $(hdrdir)/ruby/internal/variable.h +id.o: $(hdrdir)/ruby/internal/warning_push.h +id.o: $(hdrdir)/ruby/internal/xmalloc.h +id.o: $(hdrdir)/ruby/missing.h +id.o: $(hdrdir)/ruby/ruby.h +id.o: $(hdrdir)/ruby/st.h +id.o: $(hdrdir)/ruby/subst.h +id.o: id.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/thread/id/extconf.rb b/ext/-test-/thread/id/extconf.rb new file mode 100644 index 0000000000..a0ae0eff15 --- /dev/null +++ b/ext/-test-/thread/id/extconf.rb @@ -0,0 +1,3 @@ +if have_func("gettid") + create_makefile("-test-/thread/id") +end diff --git a/ext/-test-/thread/id/id.c b/ext/-test-/thread/id/id.c new file mode 100644 index 0000000000..b46a5955e2 --- /dev/null +++ b/ext/-test-/thread/id/id.c @@ -0,0 +1,15 @@ +#include <ruby.h> + +static VALUE +bug_gettid(VALUE self) +{ + pid_t tid = gettid(); + return PIDT2NUM(tid); +} + +void +Init_id(void) +{ + VALUE klass = rb_define_module_under(rb_define_module("Bug"), "ThreadID"); + rb_define_module_function(klass, "gettid", bug_gettid, 0); +} diff --git a/ext/-test-/thread/instrumentation/depend b/ext/-test-/thread/instrumentation/depend index e2fcd060d8..63e1c7e44f 100644 --- a/ext/-test-/thread/instrumentation/depend +++ b/ext/-test-/thread/instrumentation/depend @@ -52,6 +52,7 @@ instrumentation.o: $(hdrdir)/ruby/internal/attr/noexcept.h instrumentation.o: $(hdrdir)/ruby/internal/attr/noinline.h instrumentation.o: $(hdrdir)/ruby/internal/attr/nonnull.h instrumentation.o: $(hdrdir)/ruby/internal/attr/noreturn.h +instrumentation.o: $(hdrdir)/ruby/internal/attr/packed_struct.h instrumentation.o: $(hdrdir)/ruby/internal/attr/pure.h instrumentation.o: $(hdrdir)/ruby/internal/attr/restrict.h instrumentation.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -111,7 +112,6 @@ instrumentation.o: $(hdrdir)/ruby/internal/intern/enumerator.h instrumentation.o: $(hdrdir)/ruby/internal/intern/error.h instrumentation.o: $(hdrdir)/ruby/internal/intern/eval.h instrumentation.o: $(hdrdir)/ruby/internal/intern/file.h -instrumentation.o: $(hdrdir)/ruby/internal/intern/gc.h instrumentation.o: $(hdrdir)/ruby/internal/intern/hash.h instrumentation.o: $(hdrdir)/ruby/internal/intern/io.h instrumentation.o: $(hdrdir)/ruby/internal/intern/load.h @@ -128,6 +128,7 @@ instrumentation.o: $(hdrdir)/ruby/internal/intern/re.h instrumentation.o: $(hdrdir)/ruby/internal/intern/ruby.h instrumentation.o: $(hdrdir)/ruby/internal/intern/select.h instrumentation.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +instrumentation.o: $(hdrdir)/ruby/internal/intern/set.h instrumentation.o: $(hdrdir)/ruby/internal/intern/signal.h instrumentation.o: $(hdrdir)/ruby/internal/intern/sprintf.h instrumentation.o: $(hdrdir)/ruby/internal/intern/string.h @@ -142,12 +143,12 @@ instrumentation.o: $(hdrdir)/ruby/internal/memory.h instrumentation.o: $(hdrdir)/ruby/internal/method.h instrumentation.o: $(hdrdir)/ruby/internal/module.h instrumentation.o: $(hdrdir)/ruby/internal/newobj.h -instrumentation.o: $(hdrdir)/ruby/internal/rgengc.h instrumentation.o: $(hdrdir)/ruby/internal/scan_args.h instrumentation.o: $(hdrdir)/ruby/internal/special_consts.h instrumentation.o: $(hdrdir)/ruby/internal/static_assert.h instrumentation.o: $(hdrdir)/ruby/internal/stdalign.h instrumentation.o: $(hdrdir)/ruby/internal/stdbool.h +instrumentation.o: $(hdrdir)/ruby/internal/stdckdint.h instrumentation.o: $(hdrdir)/ruby/internal/symbol.h instrumentation.o: $(hdrdir)/ruby/internal/value.h instrumentation.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/thread/instrumentation/instrumentation.c b/ext/-test-/thread/instrumentation/instrumentation.c index d2a2c2740b..25e2902a78 100644 --- a/ext/-test-/thread/instrumentation/instrumentation.c +++ b/ext/-test-/thread/instrumentation/instrumentation.c @@ -2,90 +2,136 @@ #include "ruby/atomic.h" #include "ruby/thread.h" -static rb_atomic_t started_count = 0; -static rb_atomic_t ready_count = 0; -static rb_atomic_t resumed_count = 0; -static rb_atomic_t suspended_count = 0; -static rb_atomic_t exited_count = 0; - -#if __STDC_VERSION__ >= 201112 - #define RB_THREAD_LOCAL_SPECIFIER _Thread_local -#elif defined(__GNUC__) && !defined(RB_THREAD_LOCAL_SPECIFIER_IS_UNSUPPORTED) - /* note that ICC (linux) and Clang are covered by __GNUC__ */ - #define RB_THREAD_LOCAL_SPECIFIER __thread -#else - #define RB_THREAD_LOCAL_SPECIFIER +#ifndef RB_THREAD_LOCAL_SPECIFIER +# define RB_THREAD_LOCAL_SPECIFIER #endif -static RB_THREAD_LOCAL_SPECIFIER unsigned int local_ready_count = 0; -static RB_THREAD_LOCAL_SPECIFIER unsigned int local_resumed_count = 0; -static RB_THREAD_LOCAL_SPECIFIER unsigned int local_suspended_count = 0; +static VALUE timeline_value = Qnil; + +struct thread_event { + VALUE thread; + rb_event_flag_t event; +}; + +#define MAX_EVENTS 1024 +static struct thread_event event_timeline[MAX_EVENTS]; +static rb_atomic_t timeline_cursor; static void -ex_callback(rb_event_flag_t event, const rb_internal_thread_event_data_t *event_data, void *user_data) +event_timeline_gc_mark(void *ptr) { + rb_atomic_t cursor; + for (cursor = 0; cursor < timeline_cursor; cursor++) { + rb_gc_mark(event_timeline[cursor].thread); + } +} + +static const rb_data_type_t event_timeline_type = { + "TestThreadInstrumentation/event_timeline", + {event_timeline_gc_mark, NULL, NULL,}, + 0, 0, + RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static void +reset_timeline(void) +{ + timeline_cursor = 0; + memset(event_timeline, 0, sizeof(struct thread_event) * MAX_EVENTS); +} + +static rb_event_flag_t +find_last_event(VALUE thread) +{ + rb_atomic_t cursor = timeline_cursor; + if (cursor) { + do { + if (event_timeline[cursor].thread == thread){ + return event_timeline[cursor].event; + } + cursor--; + } while (cursor > 0); + } + return 0; +} + +static const char * +event_name(rb_event_flag_t event) { switch (event) { case RUBY_INTERNAL_THREAD_EVENT_STARTED: - RUBY_ATOMIC_INC(started_count); - break; + return "started"; case RUBY_INTERNAL_THREAD_EVENT_READY: - RUBY_ATOMIC_INC(ready_count); - local_ready_count++; - break; + return "ready"; case RUBY_INTERNAL_THREAD_EVENT_RESUMED: - RUBY_ATOMIC_INC(resumed_count); - local_resumed_count++; - break; + return "resumed"; case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED: - RUBY_ATOMIC_INC(suspended_count); - local_suspended_count++; - break; + return "suspended"; case RUBY_INTERNAL_THREAD_EVENT_EXITED: - RUBY_ATOMIC_INC(exited_count); - break; + return "exited"; } + return "no-event"; } -static rb_internal_thread_event_hook_t * single_hook = NULL; - -static VALUE -thread_counters(VALUE thread) +static void +unexpected(bool strict, const char *format, VALUE thread, rb_event_flag_t last_event) { - VALUE array = rb_ary_new2(5); - rb_ary_push(array, UINT2NUM(started_count)); - rb_ary_push(array, UINT2NUM(ready_count)); - rb_ary_push(array, UINT2NUM(resumed_count)); - rb_ary_push(array, UINT2NUM(suspended_count)); - rb_ary_push(array, UINT2NUM(exited_count)); - return array; + const char *last_event_name = event_name(last_event); + if (strict) { + rb_bug(format, thread, last_event_name); + } + else { + fprintf(stderr, format, thread, last_event_name); + fprintf(stderr, "\n"); + } } -static VALUE -thread_local_counters(VALUE thread) +static void +ex_callback(rb_event_flag_t event, const rb_internal_thread_event_data_t *event_data, void *user_data) { - VALUE array = rb_ary_new2(3); - rb_ary_push(array, UINT2NUM(local_ready_count)); - rb_ary_push(array, UINT2NUM(local_resumed_count)); - rb_ary_push(array, UINT2NUM(local_suspended_count)); - return array; -} + rb_event_flag_t last_event = find_last_event(event_data->thread); + bool strict = (bool)user_data; -static VALUE -thread_reset_counters(VALUE thread) -{ - RUBY_ATOMIC_SET(started_count, 0); - RUBY_ATOMIC_SET(ready_count, 0); - RUBY_ATOMIC_SET(resumed_count, 0); - RUBY_ATOMIC_SET(suspended_count, 0); - RUBY_ATOMIC_SET(exited_count, 0); - local_ready_count = 0; - local_resumed_count = 0; - local_suspended_count = 0; - return Qtrue; + if (last_event != 0) { + switch (event) { + case RUBY_INTERNAL_THREAD_EVENT_STARTED: + unexpected(strict, "[thread=%"PRIxVALUE"] `started` event can't be preceded by `%s`", event_data->thread, last_event); + break; + case RUBY_INTERNAL_THREAD_EVENT_READY: + if (last_event != RUBY_INTERNAL_THREAD_EVENT_STARTED && last_event != RUBY_INTERNAL_THREAD_EVENT_SUSPENDED) { + unexpected(strict, "[thread=%"PRIxVALUE"] `ready` must be preceded by `started` or `suspended`, got: `%s`", event_data->thread, last_event); + } + break; + case RUBY_INTERNAL_THREAD_EVENT_RESUMED: + if (last_event != RUBY_INTERNAL_THREAD_EVENT_READY) { + unexpected(strict, "[thread=%"PRIxVALUE"] `resumed` must be preceded by `ready`, got: `%s`", event_data->thread, last_event); + } + break; + case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED: + if (last_event != RUBY_INTERNAL_THREAD_EVENT_RESUMED) { + unexpected(strict, "[thread=%"PRIxVALUE"] `suspended` must be preceded by `resumed`, got: `%s`", event_data->thread, last_event); + } + break; + case RUBY_INTERNAL_THREAD_EVENT_EXITED: + if (last_event != RUBY_INTERNAL_THREAD_EVENT_RESUMED && last_event != RUBY_INTERNAL_THREAD_EVENT_SUSPENDED) { + unexpected(strict, "[thread=%"PRIxVALUE"] `exited` must be preceded by `resumed` or `suspended`, got: `%s`", event_data->thread, last_event); + } + break; + } + } + + rb_atomic_t cursor = RUBY_ATOMIC_FETCH_ADD(timeline_cursor, 1); + if (cursor >= MAX_EVENTS) { + rb_bug("TestThreadInstrumentation: ran out of event_timeline space"); + } + + event_timeline[cursor].thread = event_data->thread; + event_timeline[cursor].event = event; } +static rb_internal_thread_event_hook_t * single_hook = NULL; + static VALUE -thread_register_callback(VALUE thread) +thread_register_callback(VALUE thread, VALUE strict) { single_hook = rb_internal_thread_add_event_hook( ex_callback, @@ -94,13 +140,33 @@ thread_register_callback(VALUE thread) RUBY_INTERNAL_THREAD_EVENT_RESUMED | RUBY_INTERNAL_THREAD_EVENT_SUSPENDED | RUBY_INTERNAL_THREAD_EVENT_EXITED, - NULL + (void *)RTEST(strict) ); return Qnil; } static VALUE +event_symbol(rb_event_flag_t event) +{ + switch (event) { + case RUBY_INTERNAL_THREAD_EVENT_STARTED: + return rb_id2sym(rb_intern("started")); + case RUBY_INTERNAL_THREAD_EVENT_READY: + return rb_id2sym(rb_intern("ready")); + case RUBY_INTERNAL_THREAD_EVENT_RESUMED: + return rb_id2sym(rb_intern("resumed")); + case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED: + return rb_id2sym(rb_intern("suspended")); + case RUBY_INTERNAL_THREAD_EVENT_EXITED: + return rb_id2sym(rb_intern("exited")); + default: + rb_bug("TestThreadInstrumentation: Unexpected event"); + break; + } +} + +static VALUE thread_unregister_callback(VALUE thread) { if (single_hook) { @@ -108,7 +174,18 @@ thread_unregister_callback(VALUE thread) single_hook = NULL; } - return Qnil; + VALUE events = rb_ary_new_capa(timeline_cursor); + rb_atomic_t cursor; + for (cursor = 0; cursor < timeline_cursor; cursor++) { + VALUE pair = rb_ary_new_capa(2); + rb_ary_push(pair, event_timeline[cursor].thread); + rb_ary_push(pair, event_symbol(event_timeline[cursor].event)); + rb_ary_push(events, pair); + } + + reset_timeline(); + + return events; } static VALUE @@ -132,10 +209,10 @@ Init_instrumentation(void) { VALUE mBug = rb_define_module("Bug"); VALUE klass = rb_define_module_under(mBug, "ThreadInstrumentation"); - rb_define_singleton_method(klass, "counters", thread_counters, 0); - rb_define_singleton_method(klass, "local_counters", thread_local_counters, 0); - rb_define_singleton_method(klass, "reset_counters", thread_reset_counters, 0); - rb_define_singleton_method(klass, "register_callback", thread_register_callback, 0); + rb_global_variable(&timeline_value); + timeline_value = TypedData_Wrap_Struct(0, &event_timeline_type, (void *)1); + + rb_define_singleton_method(klass, "register_callback", thread_register_callback, 1); rb_define_singleton_method(klass, "unregister_callback", thread_unregister_callback, 0); rb_define_singleton_method(klass, "register_and_unregister_callbacks", thread_register_and_unregister_callback, 0); } diff --git a/ext/-test-/thread/lock_native_thread/depend b/ext/-test-/thread/lock_native_thread/depend new file mode 100644 index 0000000000..a32843e531 --- /dev/null +++ b/ext/-test-/thread/lock_native_thread/depend @@ -0,0 +1,163 @@ +# AUTOGENERATED DEPENDENCIES START +lock_native_thread.o: $(RUBY_EXTCONF_H) +lock_native_thread.o: $(arch_hdrdir)/ruby/config.h +lock_native_thread.o: $(hdrdir)/ruby/assert.h +lock_native_thread.o: $(hdrdir)/ruby/backward.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/assume.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/attributes.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/bool.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/inttypes.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/limits.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/long_long.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/stdalign.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/stdarg.h +lock_native_thread.o: $(hdrdir)/ruby/defines.h +lock_native_thread.o: $(hdrdir)/ruby/intern.h +lock_native_thread.o: $(hdrdir)/ruby/internal/abi.h +lock_native_thread.o: $(hdrdir)/ruby/internal/anyargs.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/char.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/double.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/int.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/long.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/short.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/assume.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/artificial.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/cold.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/const.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/constexpr.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/deprecated.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/error.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/forceinline.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/format.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noalias.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noexcept.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noinline.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/nonnull.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noreturn.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/pure.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/restrict.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/warning.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/weakref.h +lock_native_thread.o: $(hdrdir)/ruby/internal/cast.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_since.h +lock_native_thread.o: $(hdrdir)/ruby/internal/config.h +lock_native_thread.o: $(hdrdir)/ruby/internal/constant_p.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rarray.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rbasic.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rbignum.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rclass.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rdata.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rfile.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rhash.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/robject.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rregexp.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rstring.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rstruct.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +lock_native_thread.o: $(hdrdir)/ruby/internal/ctype.h +lock_native_thread.o: $(hdrdir)/ruby/internal/dllexport.h +lock_native_thread.o: $(hdrdir)/ruby/internal/dosish.h +lock_native_thread.o: $(hdrdir)/ruby/internal/error.h +lock_native_thread.o: $(hdrdir)/ruby/internal/eval.h +lock_native_thread.o: $(hdrdir)/ruby/internal/event.h +lock_native_thread.o: $(hdrdir)/ruby/internal/fl_type.h +lock_native_thread.o: $(hdrdir)/ruby/internal/gc.h +lock_native_thread.o: $(hdrdir)/ruby/internal/glob.h +lock_native_thread.o: $(hdrdir)/ruby/internal/globals.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/attribute.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/builtin.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/c_attribute.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/extension.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/feature.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/warning.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/array.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/bignum.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/class.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/compar.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/complex.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/cont.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/dir.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/enum.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/enumerator.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/error.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/eval.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/file.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/hash.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/io.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/load.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/marshal.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/numeric.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/object.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/parse.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/proc.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/process.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/random.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/range.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/rational.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/re.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/ruby.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/select.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/set.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/signal.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/sprintf.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/string.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/struct.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/thread.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/time.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/variable.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/vm.h +lock_native_thread.o: $(hdrdir)/ruby/internal/interpreter.h +lock_native_thread.o: $(hdrdir)/ruby/internal/iterator.h +lock_native_thread.o: $(hdrdir)/ruby/internal/memory.h +lock_native_thread.o: $(hdrdir)/ruby/internal/method.h +lock_native_thread.o: $(hdrdir)/ruby/internal/module.h +lock_native_thread.o: $(hdrdir)/ruby/internal/newobj.h +lock_native_thread.o: $(hdrdir)/ruby/internal/scan_args.h +lock_native_thread.o: $(hdrdir)/ruby/internal/special_consts.h +lock_native_thread.o: $(hdrdir)/ruby/internal/static_assert.h +lock_native_thread.o: $(hdrdir)/ruby/internal/stdalign.h +lock_native_thread.o: $(hdrdir)/ruby/internal/stdbool.h +lock_native_thread.o: $(hdrdir)/ruby/internal/stdckdint.h +lock_native_thread.o: $(hdrdir)/ruby/internal/symbol.h +lock_native_thread.o: $(hdrdir)/ruby/internal/value.h +lock_native_thread.o: $(hdrdir)/ruby/internal/value_type.h +lock_native_thread.o: $(hdrdir)/ruby/internal/variable.h +lock_native_thread.o: $(hdrdir)/ruby/internal/warning_push.h +lock_native_thread.o: $(hdrdir)/ruby/internal/xmalloc.h +lock_native_thread.o: $(hdrdir)/ruby/missing.h +lock_native_thread.o: $(hdrdir)/ruby/ruby.h +lock_native_thread.o: $(hdrdir)/ruby/st.h +lock_native_thread.o: $(hdrdir)/ruby/subst.h +lock_native_thread.o: $(hdrdir)/ruby/thread.h +lock_native_thread.o: lock_native_thread.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/thread/lock_native_thread/extconf.rb b/ext/-test-/thread/lock_native_thread/extconf.rb new file mode 100644 index 0000000000..832bfde01a --- /dev/null +++ b/ext/-test-/thread/lock_native_thread/extconf.rb @@ -0,0 +1,2 @@ +# frozen_string_literal: false +create_makefile("-test-/thread/lock_native_thread") diff --git a/ext/-test-/thread/lock_native_thread/lock_native_thread.c b/ext/-test-/thread/lock_native_thread/lock_native_thread.c new file mode 100644 index 0000000000..2eb75809a9 --- /dev/null +++ b/ext/-test-/thread/lock_native_thread/lock_native_thread.c @@ -0,0 +1,50 @@ + +#include "ruby/ruby.h" +#include "ruby/thread.h" + +#ifdef HAVE_PTHREAD_H +#include <pthread.h> + +static pthread_key_t tls_key; + +static VALUE +get_tls(VALUE self) +{ + return (VALUE)pthread_getspecific(tls_key); +} + +static VALUE +set_tls(VALUE self, VALUE vn) +{ + pthread_setspecific(tls_key, (void *)vn); + return Qnil; +} + +static VALUE +lock_native_thread(VALUE self) +{ + return rb_thread_lock_native_thread() ? Qtrue : Qfalse; +} + +void +Init_lock_native_thread(void) +{ + int r; + + if ((r = pthread_key_create(&tls_key, NULL)) != 0) { + rb_bug("pthread_key_create() returns %d", r); + } + pthread_setspecific(tls_key, NULL); + + rb_define_method(rb_cThread, "lock_native_thread", lock_native_thread, 0); + rb_define_method(rb_cThread, "get_tls", get_tls, 0); + rb_define_method(rb_cThread, "set_tls", set_tls, 1); +} + +#else // HAVE_PTHREAD_H +void +Init_lock_native_thread(void) +{ + // do nothing +} +#endif // HAVE_PTHREAD_H |
