diff --git a/thread.c b/thread.c index 01007b1862..7bcf64741c 100644 --- a/thread.c +++ b/thread.c @@ -79,8 +79,9 @@ st_delete_wrap(st_table *table, st_data_t key) #define THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION -static void set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *ptr, - rb_unblock_function_t **oldfunc, void **oldptr); +static void set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg, + struct rb_unblock_callback *old); +static void reset_unblock_function(rb_thread_t *th, const struct rb_unblock_callback *old); #define GVL_UNLOCK_BEGIN() do { \ rb_thread_t *_th_stored = GET_THREAD(); \ @@ -95,9 +96,8 @@ static void set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, v #define BLOCKING_REGION(exec, ubf, ubfarg) do { \ rb_thread_t *__th = GET_THREAD(); \ int __prev_status = __th->status; \ - rb_unblock_function_t *__oldubf; \ - void *__oldubfarg; \ - set_unblock_function(__th, ubf, ubfarg, &__oldubf, &__oldubfarg); \ + struct rb_unblock_callback __oldubf; \ + set_unblock_function(__th, ubf, ubfarg, &__oldubf); \ __th->status = THREAD_STOPPED; \ thread_debug("enter blocking region (%p)\n", __th); \ GVL_UNLOCK_BEGIN(); {\ @@ -106,7 +106,7 @@ static void set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, v GVL_UNLOCK_END(); \ thread_debug("leave blocking region (%p)\n", __th); \ remove_signal_thread_list(__th); \ - set_unblock_function(__th, __oldubf, __oldubfarg, 0, 0); \ + reset_unblock_function(__th, &__oldubf); \ if (__th->status == THREAD_STOPPED) { \ __th->status = __prev_status; \ } \ @@ -195,7 +195,7 @@ rb_thread_debug(const char *fmt, ...) static void set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg, - rb_unblock_function_t **oldfunc, void **oldarg) + struct rb_unblock_callback *old) { check_ints: RUBY_VM_CHECK_INTS(); /* check signal or so */ @@ -205,21 +205,28 @@ set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg, goto check_ints; } else { - if (oldfunc) *oldfunc = th->unblock_function; - if (oldarg) *oldarg = th->unblock_function_arg; - th->unblock_function = func; - th->unblock_function_arg = arg; + if (old) *old = th->unblock; + th->unblock.func = func; + th->unblock.arg = arg; } native_mutex_unlock(&th->interrupt_lock); } +static void +reset_unblock_function(rb_thread_t *th, const struct rb_unblock_callback *old) +{ + native_mutex_lock(&th->interrupt_lock); + th->unblock = *old; + native_mutex_unlock(&th->interrupt_lock); +} + static void rb_thread_interrupt(rb_thread_t *th) { native_mutex_lock(&th->interrupt_lock); RUBY_VM_SET_INTERRUPT(th); - if (th->unblock_function) { - (th->unblock_function)(th->unblock_function_arg); + if (th->unblock.func) { + (th->unblock.func)(th->unblock.arg); } else { /* none */ diff --git a/thread_pthread.c b/thread_pthread.c index 58ce378841..e5a6566267 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -424,8 +424,8 @@ native_sleep(rb_thread_t *th, struct timeval *tv) GVL_UNLOCK_BEGIN(); { pthread_mutex_lock(&th->interrupt_lock); - th->unblock_function = ubf_pthread_cond_signal; - th->unblock_function_arg = th; + th->unblock.func = ubf_pthread_cond_signal; + th->unblock.arg = th; if (RUBY_VM_INTERRUPTED(th)) { /* interrupted. return immediate */ @@ -451,8 +451,8 @@ native_sleep(rb_thread_t *th, struct timeval *tv) thread_debug("native_sleep: pthread_cond_timedwait end (%d)\n", r); } } - th->unblock_function = 0; - th->unblock_function_arg = 0; + th->unblock.func = 0; + th->unblock.arg = 0; pthread_mutex_unlock(&th->interrupt_lock); th->status = prev_status; diff --git a/thread_win32.c b/thread_win32.c index a83ede0b94..63425511c1 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -220,8 +220,8 @@ native_sleep(rb_thread_t *th, struct timeval *tv) int status = th->status; th->status = THREAD_STOPPED; - th->unblock_function = ubf_handle; - th->unblock_function_arg = th; + th->unblock.func = ubf_handle; + th->unblock.arg = th; if (RUBY_VM_INTERRUPTED(th)) { /* interrupted. return immediate */ @@ -232,8 +232,8 @@ native_sleep(rb_thread_t *th, struct timeval *tv) thread_debug("native_sleep done (%lu)\n", ret); } - th->unblock_function = 0; - th->unblock_function_arg = 0; + th->unblock.func = 0; + th->unblock.arg = 0; th->status = status; } GVL_UNLOCK_END(); diff --git a/vm_core.h b/vm_core.h index 8f39c68995..f0fdafef2d 100644 --- a/vm_core.h +++ b/vm_core.h @@ -373,6 +373,11 @@ struct rb_vm_trap_tag { #define RUBY_VM_VALUE_CACHE_SIZE 0x1000 #define USE_VALUE_CACHE 0 +struct rb_unblock_callback { + rb_unblock_function_t *func; + void *arg; +}; + typedef struct rb_thread_struct rb_thread_t; struct rb_thread_struct @@ -418,9 +423,8 @@ struct rb_thread_struct int exec_signal; int interrupt_flag; - rb_unblock_function_t *unblock_function; - void *unblock_function_arg; rb_thread_lock_t interrupt_lock; + struct rb_unblock_callback unblock; struct rb_vm_tag *tag; struct rb_vm_trap_tag *trap_tag;