From c54c38a95572cc1bf9d6a02fdc18500878968932 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 9 Feb 2014 00:50:03 +0000 Subject: [PATCH] prepare for rb_thread_blocking_region removal It'll be OK to use rb_thread_call_without_gvl when rb_thread_blocking_region is not detectable at all. We still use rb_thread_blocking_region for Ruby 2.0-2.1 because rb_thread_call_without_gvl was detectable in 1.9.3, but not usable as an internal symbol. ref: https://bugs.ruby-lang.org/issues/9502 --- ext/io_splice/extconf.rb | 1 + ext/io_splice/io_splice_ext.c | 45 ++++++++++++++++++++++++++----------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/ext/io_splice/extconf.rb b/ext/io_splice/extconf.rb index 52dab83..bfd655a 100644 --- a/ext/io_splice/extconf.rb +++ b/ext/io_splice/extconf.rb @@ -5,6 +5,7 @@ have_func('splice', %w(fcntl.h)) or abort 'splice(2) not defined' have_func('tee', %w(fcntl.h)) or abort 'tee(2) not defined' have_func('pipe2', %w(fcntl.h unistd.h)) have_func('rb_thread_blocking_region') +have_func('rb_thread_call_without_gvl') have_macro('F_GETPIPE_SZ', %w(fcntl.h)) have_macro('F_SETPIPE_SZ', %w(fcntl.h)) diff --git a/ext/io_splice/io_splice_ext.c b/ext/io_splice/io_splice_ext.c index 9a838df..cad5dd1 100644 --- a/ext/io_splice/io_splice_ext.c +++ b/ext/io_splice/io_splice_ext.c @@ -79,23 +79,35 @@ static int check_fileno(VALUE io) errno = saved_errno; return fd; } -#ifndef HAVE_RB_THREAD_BLOCKING_REGION + /* partial emulation of the 1.9 rb_thread_blocking_region under 1.8 */ +#if defined(HAVE_RB_THREAD_BLOCKING_REGION) && \ + defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) +/* + * Ruby 1.9 - 2.1 (we use deprecated rb_thread_blocking_region in 2.0+ + * because we can detect (but not use) rb_thread_blocking_region in 1.9.3 + */ +typedef VALUE (*my_blocking_fn_t)(void*); +# define WITHOUT_GVL(fn,a,ubf,b) \ + rb_thread_blocking_region((my_blocking_fn_t)(fn),(a),(ubf),(b)) +#elif defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) /* Ruby 2.2+ */ +#include +# define WITHOUT_GVL(fn,a,ubf,b) \ + rb_thread_call_without_gvl((fn),(a),(ubf),(b)) +#else /* Ruby 1.8 */ # include # define RUBY_UBF_IO ((rb_unblock_function_t *)-1) typedef void rb_unblock_function_t(void *); -typedef VALUE rb_blocking_function_t(void *); -static VALUE -rb_thread_blocking_region( - rb_blocking_function_t *fn, void *data1, - rb_unblock_function_t *ubf, void *data2) +typedef void * rb_blocking_function_t(void *); +static void * WITHOUT_GVL(rb_blocking_function_t *func, void *data1, + rb_unblock_function_t *ubf, void *data2) { - VALUE rv; + void *rv; assert(RUBY_UBF_IO == ubf && "RUBY_UBF_IO required for emulation"); TRAP_BEG; - rv = fn(data1); + rv = func(data1); TRAP_END; return rv; @@ -112,10 +124,7 @@ rb_thread_blocking_region( # define RARRAY_LEN(s) (RARRAY(s)->len) #endif -static VALUE io_run(rb_blocking_function_t *fn, void *data) -{ - return rb_thread_blocking_region(fn, data, RUBY_UBF_IO, 0); -} +#define io_run(fn,data) WITHOUT_GVL((fn),(data),RUBY_UBF_IO,0) struct splice_args { int fd_in; @@ -126,14 +135,14 @@ struct splice_args { unsigned flags; }; -static VALUE nogvl_splice(void *ptr) +static void * nogvl_splice(void *ptr) { struct splice_args *a = ptr; if (a->len > MAX_AT_ONCE) a->len = MAX_AT_ONCE; - return (VALUE)splice(a->fd_in, a->off_in, a->fd_out, a->off_out, + return (void *)splice(a->fd_in, a->off_in, a->fd_out, a->off_out, a->len, a->flags); } @@ -275,14 +284,14 @@ struct tee_args { }; /* runs without GVL */ -static VALUE nogvl_tee(void *ptr) +static void * nogvl_tee(void *ptr) { struct tee_args *a = ptr; if (a->len > MAX_AT_ONCE) a->len = MAX_AT_ONCE; - return (VALUE)tee(a->fd_in, a->fd_out, a->len, a->flags); + return (void *)tee(a->fd_in, a->fd_out, a->len, a->flags); } static ssize_t do_tee(int argc, VALUE *argv, unsigned dflags) @@ -403,11 +412,11 @@ struct vmsplice_args { unsigned flags; }; -static VALUE nogvl_vmsplice(void *ptr) +static void * nogvl_vmsplice(void *ptr) { struct vmsplice_args *a = ptr; - return (VALUE)vmsplice(a->fd, a->iov, a->nr_segs, a->flags); + return (void *)vmsplice(a->fd, a->iov, a->nr_segs, a->flags); } /* this can't be a function since we use alloca() */ -- 2.11.4.GIT