Skip to content

Commit e5ef64f

Browse files
committedJan 25, 2022
Call the gvl hooks
1 parent 4d48cfe commit e5ef64f

File tree

5 files changed

+53
-39
lines changed

5 files changed

+53
-39
lines changed
 

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static gvl_hook_t * single_hook = NULL;
7878

7979
static VALUE
8080
thread_register_gvl_callback(VALUE thread) {
81-
single_hook = rb_gvl_event_new(*ex_callback, 0x12);
81+
single_hook = rb_gvl_event_new(*ex_callback, RUBY_INTERNAL_EVENT_GVL_ACQUIRE_ENTER, 1);
8282

8383
return Qnil;
8484
}
@@ -95,15 +95,15 @@ thread_unregister_gvl_callback(VALUE thread) {
9595

9696
static VALUE
9797
thread_call_gvl_callback(VALUE thread) {
98-
rb_gvl_execute_hooks(0x12);
98+
rb_gvl_execute_hooks(RUBY_INTERNAL_EVENT_GVL_ACQUIRE_ENTER, 1);
9999
return Qnil;
100100
}
101101

102102
static VALUE
103103
thread_register_and_unregister_gvl_callback(VALUE thread) {
104104
gvl_hook_t * hooks[5];
105105
for (int i = 0; i < 5; i++) {
106-
hooks[i] = rb_gvl_event_new(*ex_callback, 0x12);
106+
hooks[i] = rb_gvl_event_new(*ex_callback, RUBY_INTERNAL_EVENT_GVL_ACQUIRE_ENTER);
107107
}
108108

109109
if (!rb_gvl_event_delete(hooks[4])) return Qfalse;

‎include/ruby/internal/event.h

+16-12
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,22 @@
8282
*
8383
* @{
8484
*/
85-
#define RUBY_INTERNAL_EVENT_SWITCH 0x040000 /**< Thread switched. */
86-
#define RUBY_EVENT_SWITCH 0x040000 /**< @old{RUBY_INTERNAL_EVENT_SWITCH} */
87-
/* 0x080000 */
88-
#define RUBY_INTERNAL_EVENT_NEWOBJ 0x100000 /**< Object allocated. */
89-
#define RUBY_INTERNAL_EVENT_FREEOBJ 0x200000 /**< Object swept. */
90-
#define RUBY_INTERNAL_EVENT_GC_START 0x400000 /**< GC started. */
91-
#define RUBY_INTERNAL_EVENT_GC_END_MARK 0x800000 /**< GC ended mark phase. */
92-
#define RUBY_INTERNAL_EVENT_GC_END_SWEEP 0x1000000 /**< GC ended sweep phase. */
93-
#define RUBY_INTERNAL_EVENT_GC_ENTER 0x2000000 /**< `gc_enter()` is called. */
94-
#define RUBY_INTERNAL_EVENT_GC_EXIT 0x4000000 /**< `gc_exit()` is called. */
95-
#define RUBY_INTERNAL_EVENT_OBJSPACE_MASK 0x7f00000 /**< Bitmask of GC events. */
96-
#define RUBY_INTERNAL_EVENT_MASK 0xffff0000 /**< Bitmask of internal events. */
85+
#define RUBY_INTERNAL_EVENT_SWITCH 0x00040000 /**< Thread switched. */
86+
#define RUBY_EVENT_SWITCH 0x00040000 /**< @old{RUBY_INTERNAL_EVENT_SWITCH} */
87+
/*0x00080000 */
88+
#define RUBY_INTERNAL_EVENT_NEWOBJ 0x00100000 /**< Object allocated. */
89+
#define RUBY_INTERNAL_EVENT_FREEOBJ 0x00200000 /**< Object swept. */
90+
#define RUBY_INTERNAL_EVENT_GC_START 0x00400000 /**< GC started. */
91+
#define RUBY_INTERNAL_EVENT_GC_END_MARK 0x00800000 /**< GC ended mark phase. */
92+
#define RUBY_INTERNAL_EVENT_GC_END_SWEEP 0x01000000 /**< GC ended sweep phase. */
93+
#define RUBY_INTERNAL_EVENT_GC_ENTER 0x02000000 /**< `gc_enter()` is called. */
94+
#define RUBY_INTERNAL_EVENT_GC_EXIT 0x04000000 /**< `gc_exit()` is called. */
95+
#define RUBY_INTERNAL_EVENT_OBJSPACE_MASK 0x07f00000 /**< Bitmask of GC events. */
96+
#define RUBY_INTERNAL_EVENT_GVL_ACQUIRE_ENTER 0x10000000 /** `gvl_acquire() is called */
97+
#define RUBY_INTERNAL_EVENT_GVL_ACQUIRE_EXIT 0x20000000 /** `gvl_acquire() is exiting successfully */
98+
#define RUBY_INTERNAL_EVENT_GVL_RELEASE 0x40000000 /** `gvl_release() is called */
99+
#define RUBY_INTERNAL_EVENT_GVL_MASK 0x70000000 /**< Bitmask of GVL events. */
100+
#define RUBY_INTERNAL_EVENT_MASK 0xffff0000 /**< Bitmask of internal events. */
97101

98102
/** @} */
99103

‎include/ruby/thread_native.h

+7-9
Original file line numberDiff line numberDiff line change
@@ -201,26 +201,24 @@ void rb_native_cond_initialize(rb_nativethread_cond_t *cond);
201201
*/
202202
void rb_native_cond_destroy(rb_nativethread_cond_t *cond);
203203

204-
#include <stdint.h>
205-
struct gvl_hook_event_args {
206-
//
207-
};
208-
#include <stdint.h>
204+
typedef struct gvl_hook_event_args {
205+
unsigned long waiting;
206+
} gvl_hook_event_args_t;
209207

210-
typedef void (*rb_gvl_callback)(uint32_t event, struct gvl_hook_event_args args);
208+
typedef void (*rb_gvl_callback)(uint32_t event, gvl_hook_event_args_t args);
211209

212210
// TODO: this is going to be the same on Windows so move it somewhere sensible
213211
typedef struct gvl_hook {
214212
rb_gvl_callback callback;
215-
uint32_t event;
213+
rb_event_flag_t event;
216214

217215
struct gvl_hook *next;
218216
} gvl_hook_t;
219217

220218
#include "ruby/internal/memory.h"
221219

222-
gvl_hook_t * rb_gvl_event_new(void *callback, uint32_t event);
220+
gvl_hook_t * rb_gvl_event_new(void *callback, rb_event_flag_t event);
223221
bool rb_gvl_event_delete(gvl_hook_t * hook);
224-
void rb_gvl_execute_hooks(uint32_t event);
222+
void rb_gvl_execute_hooks(rb_event_flag_t event, unsigned long waiting);
225223
RBIMPL_SYMBOL_EXPORT_END()
226224
#endif

‎thread_pthread.c

+26-15
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ static gvl_hook_t * rb_gvl_hooks = NULL;
105105
static pthread_rwlock_t rb_gvl_hooks_rw_lock = PTHREAD_RWLOCK_INITIALIZER;
106106

107107
gvl_hook_t *
108-
rb_gvl_event_new(void *callback, uint32_t event) {
108+
rb_gvl_event_new(void *callback, rb_event_flag_t event) {
109109
gvl_hook_t *hook = ALLOC_N(gvl_hook_t, 1);
110110
hook->callback = callback;
111111
hook->event = event;
@@ -155,25 +155,21 @@ rb_gvl_event_delete(gvl_hook_t * hook) {
155155
}
156156

157157
void
158-
rb_gvl_execute_hooks(uint32_t event) {
159-
if (!rb_gvl_hooks) {
160-
return;
161-
}
162-
158+
rb_gvl_execute_hooks(rb_event_flag_t event, unsigned long waiting) {
163159
if (pthread_rwlock_rdlock(&rb_gvl_hooks_rw_lock)) {
164160
// TODO: better way to deal with error?
165161
return;
166162
}
167163

168-
gvl_hook_t *h = rb_gvl_hooks;
169-
struct gvl_hook_event_args args = {};
170-
171-
do {
172-
if (h->event & event) {
173-
(*h->callback)(event, args);
174-
}
175-
} while((h = h->next));
176-
164+
if (rb_gvl_hooks) {
165+
gvl_hook_t *h = rb_gvl_hooks;
166+
gvl_hook_event_args_t args = { .waiting = waiting };
167+
do {
168+
if (h->event & event) {
169+
(*h->callback)(event, args);
170+
}
171+
} while((h = h->next));
172+
}
177173
pthread_rwlock_unlock(&rb_gvl_hooks_rw_lock);
178174
}
179175

@@ -366,6 +362,10 @@ gvl_acquire_common(rb_global_vm_lock_t *gvl, rb_thread_t *th)
366362
"we must not be in ubf_list and GVL waitq at the same time");
367363

368364
list_add_tail(&gvl->waitq, &nd->node.gvl);
365+
gvl->waiting++;
366+
if (rb_gvl_hooks) {
367+
rb_gvl_execute_hooks(RUBY_INTERNAL_EVENT_GVL_ACQUIRE_ENTER, gvl->waiting);
368+
}
369369

370370
do {
371371
if (!gvl->timer) {
@@ -377,6 +377,7 @@ gvl_acquire_common(rb_global_vm_lock_t *gvl, rb_thread_t *th)
377377
} while (gvl->owner);
378378

379379
list_del_init(&nd->node.gvl);
380+
gvl->waiting--;
380381

381382
if (gvl->need_yield) {
382383
gvl->need_yield = 0;
@@ -387,6 +388,11 @@ gvl_acquire_common(rb_global_vm_lock_t *gvl, rb_thread_t *th)
387388
gvl->timer_err = ETIMEDOUT;
388389
}
389390
gvl->owner = th;
391+
392+
if (rb_gvl_hooks) {
393+
rb_gvl_execute_hooks(RUBY_INTERNAL_EVENT_GVL_ACQUIRE_EXIT, gvl->waiting);
394+
}
395+
390396
if (!gvl->timer) {
391397
if (!designate_timer_thread(gvl) && !ubf_threads_empty()) {
392398
rb_thread_wakeup_timer_thread(-1);
@@ -405,6 +411,10 @@ gvl_acquire(rb_global_vm_lock_t *gvl, rb_thread_t *th)
405411
static const native_thread_data_t *
406412
gvl_release_common(rb_global_vm_lock_t *gvl)
407413
{
414+
if (rb_gvl_hooks) {
415+
rb_gvl_execute_hooks(RUBY_INTERNAL_EVENT_GVL_RELEASE, gvl->waiting);
416+
}
417+
408418
native_thread_data_t *next;
409419
gvl->owner = 0;
410420
next = list_top(&gvl->waitq, native_thread_data_t, node.ubf);
@@ -466,6 +476,7 @@ rb_gvl_init(rb_global_vm_lock_t *gvl)
466476
rb_native_cond_initialize(&gvl->switch_wait_cond);
467477
list_head_init(&gvl->waitq);
468478
gvl->owner = 0;
479+
gvl->waiting = 0;
469480
gvl->timer = 0;
470481
gvl->timer_err = ETIMEDOUT;
471482
gvl->need_yield = 0;

‎thread_pthread.h

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ typedef struct rb_global_vm_lock_struct {
5959
* timer.
6060
*/
6161
struct list_head waitq; /* <=> native_thread_data_t.node.ubf */
62+
volatile unsigned long waiting;
6263
const struct rb_thread_struct *timer;
6364
int timer_err;
6465

0 commit comments

Comments
 (0)
Failed to load comments.