@@ -105,7 +105,7 @@ static gvl_hook_t * rb_gvl_hooks = NULL;
105105static pthread_rwlock_t rb_gvl_hooks_rw_lock = PTHREAD_RWLOCK_INITIALIZER ;
106106
107107gvl_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
157157void
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)
405411static const native_thread_data_t *
406412gvl_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 ;
0 commit comments