summaryrefslogtreecommitdiff
path: root/ext/-test-/thread/instrumentation/instrumentation.c
diff options
context:
space:
mode:
authorJean Boussier <byroot@ruby-lang.org>2023-11-09 13:56:29 +0100
committerJean Boussier <jean.boussier@gmail.com>2023-11-13 08:45:20 +0100
commit9ca41e999159096cb0872b4babbb94bf5d1af4ce (patch)
tree997d7847124e8ddcadc75413b7eb6b0a587e1772 /ext/-test-/thread/instrumentation/instrumentation.c
parent4376a17552670021a9175bb487be8eb16a2a97e9 (diff)
GVL Instrumentation: pass thread->self as part of event data
Context: https://github.com/ivoanjo/gvl-tracing/pull/4 Some hooks may want to collect data on a per thread basis. Right now the only way to identify the concerned thread is to use `rb_nativethread_self()` or similar, but even then because of the thread cache or MaNy, two distinct Ruby threads may report the same native thread id. By passing `thread->self`, hooks can use it as a key to store the metadata. NB: Most hooks are executed outside the GVL, so such data collection need to use a thread-safe data-structure, and shouldn't use the reference in other ways from inside the hook. They must also either pin that value or handle compaction.
Diffstat (limited to 'ext/-test-/thread/instrumentation/instrumentation.c')
-rw-r--r--ext/-test-/thread/instrumentation/instrumentation.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/ext/-test-/thread/instrumentation/instrumentation.c b/ext/-test-/thread/instrumentation/instrumentation.c
index edb8738a29..4d76f4cbb3 100644
--- a/ext/-test-/thread/instrumentation/instrumentation.c
+++ b/ext/-test-/thread/instrumentation/instrumentation.c
@@ -16,11 +16,14 @@ 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 last_thread = Qnil;
+
static void
ex_callback(rb_event_flag_t event, const rb_internal_thread_event_data_t *event_data, void *user_data)
{
switch (event) {
case RUBY_INTERNAL_THREAD_EVENT_STARTED:
+ last_thread = event_data->thread;
RUBY_ATOMIC_INC(started_count);
break;
case RUBY_INTERNAL_THREAD_EVENT_READY:
@@ -122,15 +125,31 @@ thread_register_and_unregister_callback(VALUE thread)
return Qtrue;
}
+static VALUE
+thread_last_spawned(VALUE mod)
+{
+ return last_thread;
+}
+
+static VALUE
+thread_set_last_spawned(VALUE mod, VALUE value)
+{
+ return last_thread = value;
+}
+
void
Init_instrumentation(void)
{
VALUE mBug = rb_define_module("Bug");
VALUE klass = rb_define_module_under(mBug, "ThreadInstrumentation");
+ rb_global_variable(&last_thread);
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_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);
+
+ rb_define_singleton_method(klass, "last_spawned_thread", thread_last_spawned, 0);
+ rb_define_singleton_method(klass, "last_spawned_thread=", thread_set_last_spawned, 1);
}