summaryrefslogtreecommitdiff
path: root/thread_pthread.c
diff options
context:
space:
mode:
authorJean Boussier <[email protected]>2022-01-27 17:12:22 +0100
committerJean Boussier <[email protected]>2022-06-03 15:13:33 +0200
commit9125374726fbf68c05ee7585d4a374ffc5efc5db ()
tree5f820c00632eb80a336161245baaf9248dd9eb51 /thread_pthread.c
parentd142eff6586de0018c9442129201b03c826f2a1e (diff)
[Feature #18339] GVL Instrumentation API
Ref: https://bugs.ruby-lang.org/issues/18339 Design: - This tries to minimize the overhead when no hook is registered. It should only incur an extra unsynchronized boolean check. - The hook list is protected with a read-write lock as to cause contention when some hooks are registered. - The hooks MUST be thread safe, and MUST NOT call into Ruby as they are executed outside the GVL. - It's simply a noop on Windows. API: ``` rb_internal_thread_event_hook_t * rb_internal_thread_add_event_hook(rb_internal_thread_event_callback callback, rb_event_flag_t internal_event, void *user_data); bool rb_internal_thread_remove_event_hook(rb_internal_thread_event_hook_t * hook); ``` You can subscribe to 3 events: - READY: called right before attempting to acquire the GVL - RESUMED: called right after successfully acquiring the GVL - SUSPENDED: called right after releasing the GVL. The hooks MUST be threadsafe, as they are executed outside of the GVL, they also MUST NOT call any Ruby API.
Notes: Merged: https://.com/ruby/ruby/pull/5500
-rw-r--r--thread_pthread.c108
1 files changed, 107 insertions, 1 deletions
@@ -98,6 +98,95 @@
# endif
#endif
enum rtimer_state {
/* alive, after timer_create: */
RTIMER_DISARM,
@@ -295,6 +384,10 @@ thread_sched_to_running_common(struct rb_thread_sched *sched, rb_thread_t *th)
// waiting -> ready
thread_sched_to_ready_common(sched, th);
// wait for running chance
do {
if (!sched->timer) {
@@ -319,6 +412,10 @@ thread_sched_to_running_common(struct rb_thread_sched *sched, rb_thread_t *th)
// ready -> running
sched->running = th;
if (!sched->timer) {
if (!designate_timer_thread(sched) && !ubf_threads_empty()) {
rb_thread_wakeup_timer_thread(-1);
@@ -337,6 +434,10 @@ thread_sched_to_running(struct rb_thread_sched *sched, rb_thread_t *th)
static rb_thread_t *
thread_sched_to_waiting_common(struct rb_thread_sched *sched)
{
rb_thread_t *next;
sched->running = NULL;
next = ccan_list_top(&sched->readyq, rb_thread_t, sched.node.readyq);
@@ -687,9 +788,14 @@ native_thread_init(struct rb_native_thread *nt)
void
Init_native_thread(rb_thread_t *main_th)
{
#if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
if (condattr_monotonic) {
- int r = pthread_condattr_init(condattr_monotonic);
if (r == 0) {
r = pthread_condattr_setclock(condattr_monotonic, CLOCK_MONOTONIC);
}